v8 Framework

Framework v8

This page is about previous versions of the SigTech v8 framework.
Please see Release notes | SigTech framework v8: Latest for information on the latest framework version.
Pages in this category
On this page

v8.15.0 (Feb 2023)

In this release

New curve CollateralizedOISCurve added

A new discount curve called CollateralizedOISCurve has been added to the framework. This new curve implements discounting on-the-fly using a collateral OIS discount curve and FX forwards. The curve applies the discounts based on collateral posted in a different currency (USD by default). The future cash flows are converted to the collateral currency using FX forwards and discounted using the collateral OIS curve.
The following code creates a curve that discounts JPY cash flows assuming that USD collateral is used for the instrument.
group_name="OIS ICE CURVE GROUP",

Date range parameters added to pnl_explain()

Two new start_date and end_date parameters have been added to the portfolio_greeks and pnl_explain functions (these functions belong to the rolling options/swaption strategies and also the DeltaHedgingStrategy).
Pass the start and end dates as a datetime. For example, start_date=datetime.date(2020,1,1).
This new feature has been introduced to increase the computation speeds. If a small date range is entered then the greeks and pnl are calculated for just this small date range, making the calculations faster.

New input data_points added to portfolio_greeks function

A new optional parameter data_points has been added to the portfolio_greeks function. When using this parameter in the rolling options strategies and the DeltaHedgingStrategy, the reported greek times will be overridden with the times specified by the data points list passed to the data_points parameter.
An example of this is shown below:
# creates the strategy
# calls the function with the new data points

Transaction costs updates

The interface for the defined transaction costs has been improved. These improvements include:
  • When entering parameters into a model, you must now enter them as a dictionary of parameter values. Previously, this was supported for only some transaction cost models but with this release, it is now available for all models.
  • The docstrings for each model have been updated and now also provide an example of how these transaction costs work.
  • Previously, some instruments (such as bonds and single stocks) used cost models defined on the objects instead of being defined via configured models. This made it harder to get additional information on the cost models. With this release, these cost models are now included.

Limits removed when plotting portfolio_table

Previously, when calling plot.portfolio_table with more than 100 rows the table would error.
With this release, if there are more than 100 rows the table is still plotted but a warning message is provided telling you that only the last 100 rows of the portfolio_table have been plotted.
If you want to view a DataFrame version of the portfolio_table, pass the argument as_df=True. In previous releases, the DataFrame would also error if there were more than 100 nows. With this release, the DataFrame returns every row available, even if there are more than 100 rows.

New parameter basket_creation_kwargs added to DynamicOptionsStrategy

