finds.backtesting.backtest

Evaluate backtests, event studies and risk premiums

  • Walk-forward portfolio rebalances Backtest: Sharpe ratio, appraisal ratio, …

Copyright 2022, Terence Lim

MIT License

class finds.backtesting.backtest.BackTest(sql: SQL, bench: Benchmarks, rf: Series, max_date: int, table: str = 'backtests', verbose: int = 1)[source]

Bases: object

Base class for computing portfolio backtest returns

Parameters:
  • sql – Database connection to store results

  • bench – Structured dataset to retrieve riskfree and benchmark returns

  • rf – Column name of riskfree rate in benchmark dataset

  • max_date – Last date of any backtest

  • table – Name of table in user database to store results in

Notes

  • If backtest dates appears to be monthly frequency, monthly risk free rates will be retrieved and used rather than compounding from daily (reduce precision errors). Assumes that monthly risk free rates also available through {bench}, with name suffixed by “(mo)”.

Examples:

>>> backtest = BackTest(user, bench, 'RF', 20200930)
__call__(stocks: Stocks, holdings: Dict[int, Series], label: str, overlap: int = 0) DataFrame[source]

Compute holding returns and rebalance statistics

Parameters:
  • stocks – Structured data set with stocks data

  • holdings – Sequence of holdings keyed by rebalance date Each Series is indexed by permno, with weights in column Last item (can be empty) is dropped for calculating returns

  • label – Name to save this backtest

  • overlap – Number of months to smooth overlapping holdings

Returns:

DataFrame of holdings returns after every rebalance data

Notes

  • if CRSP (i.e. ‘delist’ table exists and using monthly), include dlst returns

fit(benchnames: List[str], beg: int = 0, end: int = 0, haclags: int = 1) DataFrame[source]

Compute performance attribution against benchmarks

Parameters:
  • benchnames – Names of benchmark returns to compute attribution against

  • beg – date range of returns

  • end – date range of returns

  • haclags – number of Newey-West lags for robustcov statistics

Returns:

DataFrame of excess returns performance following each rebalance date

Annualized (dict) performance ratios:

  • ‘excess’: annualized excess (of portfolio weight*riskfree) return

  • ‘sharpe’: annualized sharpe ratio

  • ‘alpha’: annualized alpha

  • ‘appraisal’: annualized appraisal ratio

  • ‘welch-t’: t-stat for structural break after 2002

  • ‘welch-p’: p-value for structural break after 2002

  • ‘turnover’: annualized total turnover rate

  • ‘buys’: annualized buy rate

  • ‘sells’: annualized sell rate

get_series(field: str = 'ret', start: int = 19000000, end: int = 0) DataFrame[source]

Retrieve saved backtest as a series

plot(label: str = '', num: int = 1, flip: bool | None = False, drawdown: bool = False, figsize: Tuple[float, float] = (10, 5), marker: str | None = '', fontsize: int = 9)[source]

Plot time series of excess vs benchmark returns

Parameters:
  • num – Figure number to use in plt

  • label – legend label

  • flip – Whether to flip returns. If None, then auto-detect

  • drawdown – To plot peak and trough points of maximum drawdown

read(label: str = '')[source]

Load backtest performance returns from database

write(label: str)[source]

Save backtest performance returns to database

finds.backtesting.backtest.compound_ret(rets: Series, intervals: Tuple | List[Tuple]) List[float][source]

Compounds series of returns between (list of) date tuples (inclusive)