Appearance
Orders
All order methods return OrderResult:
python
OrderResult(
success=True,
order_id=738082887,
message=None,
raw={'result': [...], 'status': 'success'}
)Market Orders
python
result = client.buy_market("SPY", 10)
result = client.sell_market("SPY", 10)Example response:
python
OrderResult(
success=True,
order_id=1093165422,
message=None,
raw={
'status': 'success',
'result': [{
'order_id': '1093165422',
'local_order_id': 'AQC-XXXX-1769537231772',
'order_status': 'PreSubmitted',
'encrypt_message': '1'
}]
}
)Sell market example:
python
OrderResult(
success=True,
order_id=1093165452,
message=None,
raw={
'status': 'success',
'result': [{
'order_id': '1093165452',
'local_order_id': 'AQC-XXXX-1769537923167',
'order_status': 'PreSubmitted',
'encrypt_message': '1'
}]
}
)Limit Orders
python
result = client.buy_limit("SPY", 10, price=690.50)
result = client.sell_limit("SPY", 10, price=695.00)Example response:
python
OrderResult(
success=True,
order_id=1093165424,
message=None,
raw={
'status': 'success',
'result': [{
'order_id': '1093165424',
'local_order_id': 'AQC-XXXX-1769537238542',
'order_status': 'Submitted',
'encrypt_message': '1'
}]
}
)Sell limit example:
python
OrderResult(
success=True,
order_id=1093165453,
message=None,
raw={
'status': 'success',
'result': [{
'order_id': '1093165453',
'local_order_id': 'AQC-XXXX-1769537931033',
'order_status': 'Submitted',
'encrypt_message': '1'
}]
}
)Stop Orders
python
result = client.buy_stop("SPY", 10, stop_price=695.00)
result = client.sell_stop("SPY", 10, stop_price=685.00)Example (rejected):
text
sell_stop: OrderResult(
success=True,
order_id=None,
message=None,
raw={'status': 'success', 'result': {'error': 'Invalid order price fields'}}
)Stop-Limit Orders
python
result = client.buy_stop_limit("SPY", 10, stop_price=695.00, limit_price=695.50)
result = client.sell_stop_limit("SPY", 10, stop_price=685.00, limit_price=684.50)Example (submitted):
text
sell_stop_limit: OrderResult(
success=True,
order_id='1093166084',
message=None,
raw={'status': 'success', 'result': [{'order_id': '1093166084', 'local_order_id': 'AQC-XXXX-1769541324981', 'order_status': 'PreSubmitted', 'encrypt_message': '1'}]}
)
order status: {'order_id': '1093166084', 'status': 'PreSubmitted', 'symbol': 'SPY', 'side': 'SELL', 'quantity': 1.0, 'filled_quantity': 0.0, 'remaining_quantity': 1.0, 'avg_fill_price': None, 'limit_price': '0.01', 'order_type': 'Stop Limit', 'tif': 'CLOSE'}Common Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
symbol | str | required | Ticker symbol |
quantity | int | required | Order quantity |
price | float | - | Limit price |
stop_price | float | - | Stop trigger price |
limit_price | float | - | Limit price for stop-limit |
conid | int | None | Contract ID (auto-resolved if None) |
tif | str | "DAY" | Time in force: DAY, GTC, IOC, OPG |
exchange | str | "SMART" | Routing exchange |
force | bool | True | Auto-confirm IBKR warnings |
Cancel Order
python
success = client.cancel_order(738082887) # Returns boolCancel All Orders
Cancels all open orders for the strategy in a single call:
python
cancelled_count = client.cancel_all_orders() # Returns intReturns: Number of orders cancelled.
Wait for Fill
python
status = client.wait_for_fill(order_id, timeout=30)Returns: Dict
python
{
'status': 'Filled',
'filled_quantity': 10,
'avg_fill_price': 690.54
}Wait for Submitted
Waits until an order is acknowledged by the exchange. Critical for multi-leg strategies where you need to confirm the first leg is accepted before placing subsequent legs.
python
acknowledged = client.wait_for_submitted(order_id, timeout=30, poll_interval=0.3)Returns: bool - True if order reached submitted/presubmitted/filled status, False if rejected/cancelled/timeout.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
order_id | str|int | required | Order ID to monitor |
timeout | int | 30 | Max seconds to wait |
poll_interval | float | 0.3 | Seconds between status checks |
Example - Iron Condor leg sequencing:
python
# Place first leg
result = client.place_order(symbol="SPX", quantity=1, side="SELL", ...)
if result.success and result.order_id:
# Wait for exchange acknowledgment before placing next leg
if client.wait_for_submitted(result.order_id, timeout=15):
# Safe to place second leg
client.place_order(symbol="SPX", quantity=1, side="BUY", ...)
else:
# First leg rejected - don't place second leg
logger.error("First leg not acknowledged")Order Status
python
status = client.get_order_status(order_id)Returns: Dict
python
{
'order_id': 1093165422,
'status': 'Filled',
'symbol': 'SPY',
'side': 'BUY',
'quantity': 1.0,
'filled_quantity': 1.0,
'remaining_quantity': 0.0,
'avg_fill_price': '695.01',
'limit_price': '',
'order_type': 'Market',
'tif': 'CLOSE',
'raw': { ... }
}Sell status example:
python
{
'order_id': 1093165452,
'status': 'Filled',
'symbol': 'SPY',
'side': 'SELL',
'quantity': 1.0,
'filled_quantity': 1.0,
'remaining_quantity': 0.0,
'avg_fill_price': '695.64',
'limit_price': '',
'order_type': 'Market',
'tif': 'CLOSE',
'raw': { ... }
}Bracket Orders
python
result = client.place_bracket_order(
symbol="SPY",
quantity=10,
side="BUY",
entry_price=690.00,
stop_loss=685.00,
take_profit=700.00,
entry_type="LMT"
)Trailing Stop
python
result = client.place_trailing_stop(
symbol="SPY",
quantity=10,
side="SELL",
trail_amount=2.00, # or trail_percent=0.5
)Combo Orders
Combo orders (spreads) allow you to trade multiple option legs as a single order. This is essential for strategies like vertical spreads, iron condors, and butterflies.
ComboLeg Parameters
python
from aqc_trading_sdk import ComboLeg
ComboLeg(
conid=123456, # Contract ID (required)
ratio=1, # Leg ratio (required)
action="SELL", # "BUY" or "SELL" (required)
exchange="CBOE" # Routing exchange (required for options)
)Exchange Routing
Important
The exchange parameter is required for option combo legs and must match the underlying:
| Underlying | Exchange | Description |
|---|---|---|
| SPX/SPXW | CBOE | Index options route through CBOE |
| SPY, QQQ, TQQQ | SMART | ETF options use SMART routing |
Combo Order Side
Key Concept
For combo orders, side="BUY" means you are buying the spread structure (opening the position), regardless of whether it's a credit or debit spread. The individual leg actions (action="SELL" or action="BUY") determine which legs are sold and bought.
Bear Call Spread (Credit Spread)
Sell a lower-strike call, buy a higher-strike call:
python
from aqc_trading_sdk import ComboLeg
# Get option contracts first
short_call = client.get_option_contract(
symbol="SPX", expiry="20260130", strike=6100, right="C", trading_class="SPXW"
)
long_call = client.get_option_contract(
symbol="SPX", expiry="20260130", strike=6110, right="C", trading_class="SPXW"
)
# Filter for exact expiry
short_conid = [c for c in short_call if c.get("maturityDate") == "20260130"][0]["conid"]
long_conid = [c for c in long_call if c.get("maturityDate") == "20260130"][0]["conid"]
# Build combo legs - CBOE for SPX options
legs = [
ComboLeg(conid=short_conid, ratio=1, action="SELL", exchange="CBOE"),
ComboLeg(conid=long_conid, ratio=1, action="BUY", exchange="CBOE")
]
# Place the combo order
result = client.place_combo_order(
legs=legs,
quantity=1,
side="BUY", # "BUY" the spread structure
order_type="MKT", # or "LMT" with price
price=None
)Bull Put Spread (Credit Spread)
Sell a higher-strike put, buy a lower-strike put:
python
from aqc_trading_sdk import ComboLeg
# Get option contracts
short_put = client.get_option_contract(
symbol="SPX", expiry="20260130", strike=6000, right="P", trading_class="SPXW"
)
long_put = client.get_option_contract(
symbol="SPX", expiry="20260130", strike=5990, right="P", trading_class="SPXW"
)
short_conid = [c for c in short_put if c.get("maturityDate") == "20260130"][0]["conid"]
long_conid = [c for c in long_put if c.get("maturityDate") == "20260130"][0]["conid"]
legs = [
ComboLeg(conid=short_conid, ratio=1, action="SELL", exchange="CBOE"),
ComboLeg(conid=long_conid, ratio=1, action="BUY", exchange="CBOE")
]
result = client.place_combo_order(
legs=legs,
quantity=1,
side="BUY",
order_type="MKT",
price=None
)ETF Options (SPY Example)
For ETF options, use exchange="SMART":
python
from aqc_trading_sdk import ComboLeg
# SPY Bear Call Spread
short_conid = 123456 # SPY call conid
long_conid = 789012 # SPY call conid (higher strike)
legs = [
ComboLeg(conid=short_conid, ratio=1, action="SELL", exchange="SMART"),
ComboLeg(conid=long_conid, ratio=1, action="BUY", exchange="SMART")
]
result = client.place_combo_order(
legs=legs,
quantity=1,
side="BUY",
order_type="LMT",
price=0.50 # Net credit/debit
)Combo Order Response
Successful combo order:
python
OrderResult(
success=True,
order_id='500500259',
message=None,
raw={
'status': 'success',
'result': [{
'order_id': '500500259',
'local_order_id': 'AQC-XXXX-1769654321000',
'order_status': 'PreSubmitted'
}]
}
)Error Handling
If IBKR rejects the combo, the SDK returns success=False with the error message:
python
OrderResult(
success=False,
order_id=None,
message='Riskless combination orders are not allowed',
raw={'error': 'Riskless combination orders are not allowed'}
)Common rejection reasons:
- "Riskless combination orders are not allowed" - Both legs have same strike/expiry
- "The size of the order is invalid" - Quantity is 0 or negative
- Missing exchange parameter - Legs don't specify routing exchange
How Combo Orders Work (Server-Side)
For combo orders, IBKR requires a spread conidex string. The server builds it as:
{spread_conid}@{exchange};;;{leg_conid1}/{signed_ratio},{leg_conid2}/{signed_ratio}signed_ratiois positive for BUY legs and negative for SELL legs- For index options (e.g., SPXW), the server uses
spread_conid=0and the leg exchange (CBOE) - Final
conidexexample:0@CBOE;;;843975599/-1,843975601/1
Options with conid
For options, always provide the conid:
python
# Get option conid first
contracts = client.get_option_contract(
symbol="SPX", expiry="20260126", strike=6900, right="P", trading_class="SPXW"
)
opt_conid = contracts[0]["conid"]
# Place order with conid
result = client.buy_limit("SPX", 1, price=5.00, conid=opt_conid)