第3章:订单生命周期管理
订单生命周期,说白了就是一笔订单从出生到消亡的全过程。我做了这么多年量化系统,见过太多因为状态机没设计好导致的惨案——资金对不上、成交记录丢失、甚至整个系统崩溃。今天咱们就来聊聊这个核心话题。
3.1 订单状态机:订单的“人生轨迹”
每个订单都有它的“人生”。从提交到交易所开始,它就会经历一系列状态变化。我个人习惯把状态机画在纸上,再动手写代码。你想想看,如果连状态图都画不清楚,代码怎么可能写对?
核心状态定义:
- New:订单刚提交,还没成交
- PartiallyFilled:部分成交了,还剩一些没成交
- Filled:全部成交,订单使命完成
- Cancelled:被用户主动撤销
- Rejected:被交易所驳回,比如价格不对、资金不足
这里有个坑——Rejected 和 Cancelled 是两码事。Rejected 是交易所不认这个订单,Cancelled 是用户自己不想玩了。我曾经见过一个新手把这两个状态混在一起处理,结果撤单失败还以为是系统bug,排查了整整两天。
避坑指南:我曾经在状态机里漏掉了 PartiallyFilled 到 Cancelled 的路径。结果用户撤单时,系统直接报错。嗯,从那以后我写状态机都会画一张完整的图,逐个路径检查。
3.2 订单类型:不同的“武器”
订单类型就是你的交易武器。选对了,事半功倍;选错了,可能血本无归。我建议每个交易员都像熟悉自己的手指一样熟悉这些订单类型。
3.2.1 限价单(Limit Order)
限价单是最基础的订单类型。你指定一个价格,只有市场价达到这个价格时才会成交。说白了,就是“我只愿意在这个价格买/卖”。
限价单的特点:
- 价格可控:你说了算
- 成交不确定:可能等很久,也可能永远不成交
- 适合做市商:挂单赚差价
3.2.2 市价单(Market Order)
市价单就是“不管什么价格,立刻成交”。我见过有人用市价单在流动性差的品种上吃大亏——滑点能让你怀疑人生。
注意:市价单在极端行情下可能成交在非常差的价格。我曾经在2015年股灾时看到有人用市价单卖出,结果成交价比预期低了5%。所以,流动性差的时候慎用市价单。
3.2.3 冰山订单(Iceberg Order)
冰山订单是个好东西。它把大单拆成小单,只露出“冰山一角”。你想想看,如果你直接挂一个100万股的买单,市场会怎么反应?价格肯定瞬间被拉高。
// 冰山订单示例
class IcebergOrder {
int totalQuantity; // 总数量:100000股
int displayQuantity; // 显示数量:5000股
int filledQuantity; // 已成交数量
void onFill(int fillQty) {
filledQuantity += fillQty;
if (filledQuantity % displayQuantity == 0) {
// 露出下一层冰山
placeNewOrder();
}
}
}
实战经验:我个人习惯把冰山订单的显示量设为总量的5%-10%。太小了容易被交易所风控拦截,太大了又起不到隐藏效果。这个比例是我踩过坑之后总结出来的。
3.2.4 止损单(Stop Order)
止损单是用来控制风险的。当价格达到你设定的止损价时,它会变成市价单或限价单。说白了,就是“亏到一定程度我就跑”。
| 订单类型 | 触发条件 | 成交方式 | 适用场景 |
|---|---|---|---|
| 限价单 | 价格达到指定价 | 限价成交 | 做市、低买高卖 |
| 市价单 | 立即 | 市价成交 | 快速建仓/平仓 |
| 冰山订单 | 价格达到指定价 | 分批限价成交 | 大单交易 |
| 止损单 | 价格触发止损价 | 转为市价/限价 | 风险控制 |
3.3 状态机与订单类型的结合
不同类型的订单,状态机的流转路径其实是一样的。区别在于触发条件和成交逻辑。比如止损单在触发前是“休眠”状态,触发后才进入正常的 New 状态。
核心原则:状态机是骨架,订单类型是血肉。骨架不变,血肉可以灵活替换。我建议把状态机做成通用模块,订单类型做成插件。这样加新订单类型时,只需要写插件,不用动核心逻辑。
嗯,这里要注意一点:冰山订单的状态机里,PartiallyFilled 状态会反复出现。每次露出新的一层,其实都是一个新的子订单在流转。我个人习惯用“父订单-子订单”的模式来管理,父订单记录总量,子订单负责实际成交。
曾经踩过的坑:我在做冰山订单时,一开始把子订单的状态直接映射到父订单上。结果父订单显示 PartiallyFilled,但子订单已经 Filled 了,数据完全对不上。后来改成父订单只做统计,子订单独立管理状态,问题才解决。
最后说一句:订单生命周期管理是量化系统的地基。地基不稳,上面盖再漂亮的房子也是白搭。我建议你在写代码之前,先把状态图画清楚,把订单类型的逻辑理明白。磨刀不误砍柴工,这句话在量化交易里尤其适用。