Skip to content

quantpylib.simulator.alpha

quantpylib.simulator.alpha is our core backtesting module, and exposes multiple abstract base classes that can be easily extended to implement your own custom trading strategies. quantpylib.simulator.alpha.BaseAlpha encodes the underlying backtest logic, and quantpylib.simulator.alpha.Alpha extends BaseAlpha and implements important features such that the user only has to write code for generating relative forecasts/signals. Position-sizing, risk-management, volatility targeting, PnL accounting and trade simulation is then handled by the backtest logic.

In addition, we provide simple but powerful access to an assortment of performance metrics and hypothesis tests (monte carlo permutation tests) on any instance of the BaseAlpha object to test for strategy effectiveness.

Users would likely only have to interact with the abstract quantpylib.simulator.alpha.Alpha class, and implement thecompute_forecasts and compute_signals function in custom-classes that extend the Alpha class. Additionally, users may opt to use our automatic formulaic parser and use quantpylib.simulator.gene.GeneticAlpha that extends the Alpha class to opt for a no-code backtest by just encoding their trading strategy as a simple Python str, for which all the abstract functions would be automatically implemented.

Using the quantpylib.simulator.gene.GeneticAlpha is the simplest and recommended way of using our BaseAlpha and Alpha classes, as no additional code needs to be written. If the primitives supported by our gene module is not sufficient to encode your trading strategy, then the Alpha class should be sufficient for most needs.

Alpha

__init__

Parameters:

Name Type Description Default
start datetime

Start of backtest simulation. If not tz-aware, assumed UTC. If not given, assume min of OHLC dataset in dfs.

None
end datetime

Start of backtest simulation. If not tz-aware, assumed UTC. If not given, assume max of OHLC dataset in dfs.

None
dfs dict

inst : OHLCV/other Dataframes used for computations. Default is an empty dictionary.

{}
instruments list

List of traded instruments.

[]
execrates ndarray

Execution rates for each instrument. Default is None.

None
commrates ndarray

Commission rates for each instrument. Default is None.

None
longswps ndarray

Long annualized swap/funding rates for each instrument. Positive swaps means long positions incur swap fees. Default is None.

None
shortswps ndarray

Short annualized swap/funding rates for each instrument. Positive swaps means short positions incur swap fees. Default is None.

None
granularity Period

The granularity of each trading signal evaluation. Datapoints of lower granularity than specified are ignored. Last known datapoint of multiple entries in the same granularity interval is taken. Default is Period.DAILY.

DAILY
positional_inertia float

Parameter controlling position change inertia. Default is 0.

0
portfolio_vol float

Target portfolio volatility. Default is 0.20, representing 20% annualized volatility.

0.2
weekend_trading bool

Indicates if there is weekend trading, such as in cryptocurrency markets. Defaults to False.

False
around_the_clock bool

Indicates if there is 24H trading, such as in cryptocurrency and fx markets. Defaults to False.

False
currency_denomination str

Currency denomination for the portfolio. Default is "USD".

'USD'
starting_capital float

Amount to begins the backtest with. Defaults to 10000.0.

10000.0

Notes: execrates, commrates, longswps, shortswps are presented in decimals. execrates = [0.001, 0.005, ...] encodes that 0.1% of notional value transacted is deducted as execution costs for first instrument, second instrument... commrates specify commisions in the same units (as percentage of notional value), as for overnight swap rates for both long and short positions.

For the dfs dictionary passed into BaseAlpha objects, it should contain the DataFrames for all data required in the trading strategy. Minimally, dfs should contain key-value pair of (ticker:pd.DataFrame) with OHLCV data for PnL accounting. The pd.DataFrame objects provided should have timezone aware DatetimeIndex properties. For instance:
{
    'BRKB':
                                open      high       low        close        adj_close volume
    datetime
    2000-01-03 00:00:00+00:00  1825.0000  1829.0000  1741.0000  1765.0000    35.3000   873500     
    2000-01-04 00:00:00+00:00  1725.0000  1733.0000  1695.0000  1704.0000    34.0800  1380000     
    2000-01-05 00:00:00+00:00  1707.0000  1773.0000  1695.0000  1732.0000    34.6400   997000     
    2000-01-06 00:00:00+00:00  1745.0000  1804.0000  1727.0000  1804.0000    36.0800   917000     
    2000-01-07 00:00:00+00:00  1830.0000  1848.0000  1805.0000  1820.0000    36.4000  1001500     
    ...                              ...        ...        ...        ...        ...      ...     
    2009-12-24 00:00:00+00:00  3281.9999  3295.9899  3274.9999  3286.9999    65.7400   607600     
    2009-12-28 00:00:00+00:00  3279.9999  3289.9999  3274.9999  3285.3699    65.7074  1080250     
    2009-12-29 00:00:00+00:00  3284.9999  3289.6899  3269.9999  3279.9999    65.6000  1105300     
    2009-12-30 00:00:00+00:00  3282.9999  3289.6499  3279.9999  3289.6499    65.7930   560350     
    2009-12-31 00:00:00+00:00  3289.9999  3300.9899  3279.9999  3285.9999    65.7200   972900 
} 

