前言
自己一直对自动化交易系统有着浓厚的兴趣,但由于平时较忙,属于纸上谈兵,直到去年年底开始有些业余时间开始实践。整个过程令人兴奋,从一开始有了个策略想法,然后着手写代码回测证明能够实现理论盈利。于是开始实现系统,上线,小额试水,逐渐调高本金,调优。最终,实现账面上的真实盈利。本文则是对该系统实现的一个阶段总结与分享。
目标
实现一套自动化交易系统(平台),能够回测/执行自定义的交易策略(交易对象为比特币)。该系统需要具备以下特性:
- 易于扩展:随着不断对自动化交易的理解,系统能够适应不断丰富的功能
- 易于回测:能够基于历史价格对策略进行回测,评估有效性,调优参数
- 易于调试:能够重现历史执行状态,重现系统问题
- 低延迟:能够支持中频交易(非高频),tick-to-trade在3秒以内
事件驱动
记录所有时间序列事件(报价,订单,账户等变化事件),通过对事件的回放从而可以重现任何时间点的历史状态。
架构 V1.0
特点: 单交易策略单执行流
ets_arch_v1.png- 各种Feed将Exchange的不同变化按时间序列转换为事件放进Event Queue,后者会将事件持久化到Event Logs
- Engine将产生的订单放入Order Queue,由Execution异步请求Exchange,并将执行结果送回Event Queue
- 订单是否被fill的结果由Order Feed捕捉相应Order变化事件
策略引擎组成
ets-engine.png- Event Handlers处理所有事件,更新当前系统状态
- Validator可以按需定制,如检查Order是否fill,价格延迟是否较高,损失是否过大等
- 鉴于Deflection是耗时操作,因此放在Strategy之后执行(在下一次Strategy执行时产生效果),以避免增加R2D延迟
- 整个过程由单线程执行
回测支持
ets-regression.png- 通过Event Logs读取持久化的历史价格事件(忽略其它事件)进行策略回测,参数调优
- Fake Client不发送请求至Exchange,而是模拟fill order事件
调试支持
ets-replay.png- 通过回放Event Logs里所有事件(包括错误等)以恢复任何历史时间点状态
- Fake Execution可以只是简单的控制台输出
- 有多种方式可以选择设置Clock以回放出与历史相一致的时间(这里不多叙述)
架构 V2.0
特点: 单交易策略多执行流
多执行流提供了以下优势:
- 可以减少单执行流的Order Size,从而降低实际交易产生的摩擦
- 不同执行流锚定不同的价格梯度,从而提高策略深度和Scalability
- Dispatch Event Queue将事件发送到所有执行流各自的Event Queue上
- 执行流相互独立,各自运行于单独线程,无需线程同步(除了下面讲到的令牌场景作为例外)
架构 V3.0 (TBD)
特点: 多交易策略多执行流
通过多交易策略捕捉更多日内交易机会
一些问题的处理策略
延时衡量
目前系统所需衡量的延迟有:
- tick-to-receive (T2R): 交易所报价到系统收到价格间的延迟(主要取决于网络延迟,交易所系统的成熟度/健康度)
- receive-to-decision (R2D):收到价格到订单决策间的延迟
- decision-to-execution (D2E):订单决策与订单执行间的延迟(应该很小)
- execution-to-executed (E2E):订单执行所需时间(主要取决于网络延迟,交易所系统的成熟度),目前不属于系统优化范畴
- executed-to-filled (E2F):订单被交易所满足所需时间,目前不属于系统优化范畴
所见非所得
由于订单决策价格(Decision Price)往往与实际执行价格不完全相等(目前都是采用Market Order下单),目前采取的策略有:
- 引入“摩擦力”,订单决策基于所看到的价格加上预设摩擦力
- 将订单执行后实际产生的摩擦力记入交易成本
- 减小每次交易的Order Size,从而降低市场价格影响
策略饥饿
当市场表现与策略所定参数长时间相悖,导致策略长时间不被执行(饥饿),错过交易机会。目前采取的策略有:
- 动态根据市场表现调整策略参数(Deflection)
- 采用多执行流,提高策略深度
极端场景
默认情况下策略会自动调整来适应当前市场变化,以此减少饥饿,但当市场进入极端场景时,可能会被套牢。目前采取的策略是:
- 限定策略参数动态调整的范围,允许在极端场景下的饥饿,这样可以避免因套牢产生的损失,并且一旦市场又回归常态,也避免因套牢而产生的进一步饥饿。
多执行流冲突
当运行多执行流,市场的快速波动可能同时触发多个执行流的策略下单。为了避免使情况复杂化,采用如下策略简化执行:
- 执行流共享同一令牌,当多个执行流下单条件被同时触发时(不常见),需要先请求令牌,只有获得令牌的执行流才能执行下单。
网友评论