1 介绍
在上篇文章里,我们讲了backtrader的基本入门知识,它是用于量化回测的开源框架,今天我们进一步来探索策略评估模块,这个模块顾名思义是为了评估交易策略在历史数据上的表现,它的输出一般要么是指标、要么是图表。
与backtrader结合的策略评估模块主要有empyrical、pyfolio、quantstats、backtrader_bokeh、backtrader_plotting、btplotting、backtrader_plotly,其中最常见的是pyfolio和quantstats两个工具包,而empyrical本身被pyfolio所调用。
本文除了给出backtrader与两个工具包相契合的代码以及输出之外,同时也陈列了每个工具包所包含的指标、图标和报告,以供初学者进行对比。
2 backtrader启动代码
backtrader采用与zipline相同的方式来对接pyfolio,具体而言我们需要在Cerebro中添加PyFolio分析器,它可以用于跟踪整个策略在模拟交易时的情况,并在最后使用 get_pf_items() 方法来获取回测期间的交易信息,如每天的收益、持仓和交易明细等。
cerebro = bt.Cerebro()
rawdata = pd.read_csv('../data/stock/600036SH.csv', index_col=0, parse_dates=True)
data = bt.feeds.PandasData(dataname=rawdata, datetime=None, open=1, high=2,
low=3, close=4, volume=8, openinterest=-1)
cerebro.adddata(data)
cerebro.addsizer(bt.sizers.AllInSizer, percents=95) # 投入百分之九十五的资金
cerebro.broker.setcash(10000.0)
cerebro.broker.setcommission(commission=0.002) # 手续费
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='_SharpeRatio')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='_DrawDown')
best_params = opt_strategy_params(cerebro,
fast_window=range(20, 25),
slow_window=range(45, 50))
cerebro.addstrategy(MyStrategy, **best_params)
print('初始资金: %.2f' % cerebro.broker.getvalue())
results = cerebro.run()
print('最终资金: %.2f' % cerebro.broker.getvalue())
strat = results[0]
print('夏普比率:', strat.analyzers._SharpeRatio.get_analysis())
print('回撤指标:', strat.analyzers._DrawDown.get_analysis())
pyfoliozer = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
3 pyfolio示例
pyfolio属于国外著名量化平台quantopian的遗产,在公司倒闭之后,它的组件仍然处于开源,其中zipline是它的回测框架,而pyfolio就是对应的策略评估模块。它大体分成了三个子功能,分别是指标计算、图表绘制和报告生成。
在这里我们仅使用 create_full_tear_sheet 方法来完成报告生成功能,它蕴含了较为全面的指标和图表,得到策略评估报告。
import pyfolio as pf
returns.index = returns.index.tz_convert(None)
benchmark_ret = rawdata.close.pct_change().fillna(0)
pf.create_full_tear_sheet(returns,
benchmark_rets=benchmark_ret,
positions=positions,
transactions=transactions)
同时,我们也深入pyfolio的子功能文件,通过遍历它的所有变量和函数来简单陈列其包含的功能。首先我们还是看看它可以计算出哪些指标,主要关注小写字母。
[f for f in dir(pf.timeseries) if f[0] != '_']
['APPROX_BDAYS_PER_MONTH',
'APPROX_BDAYS_PER_YEAR',
'DAILY',
'DEPRECATION_WARNING',
'FACTOR_STAT_FUNCS',
'OrderedDict',
'PERIODS',
'SIMPLE_STAT_FUNCS',
'STAT_FUNC_NAMES',
'aggregate_returns',
'alpha',
'alpha_beta',
'annual_return',
'annual_volatility',
'beta',
'calc_bootstrap',
'calc_distribution_stats',
'calmar_ratio',
'common_sense_ratio',
'cum_returns',
'deprecated',
'division',
'downside_risk',
'ep',
'extract_interesting_date_ranges',
'forecast_cone_bootstrap',
'gen_drawdown_table',
'get_max_drawdown',
'get_max_drawdown_underwater',
'get_top_drawdowns',
'get_turnover',
'gross_lev',
'linear_model',
'max_drawdown',
'normalize',
'np',
'omega_ratio',
'partial',
'pd',
'perf_stats',
'perf_stats_bootstrap',
'rolling_beta',
'rolling_regression',
'rolling_sharpe',
'rolling_volatility',
'sharpe_ratio',
'simulate_paths',
'sortino_ratio',
'sp',
'stability_of_timeseries',
'stats',
'summarize_paths',
'tail_ratio',
'value_at_risk',
'var_cov_var_normal']
再看看它有哪些图可以进行绘制,一般而言,图表总是要比单纯的指标会更加直观,主要关注以plot开端的名称。
[f for f in dir(pf.plotting) if f[0] != '_']
['APPROX_BDAYS_PER_MONTH',
'FigureCanvasAgg',
'FuncFormatter',
'MM_DISPLAY_UNIT',
'OrderedDict',
'STAT_FUNCS_PCT',
'axes_style',
'capacity',
'customize',
'datetime',
'division',
'ep',
'figure',
'matplotlib',
'np',
'patches',
'pd',
'plot_annual_returns',
'plot_capacity_sweep',
'plot_cones',
'plot_daily_turnover_hist',
'plot_daily_volume',
'plot_drawdown_periods',
'plot_drawdown_underwater',
'plot_exposures',
'plot_gross_leverage',
'plot_holdings',
'plot_long_short_holdings',
'plot_max_median_position_concentration',
'plot_monthly_returns_dist',
'plot_monthly_returns_heatmap',
'plot_monthly_returns_timeseries',
'plot_perf_stats',
'plot_prob_profit_trade',
'plot_return_quantiles',
'plot_returns',
'plot_rolling_beta',
'plot_rolling_returns',
'plot_rolling_sharpe',
'plot_rolling_volatility',
'plot_round_trip_lifetimes',
'plot_sector_allocations',
'plot_slippage_sensitivity',
'plot_slippage_sweep',
'plot_turnover',
'plot_txn_time_hist',
'plotting_context',
'plt',
'pos',
'pytz',
'show_and_plot_top_positions',
'show_perf_stats',
'show_profit_attribution',
'show_worst_drawdown_periods',
'sns',
'sp',
'timeseries',
'txn',
'utils',
'wraps']
最后,我们对pyfolio可以绘制的报告类型进行陈列,它可以很方便地给出主要指标和图表,主要看以create开端的名称。
[f for f in dir(pf.tears) if f[0] != '_']
['FACTOR_PARTITIONS',
'Markdown',
'capacity',
'create_capacity_tear_sheet',
'create_full_tear_sheet',
'create_interesting_times_tear_sheet',
'create_perf_attrib_tear_sheet',
'create_position_tear_sheet',
'create_returns_tear_sheet',
'create_round_trip_tear_sheet',
'create_simple_tear_sheet',
'create_txn_tear_sheet',
'display',
'division',
'ep',
'gridspec',
'pd',
'perf_attrib',
'plotting',
'plt',
'pos',
'round_trips',
'sns',
'time',
'timer',
'timeseries',
'txn',
'utils',
'warnings']
4 quantstats示例
quantstats是代替pyfolio的另一个策略评估工具包,相比于随着quantopian倒闭后逐渐暂停维护的pyfolio而言,它仍然属于一个较为活跃的仓库,同时提供更加便捷的功能,比如可以自动将报告保存成html文件,方便记录和分享。
在这里,我们就使用 html 方法来生成报告,并使用浏览器进行打开。
import quantstats as qs
returns.index = returns.index.tz_convert(None)
benchmark_ret = rawdata.close.pct_change().fillna(0)
qs.reports.html(returns, benchmark=benchmark_ret,
output='stats.html', title='Stock Sentiment')
同样的,我们也对quantstats的指标、画图和报告三个子功能进行遍历和输出。相比于pyfolio的变量和函数名相互参杂,quantstats看起来更加干净,所看即所得。
[f for f in dir(qs.stats) if f[0] != '_']
['adjusted_sortino',
'autocorr_penalty',
'avg_loss',
'avg_return',
'avg_win',
'best',
'cagr',
'calmar',
'common_sense_ratio',
'comp',
'compare',
'compsum',
'conditional_value_at_risk',
'consecutive_losses',
'consecutive_wins',
'cpc_index',
'cvar',
'distribution',
'drawdown_details',
'expected_return',
'expected_shortfall',
'exposure',
'gain_to_pain_ratio',
'geometric_mean',
'ghpr',
'greeks',
'implied_volatility',
'information_ratio',
'kelly_criterion',
'kurtosis',
'max_drawdown',
'monthly_returns',
'omega',
'outlier_loss_ratio',
'outlier_win_ratio',
'outliers',
'payoff_ratio',
'pct_rank',
'probabilistic_adjusted_sortino_ratio',
'probabilistic_ratio',
'probabilistic_sharpe_ratio',
'probabilistic_sortino_ratio',
'profit_factor',
'profit_ratio',
'r2',
'r_squared',
'rar',
'recovery_factor',
'remove_outliers',
'risk_of_ruin',
'risk_return_ratio',
'rolling_greeks',
'rolling_sharpe',
'rolling_sortino',
'rolling_volatility',
'ror',
'serenity_index',
'sharpe',
'skew',
'smart_sharpe',
'smart_sortino',
'sortino',
'tail_ratio',
'to_drawdown_series',
'treynor_ratio',
'ulcer_index',
'ulcer_performance_index',
'upi',
'value_at_risk',
'var',
'volatility',
'warn',
'win_loss_ratio',
'win_rate',
'worst']
[f for f in dir(qs.plots) if f[0] != '_']
['daily_returns',
'distribution',
'drawdown',
'drawdowns_periods',
'earnings',
'histogram',
'log_returns',
'monthly_heatmap',
'monthly_returns',
'plotly',
'returns',
'rolling_beta',
'rolling_sharpe',
'rolling_sortino',
'rolling_volatility',
'snapshot',
'to_plotly',
'warnings',
'yearly_returns']
[f for f in dir(qs.reports) if f[0] != '_']
['basic',
'full',
'html',
'iDisplay',
'iHTML',
'metrics',
'plots',
'relativedelta']
5 参考文献
《量化策略——准备3 数据、Backtrader回测框架与quantstats评价指标》:https://blog.csdn.net/weixin_35757704/article/details/128302003 《量化投资分析工具quantstats介绍及其在backtrader量化框架中使用》:https://zhuanlan.zhihu.com/p/507760842 《【BackTrader】教学课程第二讲策略绩效分析》:https://mp.weixin.qq.com/s/D_CHja6Kamls-CbyomENlg 《策略回测收益指标计算》:https://ghost.atibm.com/ce-lue-hui-ce-shou-yi-zhi-biao-ji-suan/ 《quantstats中英对照》:https://www.weishadian.com/index.php/2022/01/12/quantstats中英对照/ 《pyfolio技术文档》:https://pyfolio.ml4trading.io/api-reference.html 《quantstats官方仓库》:https://github.com/ranaroussi/quantstats 《Portfolio Analysis》:https://notebook.community/d00d/quantNotebooks/Notebooks/PortfolioAnalysis 《The easiest way to evaluate the performance of trading strategies in Python》:https://towardsdatascience.com/the-easiest-way-to-evaluate-the-performance-of-trading-strategies-in-python-4959fd798bb3 《用 pyfolio 进行量化交易回测》:https://zhuanlan.zhihu.com/p/417026785?utm_id=0