aggTrades 就是聚合之后的逐笔交易记录,也就是币安把连续的几笔在同一时间、同一方向、同一价位成交的交易聚合成一笔记录,类似 k 线的一根,但是只有一个价格,没有最高最低价之类。比如盘口挂了一笔大单,很多小订单去吃它,那么这些在很短时间内(毫秒级)同时到达的订单,就会被聚合在一起。或者可能就是撮合引擎一次能够撮合的订单。
如果是多周期的,那么可以获取它们的公约数周期 k 线,然后各个策略根据自己的需求再 resample 就可以了。
如果要简化一点,一劳永逸,那么直接获取 15 分钟的 k 线最好,因为中低频策略,特别是趋势跟随这类,周期低于 15 分钟的,长期来看基本很难赚钱。
例如,你有 15 分钟,1 小时,4 小时的策略,那么行情中心仅仅获取 15 分钟的 k 线就行了。如果 resample 之后大周期的 k 线长度不够,那么就得在启动时刻,把 15 分钟的 k 线在数据库中多保存一些。
因为 websocket 只是推送最近更新的 k 线信息,如果你的策略用到的 k 线周期比较大,而且回溯时间又长的话,例如 4 小时的 ma150,那么就是 600 个小时(25天)的数据,15 分钟一根 k 线的话,需要 2400 根。这个得靠在行情中心启动的时候,通过 rest api 一次性获取保存,作为之后不断更新的基础。
如果要求不高,你甚至可以用它来合成所有合约的粗糙 k 线,完全避开采用 websocket 的方案。这种 k 线就算不能用来交易,也可以用在诸如全市场信息扫描上,然后根据自己设计的策略算法,例如什么均线发散、收敛,简单的形态识别等等,给主观交易员提供入场信号。不然,那么多币,怎么看得过来。如果有水平高的日内交易员,这种工具可能就会有用,辅助交易。我之前就给别人写过类似工具,行情好的时候确实不错,不过最近没啥行情了。
第三,websocket 如果链接断了,或者遇到前面讲的 listenKey 更新,或者到期之类的问题,如果程序没有及时发现,而这个时候恰好又有交易,那么如果仅仅依赖 websocket,就会造成比较大的问题,因为错过的账户更新信息不会再次推送。要规避这类潜在问题发生的可能性,也得依赖 rest api 获取确定的账户信息。那么最后总得依赖 rest api,岂不是多此一举?
综上,对于中低频交易,还不如直接采用 rest api 获取账户信息。重要数据源,最好奉行 SSOT(Single Source Of Truth 可信单一数据源),不然可能造成潜在混乱,这个概念可以自行谷歌,在依靠数据处理的编程中非常有用。
那么,如果只采用 rest api 获取账户信息,可以在本地代码内存里维护一个临时账户信息表,特别是可用资金,这样可以减少频繁访问交易所,关键是快,可以把单子一次性都发出去,类似批量下单,然后再慢慢处理更新后面的逻辑,下单快了,滑点自然就小一点。
另外,要判断算法止损单是否成交,可以使用近期的 high low 价格,而不是直接去获取挂单的状态,因为判断单子是否成交,需要不断去 poll,比较频繁,会造成很多无效 api 访问。而 websocket 的 k 线价格更新是非常及时的,而且不占用 api 频率限制。
同理,一些退场单子也可以如此。如果你的退场信号是依靠 bar 内的价格,那么采用近期 high low 价格可能更好。因为有的时候价格触发了,又会立即回归,如果你的检查频率不是太高,那么就有可能错过。为了保证交易策略的一致性,检查 high low 这样的价格就不会错过。这样处理还有额外好处,就是实际成交价格可能会更有利,相比于真正的触发价格。
实盘总体架构上,子策略多,又要求获取各类信息及时,就要有一个专门的 websocket 行情中心来分担任务。再配一个 Restful 的 Plan B 行情中心做备份。这样万一 websocket 掉线连接不上的时候,还有一个比较新的价格来判断是否需要离场。跑路的时候要快,宁愿跑错,也比被堵在里面,不知未来如何要强。
可以在整点前 n 秒提前计算信号跑路,那个时候还没开始拥挤,因为可能大多数自动化策略都是等到整点 k 线关仓价出来之后,才开始计算信号的。不过这样操作带来的问题就是,可能会产生错误信号,例如价格马上又回去了,本来不该有信号的,false positive 发生了。这时就看你的取舍了,要不要这么干。不过,可以再加一定阈值,超过了才触发,这样防止短时间价格回归造成的误发信号。滑点能减少一点是一点吧。
还有就是采用时间 offset 或者 shift k 线这类偏移信号的方法,不在整点产生信号,不跟别人卷到一起去,更好地避开拥挤。还有就是 TWAP 等等方式。