Risk control and order lifecycle

This chapter helps you understand two things: why orders sometimes “don’t go through”; and why, even after going through, sometimes they remain “partially completed.” The key difference is between risk control order rejection and counter order rejection—these are the most common pitfalls in Live troubleshooting.

Dear user, “no trade” in simulated trading doesn’t always mean the strategy isn’t sending a signal. It could be that local risk control blocked it, or it could be that the simulated brokerage isn’t accepting the order. We’ll explain these two paths separately so you won’t mistakenly think that risk control rejection means “the brokerage is malfunctioning.”

0. 适用场景

  • You can now run live, but you need to determine exactly what happened in the “unsold/rejected/cancelled” cases.

  • You want to link interface prompts, logs, and order status into a same explainable chain.

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

Many users, when encountering order rejections for the first time, assume “they’re all rejected by brokerage firms.” In qteasy, please first clarify:

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

In the live subsystem, an order goes through several stages from strategy signal to final execution: RiskManager (optional) → Local order creation → Broker processing → Execution report. The table below summarizes three possible outcomes—when troubleshooting, first match the category to the “Type” column, then click “First check which part” to open the corresponding log.

Column Meanings: Type is the path name; What You Will See is the interface/return value characteristic; Is There a Record in the Orders Table? indicates whether a new row has been added to the local sys_op_trade_orders; Where to Check First is the first piece of evidence for the suggestion.

How to use: When the CLI displays “Order rejected by risk rule”, select the “Risk Rejection” line and check the “risk_log”. If the order list contains “rejected” and no broker number, select the “Counter Rejection” line.

Type

What will you see?

Is there a record in the order form?

Where to search first

Order rejection due to risk control

CLI rejection reason (English); Submission result is empty {}

No new lines

risk_log<RISK REJECTED>

Counter service for rejected orders

There is an order line with status=rejected and the broker number is empty.

have

Order form, trace

Application Successful

submitted etc., may be followed by a transaction.

Yes, and it usually has a broker_order_id.

Order table, trade_log

For the complete comparison table, see:doc:6-trader-snapshot-gate.

The RiskManager acts like a review panel before placing an order: it checks the OrderIntent and AccountSnapshot sequentially according to the rule chain you assembled (whitelist, single transaction limit, transaction period, etc.); if any rule fails, it generates a RiskDecision—a rejection, accompanied by the English reason and rule_id.

If approved, qteasy will then proceed with creating and verifying the order, and submit it to the Broker’s submit_with_ack function to see if the counter will accept it.

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

Before placing an order during live trading, if you have configured RiskManager for Trader:

  1. Qteasy assembles account snapshots based on the current ledger

  2. Submit the “order to be placed” to the rule chain for evaluation.

  3. Rejection: Orders are not written to the order table, and the order is not entered into the brokerage queue; English rejections are due to being written to the system log and risk_log.

  4. Approval: Continue submitting as before, without risk control.

If you do not pass in RiskManager, the local rule chain will be skipped, and the process of creating and submitting the order will proceed directly—the behavior is closer to the old version.

2.1 Rule Example (for easier understanding of thresholds)

RiskManager evaluates the rule chain before a Trader submits an order—like checking off items on a checklist at a review desk. The table below lists common rule types and user-visible results to help you understand rule_id and rejection reasons; not a complete list of built-in rules (rules are assembled by you in Python).

The meaning of each column: Scenario refers to the business context; The rules you set refer to the rule semantics; What will happen refers to the performance in the live session.

How to use: Compare the risk_log or the rule_id (e.g., MAX_ORDER_QTY) in the CLI’s English rejection reason to find similar scenarios, and then adjust the threshold or whitelist.

Example: Rejection due to MAX_ORDER_QTY → corresponding “Single Transaction Quantity” row → reduce the number of delegates or increase the rule limit.

Scene

The rules you set

what happens

White list

Only 000001.SZ is allowed.

Order placed for 000300.SZRejected, log indicates it’s not on the list.

Number of transactions per transaction

Maximum 500 shares

Request to buy 501 shares → Rejected; 500 shares and other requests approved → Proceeded

Trading Hours

Only from 9:30–11:30 and 13:00–15:00

Orders placed during lunch break → Rejected

