風控與訂單生命週期

本章幫您弄清兩件事:訂單爲什麼有時「沒出去」;出去之後爲什麼有時一直「部分成交」。重點區分風控拒單櫃檯拒單——這是 live 排錯最常見的坑。

親愛的用戶,模擬實盤裏「沒成交」並不總意味着策略沒信號。可能是本地風控攔下了,也可能是模擬券商不收單。我們把兩條路徑分開講,您就不會誤把風控拒單當成「券商壞了」。

0. 适用场景

  • 您已能運行 live,但需要判斷「未成交 / 拒單 / 撤單」到底發生了什麼

  • 您想把界面提示、日誌與訂單狀態串成同一條可解釋鏈路

1. 核心概念:两条「拒单」路径

很多用戶第一次遇到拒單,會以爲「都是券商拒的」。在 qteasy 裏,請先分清:

                    ┌─ 风控拒单:复核台打回,委托单未入库、未递柜台
策略信号 → 订单意图 ─┤
                    └─ 柜台受理拒单:已入库,券商同步回复「不收」,status=rejected
                              ↓(若受理成功)
                         异步成交回报 → partial-filled → filled

在 live 子系統中,訂單從策略信號到最終成交須經過 RiskManager(可選)→ 本地建單 → Broker 受理 → 成交回報 幾站。下表歸納三種結局——排錯時請先對號入座「類型」列,再按「優先查哪裏」打開對應日誌。

各列含義類型爲路徑名稱;您會看到什麼爲界面/返回值特徵;訂單表有記錄嗎指本地 sys_op_trade_orders 是否新增行;優先查哪裏爲建議的第一份證據。

如何使用:CLI 出現英文 Order rejected by risk rule → 選「風控拒單」行 → 查 risk_log;訂單列表裏有 rejected 且無 broker 號 → 選「櫃檯受理拒單」行。

類型

您會看到什麼

訂單表有記錄嗎

優先查哪裏

風控拒單

CLI 英文拒因;提交結果爲空 {}

沒有新行

risk_log<RISK REJECTED>

櫃檯受理拒單

有訂單行,status=rejected,broker 號爲空

訂單表、trace

受理成功

submitted 等,隨後可能有成交

有,且通常有 broker_order_id

訂單表、trade_log

完整對照表見 :doc:6-trader-snapshot-gate

RiskManager(風控管理器) 像下單前的複覈臺:按您組裝的規則鏈(白名單、單筆上限、交易時段等)依次檢查 OrderIntent(訂單意圖)AccountSnapshot(賬戶快照);任一規則不通過則產出 RiskDecision(風控決策)——拒絕,並帶英文 reasonrule_id

若放行,qteasy 才繼續建單、校驗,並交給 Broker(券商)submit_with_ack 聽櫃檯是否受理。

2. 风控如何工作(用户视角)

在 live 下單前,若您爲 Trader 配置了 RiskManager

  1. qteasy 根據當前賬本組裝賬戶快照

  2. 把「這一筆打算下的單」交給規則鏈評估

  3. 拒絕:不寫訂單表、不進券商隊列;英文拒因寫入系統日誌與 risk_log

  4. 放行:與未配風控時一樣,繼續提交

若您沒有傳入 RiskManager,則跳過本地規則鏈,直接進入建單與提交——行爲與舊版更接近。

2.1 規則示例(便於理解閾值)

RiskManager 在 Trader 提交訂單之前評估規則鏈——像複覈臺按 checklist 逐項打勾。下表列舉常見規則類型及用戶可見結果,幫助您理解 rule_id 與拒因;不是內置規則全量列表(規則由您在 Python 中組裝)。

各列含義場景爲業務情境;您設定的規則爲規則語義;會發生什麼爲 live 中的表現。

如何使用:對照 risk_log 或 CLI 英文拒因中的 rule_id(如 MAX_ORDER_QTY)反查類似場景,再調整閾值或白名單。

示例:拒因含 MAX_ORDER_QTY → 對應「單筆數量」行 → 減小委託數量或提高規則上限。

場景

您設定的規則

會發生什麼

白名單

只允許 000001.SZ

000300.SZ 下單 → 拒絕,日誌說明不在名單

單筆數量

最多 500 股

