# 下单、撤单与结果跟踪

下单会向真实期货公司提交委托。先在适当测试环境充分验证策略。本文片段假定已经创建 CTP 账户、观察订单并完成同步；完整下载示例要求显式传入 `--execute` 才会下单。

## 限价委托

```python
if api.trading_status() != "READY":
    raise RuntimeError("交易账户尚未就绪")

results = api.insert_order(
    symbol=symbol,
    direction="BUY",
    offset="OPEN",
    volume=1,
    limit_price=limit_price,
)
tracked_ids = set()
for result in results:
    print(result.status, result.order_id, result.message)
    if result.status in {"SUBMITTED", "UNKNOWN"} and result.order_id:
        tracked_ids.add(result.order_id)
```

`direction` 为 `BUY` / `SELL`；输入 `offset` 为 `OPEN` / `CLOSE`。`volume` 为正整数手数，`limit_price` 为符合最小变动价位的有效限价。SDK 仅支持普通投机限价委托。

## 即时提交结果

| TradingResult.status | 含义 | 正确处理 |
| --- | --- | --- |
| `SUBMITTED` | 已交给交易接口 | 等待订单回报；不等于柜台接受或成交 |
| `REJECTED` | 本地拒绝或明确未发送 | 检查 message；下单不会创建订单，order_id 为 None |
| `UNKNOWN` | 提交结果不明 | 保留订单号等待自然回报，**不自动重发** |

返回值为 `list[TradingResult]`，并非订单号列表。拆单会产生多个子单结果；前一子单失败或结果不明时，剩余子单可能返回未发送的拒绝结果。`CLOSE` 由 SDK 按合约和可平持仓规则处理，实际订单快照中的 offset 还可能是 `CLOSE_TODAY` / `CLOSE_YESTERDAY`。

## 跟踪最终状态

在下单前创建 `orders = api.watch_order()`，之后通过同一个更新循环跟踪：

```python
while tracked_ids:
    api.wait_update()
    if api.trading_status() != "READY":
        continue
    snapshot = orders.data()
    for order_id in list(tracked_ids):
        order = snapshot.get(order_id)
        if order is None:
            continue
        print(order_id, order.status, order.volume_traded, order.status_msg)
        if order.status in {"FILLED", "CANCELLED", "REJECTED"}:
            tracked_ids.remove(order_id)
```

示例是观察逻辑，业务程序应另行提供等待期限和后续处理。`PENDING` 待回报；`ALIVE` 尚未确认终态；`FILLED` 全部成交；`CANCELLED` 未全成且不再排队；`REJECTED` 提交失败或被拒。取消后的 `volume_left` 仍可大于零。

## 撤单

```python
results = api.cancel_order(order_id)
for result in results:
    print(result.status, result.order_id, result.message)
```

传本地 `order_id`，不是 `order_sys_id`。不存在、已结束或已经在撤单处理中的订单返回 `[]`。尚未确认或缺少系统订单号时立即拒绝，不缓存撤单意图。最终结果查看订单的 `status`、`cancel_pending`、`cancel_error`，不能把撤单 `SUBMITTED` 当作已撤成功。

## 错误与退出

下单或撤单的业务拒绝一般不抛异常、不自动重试、不单独改变会话状态。线程错误、关闭后调用等仍可立即报错。关闭 `ExApi` 不会撤销订单；如果策略退出时需要撤单，应自行发起并跟踪结果，不盲目重发委托。
