从有想法到实战,量化交易环节中的每一步,从来都不是一马平川。那些拥有丰富经验的交易者都明白,要想开发一个持续稳定盈利的交易策略,并非易事。但是,有许多量化初学者常常凭借某一回测结果,就轻易地确定他们的交易规则。
诚然,这种方式能够完美地契合他们所观察到的某一特殊现象,然而,一旦这一规则被投入更精细的数据或者较长的历史数据中验证时,他们就会发现这些策略其实并不有效,甚至可能更糟。
交易者常犯的错误之一,就是基于历史数据回测的绩效来做交易决策。最近几年,伴随着国内量化交易的发展,很多量化交易者开始研究策略、进行回测、实盘交易,但对于量化初学者来说,这里面有许许多 “ 坑 ”。
比如一些网友分享的策略,回测看起来很美,但在实际交易中因摩擦成本出现时,一个理论上赚钱的策略马上就会下降到盈亏平衡点。后面我们会陆续发布 [策略粉碎] 系列文章,帮助大家识别策略中的 “ 坑 ” ,如果你有幸读到这些文章,至少会少走很多弯路。
我们做一个简单的跨期套利策略,来进一步阐述。
在技术分析方法中有一种追踪趋势的布林通道法,其原理是基于统计学中的标准差。布林通道由一根中轨和用标准差计算出的上轨和下轨三条线构成。
计算时,我们选取一组历史数据,其均值即布林通道中轨,上轨的取值为均值加上该组数据的 2 倍标准差,下轨的取值为均线减去 2 倍的标准差。这次我们把上下轨的标准差均设置为 1.5 倍。
根据统计学原理,被统计的数据中将有 96%的数据落在这上下两条轨道中。换句话说,如果一个价格落在轨道之外的话,随后也会很快回落至上下轨之内。
那么,如果相邻两个合约价差波动落于上下轨道(用统计方法设定上下两个置信区间)外侧,就意味着出现套利机会。落在外侧的概率很小,即使出现,也会很快回落。
如果实际价差落在上方,可进行买近月,卖远月(期望价差缩小)的操作;反之则买远月,卖近月(期望价差扩大),两个反向合约都在触及中轨后(过去某个固定时间周期内的该价差平均值)获利了结。
这个策略方法非常普遍,实现起来也非常简单,首先绘制套利的两个合约的价差。之后再进行技术分析,如果当价差超过上轨乘以波动率系数时,做空价差,当价差超过下轨乘以波动率系数时,做多价差。当价差回归均值时平仓。
因为价差与单品种价格波动来比较,有一个特点,就是一般用于套利交易的合约配对,其价差都具有一定的均值回归特性,即价差一般会在一个范围内波动,价差太大时,后期变小的可能性就大,价差太小时,后期变大的可能性就大。整个策略逻辑一点都不复杂,甚至还很简单,但是回测的结果出乎意料...
我们先用 BotVS 量化交易平台的模拟级别数据回测一下。
回测配置环境如下:
回测绩效如下图:胜率 70%,很暴力很惊艳有没有?而且几乎没有回撤...!
接下来,我们再用交易开拓者,按照同样的条件和环境,回测一下,看看有没有区别。
设置如下图:
这个策略的回测效果不仅远远胜过市场的平均收益率,而且几乎没有回撤。即便与投资银行、对冲基金等专业机构的产品表现相比,策略的回测表现也处于明显上风,其程度甚至可以到达令人难以置信的地步。
那有人问,你一直用这个策略不是发大财了? 呃......答案当然是否定的。
我们再次用 BotVS 量化交易平台,只不过这次我们用实盘级 Tick 回测引擎,按照同样的条件和环境,回测一下,看看有没有区别,好做对比。
说明一点,策略源码无论是逻辑还是内容,没有那些低级错误。这是一个完整而且没有错误的策略。但为什么差那么多,差在哪...?
在找问题之前,先科普下 BotVS 量化交易平台两种不同的回测模式:
1、模拟级别回测:模拟级别的 Tick 生成与 MT5 交易平台机制是一样的。即按照回测系统的底层 K 线数据,按照一定算法,在给定的底层 K 线 Bar 的最高价、最低价、开盘价、收盘价的数值构成的 框架内,模拟出 ticker 数据插值到这个 Bar 的时间序列中(该 Bar 的周期中从开始到结束,的时间序列就是模拟出的 ticker 数据)。
2、实盘级别回测:实盘级别回测,ticker 是真实记录的数据,并非模拟生成,但是在回测中如果一定时间内 ticker 数据没有变化,考虑到回测系统运行的效率,回测系统中会跳过 ticker 没有变化的时间段,直到 ticker 数据变化。
换句话说,真实的 ticker 级别数据 在 Bar 的时间序列中。对于基于 ticker 级别数据的策略来说,使用实盘级别回测更贴近真实交易环境。
那么在模拟级别的 K 线中,导致这种问题的主要因素就出现了:
以 1 分钟 K 线为例,收盘价来自于当前时间周期内的最后一个成交价格,如果是成交量比较活跃的主力合约,最后一个成交价格可能是 58 秒;如果是成交量不活跃的次主力合约,在这个 60 秒之内,最后一个成交价格可能是 35 秒,之后就没有再成交的价格了。
假设价差的布林带上轨是 45,当前时间是 1 分钟周期内的第 35 秒,A 合约价格是 5050,B 合约价格是 5015,此时的价差是 35 ;随着时间的推移,在第 58 秒的时候,A 合约的价格达到 5061,B 合约没成交价,价格依然是 5015,此时的价差是 46 ;那么此时策略达到做空价差的条件。回测引擎会在价差为 46 时,撮合成交。
但在标准 Tick 实盘级中,B 合约因为没有最新的挂单,显示的只是已经过去的价格,那么回测引擎不会拿过去的价格来撮合成交。在我们逐根检查数据中发现,不管是 A 合约还是 B 合约,只要出现上述这种状态,都会导致出现类似的问题。
除了上面主要因素外,还有下面部分客观因素:
1、单腿风险。Bar 级别回测的时候两个合约是 100%成交的。在实盘的时候,是无法保证的,有可能会出现只成交一个合约。
2、策略容错性。Bar 级别回测的时候是没有滑点的,除非你有设置,但是在实盘的时候会因为各种原因导致价格不能及时成交,要么撤单,要么追单。特别是流动性不好的品种,下单时还有可能造成市场冲击。
3、在 Bar 模式中回测。在 Bar 模式运行回测中,每根 Bar 调用一次函数,先撮合订单,再运行 Bar。如果在上一根 Bar 的开盘价或者收盘价下了订单,那么回测是用下一个 Bar 的 OHLC 价格来撮合订单。
策略在 bar 中回测,基于的是静态的历史数据,一根 bar 的开高低收,价格有可能先往上冲,也有先有可能往下。那么回测的结果就可能会用到过去的数据或者未来的数据。
所以,在 Bar 级的数据里面,用 Tick 级别的交易条件,产生漂亮资金线的回测是骗人的, BotVS 平台的 Tick 级回测就是专门用来高仿真实盘环境的, 是目前市面上对实盘还原度最高的一种回测机制 !
重点来了~如何避免?
几乎所有的回测系统,如果不用 Tick 级回测,都避免不了偷价问题,即便是你策略的逻辑上没有偷价,但在模拟级回测撮合引擎中其实已经暗藏了偷价。
标准 Tick 实盘级回测中,能最大程度的还原真实的交易环境。每一个都是真实成交价格、真实最后成交量以及真实的盘口买一价和卖一价,以盘口价格做价差对比的话,那么很大程度避免这种问题。
还有,特别是交易频率比较高的策略,如果策略进场点和出场点在同一根 bar 同时出现开平仓的时候,就必须开启 Tick 级别的回测模式。
另外,单腿问题无法完全避免,只能减少发生的概率。比如只操作流动性好的品种。或者下单时先完成流动性低的品种,再完成流动性高的品种。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.