前言
《WonderTrader架构详解》系列文章,上一篇介绍了WonderTrader的信号执行的处理机制。平台的数据和信号执行机制已经完成以后,接下来就是要考虑如何生成信号了,也就是说策略如何编写。在解决策略编写的问题之前,首先要解决的就是平台要支持哪些策略。本文作为系列文章的第四篇,将针对WonderTrader对不同策略的支持展开讨论。
往期文章列表:
策略的分类
如何对策略进行分类,这个问题本身就很复杂。很多介绍策略的书都会对策略进行一个分类,然后再展开介绍,但是每位作者都有自己的分类标准,所以每本书里介绍的策略分类也不尽相同。笔者曾经拜读过几本,比较有代表性的就是丁鹏的《量化投资——策略与技术》。这本书里大致分为以下几个大类策略:
量化选股策略
- 多因子选股
- 风格轮动选股
- 行业轮动选股
- 资金流选股
- 动量反转选股
- ……
量化择时策略
- 趋势追踪择时
- 市场情绪择时
- 有效资金择时
- 牛熊线择时
- Hurst指数择时
- ...
股指期货套利
- 期现套
- 跨期套
商品期货套利
- 期现套
- 跨期套
- 跨品种套利
- 跨市场套利
统计套利
- 配对交易
- 股指套利
- 融券套利
- 外汇套利
- ……
然而对于量化平台来说,以上的分类都没有实际的意义。为什么呢?因为平台需要考虑的是从技术角度如何对策略进行分类,而上面展示的策略分类都是从策略实现的逻辑和目标交易品种来进行分类的。
那么从技术实现的角度角度对策略进行分类要考虑哪些问题呢?
行情数据的需求
从技术实现的角度来说,策略对数据的需求会引起很大的架构变动。比如说有些策略需要K线数据进行信号的计算,有些策略需要
tick
数据进行信号的计算,而有些策略同时需要K线
数据和tick
数据进行计算。平台在对策略开放接口的时候,就必须要考虑到不同策略的数据需求。
以趋势追踪策略为例,趋势追踪策略一般使用K线
数据进行信号计算,但是在实际运营的过程中可能也需要利用实时的tick
数据进行一个止盈止损逻辑的触发。
平台在考虑策略对数据的需求的同时,还需要考虑在实盘过程中对策略所需要的数据如何进行缓存、如何进行实时的更新、以及如何传递给策略。信号执行的需求
策略对信号执行的需求,主要是执行响应速度和执行方法两个方面。对于很多日频调仓的策略来说,如多因子选股,一般情况下需要执行较大数量的调仓,对于执行的要求相对较低,主要根据执行当天的平均成交价作为一个参考基准,在一天内执行完成即可。而对于高频策略来说,单次执行的数量一般较少,需要立即响应信号,在微秒级的延迟下发出下单指令。而对于日内调仓的策略来说,单次执行的数量介于多因子和高频之间,对执行的要求也介于二者之间:一方面不希望太大的延迟,造成太大的滑点;另一方面需要也不可能以一天的成交均价作为基准,反而以下一个周期的开盘价作为成交价的参考基准。
重算调度的需求
不管是何种策略,都需要一个机制驱动策略进行核心逻辑的计算。一般策略采用的驱动方式主要是事件驱动和时间驱动。时间驱动,就是到了某个规则确定的时间节点,驱动策略的核心逻辑进行重算。而事件驱动,我们这里主要指的是
K线
闭合、K线
开始、tick
进入等事件。对于基于K线
的日内趋势策略,一般需要在K线
闭合的时候进行重算;而基于日K线
的跨日趋势策略,则可以在收盘后到第二天开盘前进行重算;对于高频策略,则需要在每一笔tick
到来的时候进行重算。跟踪标的的需求
跟踪标的的需求,主要考虑的是跟踪的标的数量。如果你是做国内商品期货的,一般情况下,即使活跃品种的主力合约全部跟踪,也只有40多个。而如果要跟踪沪深300的成分股、或者中证1000的成分股,那么如何设计才能够满足这样的应用场景,就是一个非常重要的问题。
综合上面几点,WonderTrader最终从技术实现的角度将策略分类成三个大类:
日内趋势类策略
日内趋势类策略,不是说策略只做日内交易,而是指策略会在日内触发信号,即在交易时间内的某个时间点触发信号。这类策略一般策略逻辑都是基于
分钟K线
数据进行核心逻辑的重算,利用tick
数据进行止盈止损逻辑的计算。这类策略信号强度一般较高,不需要在执行的过程中根据订单的成交情况动态调整执行策略,能够容忍一定程度的滑点,属于笔者在上一篇《信号与执行》中提到的“重逻辑轻执行”的策略。高频类策略
高频类策略,主要利用
tick
数据触发核心逻辑重算,对于信号响应的延迟特别敏感,而且出现信号以后,还需要根据订单的执行情况实时调整信号。这类策略的盈利空间很小所以对滑点的容忍度非常低,因此需要平台处理信号要尽可能地快,属于笔者在上一篇《信号与执行》中提到的“轻逻辑重执行”的策略。选股类策略
选股类策略,主要指的是日频以上周期调仓的策略,以多因子选股策略为代表,所以称为选股类策略。选股类策略,计算量大、计算时间长,资金容量大,信号的特点是数量大,对滑点也不敏感。因此这类策略对于信号执行的效果容忍度也比较高。不过正是因为这些特点,选股类策略如果搭配更合适的执行算法的话,对绩效可以提升好几个点。对于大规模的资金容量来说,几个点的提升也是一个非常可观的数字了。因此选股类策略,对执行算法的需求,就体现需要在更长的时间跨度上,找到更合适的买卖点。
WonderTrader的策略引擎
针对上面的策略技术分类,WonderTrader提供了三种策略引擎,以满足不同类型策略的需求。
CTA引擎
CTA引擎(类名WtCtaEngine
),是WonderTrader针对日内趋势类策略设计的策略引擎,因为最早主要是针对CTA
策略的,所以引擎名字就按照CTAEngine
沿用下来了。
CTA
策略在初始化的时候,会向CTA引擎订阅一个主K线,也可以同时订阅其他周期或者其他品种的K线
。CTATicker
收到行情以后,会根据时间戳判断是否有K线
闭合,如果有K线
闭合,则触发策略的on_bar
回调;如果闭合的是主K线,则检查是否所有的K线
都已经闭合;如果所有K线
都已经闭合,则触发策略的on_schedule
回调进行策略核心逻辑的重算。如果出现新的信号,则由CTAEngine
汇总以后得到一个目标组合,再丢给执行管理器。执行管理器则将目标组合分发到各个执行通道,并由执行通道转成交易指令下达交易所。如果没有K线
闭合或者K线
闭合事件已经处理完成,再触发策略的on_tick
回调进行风控运算。
下图展示了CTA引擎中策略信号产生和执行的基本流程:
HFT引擎
HFT引擎(类名WtHftEngine
),是WonderTrader针对高频类策略设计的策略引擎。
HFT
策略在初始化的时候,会向HFT引擎订阅一些合约的tick
数据(如果通道支持的话,还可以订阅股票Level2
数据),也可以订阅K线
数据(不分主次)。HFTTicker
收到行情以后,和CTA
引擎不同的是,不会检查是否有K线
闭合,而是直接触发策略的on_tick
回调进行核心逻辑的重算。如果出现新的信号,则直接通过交易通道发出交易指令。交易通道收到订单回报以后,会触发策略的on_order
回调,如果策略有调整,则再发出新的交易指令。交易通道收到成交回报以后,会触发策略的on_trade
回调,如果有相应的调整,又会发出新的交易指令。
下图展示了HFT引擎中策略信号产生和执行的基本流程:
SEL引擎
SEL引擎(类名WtSelEngine
),是WonderTrader针对选股类策略设计的策略引擎。由于选股类策略具有计算时间长和计算量大的特点,并且通常是非交易时间重算,所以SEL
引擎本质上是一个时间驱动的引擎。SEL
引擎在设计的时候,要兼顾盘后计算和盘中计算两种需求,所以整个策略的重算是异步的。
SEL
策略在初始化的时候,会向SEL引擎注册一个时间驱动的策略。例如每天、每周、每月、每年指定的时间触发重算,或者在交易时间内每N
分钟触发重算。在非交易时间,因为没有行情接入,所以SEL
引擎会根据本地时间进行比较,如果满足时间条件,则触发策略的on_schedule
回调进行核心逻辑的重算。如果注册的是交易时间内的分钟线驱动,则通过SELTicker
根据最新接收到的tick
数据的时间戳进行行情时间同步,再触发策略的on_schedule
回调进行核心逻辑的重算。如果有新的信号产生,则将目标组合丢给执行管理器。执行管理器则将目标组合分发到各个执行通道,执行通道会根据预设的算法交易进行拆单,并根据算法交易的逻辑在合适的实时机由执行通道转成交易指令下达交易所。
策略引擎现状的思考
前面介绍的WonderTrader不同的策略引擎的核心逻辑,已经基本上可以覆盖市面上绝大部分策略调度的需求了。不过对于WonderTrader的策略引擎,笔者目前也存在一些疑虑。
HFT引擎对做市策略的支持
WonderTrader为了简化策略的逻辑,将策略的信号全部简化为买和卖。这样的简化,省掉了策略研发人员很多事情,比如:到底是买开还是买平?可平今仓剩余多少、可平昨仓剩余多少?现在买进的信号要拆成几个单子下出去?单笔下单的最大数量是多少?WonderTrader会把这些问题全部自动处理掉。比如:自动根据持仓确定是开仓还是平仓;自动根据预设的开平方案控制是平仓还是锁仓;自动根据可平数量拆分信号为多个订单。笔者相信绝大部分策略研发都会喜欢这样的简化,但是有一种策略可能会例外:做市策略。
做市策略一般的交易逻辑是在高位挂一个卖单,同时在低位挂一个买单,通过赚取两个单子之间的价差获取收益。问题在于,如果按照前面提到的一些自动处理方案,开始的时候是没有持仓的,同时挂的两个订单成交以后,持仓呈一多一空的状态,净头寸仍然为0
。如果这个时候出现第二轮信号,就可能会出现一些问题:买入订单会平掉空头的头寸,卖出订单会平掉多头的头寸。持仓的情况会如此反复,对于有些策略来说可能就不大适应了。
SEL引擎回测的难点
SEL
引擎回测的难点起源于实盘中的策略的核心逻辑是异步执行的。比如说,t0
时刻触发了策略的重算,重算时间较长,一直持续到t1
时刻。如果在生产环境下,直接在t1
时刻执行新的信号即可。但是对于回测环境下,如果采用同步回测的方式,回测时执行的价格为t0
时刻的p0
;如果采用异步方式回测的话,回测行情回放的时间又比生产环境快很多,到了t1
时刻行情早已回放超过t1
了,这时的执行价格变成了t2
时刻的p2
了,而不是t1
时刻的p1
。综合来说,SEL
引擎回测结果的参考价值要比CTA
引擎小很多。笔者也曾经考虑过,根据重算时间t
,计算t0+t
时刻,找到该时刻的pt
作为执行价格。这样的处理方式看起来比较可行,但是也会引入更多的复杂度。
WonderTrader的规划
前面大致介绍了WonderTrader各个策略引擎的一些基本情况。经过多方调研,笔者认为从底层来说WonderTrader支持的应用场景已经足够丰富了。但是在WonderTrader运用和推广的过程中,笔者也发现了一些预计之外的需求,这些也是后面WonderTrader完善的方向。
完善交易接口
目前来说,WonderTrader只支持普通的交易接口,可以笼统地概括为现金业务的交易接口。实际上还有其他业务类型,例如ETF申赎、期权询价报价、期权行权、两融业务等等。笔者后面会根据实际的需要逐步的完善这些接口,让WonderTrader支持更多的业务类型。
适配更多品种
从WonderTrader目前的推广的反馈来看,不少用户希望利用WonderTrader进行数字货币的交易。然后由于数字货币7×24小时交易的特点,目前WonderTrader还不能很好的支持。抛开技术细节不谈,根源还是在于WonderTrader本来设计的目标就是针对常规的交易市场的,即使是NYMEX
这样的交易所,每天也有1个小时的休市时间。当然,这不能成为WonderTrader固步自封的理由,所以未来WonderTrader也会逐笔完善对不同市场和不同品种的适配。
为应用层开放功能扩展接口
WonderTrader在设计的时候,为了保证底层的执行效率,所有的功能组件都是用C++
开发的。功夫不负有心人,WonderTrader系统内部延迟,在一般台式机上也能达到10微秒以内。但是在推广的过程中,笔者发现部分用户实际上是基于wtpy
做开发的,并没有C++
的开发能力。但是这样的用户想要做一些二次开发的话,都需要C++
底层做同步调整,于是这些用户只能望而却步了。鉴于这样的情况,笔者也反复斟酌了一下,计划在未来考虑将行情接入模块、交易模块向应用层子框架开发。这样的好处就是,一些二次开发的门槛也同步降低了,可以丰富WonderTrader的生态,给不同需求的人群提供更丰富的选择。
结束语
本文对WonderTrader的策略引擎的介绍就到此结束了,希望本文能给一些想要使用WonderTrader进行策略开发的朋友一些指引。笔者水平有限,难免有错漏之处,还请各位朋友多多包涵指正。下一篇,笔者将针对不同的策略引擎,来详细介绍WonderTrader不同类型策略的回测的机制,望各位读者届时多多捧场。
最后再安利一下WonderTrader
WonderTrader旨在给各位量化从业人员提供更好的轮子,将技术相关的东西都封装在平台中,打造更高效的底层框架,力求给策略研发带来更好的策略开发和交易体验。
WonderTrader的github
地址:https://github.com/wondertrad...
WonderTrader官网地址:https://wondertrader.github.io
wtpy的github
地址:https://github.com/wondertrad...
市场有风险,投资需谨慎。以上陈述仅作为对于历史事件的回顾,不代表对未来的观点,同时不作为任何投资建议。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。