全实战进阶系列-CTA策略, 平台小鹅通,by 用 Python 的交易员
回测 Demo
基于 examples/cta_backtesting
两个 notebook
backtesting.ipynb
: 常规的单标 CTAportfolio.ipynb
: 组合回测
backtesting.ipynb
- 创建回测
1
2
3engine = BacktestingEngine()
engine.set_parameters(...) # 回测参数
engine.add_strategy(AtrRsiStrategy, {}) # 添加策略 - 运行回测
1
2
3
4
5engine.load_data() # 载入数据
engine.run_backtesting() # 跑回测, 得到成交记录
df = engine.calculate_result() # 从成交记录到盯市盈亏
engine.calculate_statistics() # 计算统计指标
engine.show_chart() # 显示结果
- 创建回测
引擎(BacktestingEngine)代码
set_parameters
: 仅仅保存参数add_strategy
: 添加策略类(继承CtaTemplate
)和实例化策略对象load_data
: 载入历史数据, 保存在self.history_data
, 会调用load_bar_data
或者load_tick_data
从数据库读取数据run_backtesting
: 跑回测,本身支持 Tick / K 线,但是图形界面只支持 K 线- 调用 strategy (
CtaTemplate
子类) 的on_init
函数进行初始化 - 如果 strategy 调用了
self.load_bar
,engine 则会把对应的历史数据推送给策略进行初始化 - 完成后 engine 标记
self.strategy.inited = True
- 下一步,engine 调用
on_start
函数启动策略 - 启动完成后,engine 标记
self.strategy.trading = True
- 对于剩下的数据,调用
new_bar
/new_tick
将剩下的数据用于回测
- 调用 strategy (
calculate_result
: 把交易聚合成逐日盈亏calculate_statistics
: 基于逐日盈亏计算统计指标,比较多利用了 pandas 的向量化show_chart
: 用matplotlib
可视化指标new_bar
/new_tick
- 缓存最新的 K 线 / Tick 数据,模拟撮合限价单(
cross_limit_order
)和停止单(cross_stop_order
) - 将最新的 K 线 / Tick 推给
strategy.on_bar
(防止未来函数,因为实盘走完 K 线之后才会下单) - 更新收盘价,方便计算逐日盯市盈亏
- 缓存最新的 K 线 / Tick 数据,模拟撮合限价单(
cross_limit_order
(K 线)long_cross_price = self.bar.low_price
, 对于 long (下在 bid), 如果最低价大于买单,则有成交机会short_cross_price = self.bar.high_price
, 对于 short (下在 ask), 如果最高价大于卖单,则有成交机会long_best_price = self.bar.open_price
,short_best_price = self.bar.open_price
, 按 taker 模拟撮合, 可能按开盘价成交- 模拟撮合,遍历所有 limit order:
- 对于状态等于
Status.SUBMITTING
的,更新为Status.NOTTRADED
,调用on_order
回调 - 若
order.price >= long_cross_price
/order.price <= short_cross_price
, 计算是否成交, 不成交则直接continue
- 若成交, 则认为全部成交, 更新状态为
Status.ALLTRADED
,调用on_order
回调 - 按照限价单的 price, 以及 best_price, 计算成交价格
- 生成成交记录
TradeData
, 维护strategy.pos
, 调用on_trade
回调
- 对于状态等于
cross_stop_order
(K 线)long_cross_price = self.bar.high_price
,short_cross_price = self.bar.low_price
,short_best_price = long_best_price = self.bar.open_price
- 模拟撮合,遍历所有 stop order:
- 若
order.price <= long_cross_price
/order.price >= short_cross_price
, 停止单触发,新增一个限价单OrderData
- 按照停止单的 price, 以及 best_price, 计算成交价格
- 生成成交记录
TradeData
- 更新原停止单状态为,
StopOrderStatus.TRIGGERED
, 调用on_stop_order
回调 - 对生成的限价单, 调用
on_order
回调 - 维护
strategy.pos
, 调用on_trade
回调
- 若
Dual Thrust
- 根据上一天的 K 线, 定义多空入场位置(
long_entry
,short_entry
) - 收到每一根 K 线
- 如果开没有开过仓
- 价格到了开盘价以上, 在
long_entry
下买入停止单 - 价格到了开盘价以下, 在
short_entry
下卖出停止单
- 价格到了开盘价以上, 在
- 如果已经开仓
- 持多仓, 在
short_entry
下卖出停止单平仓 - 持空仓, 在
long_entry
下买入停止单平仓
- 持多仓, 在
- 对于每日要收盘的品种,如果时间到达了快要收盘的时候,无论如何,都要平仓
- 如果开没有开过仓