Daily transaction volume

Daily cumulative total + This transaction exceeding the limit

Rejected; Not exceeded → Released

Assembly method: Before creating the Trader, construct RiskManager([Rule 1, Rule 2, ...]) in Python and pass it in; otherwise, close the local rule chain. See :doc:2-configuration-and-run and tutorial for details.

2.2 User-visible English rejection reason example

CLI/TUI will display something like:

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

Meaning: Risk control rule MAX_ORDER_QTY indicates the quantity has exceeded the limit. Please search in risk_log. Check the details.

3. 订单状态生命周期

After successful processing, the order will go through typical statuses in Live (which you can see in the CLI orders or logs):

submitted → partial-filled → filled

It is also possible that:

submitted → canceled

After successful processing, the order will go through several status in the live session (visible via CLI orders or logs). These statuses describe “where the order is progressing on the brokerage’s side,” which is different from risk control rejection (where the order was never submitted). The table below covers the most common statuses; a complete enumeration is subject to the actual output during runtime.

The meaning of each column: Status is the English status name; Meaning is the investment semantics; What you should pay attention to are the checkpoints for investigation or confirmation.

How to use: If stuck in a certain state for a long time → check the line “What should you pay attention to” → if necessary, go to the script D/E:doc:5-artifacts-and-troubleshooting.

Status

Meaning

What should you pay attention to?

submitted

The counter has received the orders, but not all transactions have been completed.

Does it have a broker_order_id?

partial-filled

Partial transactions completed, cumulative volume < order volume.

Is the cumulative trading volume increasing?

filled

The cumulative transaction volume reached the order volume

Have your holdings and cash balances been updated?

canceled

Order cancelled

Final state after market close or manual order cancellation

Often rejected

Refusal during counter service stage

The broker number is usually empty; this is not a risk control order rejection.

Investigation Approach:

  • “No submissions were submitted” → First check the risk control and pre-submission verification (§1 Table)

  • “Always partially filled” → Check if the transaction returns are continuously arriving (§4)

4. 分批成交与全部成交

When a large order is split into multiple transactions, the status will initially remain at partial-filled, like “Only part of the order has been filled.” Once the cumulative transaction volume reaches the target order quantity, Qteasy will update the status to filled. If you see a prolonged period of partial-filled status, please compare the transaction data with the target quantity—sometimes it simply means that market conditions or demo matching haven’t yet filled the entire order.

5. 收盘后未成交订单

After the market closes, qteasy will use the post_close task to close all pending orders for the day.

  • **submitted / partial-filled: This indicates that the order was submitted to the counter, and the remaining amount was withdrawn at the close. The final state is **canceled (there may be cancellation transaction records).

  • created: This is considered a local draft of an unsuccessful order (e.g., an interrupted order placement process or a legacy issue). It is set to rejected at the close of trading. It should not be confused with intraday order rejections, nor should it be written into the cancellation transaction results.

For you: After the market closes, please check the post_close logs and reconcile reconciliation outputs to confirm whether orders in transit have been closed according to the rules, without having to remember the internal API names.

6. 遇到异常时建议顺序

  1. CLI/TUI Instant English Prompts (Note down rule_id or your order number first)

  2. risk_log: Does it exist? (Risk control path)

  3. Order and Transaction Records: Status sequence, whether broker_order_id is written back.

For a more systematic decision tree, see §3 of :doc:5-artifacts-and-troubleshooting.

7. 快速判定清单

  • Has this order entered the submission process (can it be found in the order table or logs)?

  • If not submitted: Can you find rule_id / reason in risk_log or the interface?

  • If submitted: Are there corresponding transaction results? Is the status consistent with the cumulative amount?

  • Are order rejection types clearly distinguished: Risk Control (line with no order) vs. Counter (rejected line)

8. 相关跳转

  • Configuration and Run: :doc:2-configuration-and-run

  • Troubleshooting Manual: :doc:5-artifacts-and-troubleshooting

  • Order Rejection and Access Control Details: :doc:6-trader-snapshot-gate

  • CLI command: :doc:8-cli-trader-capability-matrix

  • Dual path tutorial: tutorials/8-live-trade-risk-and-broker-walkthrough.md