订单管理与风控闸门
OMS 的职责
Section titled “OMS 的职责”订单管理系统(OMS)位于策略与券商之间,职责有三:
- 订单状态机:订单从创建到终结的全生命周期管理;
- 券商对接:API 封装、重试、幂等性处理;
- 下单前风控(pre-trade risk):所有订单的最后一道检查闸门。
订单的状态转移必须显式定义:
created → submitted → acknowledged → partially_filled → filled ↘ rejected ↘ cancelled ↘ expired工程要点:
- 状态持久化:每次状态变更写入持久存储,进程重启后可恢复——"重启后不知道自己有哪些未完成订单"是实盘最危险的失忆;
- 状态由回报驱动:本地状态只信任券商回报(acknowledged / filled),不对"应该成交了"做乐观推断;
- 超时处理:submitted 超过阈值无回报,主动查询而非等待。
券商 API 的幂等性
Section titled “券商 API 的幂等性”重复下单是最常见的实盘事故:网络超时后重试,第一笔其实已成交——结果买了双倍。处理:
- 每个逻辑订单带唯一 client_order_id,重试复用同一 ID;
- 重试前先查询订单状态,不做盲目重发;
- 对账时用 client_order_id 对齐本地与券商记录。
import uuidimport time
class OMS: def __init__(self, broker): self.broker = broker self.orders: dict[str, dict] = {} # client_order_id → 状态
def place(self, symbol: str, side: str, size: float) -> str: oid = str(uuid.uuid4()) self.orders[oid] = {"symbol": symbol, "side": side, "size": size, "status": "created", "ts": time.time()} resp = self.broker.submit(client_order_id=oid, symbol=symbol, side=side, size=size) # 幂等 ID self.orders[oid]["status"] = resp["status"] return oid
def retry(self, oid: str) -> str: """重试前先查询,不做盲目重发""" status = self.broker.query(oid) if status is None: # 确认未受理才重发 resp = self.broker.submit(client_order_id=oid, **self.orders[oid]) self.orders[oid]["status"] = resp["status"] return self.orders[oid]["status"]下单前风控:闸门清单
Section titled “下单前风控:闸门清单”所有风控检查在下单前同步执行,超限直接拒单并告警:
- 单笔订单金额上限
- 单日累计亏损上限(触发后当日停止交易)
- 持仓集中度(单一标的/行业占比上限)
- 订单价格合理性检查(偏离现价超过阈值拒单——防"胖手指")
- 目标持仓一致性(本单是否与目标组合一致,见均值—方差与其失败)
- 交易时段与规则检查(该时段该市场是否可交易,见第十二卷)
量化中的用法
Section titled “量化中的用法”- 订单状态机持久化,重启可恢复;
- 幂等 client_order_id + 重试前查询,杜绝重复下单;
- 闸门清单固化为代码,每条超限都告警并记录。
- 所有风控检查在下单前同步执行,超限直接拒单并告警
- 订单状态必须持久化,重启后可恢复
- 券商 API 的幂等性问题:重复下单是最常见的实盘事故