# Risk Config Lint

> 逐项审查交易系统的风控配置(risk_config.json/yaml)与 pre-trade 风控代码,定位"会让风控形同虚设、实盘爆仓"的工程缺陷,精确到 文件:行,按严重度输出"风控体检报告"。覆盖限额/回撤/杠杆/kill-switch/防胖手指/保证金/爆仓模拟/并发在途订单/单点故障/运维/密钥。触发词(中):风控审查、风控体检、风控配置、仓位上限、敞口上限、回撤止损、最大回撤、kill-switch、爆仓保护、强平、维持保证金、防胖手指、限额、在途订单。触发词(英):risk config、risk limit、risk audit、kill switch、kill-switch、fat finger、fat-finger、liquidation、margin、drawdown stop、position limit、in-flight order、risk-config-lint。不适用:策略 alpha/信号逻辑/调参寻优、行情数据源运维、回测可信度审查(用 backtest-guard)、连接器可靠性(用 connector-forge)、非风控的通用代码审查;也绝不承诺"绝对不爆仓/绝对安全"——本 skill 只做工程审查,不替代实盘风控演练。

- Skill: `paidaxing1234/risk-config-lint` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add paidaxing1234/risk-config-lint`
- Raw SKILL.md: https://api.skillmd.com/api/skills/paidaxing1234/risk-config-lint/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: MIT
- Author: paidaxing1234 (https://skillmd.com/u/paidaxing1234)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/paidaxing1234/risk-config-lint

---


# risk-config-lint / 风控体检

## 核心理念

风控是整条交易链路的**最后一道闸**:它平时不赚一分钱,存在感为零;可一旦漏了,就是本金归零、穿仓欠债。所以判断风控好坏,不看它"有没有",而看它"在最坏的那一刻有没有真正生效"。

本 skill 盯的是一类特别阴险的缺陷:**看着有风控、实际没生效**。配置里写满了 `max_position`、`daily_loss_limit`、`kill_switch`,下单路径却根本没调用它们;止损算法分母用错,账户从峰值深跌却永不触发;限额加载失败时 `except: pass` 继续裸奔下单;或者风控只看"已成交持仓",多笔并发在途订单合计早已超限——这些都比"压根没风控"更危险,因为它们给了你**虚假的安全感**。

审查时坚持三条判据:

1. **是不是 pre-trade 阻断,而非 post-trade 告警** —— 风控必须在订单离开本机前同步拦截,事后发现等于"先开枪再瞄准"。
2. **失败时是 fail-closed 还是 fail-open** —— 风控自身出错(配置加载失败、依赖超时、检查抛异常、状态过期未对账)时,必须拒单/停机,绝不能"出错就放行"。
3. **触发后是程序闭环,还是靠人** —— 救命动作(平仓/撤单/停机)必须程序自动执行,不能押注"人正好在线且反应够快"。

再加一条贯穿全程的追问:**它喂进去的状态、它放过去的并发,是真的吗?** 限额只有在"持仓/资金状态真实"且"并发订单合并计敞口"时才真生效。

## 何时启用

- 用户把 `risk_config.json` / `risk_limits.yaml` 之类风控配置,或 pre-trade 风控、下单校验代码丢过来,让你审"靠不靠谱/会不会爆仓"。
- 用户问:"我的风控有没有漏洞""为什么实盘亏穿了风控没拦住""帮我看看 kill-switch / 止损 / 杠杆上限对不对""限额是不是真生效了""并发下单会不会超限"。
- 实盘上线前的风控体检、风控代码 code review、风控配置变更评审。

**不适用**:策略 alpha/信号/调参(那是策略层),回测可信度(用 `backtest-guard`),连接器断线重连(用 `connector-forge`),热路径微秒优化(用 `latency-audit`)。本 skill 也**绝不承诺"绝对不爆仓/绝对安全"**——只做工程缺陷审查。

## 审查协议

按以下步骤系统过一遍,不要跳:

1. **定位风控边界**:找到风控配置文件,以及下单路径(`place_order` / `submit_order` / `new_order` / `send`)的**唯一收口处**。确认风控检查在 `submit` **之前**(pre-trade)还是在 `on_fill`/对账回调里(post-trade)。
2. **逐类过一遍**:限额(单笔/总敞口/单品种/集中度)→ 并发与在途订单(检查-下单是否原子、在途单是否计入敞口)→ 回撤止损(日内/最大回撤/口径/自动平仓)→ 杠杆(全局/单品种上限)→ kill-switch(存在/自动触发/复位/救命通道隔离)→ 防胖手指(价格/数量边界、限频、挂单数)→ 保证金/爆仓(维持保证金/强平模拟/负现金)→ 状态可信(持仓/资金是否对账、是否有陈旧度阈值)→ 单点(告警渠道/心跳/环境隔离/密钥)。
3. **精确定位**:每条缺陷都要给出 `文件:行` 与触发它的具体场景,不要泛泛而谈。配置缺失项就指出"该有却没有"的字段。找不到证据的项标"未发现/需人工确认",不臆测。
4. **区分 fail-open vs fail-closed**:对每条风控,追问"如果它自己挂了会怎样"。`except: pass`、空默认 dict、`limits or {}`、加载失败继续下单、状态对账失败仍放行——都是致命的 fail-open。
5. **区分硬限制 vs 软限制**:资金/敞口类必须是硬拦截(超限即拒单),只 `log.warning` 不 `raise/return reject` 的等于没拦。
6. **区分"已生效"与"仅配置存在"**:配置里有字段不等于风控生效,必须从 `place_order` 反向追踪到一个会 `raise/return reject` 的 gate,确认它被真正调用、并且喂给它的敞口口径包含在途订单。

> 本 skill 力求**自包含**:下文已内联两大类陷阱中每一条的检测要点。`references/risk-pitfalls.md`(若仓库提供)是**可选延伸**,含更细的代码反例与正则提示;该文件缺失时,仅凭本 SKILL.md 即可独立完成一次完整审查。

## 两大类陷阱

### 第一类:限额 / 并发在途 / 回撤 / 杠杆 / kill-switch / 防胖手指

下单链路本身的硬约束。逐条检测要点:

- **风控只在 post-trade 拦截,缺 pre-trade gate**(致命):超限敞口已真实建立才发现,极端行情根本平不出来。所有硬限额必须在订单离开本机前同步阻断。检测:`on_fill`/对账回调里才出现限额比较,而 `submit` 前没有。
- **缺失单笔下单上限 / 总敞口上限 / 无界杠杆**(致命):一个 bug、一个 NaN、一次错误信号缩放就能打出远超净值的巨单;多策略叠加把局部风险放大成系统性爆仓。检测:配置缺 `max_order_notional` / `max_gross_exposure`,或下单直接照 `signal_qty` 走、对 NaN/inf/负数无拦截。
- **敞口口径漏算在途订单(并发竞态)**(致命):"检查-下单"非原子。风控只看**已成交持仓**判断是否超限,而多笔尚未成交的在途订单(pending / open orders)不计入敞口——每笔单独过 gate 都合规,合计却远超限额。高并发或快速连发时,这是和"缺失单笔上限"同级的爆仓路径。检测:gate 里的敞口仅来自 position/balance,不含 open-order notional;检查与提交之间无锁、无预扣额度。修复:敞口 = 已成交持仓 + 所有在途未成交订单的预留名义(reserved notional);检查与下单要么持锁原子化、要么用 reserve-then-commit(下单前预扣额度、成交/撤单/超时后释放)。修复后必须在 testnet 用并发打单复测。
- **缺失日内/最大回撤止损 + 口径错误**(致命/高危):没有账户级回撤熔断=无底洞;分母用初始资金而非历史峰值、equity 不含浮亏、重启把 peak 重置,都会让"有止损却永不触发"。检测:回撤分母是 `initial_capital` 而非 running peak;equity 只算 realized;`peak` 是进程内变量、无持久化。
- **无自动平仓 / 触发后只告警**(致命):救命操作押在"人正好醒着"上,半夜插针无人响应。检测:回撤/kill 触发后只 `log`/`alert`,无 `cancel_all`/`flatten`/进只减仓态的程序动作。
- **缺失全局 kill-switch / 只能手动 / 复位不受控**(致命/高危):系统性异常时没有毫秒级一键停机;或冷却到点自动复位,根因没排查反复触发震荡熔断。检测:无全局开关,或 reset 由定时器自动触发而非人工受控放行。
- **救命动作通道未与业务下单隔离**(高危):kill-switch 要平仓撤单,但紧急平仓/撤单单若走同一条被打爆的限频令牌桶或同一拥塞链路,救命单发不出去,风控空转。检测:`cancel_all`/`flatten` 与普通下单共用同一限频桶、无紧急配额。修复:紧急动作走独立配额或绕过普通限频。
- **防胖手指缺失**:无价格 sanity(离参考价偏离上限)、无数量 sanity(NaN/inf/负数/未对齐 stepSize)、无限频令牌桶、无最大挂单数——一次胖手指或一场下单洪水就能毁账户。检测:下单前无 price-band/qty-band 校验,无 token bucket,无 `max_open_orders`。

> **限频严重度口径**:限频(rate limit)缺失默认 **HIGH**;但当限频不当导致**救命动作(撤单/平仓)也发不出去**时,升级为 **FATAL**。

完整 14 条(含单品种上限、集中度、per-symbol 杠杆等)的更细代码反例,见可选的 `references/risk-pitfalls.md` 的 `limits` 段。

### 第二类:保证金 / 爆仓 / 状态可信 / 单点故障 / 运维 / 密钥

风控的"生存性"与运维面。逐条检测要点:

- **风控限额未在下单前真正强制执行**(致命):配置里有完整限额,下单链路却不调用——限额只用于事后报表/告警,风控形同虚设。从 `place_order` 反向追踪,确认必经一个会 `raise/return reject` 的 gate。
- **限额加载失败时 fail-open**(致命):配置/配置中心不可达就"暂时不限额继续跑"。恰在系统异常时风控自动关闭。必须 fail-closed——加载不出限额就不许下单。检测:`except Exception: limits = {}`、`limits or {}`、加载失败仅 `log` 后继续。
- **风控异常被吞掉静默失效**(致命):风控检查 `try/except: pass` 后照常下单,遇到 edge case 就静默关闭,比没风控更危险。
- **风控所依赖的持仓/资金状态未对账**(高危):pre-trade gate 判敞口,但它喂进去的 position/equity 若取自本地缓存且与交易所长期不对账(reconcile),缓存漂移会让 gate 基于**错误持仓**放行。限额"真生效"的前提是输入状态是真的。检测:gate 用的持仓/资金无定期 reconcile、无陈旧度(staleness)阈值;状态过期或对账失败仍放行。修复:定期对账 + staleness 阈值,状态过期或对账失败按 fail-closed 拒单。
- **无维持保证金检查 / 无爆仓模拟 / 允许负现金**(致命):不算维持保证金率与强平价,就无法回答"此刻离爆仓还有多远";下单不前置扣减冻结资金,并发下单击穿到负现金。检测:用杠杆/合约却无 `maintenance_margin`/`liquidation_price` 计算,下单前不冻结/扣减可用资金。
- **testnet/live 标志混淆 / 环境未隔离**(致命/高危):测试策略连实盘打真钱,或实盘风控连测试网裸奔;测试流量污染实盘风控状态。检测:`testnet`/`live` 由同一可变标志切换、无强隔离,风控状态库 test 与 live 混用。
- **无心跳/deadman switch + 告警单点**(致命/高危):进程静默死亡持仓裸奔无人知;告警只走单一渠道,渠道挂了风控等于失明。检测:无风控线程心跳/watchdog;`alert` 仅单一 telegram/邮件通道。
- **密钥写进风控配置/仓库**(致命):明文 API key/secret 进 git 或镜像=直接资金失窃路径。检测:配置文件/仓库内出现 `api_key`/`secret` 明文值而非 env 注入。
- **配置无 schema 校验 / 限额硬编码不可热加载 / 多策略限额未隔离**(高危):字段缺失/类型错误启动不报错;改限额要重启;多策略共用一份限额互相挤占。

完整 16 条的更细代码反例,见可选的 `references/risk-pitfalls.md` 的 `ops` 段。

## 风控体检报告(输出模板)

审查结束后,用下面这张可截图的表格汇报。先给总览结论,再逐条展开。

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
          风控体检报告 / Risk Config Lint
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
审查对象 : risk_config.json + order_gate.py
体检结论 : ❌ 不可上线(4 致命 / 2 高危)
一句话   : 限额配置齐全但下单路径未调用,pre-trade gate 缺失且并发在途单不计敞口,风控形同虚设
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[FATAL-1] 风控只在 post-trade 拦截,缺 pre-trade gate
  位置   : order_gate.py:42  submit_order()
  现状   : submit() 前无任何风控校验,超限在 on_fill 才告警
  影响   : 超额敞口已成交,极端行情平不出 → 爆仓
  修复   : 所有订单提交前同步过统一 risk gate,任一不过即 raise RejectOrder

[FATAL-2] 缺失单笔下单上限 (max order notional)
  位置   : order_gate.py:18 / risk_config.json 缺 max_order_notional 字段
  现状   : 直接照 signal_qty 下单,NaN/巨大值无拦截
  修复   : 按 notional 校验 + 拒绝 NaN/负数/inf,上限随净值缩放

[FATAL-3] 敞口口径漏算在途订单(并发竞态)
  位置   : order_gate.py:30  check_exposure() 仅读 position
  现状   : 检查与下单非原子,在途未成交订单不计入敞口;连发 N 笔各自合规、合计超限
  影响   : 快速连发/并发时实际敞口数倍于限额 → 超限建仓 → 爆仓
  修复   : 敞口=持仓+在途预留名义;检查-下单持锁原子化或 reserve-then-commit,testnet 并发复测

[FATAL-4] 限额加载失败 fail-open
  位置   : config_loader.py:55  except Exception: limits = {}
  现状   : 配置加载失败时用空 dict 继续,等于无限额
  修复   : fail-closed,加载失败拒绝启动 / 保留上一份已知良好限额

[HIGH-1] 缺失日内回撤止损
  位置   : 下单循环 strategy.py:80,无账户级回撤检查
  修复   : 账户级 DAILY_LOSS_LIMIT + MAX_DRAWDOWN(分母用历史峰值、含浮亏),触发进只减仓态

[HIGH-2] 告警单点 + 无 deadman switch
  位置   : alert.py:12 仅单一 telegram bot
  修复   : 多渠道冗余 + 风控线程心跳 + 独立 watchdog

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
通过项   : ✅ 杠杆本地上限校验  ✅ 价格 fat-finger 边界
上线判定 : 致命项全部修复 + 复测前,禁止接实盘资金
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

要点:每条至少含 **位置(文件:行)/ 现状 / 影响 / 修复**;总览给出致命与高危计数;明确"能不能上线"的硬结论。找不到证据的项标"未发现/需人工确认",不硬凑。

## 严重度定义

| 级别 | 含义 | 处置 |
|------|------|------|
| **FATAL 致命** | 会直接导致本金归零、穿仓欠债或风控整体失效(pre-trade 缺失、在途订单不计敞口、fail-open、无止损、无界杠杆、密钥泄露)。 | **上线前必修**,不修则禁止接实盘资金 |
| **HIGH 高危** | 显著放大爆仓概率或在常见故障下失效(集中度、单品种上限、限频缺失、救命通道未隔离、状态未对账、告警单点、无热加载)。 | 强烈建议上线前修复 |
| **MEDIUM 中** | 维护性/受控性缺陷,极端场景才出问题(复位流程、schema 校验细节)。 | 排期修复 |
| **LOW 低** | 风格、冗余、可观测性增强建议。 | 可选 |

> **限频严重度补充**:限频(rate limit)缺失默认归 **HIGH**;若该缺失导致救命动作(撤单/平仓)也被限掉发不出去,则升级为 **FATAL**。

## 重要说明

- 本 skill 是**工程审查**:只检查"风控代码与配置在工程上有没有漏洞",**不替代实盘风控演练、压力测试与小资金灰度**。审过 ≠ 安全。
- **绝不承诺"绝对不爆仓 / 绝对安全"**。市场风险、交易所风险、黑天鹅无法靠代码消除;本 skill 只帮你堵住"本可避免的工程漏洞"。
- **所有 FATAL 项,上线前必须修复**;HIGH 项强烈建议修复后再接实盘资金。修复后务必在 testnet/小资金上复测风控触发路径(故意打超限单、**故意并发连发验证在途订单计敞口**、故意触发回撤、故意拔网线验证 deadman、故意打爆限频验证救命单仍能发出),确认每条闸都真的合上了,而不只是"配置里写了"。
- 报告里区分**已生效**与**仅配置存在**:配置里有字段不等于风控生效,必须追踪到下单路径确认它被真正调用、能阻断,且喂给它的敞口口径包含在途订单、状态来源已对账。
