第十六章:实盘交易系统
实盘交易系统,说白了就是你的策略从回测走向真金白银的最后一公里。我见过太多人,回测曲线漂亮得不行,一上实盘就崩。为什么?因为实盘要考虑的东西,回测里根本碰不到。
这一章,我们聊聊系统架构、低延迟、FIX协议、订单管理和风控。嗯,都是硬骨头,但啃下来,你就能真正把策略跑起来。
系统架构设计:别把鸡蛋放一个篮子里
我个人习惯把交易系统拆成三层:
- 策略层:负责生成信号,不碰交易细节
- 执行层:负责把信号变成订单,管理FIX连接
- 风控层:独立于策略,专门做检查
为什么要拆?我在项目中遇到过一件事:策略层有个bug,循环里忘了加sleep,瞬间发了上千个订单。幸好风控层独立运行,直接截断了。要是耦合在一起,那天就爆仓了。
核心原则:策略、执行、风控必须解耦。任何一个模块挂了,不能影响其他模块。
架构上,我建议用事件驱动。每个模块只关心自己订阅的事件。比如策略层发布“买入信号”事件,执行层收到后去下单。这样改一个模块,其他模块不用动。
低延迟技术:每一微秒都很重要
做高频交易的朋友,对延迟特别敏感。但就算你不是高频,低延迟也有好处——减少滑点,提高成交率。
我常用的几个技巧:
- 避免锁竞争:用无锁队列(比如Disruptor)传递数据。Python里可以用
queue.Queue,但性能不够时,我换过multiprocessing.Queue,延迟降了一半。 - 内存预分配:别在交易循环里动态创建对象。提前分配好,复用。
- 减少系统调用:网络IO、磁盘IO能少就少。日志可以异步写,别阻塞主流程。
避坑指南:我曾经为了追求低延迟,把所有日志都关了。结果出问题查不了原因。后来我改成“关键日志同步写,普通日志异步写”。平衡很重要。
还有一个容易被忽略的点:CPU亲和性。把交易进程绑定到特定CPU核心,避免上下文切换。Linux下用taskset命令就能搞定。
FIX协议:交易界的通用语言
FIX协议,说白了就是交易所和你的系统之间怎么说话。它定义了一堆标签(Tag),比如55是股票代码,44是价格,38是数量。
一个简单的FIX消息长这样:
8=FIX.4.2|9=78|35=D|49=CLIENT|56=BROKER|34=1|52=20250320-10:00:00|55=600519|44=150.00|38=100|10=123|
解释一下:
35=D:表示这是一条新订单(New Order Single)55=600519:股票代码,贵州茅台44=150.00:价格38=100:数量10=123:校验和
我建议用现成的FIX引擎,比如quickfix(Python有绑定)。自己手写解析?别折腾,容易出错。
注意:FIX协议版本很多,FIX.4.2、FIX.4.4、FIX.5.0……不同交易所支持的版本不一样。对接前一定要确认好。
订单管理:别让订单“飞”了
订单管理,核心就三件事:
- 订单状态跟踪:新订单、部分成交、全部成交、已撤销……每个状态都要记录。
- 订单生命周期:从生成到成交,中间可能经历多次修改、部分成交。
- 异常处理:订单超时、被拒、连接断开……怎么办?
我习惯用一个订单状态机来管理。每个订单就是一个状态机实例,事件驱动它流转。
举个例子:
class Order:
def __init__(self, order_id, symbol, side, price, qty):
self.order_id = order_id
self.symbol = symbol
self.side = side
self.price = price
self.qty = qty
self.filled_qty = 0
self.status = 'NEW' # 初始状态
def on_fill(self, fill_qty, fill_price):
self.filled_qty += fill_qty
if self.filled_qty >= self.qty:
self.status = 'FILLED'
else:
self.status = 'PARTIALLY_FILLED'
# 记录成交明细
self.fills.append({'qty': fill_qty, 'price': fill_price})
嗯,代码很简单,但实际中要考虑并发。多个线程同时修改订单状态?加锁或者用原子操作。
风控模块:最后的防线
风控模块,我把它放在执行层前面。所有订单必须先过风控,才能发出去。
常见的风控规则:
| 规则 | 说明 | 示例 |
|---|---|---|
| 最大持仓限制 | 单品种持仓不能超过某个值 | 茅台最多1000股 |
| 最大订单频率 | 每秒最多发N个订单 | 每秒不超过10笔 |
| 最大亏损限制 | 当日亏损超过阈值,停止交易 | 亏损超过5%自动平仓 |
| 价格偏离检查 | 订单价格不能偏离市场太远 | 不能超过最新价的±2% |
我的经验:风控规则要分层。第一层是硬性规则(比如最大持仓),直接拒绝订单。第二层是软性规则(比如频率限制),可以报警但不阻断。这样既安全又灵活。
还有一个容易被忽视的点:风控模块本身也要监控。如果风控模块挂了,所有订单都发不出去。我一般会加一个“心跳检测”,风控模块每秒钟发一个心跳,如果超过3秒没收到,自动切换到备用风控。
系统架构图
下面这张图,展示了我常用的实盘系统架构。你想想看,数据从行情进来,到策略生成信号,再到执行和风控,最后到交易所,每一步都很清晰。
这张图里,行情数据先喂给策略层,策略生成信号后发给风控层。风控层检查通过,才交给执行层。执行层通过FIX协议把订单发给交易所。成交回报走虚线路径,异步更新行情和策略状态。
一个小建议:刚开始做实盘,别追求极致的低延迟。先把功能跑通,再慢慢优化。我见过有人花三个月优化了10微秒,结果策略本身就有问题,白忙活。
好了,这一章的内容就这些。实盘交易系统是个大工程,但拆开来看,每一块都不难。关键是理解它们怎么配合,以及每个模块的边界在哪里。