fix(risk): trigger cooldown only on user-initiated closes

Remove external-close risk hooks; register user_instance, user_hub, and user_trend_stop via hub API and trend stop; update docs and tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-17 19:14:05 +08:00
parent 850ffcd7d2
commit b6acbf4b2c
14 changed files with 423 additions and 131 deletions
+37 -19
View File
@@ -1,10 +1,11 @@
# 账户冷静期 / 日冻结风控
四所实例(币安 / OKX / Gate / Gate 趋势)共用 `account_risk_lib.py`,在手动平仓、外部平仓与交易复盘保存时更新 `account_risk_state` 表,并在开仓前 `precheck_risk` 拦截
四所实例(币安 / OKX / Gate / Gate 趋势)共用 `account_risk_lib.py`
**仅用户主动平仓**计入风控;交易所止盈/止损、空仓同步、改保本/改委托等**不触发**冷静期。
## 状态展示
实例页顶「交易所」标签旁、中控监控卡片账户名后显示
实例页顶、中控监控卡片账户名
| 状态 | 含义 |
|------|------|
@@ -13,42 +14,59 @@
| 4h冻结 | 冷静期中(默认 4 小时) |
| 日冻结 | 当日禁止一切新开仓 |
## 什么算「手动平仓」(计入风控)
以下操作通过 `close_source` 登记为 **用户主动平仓**
| 来源标识 | 操作 |
|----------|------|
| `user_instance` | 实例页删单/手动平仓(`del_order` |
| `user_hub` | 中控「平仓」「全平」「紧急全平」 |
| `user_trend_stop` | 趋势计划 **「结束计划」**(手动结束) |
**不算**手动平仓(不触发风控):
- 趋势 **「保本移交下单监控」**
- 中控/实例修改委托、挂止盈止损、移动保本
- 交易所止盈/止损/条件单成交
- 后台 `reconcile_external_closes` 空仓同步(即使记账为「外部平仓」)
- 监控轮询自动止盈/止损/保本
## 触发规则
| 事件 | 行为 |
|------|------|
| 页面手动平仓 | 默认 **4h** 冷静期;累计手动平仓次数 +1 |
| 当日第 2 次手动平仓 | **日冻结**(默认上限 2 次,可配置) |
| 复盘:离场触发=手动平仓 且补充说明非空 | 将当前冷静期降为 **1h**(自上次平仓时刻起算) |
| 复盘:情绪标签任一项勾选 | **日冻结** |
| 外部平仓(`result=外部平仓` | **4h** 冷静期(正常止盈/止损不触发) |
| 第 1 次用户主动平仓 | 默认 **4h** 冷静期 |
| 第 2 次用户主动平仓(同一交易日) | **日冻结** |
| 复盘勾选任意情绪标签 | **日冻结** |
| 复盘:离场=手动平仓 且说明非空 | 将当前冷静期降为 **1h**(须存在 pending 关联交易记录) |
情绪标签`mood_issues`:怕踏空、报复开仓、盈利飘了、拿不住单、扛单、重仓违规。
情绪标签:怕踏空、报复开仓、盈利飘了、拿不住单、扛单、重仓违规。
## 环境变量
在各实例目录 `.env` 中配置(模板见各所 `.env.example`):
```env
RISK_CONTROL_ENABLED=true
RISK_COOLING_HOURS_MANUAL=4
RISK_COOLING_HOURS_EXTERNAL=4
RISK_COOLING_HOURS_MANUAL_JOURNAL=1
RISK_MANUAL_CLOSE_DAILY_LIMIT=2
RISK_MOOD_ISSUES_DAILY_FREEZE=true
```
- `RISK_CONTROL_ENABLED=false` 时关闭整套逻辑,状态始终为「正常」
- 交易日切换(`TRADING_DAY_RESET_HOUR`)会清零当日手动平仓计数与日冻结标记;未过期的冷静期按 `cooloff_until_ms` 自然到期。
`RISK_COOLING_HOURS_EXTERNAL` 已废弃(外部平仓不再触发风控)
## API
- 实例:`GET /api/account_snapshot` 返回 `risk_status``GET /api/account_risk_status`hub_bridge)供中控拉取。
- 中控:`hub_monitor` 载荷含 `risk_status`,卡片标题旁展示 `status_label`
| 接口 | 说明 |
|------|------|
| `GET /api/account_snapshot` | 返回 `risk_status` |
| `GET /api/account_risk_status` | hub_bridge,供中控拉取 |
| `POST /api/hub/account-risk/user-close` | 中控登记用户平仓,`body: { source, count }` |
## 相关代码
- `account_risk_lib.py`核心状态机
- 各所 `app.py``on_manual_close` / `on_external_close` / `on_journal_saved` 钩子
- `hub_bridge.py` — 中控聚合 `risk_status`
- `tests/test_account_risk_lib.py` — 单元测试
- `account_risk_lib.py` — 状态机`on_user_initiated_close`
- `hub_bridge.py``/api/hub/account-risk/user-close`
- `manual_trading_hub/hub.py` — 中控平仓成功后调用 user-close
- `strategy_trend_register.py``stop_trend_pullback` 结束计划时登记风控
- `tests/test_account_risk_lib.py`