You can now pass additional keyword arguments for the basket creation strategy when creating a DynamicOptionsStrategy. Pass the optional keyword arguments as a dictionary. An example of how to pass these arguments is shown in the code below:
# pass the additional keyword arguments in a dictionary.
bc_params = {'signal':signal,
strategy = sig.DynamicOptionsStrategy(
end_date=dtm.date(2022, 12, 5),

Added ability aggregate trades in bottom_trades_df

A new parameter net_trades has been added to the inspect.bottom_trades_df method. If set to True, you can now see the aggregated orders for trades happening at the same time for the same instrument.
An example of this is shown below:
from sigtech.framework.default_strategy_objects import rolling_futures
rfs = rolling_futures.es_index_front()
rfs1 = rfs.clone_object({'fixed_contracts': 1, 'ticker': 'C1'})
rfs2 = rfs.clone_object({'fixed_contracts': 2, 'ticker': 'C2'})
signal = pd.DataFrame({
'C1 STRATEGY': -1 + 0 * rfs1.history(),
'C2 STRATEGY': 1 + 0 * rfs2.history(),
ns = sig.SignalStrategy(

New parameter profit_metrics_only added to performance reports

Previously, the metrics used in the performance report and strategy widget were calculated using percentage returns or returns relative to a provided AUM.
With this release, these metrics are now calculated using the absolute P&L (with the P&L calculated in the strategy currency). By default, these metrics are chosen if the strategy valuation is negative at any point.
To access the metrics directly, use the profit_metrics_only parameter. An example of how to get the parameter is as follows:
import sigtech.framework as sig
strat = sig.default_strategy_objects.rolling_futures.es_index_front()
sig.PerformanceReport(strat, profit_metrics_only=True).report()
This new performance parameter can be included in the following custom report views:
Please note, these views are independent of the entered reference AUM.

FX spot trades can now be generated using cross identifiers

Previously, FX spot trades had to be entered by setting a trade of the cash instrument. If you were using a custom strategy, these FX spot trades have to be entered using an add_fx_spot_trade method.
With this release, FX spot trades can be entered with an FX cross identifier, which are mapped to the cash exchange. This can then control which currencies are exchanged. Additional labels have also been added to FX orders to show the FX cross gaining exposure.
An example of this new input is shown for a basket strategy below:
import datetime as dtm
import sigtech.framework as sig
env = sig.init()
env[sig.config.FX_SPOT_EXECUTION_DELAY] = dtm.timedelta(hours=1)
strategy = sig.BasketStrategy(
start_date=dtm.date(2015, 1, 10),
weights=[0.5, 0.5],

Python typings upgrades

Prior to this release and when the framework was created, Python did not have native type hinting syntax. This meant that SigTech had to use custom type hints (defined in sigtech.framework.infra.objects.dtypes).
With this release, a more up-to-date version of python has been utilized and we have now ported all typings to Python’s native type hinting.
In addition to using these native types, we have also enforced the use of beartype. This is a strict, runtime type checker. If you pass an unexpected value into a class using the beartype, an error will appear telling you the correct variable type to use instead.
The logic in our codebase tries to match an input and its type. An edge case for this logic involves the Union type. This Union type is usually used to indicate a single variable can hold multiple types of values, for example, the date variable can hold a date as a str or as a dt.datetime, hence the date can be represented as date: Union[str, dt.datetime].
However, the order of these inputs is important in the framework, as it would try to cast the variable to the type in the order given in the Union.
For example, with Union[str, dt.datetime], the framework would try to cast the variable to a string first, then to the datetime. This behaviour can be incorrect if, for example, you used a dt.datetime only as the framework would cast the variable to a string first. This may interfere with your code and cause errors.

Bug Fixes

  • If a strategy attempts to size a trade prior to the strategy start date, the framework will then change to sizing date to the valid start date of the strategy.
  • If you exceed the time point limit when plotting a portfolio_table, the number of time points displayed is reduced to fit within this limit. The time points that are reduced are from the start of the table.
  • The transaction_cost notebook has been updated.
  • A new option group, trading_group, has been added to the rolling option strategies. The trading_group lets you specify the type of traded options to use in the strategy.
  • Fill added to futures methods to fill ctd data in reindex so that it can match asof calls for individual dates.
  • Corrections were added to several default dictionary inputs for strategies and signals.
  • Several new calendars (HolidayCalendar, AuctionCalendar, EconomicCalendar) have been added to the API.

v8.14.0 (Jan 2022)

In this release

Ensure strategy names are unique

In previous releases, if different strategies were assigned the same name, the notebook could error when rerunning certain cells.
With this release, a version number is automatically added to the name of the strategy if the name provided is not unique. For example, if we have two rolling future strategies with the same ticker, "RFS 2023 Q1", then the first strategy keeps this name, but the second strategy is renamed to "RFS 2023 Q1 V2".

Local objects are also returned when using get_names method

With this release, when calling the get_names method for strategies and instruments, you can return an ordered list of object names associated with the class.
This method now accepts the following parameters:
  • include_db - set this to True to include objects from the database (default is True).
  • include_local - set this to True to include objects available in the local environment or cache (default is True).
  • include_children - set this to True to include objects from the child classes (default is False).
  • ignore_unmapped - set this to True to ignore errors caused by unmapped database objects (default is True).

Add unit_type input to positions_df methods

Previously, when using the inspect.bottom_trades_df method, the trade_price column in the returned DataFrame was incorrect and displayed values from PricingResult objects instead.
With this release, the error has been fixed and the trade_price column now displays the correct data.

Added new curve class MultiDiscountCurve

A new discounting curve MultiDiscountCurve has been added. This new curve is a mix of previously defined curves that are used at different times. The standard required arguments are currency, group_name, curve_name, and a new parameter curves_dict. This new parameter requires a dictionary of curves names, where the keys are dates from which the curves should be used.
For example:
from sigtech.framework.internal.infra.curves.dynamic_curve import MultiDiscountCurve
MultiDiscountCurve(currency='USD',group_name='DISC CURVES',curve_name='USD.MC',
curves_dict={dtm.date(2006,1,1):'USD.F3M CURVE',
The code above creates a curve that uses:
  • USD.F3M CURVE for discounting from 2006-01-01 to 2020-12-31.
  • USD.D CURVE for discounting from 2021-01-01 onwards.
This curve behaves as the other curves within the SigTech framework.

New OIS swaption added

With this release, OIS swaptions have been added. They are similar to regular LIBOR swaptions, the only difference being the underlying swap is an OIS swap instead of LIBOR. The functionality is the same as for regular swaptions; just use the prefix OIS in the class names. For example:
Unlike LIBOR swaptions, the OIS swaptions do not support old-style cash-settlement (such as the EUR standard pre November 2018), and the only cash settlement is the par market value of the underlying swap (this is the new EUR standard).
The vol surface expected for the OIS swaptions uses the relevant OIS SABR parameters USD OIS SWAPTION SABR VOLSURFACE (or any other currency).

Add dv01_exposure support for rolling future strategies on bond futures

With this release, it is now possible to set dv01_exposure for rolling future strategies using bond futures.
import datetime as dtm
import sigtech.framework as sig
s1 = sig.RollingFutureStrategy(
start_date=dtm.date(2020, 1, 3),

Bug Fixes

  • Fallback added to close trade if open is missing in stocks.
  • Un-built strategies in get_many_with_history are now allowed.
  • Default rolling bond strategies have been updated.
  • CZK, HUF and PLN cash strategies have been added with fallback.
  • Serialization of IntradayHistoryContainer has been fixed.
  • American and Barrier options have been disabled for Vol index group.
  • na values that are introduced through the batch termstructure retrieval are now dropped.
  • Bond errors with early start dates or NaN in OTR have been resolved.
  • Column names used for session data have been updated.
  • The use of custom NumPy methods in cvxpy solver is now prevented.
  • The correct future and rolling strategy dv01 has been implemented.
  • class_name in turnover grouping to allow for cash can now be used.
  • Details have been added to the info method for futures and futures contract groups.
  • Intraday history DataFrame now works with missing fields.
  • Trade price from PricingResult in bottom_trades_df now displays correct values.
  • QuantLib has been updated to version 1.28.

Latest minor release: v8.14.1 (Jan 2023)

Fixes in this release
  • The volatility option instruments and group have been renamed.
  • Correction of del item in IntradayHistoryContainer.
  • The Swaption vol surface prior_index has been fixed.
  • Vol index options are now redirected into a new class VolIndexOTCOption.
  • A fix has been added to the fx forward when the input is pd.Timestamp.

v8.13.0 (Dec 2022)

In this release

Additions to portfolio optimizer and optimized_allocations function

The following additions have been added to the portfolio optimizer and optimized_allocations function.
  • A check has been added to the time-varying signal allocation input
  • Inbuilt correlation data source has been provided
  • Initial parameter specification
  • Allow time-varying problems
This change allows you to add your own objectives and constraints to a problem. Below is an example of specifying a custom objective for an optimiser:
import pandas as pd
import datetime as dtm
import sigtech.framework as sig
amazon = sig.default_strategy_objects.single_stock_strategies.amazon_equity_rs()
apple = sig.default_strategy_objects.single_stock_strategies.apple_equity_rs()
returns = pd.concat([amazon.history(), apple.history()], axis=1, keys=[amazon.name, apple.name]).dropna().pct_change().dropna()
import cvxpy
base_opt = sig.PortfolioOptimizer()
base_opt.prefer_custom(lambda x, data: -cvxpy.quad_form(x, data['covariance']))

New input as_df added to portfolio_table() that displays the table as a DataFrame

With this release, you can pass the input as_df=True to the portfolio_table() method to return the portfolio table as a DataFrame.

Bug fixes

  • The SGD fix delay has been corrected and the DB CashIndex test usage has been removed

v8.12.0 (Dec 2022)

In this release

Return fundamental data on EquityIndex objects

In previous releases, fundamental data could only be retrieved for single stocks. With this release, fundamental data can be retrieved for equity indices also.
You can call the following for EquityIndex objects
  • fundamentals() - this returns a DataFrame of fundamental data for the equity index.
  • fundamental_fields - this returns the a list of fundamental fields for which you can collect data. You can enter these fields into the fundamental_series() input.
  • fundamental_series(field) - this return a fundamental series available for the entered field.
For example:
sig.obj.get('SPX INDEX').fundamentals()
sig.obj.get('SPX INDEX').fundamental_fields
sig.obj.get('SPX INDEX').fundamental_series('dividend_yield')

Use real-time intraday data if available

Previously, only data up until midnight from the day before is returned when calling data from the framework. With this release, you can get real-time data (or at least data from 30 minutes ago. To access this latest, intraday data, append .intraday_history() to the object on which you want to collect data. For example:
import sigtech.framework as sig
sig.obj.get('ESZ22 INDEX').intraday_history()
The code above gets the history data between midnight last night and the latest data available.

User-defined benchmarks in the Performance Report now rebase correctly

Previously, when a user-defined benchmark was used in the Performance report that was using the AUM parameter, the benchmark series was not correctly rebased relative to the AUM level.
With this release, a new parameter adjust_benchmark_by_aum has been added to the PerformanceReport constructor to fix this issue. Set this parameter to True, and the benchmark history series is considered relative to the constant AUM level (assuming a benchmark history series is provided).

Logic added to backtests to handle unfilled or partial filled orders

Trade pricer methods can now optionally return a PricingResult(price, executed_quantity) object instead of a price (but only where executed_quantity is less than or equal to the quantity given to the trade pricer method).
In this situation, the method simulates a scenario where it was not possible to execute the full quantity due to low liquidity in the market.
When the strategy calls any of the methods to add to the trade, it is possible to use a callback method. This callback method allows the strategy to decide how to proceed and whether to trade now with less than the expected quantity or to wait to trade at a point in the future.

Look-through position-based risk analytics have been added to strategies

In previous releases, risk-based portfolios were based on just historical strategy level performance. With this release, the portfolio strategy uses look-through position-based risk analytics. These new analytics include:
  • parametric_var() - calculates the value at risk (VaR) for a timeseries using the parametric (Gaussian) covariance-variance approach.
  • historical_var() - computes the VaR for a timeseries using the historical timeseries.
  • portfolio_var() - computes the portfolio’s VaR, where the portfolio is represented as a list of tuples containing portfolio units and timeseries.
  • portfolio_var_historical() - computes the portfolio’s VaR using the historical timeseries and correlations from portfolio components.
  • portfolio_var_parametric() - computes the portfolio’s VaR using the parametric (gaussian) covariance-variance approach.
  • var_portfolio_sizing() - is a sizing method based on the historical portfolio VaR of the strategy. It requires a target VaR and VaR estimation time.

Walk-forward grid optimization helper class has been added to strategies

A new helper class has been added that enables repeated grid optimization of a strategy as well as the subsequent use of optimized parameters. This walk-forward A new helper class has been added that enables repeated grid optimization of a strategy as well as the subsequent use of optimized parameters. This walk-forward optimization can help to reduce overfitting since each optimization uses the same lookback method. Additionally, this method avoids in-sample fitting since each optimization at time t only uses data available up to t.
These walk-forward grid optimization parameters include:
  • strategy_generator - the method called to return the strategy.
  • parameter_space - this is a dictionary (keyed by parameter names) and contains a list of possible values that will be iterated over at each optimization step.
  • fitting_metric - the metric method that evaluates each parameter combination.
  • fitting_lookback - the lookback of training data used at each optimization step. This can be input as a tenor string (e.g. '1M', '2W-MON') or pandas offset.
  • fitting_frequency - the time elapsed between each optimization step. This can be input as a tenor string (e.g. '1M', '2W-MON'), or as a list of dates.

Bug fixes

  • Ensure intraday delta hedged portfolio_greeks() is intraday.
  • The SOFR start date has been removed from the calculation of earliest start date in strategies that use CashIndex.
  • Inconsistencies with the End of Day (EOD) price lookup have been resolved.
  • META ticker is now used for facebook's default strategy.
  • TRBC codes have been updated.
  • RollingFutureStrategy.spot_dv01() has been changed so it is now based on positions instead of weights.
  • The use of PricingResult has been removed when using direct trade_price calls.
  • Portfolio table exposure weight now uses the current time.
  • The FXforward history now starts at the earliest available datapoint.
  • allow get_tc_model now runs for strategies.
  • Division by zero is prevent when computing RSI.
  • Ensure negative strikes work in SABR.

v8.11.0 (Nov 2022)

In this release

Intraday history data cleared when the environment is low on memory

When using the IntradayHistoryContainer and the research environment is low on memory, the intraday history data (which has not been used recently) is cleared. This happens automatically and you do not need to input or action anything.

Use Regex to find the names of the transaction cost models

With this release when searching for transaction cost you can use Regular Expressions (Regex) to find the names of the transaction cost models.

Currency input no longer mandatory for applicable default strategies

Previously, you had to input the currency of the underlying instruments used by a strategy. With this release, strategies can now infer the currency from the futures group, equity instrument, bond group, etc that is being used in the strategy.

Intraday portfolio greeks are now calculated using intraday FX data

A new input intraday has been added to the FX portfolio_greeks function. If intraday=True, the greeks are calculated using the most recent intraday data. This new input is supported for FX options only, so when intraday=True, the relevant FX forwards are calculated using the latest available FX spot and the latest available forward curves (although these forward curves are less granular).
For example, here is the new input for a rolling options strategy ro that is already defined.
This will calculate the different greeks at 5pm and once again at 6pm on 2019-01-08.
By default, intraday=False.

Bug fixes

  • The index error in live streaming has been fixed.
  • Errors with copy overrides in the ticker loop for get_single_stock_strategy have been fixed.
  • Checks put in place to make sure intraday delta is always computed using intraday data in delta hedging strategy.
  • The short conversion error has been changed to a warning with additional information.
  • Unsupported pandas logic has been removed.

v8.10.0 (Nov 2022)

In this release

New function trade_timings_df() added to inspect wrapper

A new function trade_timings_df() has been added to the inspect wrapper. Append this function to an object and a DataFrame is returned that contains the timings associated with each trade in the strategy. For example, run the following code to get the trade timing DataFrame.
qqq = sig.ReinvestmentStrategy(underlyer='QQQ UP EQUITY', currency='USD')
The DataFrame contains the following columns:
  • instrument_name - the instrument traded.
  • decision_dt - the datetime for when the decision to trade was made.
  • execution_dt - the datetime for when the trade was executed.
  • default_instrument_size_dt - the time the trade was likely to have been sized (unless this was overridden at the time).
  • default_strategy_size_dt - the time the strategy value was likely to have been sized for the purposes of a weight calculation (unless this was overridden at the time).
  • trade_size - the size of the trade.

New sizing methods added to strategies

Previously, the default sizing method targeted model units. Some strategies (i.e. BasketStrategy) could override the default sizing method.
With this release, the default sizing methods can be over ridden in all general strategies. Use sizing_quantity and default_sizing_method to configure the sizing method with values such as AUM, INITIAl_AUM or any fixed values.

New mixin strategy incorporated into existing strategies

A new strategy RatesStrategyMixin has been added. This strategy inherits aspects of the RatesStrategy, RatesStrategyBasket and RatesSignalStrategy strategies. This incorporation now provides the strategies with a pv01_exposure method, which gives a breakdown of exposures, and also changes the default sizing methods so that traded quantities should be entered in terms of pv01.

New allocation function called stop_loss added to SignalStrategy building block

With this release, SigTech has introduced a new allocation function called stop_loss to the SignalStrategy building block. This new allocation function places a stop order each time a new position is entered. This is equivalent to creating a stop strategy every time the signal changes. See the example below for how to configure the input and the required keyword arguments (allocation_kwargs).
mean_rev_signal = sig.signal_library.from_ts(mean_rev_signal_ts.to_frame(es_index_front().name))
es_mean_rev_stop_loss = sig.SignalStrategy(
start_date=dtm.date(2010, 4, 1),
allocation_kwargs={'trigger_level': 0.05, 'trigger_type': 'TRAILING_PCT_LOSS'},
To see a list of the available keyword arguments for this allocation function, call up the docstring using sig.SignalStrategy?.

Strategies can now treat listed options as OTC

When passing an exchange-traded option group as an input to any of the rolling options strategies, the options could be priced using exchange prices, stored in a database.
Alternatively, these options can also be priced from the relevant volatility surface (as over-the-counter (OTC) options created from the option’s static data). To use options priced from the relevant volatility surface, pass price_listed_as_model='VolSurface' as an input.
If you need to use the database prices as well as calculate the ‘Greeks’ for the options, pass price_listed_as_model='VolFromPrice' as an input. (The Greeks are a collective term for delta, gamma, vega, and theta of the option positions which provide a way to measure the sensitivity of an option's price to observable factors).

Strategies can now be used as sizing method inputs

With this release, an extra input has been added to the sizing_method call. This input looks at information from the strategy being used and allows this information to be incorporated in the sizing method which converts the traded units. An example of using this available input is weight based sizing, where the valuation of the strategy is required to complete the conversions.

Earliest available start date is now used when creating a strategy

It is now optional to specify a certain start date when creating a strategy (the start date used to be a mandatory input). If you do not enter a start date, SigTech scans all the market data required for the strategy to run and finds the earliest, valid start date.
You can find this start date by appending .earliest_start_date() to the end of your strategy. For example, the following prints the earliest useable start date for the 5-year US treasury notes:
us5yearNoteFuture = sig.default_strategy_objects.rolling_futures.fv_comdty_front()

Allow position sizing at execution for rolling options and swaptions

A new input, size_at_execution, has been added to all rolling option and swaption strategies.
Set size_at_execution=True to force the strategy to calculate the position sizing at the execution time instead of the standard position sizing time which is calculated using parameters from the previous day.
By default, size_at_execution=False as the execution time may occur after market close and therefore the strategy will error.
You can use the same size_at_execution input in the DeltaHedgingStrategy.

Add custom FX forward transaction costs using the environment configuration

To add custom FX forward transaction costs to your SigTech environment, enter a dictionary value containing the outright and roll values. These dictionary values should be entered as forward base points per maturity, on a monthly basis.
An example of how to input these FX forward trading costs is shown below:
{'outright':{1: 20},
'roll': {1: 10}

Bug fixes

  • The has_preloaded_history function in BondBase for calculated fields has been adjusted.
  • The fx_spot_inverse function has been fixed.
  • Fix added for shorter underlying strategy inside of delta hedged strategy.
  • Allow delta at execution in delta hedged strategy.
  • Remove exception in strategy performance viewer.
  • Allow choice of option exercise type in rolling option strategies.
  • Fix dynamic option basket dependency.
  • Default values of AlphaReport metrics based on input features have been updated.
  • Datetime error in vol surface corrected.
  • Fix for xccy swap_info in resettable swaps for periods prior to first reset.
  • History start date added to swaption name, if different from the start date.
  • Removed the wrong swap start date in rolling asset swap.
  • Allow different start date and history start date for variance swap.
  • Fix added for performance plot for aum equal to zero case.
  • QuantLib has been upgraded to the latest version (1.27).
  • history_start added to get_swaption in line with options functionality.
  • Propagate exceptions which occur while loading dependencies in a thread pool.

v8.9.0 (Aug 2022)

In this release


Set and add timezones to display methods

This release introduces a new environment variable TM_DISPLAY_TIMEZONE and a new property display_tz.
Use the TM_DISPLAY_TIMEZONE variable to change the timezone for times display in analytics interfaces. This feature can be used if the trading manager timezone (TM_TIMEZONE) differs from the timezone in which you want to display time data. The following code is an example of how to add these two separate timezones when initializing your SigTech environment:
env = sig.init()
sig.config.set('TM_TIMEZONE', 'America/New_York') #This sets the time zone for the trading manager timezone, in this case 'America/New_York'
sig.config.set('TM_DISPLAY_TIMEZONE', 'Europe/London') #This sets the time zone in which the times are displayed, in this case 'Europe/London'
For a full list of available timezones and the names which you should enter, see the Timezone database.
The display_tz property ensures a timezone is always displayed and uses the timezone provided to TM_DISPLAY_TIMEZONE. However, if TM_DISPLAY_TIMEZONE was not set, the TM_TIMEZONE is used.
Currently, the TM_DISPLAY_TIMEZONE variable only works on the analytics interfaces such as strategy.plot. By default, the portfolio_table and .diagnostics.to_dataframe() display times using the UTC timezone, however, if a TM_TIMEZONE is provided, the trading manager timezone is used to display time in these interfaces.

(Experimental) Custom metrics for AlphaReport

You can now create customised metrics for the experimental AlphaReport. The new metric will be available in the report's Metrics view.
Example usage:
def my_metric(x: pd.Series, y: pd.Series, **kwargs):