模块 2 · 模拟交易链路

一笔演示交易
怎么长出预警单?

RiskSimulatePage 提交表单 → 模拟交易入口(simulate.py)验权 → 模拟写 Core 网关(trade_gateway.py)写库 → 规则引擎(risk_engine.py)扫规则 → 聚合进 risk_alert。 像演示用的「假收银台」:钱是假的,但风控流程是真的。

四段链路(动画)

🧪模拟交易 UI
🚪模拟交易入口
⚙模拟写 Core 网关
🛡规则引擎

Preset A-3:CUST-3001 · 50 万 → 大额预警 · Preset A-1:适当性阻断

R-02 阻断 vs R-01 大额待审(同网关、不同结果)

模拟写 Core 网关(trade_gateway.py)里先跑适当性:不过 → 交易写不进去(R-02);过了 → 写入 core_trade → 规则引擎再扫 R-01 大额等 → 出 pending_review 预警。

A-1 · R-02 阻断

CUST-1001 + PROD-161725 · 风评与产品 R 档不匹配 → 网关拒绝 · 可有 suitability 类预警 · 无成交

A-3 · R-01 大额待审

CUST-3001 · 50 万申购 → 成交写入 Core → 引擎出大额类 pending_review · 台账可见

指挥 AI 时: 别把「阻断交易」和「出预警待审」混成一个状态——前者在网关,后者在引擎聚合。

代码地图

模拟交易入口(app/api/simulate.py)
薄路由:鉴权 + 调 submit_trade
模拟写 Core 网关(app/gateway/trade_gateway.py)
适当性 → 写 core_trade → 调 risk 引擎
app/service/risk/
规则引擎(risk_engine.py) · alert_service.py · 规则聚合
web/src/pages/risk/RiskSimulatePage.tsx
预设 A-1 / A-3 一键填表
CODE · 模拟交易入口(simulate.py)
if not (auth.has_role("risk_demo")
        or (auth.is_customer() and
            auth.customer_id == req.customer_id)):
    deny(auth, "AUTH_403_ROLE", ...)
return submit_trade(req.model_dump(), ...)
白话

能点「提交模拟交易」的只有两类人:带 risk_demo 的风控演示号,或客户本人买自己的单。

STAFF-30001 在 jwt_service 里配了 risk_demo,所以能造 A-3 大额演示数据。

Demo 里谁可以把新成交写进 core_trade?