13. Conditional Orders (FCO)
Place and manage Flexible Conditional Order types
Objective
Place and manage the full range of FCO (Flexible Conditional Order) types: GTD, Stop, Stop Limit, Trailing Stop, Trailing Stop Limit, OCO, Bull Bear — plus querying and cancelling FCO orders.
Flow
Authenticate (OTP) → Trading API (Place FCO) → Wait to trigger (WAIT) → Underlying order placed once condition is met- Authenticate with OTP via
Auth/Trading. - Call the
place_fco_*method matching the conditional order type you need. - The order is stored in a waiting state (
FCOStatus.WAIT) until its trigger condition is met. - Once the market price crosses the trigger threshold, the system automatically places the underlying order (LO/MTL/MP...) onto the order book.
- Query the list/details with
get_fco_by_*, or cancel withcancel_fcowhile the order hasn't triggered yet.
Conditional Order Types
| Type | Method | Description |
|---|---|---|
| GTD | place_fco_gtd | Good-Till-Date order |
| Stop | place_fco_stop | Triggers a market order once price crosses the threshold (Stop Market) |
| Stop Limit | place_fco_stop_limit | Triggers a limit order once price crosses the threshold (Stop Limit) |
| Trailing Stop | place_fco_trailing_stop | Follows the price trend at a fixed trailing amount |
| Trailing Stop Limit | place_fco_trailing_stop_limit | Trailing Stop that places a limit order on trigger |
| OCO | place_fco_oco | Places take-profit (TP) and stop-loss (SL) together — filling one cancels the other |
| Bull Bear | place_fco_bull_bear | Combines an entry order with attached TP/SL |
See the full
FCOType,FCOOperator,FCOStatusenums and detailed parameters on the Python SDK Enums page.
Sample Code — Sync
from datetime import datetime, timedelta
from ssi_sdk import Auth, Trading, Config
from ssi_sdk.enums import FCOOperator, OrderSide
from auth_helper import ensure_auth
from helpers import enum_value
config = Config(
client_id="<your_client_id>",
api_key="<your_api_key>",
api_secret="<your_api_secret>",
private_key="<your_private_key>",
)
ACCOUNT_NO = "<your_account_no>"
symbol = "SSI"
# Validity window starts from the run time; the server caps it at 31 days (from -> to)
_now = datetime.now()
from_date = _now.strftime("%Y/%m/%d 00:00:00")
to_date = (_now + timedelta(days=30)).strftime("%Y/%m/%d 23:59:59")
# OTP for conditional orders: fill in only if the account requires OTP for FCO, None otherwise
FCO_CODE = None
with Auth(config) as auth:
ensure_auth(auth, otp="<your_otp>")
with Trading(auth) as trading:
# 1. GTD order (Good-Till-Date)
gtd_res = trading.trading.place_fco_gtd(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, price=26000, price_slip=0,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" GTD: {gtd_res}")
# 2. Stop order (stop market)
stop_res = trading.trading.place_fco_stop(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, stop_price=27000,
operator=FCOOperator.GREATER_OR_EQUAL,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Stop: {stop_res}")
# 3. Stop Limit order
stop_limit_res = trading.trading.place_fco_stop_limit(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, price=27500, price_slip=0, stop_price=27000,
operator=FCOOperator.GREATER_OR_EQUAL,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Stop Limit: {stop_limit_res}")
# 4. Trailing Stop order
trailing_res = trading.trading.place_fco_trailing_stop(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.SELL,
quantity=100, active_price=28000, trailing_amount=1000,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Trailing Stop: {trailing_res}")
# 5. Trailing Stop Limit order
trailing_limit_res = trading.trading.place_fco_trailing_stop_limit(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.SELL,
quantity=100, active_price=28000, trailing_amount=1000,
price_slip=500, from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Trailing Stop Limit: {trailing_limit_res}")
# 6. OCO order (One-Cancels-the-Other)
oco_res = trading.trading.place_fco_oco(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.SELL,
quantity=100, tp_active_price=30000, sl_active_price=24000,
tp_price=30000, sl_price=24000, tp_slip=0, sl_slip=0,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" OCO: {oco_res}")
# 7. Bull Bear order
bb_res = trading.trading.place_fco_bull_bear(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, price=26000, price_slip=0,
tp_active_price=30000, sl_active_price=24000,
tp_price=30000, sl_price=24000, tp_slip=0, sl_slip=0,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Bull Bear: {bb_res}")
# 8. Query FCO order list
fco_list = trading.trading.get_fco_by_account_no(ACCOUNT_NO, page_index=1, page_size=10)
print(f" Total FCO orders: {fco_list.items_count}")
for item in fco_list.fco_list[:5]:
print(f" {item.fco_id} | {item.symbol} | {enum_value(item.type)} | {enum_value(item.status)}")
# 8b. Status history of one FCO order (SDK 3.3.0)
if getattr(gtd_res, "fco_id", None):
history = trading.trading.get_fco_status_history(gtd_res.fco_id)
for h in history:
print(f" {h.time} | {h.state} | code={h.code} | {h.detail}")
# 9. Cancel the FCO order just created (if still WAIT)
if getattr(gtd_res, "fco_id", None):
cancel_res = trading.trading.cancel_fco(gtd_res.fco_id, code=FCO_CODE)
print(f" Cancel FCO: {cancel_res}")Sample Code — Async
import asyncio
from ssi_sdk import AsyncAuth, AsyncTrading, Config
from datetime import datetime, timedelta
from ssi_sdk.enums import FCOOperator, OrderSide
from auth_helper import ensure_auth_async
config = Config(...)
ACCOUNT_NO = "<your_account_no>"
symbol = "SSI"
# Validity window starts from the run time, 31 days max
_now = datetime.now()
from_date = _now.strftime("%Y/%m/%d 00:00:00")
to_date = (_now + timedelta(days=30)).strftime("%Y/%m/%d 23:59:59")
FCO_CODE = None # OTP for FCO if the account requires it
async def main():
async with AsyncAuth(config) as auth:
await ensure_auth_async(auth, otp="<your_otp>")
async with AsyncTrading(auth) as trading:
gtd_res = await trading.trading.place_fco_gtd(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, price=26000, price_slip=0,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" GTD: {gtd_res}")
stop_res = await trading.trading.place_fco_stop(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.BUY,
quantity=100, stop_price=27000,
operator=FCOOperator.GREATER_OR_EQUAL,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" Stop: {stop_res}")
oco_res = await trading.trading.place_fco_oco(
account_no=ACCOUNT_NO, symbol=symbol, side=OrderSide.SELL,
quantity=100, tp_active_price=30000, sl_active_price=24000,
tp_price=30000, sl_price=24000, tp_slip=0, sl_slip=0,
from_date=from_date, to_date=to_date,
code=FCO_CODE,
)
print(f" OCO: {oco_res}")
fco_list = await trading.trading.get_fco_by_account_no(ACCOUNT_NO, page_index=1, page_size=10)
print(f" Total FCO orders: {fco_list.items_count}")
if getattr(gtd_res, "fco_id", None):
history = await trading.trading.get_fco_status_history(gtd_res.fco_id)
for h in history:
print(f" {h.time} | {h.state} | code={h.code} | {h.detail}")
cancel_res = await trading.trading.cancel_fco(gtd_res.fco_id, code=FCO_CODE)
print(f" Cancel FCO: {cancel_res}")
asyncio.run(main())Notes
- Validity window:
from_date/to_dateare computed from the run date (do not hard-code old dates) and the server caps the span fromfrom_datetoto_dateat 31 days. - OTP for FCO: the
place_fco_*methods andcancel_fcotake an optionalcode. Fill it in only when the account requires OTP for conditional orders, leaveNoneotherwise; never hard-code an OTP. - Status history:
get_fco_status_history(fco_id)(SDK 3.3.0) returns the status transitions (time,state,code,detail); an empty list when there are none. - An FCO order isn't placed onto the order book immediately — only once its trigger condition is met does the system create the actual underlying order (buying/selling power is checked at that moment).
- You can only cancel (
cancel_fco) an order while it's still waiting (INIT/WAIT), before it has triggered (TRI/TRIT). - The
priceparameter for GTD/Bull Bear can beOrderType.MTL/OrderType.MPto fill at market price immediately on trigger, instead of a fixed price. operator(FCOOperator) sets the comparison condition that triggers Stop/Stop Limit — e.g.GREATER_OR_EQUALfor a buy order waiting for price to rise to the threshold.- For OCO/Bull Bear, when one leg (TP or SL) fills, the other leg is automatically cancelled.
- Track FCO status updates in real time via
FCOOrderUpdateMessagein WebSocket Trading.