compute_signals async, abstract

Abstract function that should be implemented in child-class extending the Alpha class. This is where users can manipulate the dataframes in dfs dict passed by accessing self.dfs to compute useful metrics such as technical indicators.

Parameters:

Name Type Description Default
index DatetimeIndex

datetime index for intervals at specified granularity.

required

compute_forecasts abstract

Abstract function that should be implemented in child-class extending the Alpha class. Computes relative forecasts for self.instruments on dt.

Parameters:

Name Type Description Default
portfolio_i

Number of time intervals passed between date and backtest start.

required
dt datetime

The datetime for which forecasts are to be computed.

required
eligibles_row ndarray

An array mask of length len(self.instruments) that acts as a bit mask for eligible trading universe.

required

Returns:

Type Description
array

An array representing the relative forecasts for each of instruments in self.instruments with length len(self.instruments).

Notes

It is not required for the forecasts to be indicative of the number of contracts the strategy should trade. The values in the returned array need only be indicative of the relative strength in the signal forecast. For instance, [-1, 1, 1.5] means we want to be as short the first instrument as we are long the second instrument, and we want to be longer by a factor of 1.5 in the third instrument as we are in the second instrument. Position sizing in the underlying contracts are dealt with automatically in the backtest engine using volatility targeting at the instrument and strategy level. np.nan, np.inf values are treated as zero.

instantiate_eligibilities_and_strat_variables

This is where the child class can instantiate object attributes that can be used in the compute_forecasts function. Optional to implement. eligiblesdf is the default bit mask DataFrame encoding trading universe on each time point between start and end, but it may be modified in an overriding method to use a different universe set throughout the backtest.

Parameters:

Name Type Description Default
eligiblesdf DataFrame

Bit mask DataFrame. Value of 1 means the instrument is eligible to be considered for trading on given date, and value of 0 means not eligible. Computed based on the market data given in self.dfs.

required

Returns:

Type Description
DataFrame

eligiblesdf is returned to the caller, and is used as the updated (if modified) bit-mask. If the function is not implemented, the default eligiblesdf is used.

Notes

This function is optional to implement. The default implemention is a one-liner returning eligiblesdf.

The remaining functions are not abstract and no further implementation is required or warranted.

run_simulation async

Runs the entire backtest. Should only be called after concrete implementation of compute_signals and compute_forecasts.

Parameters:

Name Type Description Default
verbose

(boolean, optional) flag to print out backtest simulation information at runtime.

False

Returns:

Type Description
DataFrame

a DataFrame containing backtest statistics. Contains information about contracts held throughtout the backtest, portfolio weights, portfolio leverage, nominal exposusure, execution costs, commissions, swaps, PnL, portfolio capital and so on.

get_performance_measures

Computes the performance metrics for the trading strategy.

Returns:

Type Description
dict

A dictionary containing various performance metrics:

  • "cum_ret": Cumulative returns over time.
  • "log_ret": Logarithmic returns.
  • "max_dd": Maximum drawdown.
  • "1y_roll_dd": One-year rolling drawdown.
  • "1y_roll_max_dd": One-year rolling maximum drawdown.
  • "sortino": Sortino ratio.
  • "sharpe": Sharpe ratio.
  • "mean_ret": Mean return per annum.
  • "median_ret": Median return per annum.
  • "stdev_ret": Standard deviation of returns per annum.
  • "var_ret": Variance of returns per annum.
  • "skew_ret": Skewness of returns.
  • "kurt_exc": Excess kurtosis of returns.
  • "cagr": Compound annual growth rate.
  • "3y_roll_cagr": Three-year rolling compound annual growth rate.
  • "3y_roll_calmar": Three-year rolling Calmar ratio.
  • "omega(0)": Omega ratio.
  • "ulcer": Ulcer index.
  • "VaR95": Value at Risk at 95% confidence level.
  • "cVaR95": Conditional Value at Risk at 95% confidence level.
  • "gain_to_pain": Gain-to-pain ratio.
  • "w_summary": Summary statistics of weights.
  • "directionality": Market long bias directionality.
  • "parity_distance": Distance from a 1/n equal weight portfolio.

hypothesis_tests async

Conducts monte carlo permutation p-value hypothesis tests on the performance of the trading strategy represented by the object instance.

Parameters:

Name Type Description Default
num_decision_shuffles int

Number of decision shuffles for monto carlo permutation tests. Default is 1000.

1000
num_data_shuffles int

Number of data shuffles for permutation tests. Default is 10 (computationally expensive).

10

Returns:

Type Description
dict

A dictionary containing the results of hypothesis tests.

  • 'timer_p': p-value from asset-timing test that shuffles time-series asset returns.
  • 'picker_p': p-value from asset-picking shuffler test that shuffles cross-sectional asset returns.
  • 'trader_p1': p-value from decision-making test that shuffles both time-series and cross-sectional asset returns.
  • 'trader_p2': p-value from decision-making test that shuffles market data.