05 · 风控与资金管理:最后一道防线必须是你自己
所有对接项目里,客户最常说的一句话是「交易所/柜台不是有风控吗?」——这是最大的误解。柜台/交易所的风控是底线(强平、超限、异常交易监控),不是护栏:它只保证「不出系统性风险」,不保证「你的策略不亏钱」。
本篇讲客户端风控层为什么必须存在、由哪些模块构成、下单前后各做什么、异常怎么处理、熔断怎么设计、审计怎么留痕,以及风控系统的架构红线。
1. 为什么客户端必须有自己的风控层
| 维度 | 柜台/交易所风控 | 客户端风控 |
|---|---|---|
| 定位 | 底线:防止**穿仓**、防止市场操纵 | 护栏:保护本账户/本策略不亏超出容忍度 |
| 参数 | 固定或由柜台定,不面向策略 | 按策略、按账户灵活配置 |
| 响应 | 有延迟(人工/低频检查),强平往往是最后手段 | 毫秒级,前置拦截 |
| 覆盖 | 资金不足、异常交易行为 | 策略级**止损**、组合敞口、频率、黑名单……柜台根本不管这些 |
| 责任 | 保交易所/清算安全 | 保客户/公司自己的钱 |
三个必须自建风控的理由:
- 柜台不拦「亏钱」:你的策略连续止损 20 次、账户回撤 30%,柜台无动于衷——只要钱够、不违规,它没有义务替你止损。
- 柜台拦截有代价:资金不足被拒单已经是「事后」;强平更是带着巨大**滑点**的最后手段。客户端前置校验可以把「拒单」变成「拦截」,把「强平」变成「主动止损」。
- bug 会被放大:策略代码有 bug、参数配错、行情错误,这些柜台毫不知情——只有客户端风控能在错误的单到达柜台之前杀掉它。
一句话:柜台风控是消防队,客户端风控是防火材料。 消防队再好,也不该靠烧起来才意识到火。
💀 柜台风控是消防队客户端风控是防火材料
柜台风控是消防队,客户端风控是防火材料。 柜台不拦「亏钱」——你的策略连续止损 20 次、账户回撤 30%,柜台无动于衷,只要钱够、不违规它就没有义务替你止损。bug 会被放大,只有客户端风控能在错误的单到达柜台之前杀掉它。
2. 风控模块清单
2.1 资金风控
- 余额校验:可用资金、冻结资金、**保证金**占用,任何不足直接拦截。
- 冻结:下单时按预估保证金冻结,成交/撤单后释放——冻结逻辑与柜台结算保持一致(对冲、锁仓的处理方式各柜台不同,以柜台规则为准)。
- 可用额度:账户/策略级别的可用额度(如「该策略今天最多亏 5 万」),用掉即停。
2.2 仓位风控
- 最大手数:单笔委托、单策略、全账户的三级手数上限。
- 单标的限额:单一合约/品种的持仓上限(多空分别计)。
- 集中度:单品种占账户权益比例上限,防止「一个品种出事带崩全部」。
- 总敞口:全账户合计持仓的保证金占用、名义敞口上限。
2.3 频率风控
- 每秒/每分钟下单数:防止策略死循环或重试风暴。
- 撤单率/报撤比:频繁挂撤会被交易所判定为异常交易行为(国内期货对此有监控,可能限制交易编码),客户端要主动压制。
- 重复单检测:同一策略短时间内对同一标的的重复下单(意图外的)自动拦截。
2.4 止损风控
- 策略级强制平仓:策略亏损达到阈值 → 客户端主动平掉该策略全部持仓。
- 最大亏损熔断:账户日亏损/总亏损达到阈值 → 熔断(见第 6 节)。
- 单笔止损:对策略下达的每一笔单子附加止损条件,条件触发由风控代为下单(不依赖策略自身实现,因为策略可能已经崩溃)。
3. 下单前校验流程
风控闸门必须串行在所有下单请求的前面,任何一道闸门不通过都直接拦截:
策略/用户下单意图
│
▼
① 资金闸门:可用资金 ≥ 预估保证金 + 手续费 + 预留缓冲?
│ 否 → 拦截
▼
② 仓位闸门:本次下单后,单笔/单标的/单策略/全账户是否超限?
│ 否 → 拦截
▼
③ 频率闸门:速率、撤单率、重复单检测是否通过?
│ 否 → 拦截
▼
④ 黑白名单 + 人工审批:标的是否在禁列表?大额/特殊单是否需审批?
│ 否 → 拦截(进入审批队列)
▼
放行 → 进入交易接口(详见 04 篇下单流程)设计要点:
- 前置校验数据(资金、持仓、冻结)与账户服务同源:用账户服务的实时状态,而不是各策略自己维护的副本(副本必然过期)。
- 校验规则配置化:风控参数(限额、阈值、名单)可以在线修改、立即生效,不需要发版。
- 拦截要有原因码:每一条拦截记录「哪道闸门、什么参数、什么值超了什么值」,这是审计与优化的基础。
- 风控校验自身的失败要fail-closed:风控服务不可用或校验超时 → 默认拦截(不允许无风控的下单),而不是默认放行。
💡 风控校验自身失败必须 fail-closed
风控服务不可用或校验超时 → 默认拦截(不允许无风控的下单),而不是默认放行。 风控校验自身的失败必须 fail-closed——这是风控架构的红线,否则一道闸门失效就等于整道防线失效。
4. 下单后实时监控
4.1 持仓与资金监控
- 浮动盈亏:按实时行情重算各持仓的浮动盈亏,与策略预期对比,偏差大说明策略逻辑或行情有问题。
- 保证金占用:接近可用资金上限时预警;接近强平线时高优先级告警(客户端要能算自己的强平价——不能等柜台通知)。
- 资金流水监控:出入金、手续费、结算盈亏的流水异常(不该有变动时变动)→ 告警。
4.2 监控大盘与大额持仓
- 监控大盘:全账户、全策略的实时状态面板:持仓数、委托数、失败数、资金、当日盈亏、风控拦截数。
- 大额持仓盯盘:单品种持仓占比高的账户,行情异常波动时重点盯防,触发阈值自动降**杠杆**或主动减仓。
4.3 策略行为监控
- 策略「该出手时没出手」(信号产生但订单未发出/被拒)、订单长期未成交、回报处理延迟,都是策略异常的早期信号,比盯盈亏更早暴露问题。
5. 异常处理
5.1 接口超时重试策略
- 采用「查询优先、幂等重试」(详见 04 5.2):先查单再决定补发或标记未知。
- 重试次数与间隔设上限:超过上限 → 标记「未知状态」+ 冻结该单相关操作 + 人工介入。
5.2 半途失败的单子如何清理
- 下单请求超时、状态未知的订单:进入「待确认队列」,用查询接口持续确认;确认成交则纳入持仓,确认未成交则视意图补单或放弃。
- 撤单失败(单子已成交):以成交回报为准修正状态,绝不强行以「撤单成功」收尾。
5.3 断电断网恢复流程
断电/断网 / 进程异常退出
│
▼
进程重启 → 拉取柜台/交易所当日全部委托、成交、持仓
│
▼
重建本地状态 → 本地状态与柜台比对 → 差异处理(补回报/人工)
│
▼
风控模块自检(规则加载、配置校验、闸门可用)
│
▼
恢复顺序:先只读(行情+查询)→ 确认无误 → 再恢复下单
▼
恢复期间禁止任何自动交易,恢复动作全程留痕恢复的铁律:「先恢复状态,再恢复交易」。重启后直接恢复自动交易,等于蒙着眼睛开车(参见 04 篇 bug 清单第 7 条)。
💀 重启后直接恢复自动交易等于蒙眼开车
先恢复状态,再恢复交易。 断电、断网、进程异常退出后重启,本地状态是旧的,若第一时间恢复自动交易,等于蒙着眼睛开车——先只读(行情+查询)确认状态与柜台一致,再恢复下单,恢复期间禁止任何自动交易。
6. 熔断机制设计
6.1 三级熔断
| 级别 | 作用域 | 触发条件(示例) | 动作 | 恢复 |
|---|---|---|---|---|
| 策略级 | 单个策略 | 该策略当日亏损超阈值 / 连续 N 笔失败 | 停该策略,主动平其持仓(可选) | 人工确认后重启策略 |
| 账户级 | 单账户 | 账户日亏损/总回撤超阈值 / 保证金接近强平线 | 停止该账户全部策略,只允许平仓单 | 人工复核 + 授权恢复 |
| 全局级 | 全部账户 | 系统异常(行情中断、对账差异、风控自身故障)/ 全公司日亏阈值 | 全部停止自动交易,所有在途单转人工 | 双人确认 + 复盘报告后恢复 |
6.2 触发条件与恢复流程的设计要点
- 触发条件必须可计算、无歧义:用「实时资金 + 实时持仓 + 实时行情」计算,不能依赖策略上报的数字。
- 熔断动作必须简单粗暴:熔断后系统只剩两种操作——查询和平仓;一切自动开仓、自动加仓全部禁用。
- 恢复必须人工:熔断只能由人恢复,且建议「双人授权」(一人恢复、一人复核)。
- 熔断本身要有降级保障:熔断指令的通道要独立于交易通道(如果交易通道都断了,熔断指令也发不出去,那就用柜台侧的手工干预)。
7. 审计与留痕
7.1 全链路日志
每一笔订单从产生到终结,都要留下完整链路,回答四个问题:
谁?→ 用户/策略/信号源(策略 ID、版本)
何时?→ 时间戳(UTC,毫秒级)+ 交易日
什么?→ 请求参数快照(品种、方向、数量、价格、订单类型、clientOrderId)
结果?→ 每一步的状态与回报原文(原始报文保留)7.2 日志结构建议
{
"event": "order_insert", // 事件类型
"trace_id": "1f9c…", // 全链路追踪 ID
"ts_utc_ms": 1723708800123, // 客户端时间
"trade_day": "20260817", // 交易日
"account": "acc-001",
"strategy": {"id": "s-07", "version": "v2.3.1"},
"order": {
"client_order_id": "…",
"exchange_order_id": "…",
"symbol": "rb2610", "side": "BUY", "qty": 5,
"price": 3500.0, "type": "LIMIT"
},
"gate": "资金闸门", // 风控路径记录
"result": "ALLOW", "reason": null,
"raw_response": "<柜台原始回报原文>"
}7.3 保留时长与访问控制
- 建议保留时长:行情与成交明细 ≥ 3 年(配合监管要求与复盘需要);风控决策记录与参数变更 ≥ 3 年且不可篡改(只追加、禁止 UPDATE/DELETE)。
- 访问控制:日志库权限独立,风控与审计日志只有风控/合规可见,交易开发默认不可读。
8. 风控系统架构建议
8.1 独立进程、独立于策略代码
- 风控服务独立部署,与策略进程、交易进程解耦:策略崩溃不影响风控,风控崩溃触发 fail-closed 拦截。
- 风控代码与策略代码分仓库管理,风控变更走独立的审批与发布流程。
8.2 配置化
- 所有限额、阈值、名单、熔断参数配置化(数据库/配置中心),支持在线修改、立即生效、变更留痕。
- 每次参数变更记录「谁、何时、旧值、新值、原因」——风控参数的每一次变动都可能是事故的起因,也必须是复盘的对象。
8.3 冷备与冗余
- 风控服务至少双实例,主备切换不能造成「无风控窗口」。
- 备机平时也拉取账户状态与行情,保证切换后立即拥有完整状态,而不是从零开始预热。
- 定期演练:熔断演练、fail-closed 演练、冷备切换演练,演练纳入上线前置条件(见 01 里程碑)。
8.4 风控与对账联动
- 风控的「拦截记录」与「对账差异」(见 04 篇第 7 节)联动:对账差异未清零时,风控对该账户/该品种维持只平仓状态。
风险提示
⚠️ 风险提示
风控层的失败方式通常不是「没做风控」,而是「风控做得像摆设」:阈值设得比策略正常亏损还宽松(等于没拦)、风控参数被谁改了没人知道、熔断触发后策略还能继续下单、风控日志没留痕出事无法复盘。请把风控当作系统里唯一不允许「差不多」的模块:参数越改越严是常态、恢复必须人工、留痕必须只增不改。真实事故里最贵的不是亏掉的钱,而是事后查不出「哪个参数、哪个时刻、谁改的、为什么没拦」——审计留痕就是用来回答这些问题的。