backtest_model

class portfolio_backtester.backtest_model(strategy, involved_data_type, need_extra_data=False, trace_back=False, name='Unnamed', missing_val=False)[source]

Given a user-defined portfolio construction strategy (a function that takes in stock-related data and returns portfolio weights) and the data that the user wish the strategy to be tested on, calculate several evaluation metrics of the portfolio, including net_returns, sharpe ratio, certainty equivalent returns, turnover, etc. Various inputs can be modified to suit the needs of strategy and backtesting scenarios, such as price-impact models, transaction costs, etc.

Initiate the model with the strategy function, and clarify involved data types needed, whose sequence MUST be consistent with that of the list of dataframes used inside strategy function

Parameters
  • strategy (function) – user-defined function that serves as portfolio construction strategy

  • involved_data_type (list) – a list of strings that indicate the type of data {‘price’,’return’,’ex_return’} used in the strategy, the order of the strings will be the order that data are passed to the strategy

  • need_extra_data (bool) – indicate whether the strategy need extra_data (data other than {‘price’,’return’,’ex_return’}) to function. Note: 1. the datetime index of extra_data must match that of the provided data. 2. change-of-frequency functionality will be suspended if extra data is needed

  • trace_back (bool) – indicate whether the strategy need to trace back to past portfolios to function. Note: please handle the boundary situation where past portfolios is empty in the strategy function

  • name (str) – name of the strategy to be tested

:param missing_val : indicate whether user strategy function can handle missing values in the data on its own. True means the function can deal with missing values. False means it cannot :type missing_val: bool

backtest(data, freq_data, volume=Empty DataFrame Columns: [] Index: [], data_type='price', rf=Series([], dtype: float64), interval=1, window=60, freq_strategy='D', price_impact=False, ptc_buy=0, ptc_sell=0, ftc=0, c=1, initial_wealth=1000000.0, extra_data=Empty DataFrame Columns: [] Index: [], price_impact_model='default', power=0.6)[source]

Start the backtesting process with the built model. The function itself will not return anything. To get the results, please call respective functions.

Parameters
  • data (pd.DataFrame) – historical data that the strategy to be tested on. Index must be datetime format compatible

  • freq_data (str) – The frequency of the data provided, choose between {‘D’,’W’,’M’}, where ‘D’ for day,’W’ for week and ‘M’ for month. ‘data’ must be taken in the smallest unit of respective frequency, e.g. the frequency ‘M’ means the data is taken at each month

  • volume (pd.DataFrame or list or np.ndarray or pd.Series) – trading volume of each asset during each period (array of size T*N), or average trading volume for each asset over all periods (N-d array). If passing in as pd.DataFrame, then its index must match that of the data.

  • data_type (str) – choose from {‘price’,’return’,’ex_return’} where ‘price’ stands for price data of assets at each timestamp, ‘return’ stands for normal percentage return of each asset in each period, ‘ex_return’ stands for percentage return net of risk-free rate

  • rf (pd.Series or pd.DataFrame or int or float) – data for risk-free rate in each period. Note: if ‘rf’ is passed in as a dataframe or series, the index of ‘rf’ must match that of ‘data’

  • interval (int) – number of periods that users want their portfolios to be rebalanced, the unit is based on ‘freq_strategy’. e.g. If ‘freq_data’ is ‘D’, while ‘freq_strategy’ is ‘M’, and ‘interval’ is 2, then the portfolio will be rebalanced every 2 months using the user-defined portfolio-construction strategy

  • window (int) – length of rolling windows of ‘data’ wanted to feed into ‘strategy’ function. e.g. ‘window’=60 means each time during rebalancing, past 60 periods of ‘data’ will be passed into user-defined strategy function

  • freq_strategy (str) – The frequency on which the user want to use ‘strategy’ to rebalance the portfolio, choose between {‘D’,’W’,’M’}. If “freq_strategy” is different from “freq_data”, the library will resample data on “freq_strategy”. Note: ‘freq_data’ should be smaller than ‘freq_strategy’ with the sequence ‘D’ < ‘W’ < ‘M’

  • price_impact (bool) – indicate whether to use price-impact model or not

  • ptc_buy (pd.Series or np.ndarray or int or float) – proportional transaction cost of buying each asset, measured in basis point. Can be a Series or array that provide one cost for each asset, or a single variable that stands for universal transaction cost. Note: Cannot be a list, and must not contain provide labels

  • ptc_sell (pd.Series or np.ndarray or int or float) – proportional transaction cost of selling each asset, measured in basis point. Can be a Series or array that provide one cost for each asset, or a single variable that stands for universal transaction cost. Note: Cannot be a list, and must not contain provide labels

  • ftc (int or float) – dollar value of fixed transaction cost of each transaction, measured in one unit of any currency.

  • c (pd.Series or int or np.ndarray or float) – market depth indicators. Can be a Series or array that provide one market depth for each asset, or a single variable that stands for universal market depth. Note: Do NOT provide labels

  • initial_wealth (int or float) – dollar value of initial wealth of testing when ‘price-impact’ is true or ‘ftc’!=0

  • extra_data (pd.DataFrame) – extra_data to be passed into ‘strategy’ only when ‘need_extra_data’==True. Note: 1. the datetime index of extra_data must match that of the provided data. 2. change-of-frequency functionality will be suspended if extra data is needed

  • price_impact_model (str) – choose the price impact model you want to use from {‘default’} (testing feature, to be built on)

Returns

None

general_performance()[source]

Get a set of performance evaluation metrics of the model tested

get_ceq(x=1)[source]

Get certainty equivalent returns (ceq) of the model tested with the given risk aversion factor :param x: risk aversion factor :type x: float or int or pd.Series or np.ndarray

Returns

certainty equivalent returns

get_net_excess_returns()[source]

Get the net excess returns (net of risk-free rate) and respective dates of the model tested.

get_net_returns()[source]

Get the net returns and respective dates of the model tested

get_sharpe()[source]

Get the sharpe ratio of the model tested

get_turnover(typ='average')[source]

Get the average turnover rate of each period as well as total turnover rate over all periods of the model tested

Parameters

typ (str) – choose from {‘average’,’total’}, which indicates average turnover and total turnover respectively