提交订单
place_order_sync() 用来提交订单,并等待 orderStatus() 返回初始订单状态。它对应原始 TWS API 的:
placeOrder(orderId, contract, order) -> openOrder(orderId, contract, order, orderState) -> orderStatus(orderId, status, filled, remaining, ...)同步封装会自动调用 get_next_valid_id() 取得订单 ID,然后把它写入 order.orderId。
本地官方源码中的定义核心如下:
def place_order_sync(self, contract, order, timeout=None): if timeout is None: timeout = 5 if order.orderType in ["LMT", "MKT"] else 2
order_id = self.get_next_valid_id() order.orderId = order_id
if order_id in self.order_status: del self.order_status[order_id]
self.placeOrder(order_id, contract, order) return self._wait_for_response(order_id, "order_status", timeout)参数说明:
| 参数 | 含义 |
|---|---|
contract | 要交易的合约对象 |
order | ibapi.order.Order 订单对象 |
timeout | 等待 orderStatus() 的秒数 |
返回值是一个字典,来自 orderStatus() 回调,例如 status、filled、remaining、avgFillPrice。
Order 最小字段
Section titled “Order 最小字段”限价单最少要把这些字段写清楚:
| 字段 | 中文含义 | 示例 |
|---|---|---|
action | 买卖方向 | "BUY" 或 "SELL" |
orderType | 订单类型 | "LMT" |
totalQuantity | 数量 | Decimal("1") |
lmtPrice | 限价 | 1.00 |
tif | 有效时间 | "DAY" |
transmit | 是否发送 | True |
whatIf | 是否只做预检查 | True 或 False |
实际下单前建议先使用 whatIf=True 做预检查。它会让 TWS 评估保证金变化和订单合法性,但不会形成真实可成交订单。
whatIf 预检查示例
Section titled “whatIf 预检查示例”下面代码只做订单预检查,不提交真实订单。示例价格故意使用很低的限价,避免误以为这是交易建议。
from decimal import Decimal
from ibapi.contract import Contractfrom ibapi.order import Orderfrom ibapi.sync_wrapper import TWSSyncWrapper, ResponseTimeout
def stock_contract(symbol: str, currency: str = "USD") -> Contract: contract = Contract() contract.symbol = symbol contract.secType = "STK" contract.exchange = "SMART" contract.currency = currency return contract
def limit_order(action: str, quantity: str, limit_price: float) -> Order: order = Order() order.action = action order.orderType = "LMT" order.totalQuantity = Decimal(quantity) order.lmtPrice = limit_price order.tif = "DAY" order.whatIf = True order.transmit = True return order
app = TWSSyncWrapper(timeout=10)
try: if not app.connect_and_start("127.0.0.1", 7497, 951): raise RuntimeError("连接 TWS API 失败")
try: status = app.place_order_sync( stock_contract("AAPL"), limit_order("BUY", "1", 1.00), timeout=10, ) print(status)
except ResponseTimeout: # whatIf 预检查可能只返回 openOrder/orderState,不一定返回 orderStatus。 for order_id, item in app.open_orders.items(): state = item["orderState"] print(f"ORDER_ID={order_id}") print(f"ORDER_STATE_STATUS={state.status}") print(f"INIT_MARGIN_CHANGE={state.initMarginChange}") print(f"MAINT_MARGIN_CHANGE={state.maintMarginChange}") print(f"EQUITY_WITH_LOAN_CHANGE={state.equityWithLoanChange}")
finally: app.disconnect_and_stop()使用 TWS 模拟账户、127.0.0.1:7497、独立 clientId 检查 whatIf=True 预检查时,可能返回 openOrder 和保证金变化,但不一定返回 orderStatus(),因此同步等待可能超时:
CONNECTED=TrueORDER_STATUS_TIMEOUT=TrueOPEN_ORDER_COUNT=1OPEN_ORDER_ID=1ORDER_STATE_STATUS=PreSubmittedINIT_MARGIN_CHANGE=96.21MAINT_MARGIN_CHANGE=87.46EQUITY_WITH_LOAN_CHANGE=95.19999999995343IS_CONNECTED_AFTER_STOP=False随后重新连接查询开放订单:
CONNECTED=TrueOPEN_ORDER_COUNT=0IS_CONNECTED_AFTER_STOP=False这说明 whatIf=True 没有留下真实开放订单。它适合做下单前验证,但不适合用 place_order_sync() 的 orderStatus() 作为唯一成功条件。
缺少 tif 的真实错误
Section titled “缺少 tif 的真实错误”如果不设置 order.tif,TWS 返回:
ERROR 1 ... 10052 无效的“有效时间”:空白所以限价单示例里明确写了:
order.tif = "DAY"新手下单时不要只填方向、数量和价格。订单有效时间、是否发送、是否预检查也要明确。
真正提交订单时
Section titled “真正提交订单时”真实提交订单时,把 whatIf 改成 False:
order.whatIf = Falsestatus = app.place_order_sync(contract, order, timeout=10)print(status["status"])这会发送订单到 TWS。即使是模拟账户,也建议先在 TWS 界面确认订单预防设置、价格、数量和合约。真实账户不要直接运行从文档复制的下单代码。
orderStatus 返回字段
Section titled “orderStatus 返回字段”place_order_sync() 等待的是 orderStatus()。常见字段如下:
| 字段 | 中文含义 |
|---|---|
orderId | 订单 ID |
status | 订单状态,例如 Submitted、Filled、Cancelled |
filled | 已成交数量 |
remaining | 剩余数量 |
avgFillPrice | 平均成交价 |
permId | IBKR 永久订单 ID |
parentId | 父订单 ID |
lastFillPrice | 最近成交价 |
clientId | API 客户端 ID |
whyHeld | 被挂起原因 |
订单状态可能重复回调,也可能先收到 openOrder() 再收到 orderStatus()。正式系统要把订单状态当作事件流处理,不要只依赖一次返回。
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
10052 无效的“有效时间” | 没有设置 order.tif | 对日内限价单设置 order.tif = "DAY" |
what-if 后 ResponseTimeout | 只返回了 openOrder/orderState,没有返回 orderStatus | 从 app.open_orders 读取预检查结果 |
| 订单立即被拒绝 | 合约、价格、权限或订单预防设置不满足要求 | 先用 whatIf=True 和 TWS 界面检查 |
| 下错合约 | Contract 定义不够精确 | 先用 get_contract_details() 确认 conId 和主交易所 |
| 价格格式被拒绝 | 不符合 minTick | 用合约详情里的 minTick 校验限价 |