要買 501 股 → 拒絕;500 股且其他通過 → 放行

交易時段

僅 9:30–11:30、13:00–15:00

午休下單 → 拒絕

日成交額

當日累計 + 本筆超上限

拒絕;未超 → 放行

組裝方式:在創建 Trader 前用 Python 構造 RiskManager([規則1, 規則2, ...]) 並傳入;不傳則關閉本地規則鏈。詳見 :doc:2-configuration-and-run 與教程。

2.2 用戶可見英文拒因示例

CLI/TUI 會顯示類似:

Order rejected by risk rule [MAX_ORDER_QTY]: order quantity exceeds limit

含義:風控規則 MAX_ORDER_QTY 認爲數量超限。請到 risk_log<RISK REJECTED> 覈對細節。

3. 订单状态生命周期

受理成功後,訂單在 live 中會經歷典型狀態(您可在 CLI orders 或日誌裏看到):

submitted → partial-filled → filled

也可能:

submitted → canceled

受理成功後,訂單在 live 中會經歷若干狀態(CLI orders 或日誌可見)。這些狀態描述「委託在券商側進行到哪一步」,與風控拒單(根本沒有 submitted)不同。下表覆蓋最常見狀態;完整枚舉以運行中實際輸出爲準。

各列含義狀態爲英文狀態名;含義爲投資語義;您該關注什麼爲排查或確認時的檢查點。

如何使用:長期停在某一狀態 → 查該行「您該關注什麼」→ 必要時到 :doc:5-artifacts-and-troubleshooting 劇本 D/E。

狀態

含義

您該關注什麼

submitted

櫃檯已收單,尚未全部成交

是否有 broker_order_id

partial-filled

部分成交,累計量 < 委託量

累計成交量是否在增加

filled

累計成交量達到委託量

持倉與現金是否已更新

canceled

已撤單

收盤或手動撤單後的終態

rejected

櫃檯受理階段拒絕

broker 號通常爲空;不是風控拒單

排查思路

  • 「根本沒有 submitted」→ 先查風控與提交前校驗(§1 表)

  • 「一直是 partial-filled」→ 查成交回報是否在持續到達(§4)

4. 分批成交与全部成交

當一筆大單分多筆成交時,狀態會先停在 partial-filled,像「委託只成交了一部分」。 當累計成交量達到委託數量時,qteasy 會將狀態更新爲 filled。若您看到長期 partial-filled,請對照成交回報與目標數量——有時只是行情或模擬撮合尚未湊滿整單。

5. 收盘后未成交订单

收盤後,qteasy 會通過 post_close 任務統一收尾當日未決訂單:

  • submitted / partial-filled:視爲曾進入櫃檯,收盤撤餘量,終態爲 canceled(可能有撤單成交記錄)。

  • created:視爲未成功報單的本地草稿(如報單鏈路中斷或歷史遺留),收盤置爲 rejected與盤中櫃檯拒單混淆,也寫入撤單型成交結果。

對您而言:收盤後請關注 post_close 相關日誌與 reconcile 對賬輸出,確認在途單是否已按規則收尾,而不必記憶內部 API 名稱。

6. 遇到异常时建议顺序

  1. CLI/TUI 即時英文提示(先記下 rule_id 或訂單號)

  2. risk_log:是否有 <RISK REJECTED>(風控路徑)

  3. 訂單與成交記錄:狀態序列、broker_order_id 是否回寫

更系統的決策樹見 :doc:5-artifacts-and-troubleshooting §3。

7. 快速判定清单

  • 這筆單是否進入提交鏈路(訂單表或日誌裏能否找到)

  • 若未提交:能否在 risk_log 或界面找到 rule_id / reason

  • 若已提交:是否有對應成交回報、狀態是否與累計量一致

  • 拒單類型是否分清:風控(無訂單行)vs 櫃檯(rejected 行)

8. 相关跳转

  • 配置啓動::doc:2-configuration-and-run

  • 排錯手冊::doc:5-artifacts-and-troubleshooting

  • 拒單與門禁細節::doc:6-trader-snapshot-gate

  • CLI 命令::doc:8-cli-trader-capability-matrix

  • 雙路徑教程:tutorials/8-live-trade-risk-and-broker-walkthrough.md