Combo
Reminder
Before placing orders, you must first log in and activate your CA.
A combo order bundles two futures/options contracts into a single submission. See the TAIFEX order types introduction for the full rules and the margin page for margin information.
Build a combo contract before placing; see Contract for how.
Place¶
A combo order buys or sells the whole combo. Per the TAIFEX definition "the side of a spread order follows the far-month contract", buying a time spread means buying the far month and selling the near month. Each type is defined as follows (the Direction & Net Price Table):
| Type | sj.ComboType |
action=Buy |
action=Sell |
Net price (price) |
|---|---|---|---|---|
| Time spread | TimeSpread / WeeklyTimeSpread |
sell near, buy far | buy near, sell far | far − near (can be negative) |
| Call spread | PriceSpread |
sell higher strike, buy lower | buy higher strike, sell lower | lower-strike premium − higher-strike premium |
| Put spread | PriceSpread |
sell lower strike, buy higher | buy lower strike, sell higher | higher-strike premium − lower-strike premium |
| Straddle / Strangle | Straddle / Strangle |
buy Call, buy Put | sell Call, sell Put | Call premium + Put premium |
| Conversion / Reversal | ConversionReversal |
sell Call, buy Put (Conversion) | buy Call, sell Put (Reversal) | Put premium − Call premium |
price is the net price of the whole combo, not any single product's price — see the Direction & Net Price Table; for quotes before placing, see Combo Products.
Price range limits
Combo order prices are range-limited: for a time spread, the ceiling is the far month's limit-up minus the near month's limit-down, and the floor is the far month's limit-down minus the near month's limit-up. Orders outside the range are rejected by the exchange.
Order condition limits
- Standard option combos cannot use
ROD— sendLMTwithIOCorFOK; anRODorder is rejected by TAIFEX with9927 order-condition error. - Futures time spreads may use
RODduring continuous trading, subject to product rules. - Combo orders are not accepted during pre-open.
place_comboorder
api.place_comboorder?
Signature:
api.place_comboorder(
combo_contract: sj.ComboContract,
order: Union[sj.ComboOrder, sj.FuturesOrder],
timeout: Optional[int] = 30000,
cb: Optional[Callable[[sj.ComboTrade], None]] = None,
) -> sj.ComboTrade
Parameters
combo_contract: Combo contract (see the Contract page for how to build one)
order: Combo order (ComboOrder or FuturesOrder)
timeout: Timeout in milliseconds
cb: Optional callback function, used when timeout=0
sj.ComboOrder
action (Action): Buy/Sell {Buy, Sell}, required; both products' directions
are expanded from it per the Direction & Net Price Table
price (float or int): Net price, defined in the table above; can be negative
quantity (int): Quantity (both products share it)
price_type (FuturesPriceType): Price type {LMT, MKT, MKP}
order_type (OrderType): Order condition {ROD, IOC, FOK}
octype (FuturesOCType): Open/cover type {Auto, New, Cover, DayTrade}
combo_type (ComboType): Optional; auto-filled from the derived type, must match
when supplied
account (Account): Trading account (defaults to the primary futures account)
combo_contract legs carry no actions (see Contract for the
shape); order.action is a required field.
place_comboorder
POST /api/v1/order/place_comboorder
Content-Type: application/json
{
"combo_contract": { "legs": [ ... ] },
"order": {
"action": <Action>,
"price": <number>,
"quantity": <integer>,
"price_type": <FuturesPriceType>,
"order_type": <OrderType>,
"octype": <FuturesOCType>,
"combo_type": <ComboType>,
"account": { "broker_id": <string>, "account_id": <string> }
}
}
Parameters
combo_contract: Combo contract (see the Contract page)
order.action: Buy/Sell {Buy, Sell}, required; both products' directions are
expanded from it
order.price: Net price, can be negative
order.quantity: Quantity (both products share it)
order.price_type: Price type {LMT, MKT, MKP}
order.order_type: Order condition {ROD, IOC, FOK}
order.octype: Open/cover type {Auto, New, Cover, DayTrade}
order.combo_type: Optional combo type
order.account: Trading account (defaults to the primary futures account)
Example¶
Futures time spread, buying the spread (sell near, buy far). Composition: two futures of the same product with different delivery months, near month first.
- Contract:
legs=[near, far], no actions on the products - Order:
action=Buy(buying the spread; Shioaji expands it to sell near, buy far)
In
near = api.contracts.get("TXFH6")
far = api.contracts.get("TXFI6")
combo_contract = api.contracts.combo(legs=[near, far])
order = sj.ComboOrder(
action=sj.Action.Buy, # buy the spread: Shioaji expands to sell near, buy far
price=50, # net price (far - near)
quantity=1,
price_type=sj.FuturesPriceType.LMT,
order_type=sj.OrderType.ROD,
octype=sj.FuturesOCType.Auto,
account=api.futopt_account,
)
trade = api.place_comboorder(combo_contract, order)
trade
Out
ComboTrade(
contract=ComboContract(
legs=[
Contract(security_type='FUT', region='TW', exchange='TAIFEX', code='TXFH6'),
Contract(security_type='FUT', region='TW', exchange='TAIFEX', code='TXFI6')
],
combo_type=TimeSpread
),
order=Order(
id='46989de8',
action=<Action.Buy: 'Buy'>,
price=50.0,
quantity=1,
seqno='743595',
ordno='000000',
order_type=<OrderType.ROD: 'ROD'>,
price_type=<PriceType.LMT: 'LMT'>,
account=FutureAccount(
person_id='YOUR_PERSON_ID',
broker_id='YOUR_BROKER_ID',
account_id='YOUR_ACCOUNT_ID',
signed=true,
username=''
),
octype=<FuturesOCType.Auto: 'Auto'>
),
status=ComboStatus(
id='46989de8',
status=<OrderStatus.Submitted: 'Submitted'>,
status_code='0000',
order_datetime=datetime.datetime(2026, 8, 12, 11, 35, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_time=datetime.datetime(2026, 8, 12, 11, 35, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_price=50.0,
order_quantity=1,
deals={}
)
)
In
curl -X POST http://localhost:8080/api/v1/order/place_comboorder \
-H 'Content-Type: application/json' \
-d '{
"combo_contract": {
"legs": [
{"security_type": "FUT", "exchange": "TAIFEX", "code": "TXFH6"},
{"security_type": "FUT", "exchange": "TAIFEX", "code": "TXFI6"}
]
},
"order": {
"action": "Buy",
"price": 50,
"quantity": 1,
"price_type": "LMT",
"order_type": "ROD",
"octype": "Auto",
"account": {
"broker_id": "YOUR_BROKER_ID",
"account_id": "YOUR_ACCOUNT_ID"
}
}
}'
Out
{"contract":{"legs":[{"action":"Sell","security_type":"FUT","exchange":"TAIFEX","code":"TXFH6","symbol":"TXFH6","category":"TXF","delivery_month":"202608"},{"action":"Buy","security_type":"FUT","exchange":"TAIFEX","code":"TXFI6","symbol":"TXFI6","category":"TXF","delivery_month":"202609"}]},"order":{"id":"46989de8","action":"Buy","price":50.0,"quantity":1,"seqno":"743595","ordno":"000000","order_type":"ROD","price_type":"LMT","account":{"account_type":"F","person_id":"YOUR_PERSON_ID","broker_id":"YOUR_BROKER_ID","account_id":"YOUR_ACCOUNT_ID","signed":true,"username":""},"octype":"Auto"},"status":{"id":"46989de8","status":"Submitted","status_code":"0000","order_datetime":"2026-08-12T11:35:00+08:00","modified_price":50.0,"order_quantity":1,"deals":{}}}
Option straddle, buying the straddle (buy Call, buy Put). Composition: a Call and a Put with the same expiry and strike, Call first; standard option combos use IOC.
- Contract:
legs=[Call, Put]pluscombo_type=Straddle(required — same components as Conversion/Reversal) - Order:
action=Buy(buy Call, buy Put)
In
call = api.contracts.get("TXO34000I6")
put = api.contracts.get("TXO34000U6")
straddle_contract = api.contracts.combo(
legs=[call, put],
combo_type=sj.ComboType.Straddle,
)
order = sj.ComboOrder(
action=sj.Action.Buy, # buy the straddle: buy Call, buy Put
price=1, # net price (Call premium + Put premium)
quantity=1,
price_type=sj.FuturesPriceType.LMT,
order_type=sj.OrderType.IOC, # standard option combos cannot use ROD
octype=sj.FuturesOCType.Auto,
account=api.futopt_account,
)
trade = api.place_comboorder(straddle_contract, order)
trade
Out
ComboTrade(
contract=ComboContract(
legs=[
Contract(security_type='OPT', region='TW', exchange='TAIFEX', code='TXO34000I6'),
Contract(security_type='OPT', region='TW', exchange='TAIFEX', code='TXO34000U6')
],
combo_type=Straddle
),
order=Order(
id='a3512bd6',
action=<Action.Buy: 'Buy'>,
price=1.0,
quantity=1,
seqno='743597',
ordno='000000',
order_type=<OrderType.IOC: 'IOC'>,
price_type=<PriceType.LMT: 'LMT'>,
account=FutureAccount(
person_id='YOUR_PERSON_ID',
broker_id='YOUR_BROKER_ID',
account_id='YOUR_ACCOUNT_ID',
signed=true,
username=''
),
octype=<FuturesOCType.Auto: 'Auto'>
),
status=ComboStatus(
id='a3512bd6',
status=<OrderStatus.Submitted: 'Submitted'>,
status_code='0000',
order_datetime=datetime.datetime(2026, 8, 12, 11, 37, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_time=datetime.datetime(2026, 8, 12, 11, 37, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_price=1.0,
order_quantity=1,
deals={}
)
)
In
curl -X POST http://localhost:8080/api/v1/order/place_comboorder \
-H 'Content-Type: application/json' \
-d '{
"combo_contract": {
"legs": [
{"security_type": "OPT", "exchange": "TAIFEX", "code": "TXO34000I6"},
{"security_type": "OPT", "exchange": "TAIFEX", "code": "TXO34000U6"}
],
"combo_type": "Straddle"
},
"order": {
"action": "Buy",
"price": 1,
"quantity": 1,
"price_type": "LMT",
"order_type": "IOC",
"octype": "Auto",
"account": {
"broker_id": "YOUR_BROKER_ID",
"account_id": "YOUR_ACCOUNT_ID"
}
}
}'
Out
{"contract":{"legs":[{"action":"Buy","security_type":"OPT","exchange":"TAIFEX","code":"TXO34000I6","symbol":"TXO34000I6","category":"TXO","delivery_month":"202609","strike_price":34000.0,"option_right":"C"},{"action":"Buy","security_type":"OPT","exchange":"TAIFEX","code":"TXO34000U6","symbol":"TXO34000U6","category":"TXO","delivery_month":"202609","strike_price":34000.0,"option_right":"P"}]},"order":{"id":"a3512bd6","action":"Buy","price":1.0,"quantity":1,"seqno":"743597","ordno":"000000","order_type":"IOC","price_type":"LMT","account":{"account_type":"F","person_id":"YOUR_PERSON_ID","broker_id":"YOUR_BROKER_ID","account_id":"YOUR_ACCOUNT_ID","signed":true,"username":""},"octype":"Auto"},"status":{"id":"a3512bd6","status":"Submitted","status_code":"0000","order_datetime":"2026-08-12T11:37:00+08:00","modified_price":1.0,"order_quantity":1,"deals":{}}}
Cancel¶
trade is the combo trade to cancel; obtain it via Query Status.
cancel_comboorder
api.cancel_comboorder?
Signature:
api.cancel_comboorder(
combo_trade: sj.ComboTrade,
timeout: Optional[int] = 30000,
cb: Optional[Callable[[sj.ComboTrade], None]] = None,
) -> sj.ComboTrade
Parameters
combo_trade: Combo trade to cancel (from list_combotrades / update_combostatus)
timeout: Timeout in milliseconds
cb: Optional callback function, used when timeout=0
cancel_comboorder
POST /api/v1/order/cancel_comboorder
Content-Type: application/json
{
"trade_id": <string>
}
Parameters
trade_id: Combo trade ID (from the place response status.id)
Example¶
In
api.cancel_comboorder(trade)
In
curl -X POST http://localhost:8080/api/v1/order/cancel_comboorder \
-H 'Content-Type: application/json' \
-d '{
"trade_id": "46989de8"
}'
Query Status¶
Like the relationship between list_trades and update_status: call update_combostatus to refresh combo trades before reading them. The HTTP endpoint /order/combotrades performs the refresh and the read in a single call.
update_combostatus / list_combotrades
api.update_combostatus?
Signature:
api.update_combostatus(
account: Optional[sj.Account] = None,
timeout: Optional[int] = 30000,
cb: Optional[Callable[[List[sj.ComboTrade]], None]] = None,
) -> List[sj.ComboTrade]
api.list_combotrades?
Signature:
api.list_combotrades() -> List[sj.ComboTrade]
Parameters
update_combostatus
account: Futures account; omit to refresh all futures accounts under your name
timeout: Timeout in milliseconds
cb: Optional callback function; receives the refreshed ComboTrade list when timeout=0
list_combotrades
(No parameters; returns known combo trades from the local cache)
combotrades
POST /api/v1/order/combotrades
Content-Type: application/json
{
"account": { "broker_id": <string>, "account_id": <string> }
}
Parameters
account: Futures account
An unfilled IOC is a normal ending
A combo order sent with IOC that does not fill ends with status=Cancelled,
status_code='0000', deal_quantity=0, cancel_quantity=1, deals={} — the order was
accepted by the exchange and auto-cancelled for lack of a fill. It is not an error.
Example¶
In
api.update_combostatus(api.futopt_account)
api.list_combotrades()
Out
[
ComboTrade(
contract=ComboContract(
legs=[
ComboBase(
action=<Action.Sell: 'Sell'>,
security_type=<SecurityType.Future: 'FUT'>,
exchange=<Exchange.TAIFEX: 'TAIFEX'>,
code='TXFH6',
symbol='TXFH6',
category='TXF',
delivery_month='202608'
),
ComboBase(
action=<Action.Buy: 'Buy'>,
security_type=<SecurityType.Future: 'FUT'>,
exchange=<Exchange.TAIFEX: 'TAIFEX'>,
code='TXFI6',
symbol='TXFI6',
category='TXF',
delivery_month='202609'
)
]
),
order=Order(
id='46989de8',
action=<Action.Buy: 'Buy'>,
price=50.0,
quantity=1,
seqno='743595',
ordno='000000',
order_type=<OrderType.ROD: 'ROD'>,
price_type=<PriceType.LMT: 'LMT'>,
account=FutureAccount(
person_id='YOUR_PERSON_ID',
broker_id='YOUR_BROKER_ID',
account_id='YOUR_ACCOUNT_ID',
signed=true,
username=''
),
octype=<FuturesOCType.Auto: 'Auto'>
),
status=ComboStatus(
id='46989de8',
status=<OrderStatus.Submitted: 'Submitted'>,
status_code='0000',
order_datetime=datetime.datetime(2026, 8, 12, 11, 35, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_time=datetime.datetime(2026, 8, 12, 11, 35, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
modified_price=50.0,
order_quantity=1,
deals={}
)
)
]
In
curl -X POST http://localhost:8080/api/v1/order/combotrades \
-H 'Content-Type: application/json' \
-d '{
"account": {
"broker_id": "YOUR_BROKER_ID",
"account_id": "YOUR_ACCOUNT_ID"
}
}'
Out
[{"contract":{"legs":[{"action":"Sell","security_type":"FUT","exchange":"TAIFEX","code":"TXFH6","symbol":"TXFH6","category":"TXF","delivery_month":"202608"},{"action":"Buy","security_type":"FUT","exchange":"TAIFEX","code":"TXFI6","symbol":"TXFI6","category":"TXF","delivery_month":"202609"}]},"order":{"id":"46989de8","action":"Buy","price":50.0,"quantity":1,"seqno":"743595","ordno":"000000","order_type":"ROD","price_type":"LMT","account":{"account_type":"F","person_id":"YOUR_PERSON_ID","broker_id":"YOUR_BROKER_ID","account_id":"YOUR_ACCOUNT_ID","signed":true,"username":""},"octype":"Auto"},"status":{"id":"46989de8","status":"Submitted","status_code":"0000","order_datetime":"2026-08-12T11:35:00+08:00","modified_price":50.0,"order_quantity":1,"deals":{}}}]