Place Flexi Order¶
create_order() places one leg-based Trading API V3 FNO strategy order when the order object sets isMultiLeg=True and provides a non-empty legs list.
Flexi orders help users build complex FNO strategies with ease by grouping multiple option or future legs into one strategy order.
With basket-level execution, users can choose strategy-level entry and/or exit configs. Both time-based and price-based entry and exits are possible, along with trailing stop-loss and other trigger configurations.
LLM guidance
Use this page for one strategy order composed from FNO legs. This shape omits top-level refId, requires isMultiLeg=True, sets the strategy-level side, and uses legs[].refId plus signed legs[].unitQty. Set executionMode based on the top-level entry and exit fields. Do not use this page for multiple independent single orders; use Place Multi Order.
Basic Usage¶
from datetime import datetime
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.trading.trading_data import NubraTrader
from nubra_python_sdk.trading.trading_enum import TradingAPIVersion
nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)
instruments = InstrumentData(nubra)
market_data = MarketData(nubra)
trader = NubraTrader(nubra, version=TradingAPIVersion.V3)
def get_ref_id(asset, strike, expiry, option_type):
expiry = datetime.strptime(expiry, "%d-%m-%Y").strftime("%Y%m%d")
result = instruments.get_instruments_by_pattern([{
"exchange": "NSE",
"asset": asset,
"strike_price": str(strike * 100),
"expiry": expiry,
"option_type": option_type,
}])
return result[0].ref_id if result else None
def get_ltp(asset, strike, expiry, option_type):
ref_id = get_ref_id(asset, strike, expiry, option_type)
quote = market_data.quote(ref_id=ref_id, levels=1)
return ref_id, quote.orderBook.last_traded_price
long_call_ref_id, long_call_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "CE")
long_put_ref_id, long_put_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "PE")
entry_price = long_call_ltp + long_put_ltp
result = trader.create_order({
"isMultiLeg": True,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY_AND_EXIT",
"entryPrice": entry_price,
"legs": [
{"refId": long_call_ref_id, "unitQty": 65},
{"refId": long_put_ref_id, "unitQty": 65}
],
"entryConfig": {
"entryTime": "2026-03-20T09:20:00.000Z",
"triggers": [
{"kind": "AT_OR_ABOVE", "value": entry_price + 10}
]
},
"exitConfig": {
"exitTime": "2026-03-20T15:10:00.000Z",
"stoplossParams": {
"stoplossTriggerPrice": {"value": entry_price - 50},
"stoplossLimitPrice": {"value": entry_price - 40}
},
"targetParams": {
"targetProfitTriggerPrice": {"value": entry_price + 80},
"targetProfitLimitPrice": {"value": entry_price + 90}
}
},
"stratTags": ["python-sdk-test", "nifty-buy-straddle"],
"echoFields": "nifty_buy_straddle_example"
})
order = result.orders[0]
print(order.intentOrderId, order.isMulti, order.status)
Example Order Patterns¶
These examples show common option strategy orders built with Trading API V3 multi-leg payloads.
- each leg is passed through
legs - strategy-level pricing and controls stay on the top-level order object
- option
refIdvalues are resolved dynamically before order placement - set
isMultiLeg: True, set strategyside: "BUY", omit top-levelrefId, and set the correctexecutionMode - use
qtyas the strategy multiplier andlegs[].unitQtyas the signed lot quantity for each leg
from datetime import datetime
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.trading.trading_data import NubraTrader
from nubra_python_sdk.trading.trading_enum import TradingAPIVersion
nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)
instruments = InstrumentData(nubra)
market_data = MarketData(nubra)
trader = NubraTrader(nubra, version=TradingAPIVersion.V3)
def get_ref_id(asset, strike, expiry, option_type):
expiry = datetime.strptime(expiry, "%d-%m-%Y").strftime("%Y%m%d")
result = instruments.get_instruments_by_pattern([{
"exchange": "NSE",
"asset": asset,
"strike_price": str(strike * 100),
"expiry": expiry,
"option_type": option_type,
}])
return result[0].ref_id if result else None
def get_ltp(asset, strike, expiry, option_type):
ref_id = get_ref_id(asset, strike, expiry, option_type)
quote = market_data.quote(ref_id=ref_id, levels=1)
return ref_id, quote.orderBook.last_traded_price
long_call_ref_id, long_call_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "CE")
long_put_ref_id, long_put_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "PE")
result = trader.create_order({
"isMultiLeg": True,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY",
"entryPrice": long_call_ltp + long_put_ltp,
"legs": [
{"refId": long_call_ref_id, "unitQty": 65},
{"refId": long_put_ref_id, "unitQty": 65}
],
"stratTags": ["python-sdk-test", "nifty-buy-straddle"],
"echoFields": "buy_straddle_example"
})
Use this pattern for a two-leg same-strike buy straddle strategy.
from datetime import datetime
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.trading.trading_data import NubraTrader
from nubra_python_sdk.trading.trading_enum import TradingAPIVersion
nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)
instruments = InstrumentData(nubra)
market_data = MarketData(nubra)
trader = NubraTrader(nubra, version=TradingAPIVersion.V3)
def get_ref_id(asset, strike, expiry, option_type):
expiry = datetime.strptime(expiry, "%d-%m-%Y").strftime("%Y%m%d")
result = instruments.get_instruments_by_pattern([{
"exchange": "NSE",
"asset": asset,
"strike_price": str(strike * 100),
"expiry": expiry,
"option_type": option_type,
}])
return result[0].ref_id if result else None
def get_ltp(asset, strike, expiry, option_type):
ref_id = get_ref_id(asset, strike, expiry, option_type)
quote = market_data.quote(ref_id=ref_id, levels=1)
return ref_id, quote.orderBook.last_traded_price
long_call_ref_id, long_call_ltp = get_ltp("NIFTY", 23800, "17-03-2026", "CE")
long_put_ref_id, long_put_ltp = get_ltp("NIFTY", 23400, "17-03-2026", "PE")
result = trader.create_order({
"isMultiLeg": True,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY",
"entryPrice": long_call_ltp + long_put_ltp,
"legs": [
{"refId": long_call_ref_id, "unitQty": 65},
{"refId": long_put_ref_id, "unitQty": 65}
],
"stratTags": ["python-sdk-test", "nifty-buy-strangle"],
"echoFields": "buy_strangle_example"
})
Use this pattern for a two-leg buy strangle strategy with different call and put strikes.
from datetime import datetime
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.trading.trading_data import NubraTrader
from nubra_python_sdk.trading.trading_enum import TradingAPIVersion
nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)
instruments = InstrumentData(nubra)
market_data = MarketData(nubra)
trader = NubraTrader(nubra, version=TradingAPIVersion.V3)
def get_ref_id(asset, strike, expiry, option_type):
expiry = datetime.strptime(expiry, "%d-%m-%Y").strftime("%Y%m%d")
result = instruments.get_instruments_by_pattern([{
"exchange": "NSE",
"asset": asset,
"strike_price": str(strike * 100),
"expiry": expiry,
"option_type": option_type,
}])
return result[0].ref_id if result else None
def get_ltp(asset, strike, expiry, option_type):
ref_id = get_ref_id(asset, strike, expiry, option_type)
quote = market_data.quote(ref_id=ref_id, levels=1)
return ref_id, quote.orderBook.last_traded_price
long_put_ref_id, long_put_ltp = get_ltp("NIFTY", 23200, "17-03-2026", "PE")
short_put_ref_id, short_put_ltp = get_ltp("NIFTY", 23400, "17-03-2026", "PE")
short_call_ref_id, short_call_ltp = get_ltp("NIFTY", 23800, "17-03-2026", "CE")
long_call_ref_id, long_call_ltp = get_ltp("NIFTY", 24000, "17-03-2026", "CE")
result = trader.create_order({
"isMultiLeg": True,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY",
"entryPrice": long_put_ltp - short_put_ltp - short_call_ltp + long_call_ltp,
"legs": [
{"refId": long_put_ref_id, "unitQty": 65},
{"refId": short_put_ref_id, "unitQty": -65},
{"refId": short_call_ref_id, "unitQty": -65},
{"refId": long_call_ref_id, "unitQty": 65}
],
"stratTags": ["python-sdk-test", "nifty-iron-condor"],
"echoFields": "iron_condor_example"
})
Use this pattern for a four-leg defined-risk short-volatility strategy with wider protective wings.
from datetime import datetime
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.trading.trading_data import NubraTrader
from nubra_python_sdk.trading.trading_enum import TradingAPIVersion
nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)
instruments = InstrumentData(nubra)
market_data = MarketData(nubra)
trader = NubraTrader(nubra, version=TradingAPIVersion.V3)
def get_ref_id(asset, strike, expiry, option_type):
expiry = datetime.strptime(expiry, "%d-%m-%Y").strftime("%Y%m%d")
result = instruments.get_instruments_by_pattern([{
"exchange": "NSE",
"asset": asset,
"strike_price": str(strike * 100),
"expiry": expiry,
"option_type": option_type,
}])
return result[0].ref_id if result else None
def get_ltp(asset, strike, expiry, option_type):
ref_id = get_ref_id(asset, strike, expiry, option_type)
quote = market_data.quote(ref_id=ref_id, levels=1)
return ref_id, quote.orderBook.last_traded_price
long_put_ref_id, long_put_ltp = get_ltp("NIFTY", 23400, "17-03-2026", "PE")
short_put_ref_id, short_put_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "PE")
short_call_ref_id, short_call_ltp = get_ltp("NIFTY", 23600, "17-03-2026", "CE")
long_call_ref_id, long_call_ltp = get_ltp("NIFTY", 23800, "17-03-2026", "CE")
result = trader.create_order({
"isMultiLeg": True,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY",
"entryPrice": long_put_ltp - short_put_ltp - short_call_ltp + long_call_ltp,
"legs": [
{"refId": long_put_ref_id, "unitQty": 65},
{"refId": short_put_ref_id, "unitQty": -65},
{"refId": short_call_ref_id, "unitQty": -65},
{"refId": long_call_ref_id, "unitQty": 65}
],
"stratTags": ["python-sdk-test", "nifty-iron-butterfly"],
"echoFields": "iron_butterfly_example"
})
Use this pattern for a four-leg strategy with the short call and short put at the same strike.
Multi-Leg Behavior¶
When isMultiLeg is True, Trading API V3 treats the payload as one strategy order made from legs.
| Rule | Meaning |
|---|---|
isMultiLeg: True |
Selects the leg-based validation path. |
no top-level refId |
The instrument lives on each leg through legs[].refId. |
top-level side is required |
Use side: "BUY" for the strategy order. Leg direction still lives on each leg through the sign of legs[].unitQty. |
legs must be non-empty |
Each leg needs its own FNO refId and signed unitQty. |
qty is the strategy multiplier |
Use qty: 1 for one strategy unit. Do not put the option lot size in qty. |
legs[].unitQty is the signed lot quantity |
Positive values are buy legs and negative values are sell legs. For one NIFTY lot, use 65 or -65; for two strategy units, keep unitQty as the per-unit leg quantity and set qty: 2. |
| entry and exit controls are top-level | entryPrice, entryConfig, and exitConfig apply to the strategy order, not to individual legs. |
Execution Modes¶
Use executionMode to match the strategy lifecycle fields in the payload.
| Payload shape | executionMode |
Meaning |
|---|---|---|
The strategy has entryPrice and/or entryConfig, and no exitConfig. |
ENTRY |
Entry-only multi-leg strategy order. |
The strategy has no entryPrice or entryConfig, and has exitConfig. |
EXIT |
Exit-only multi-leg strategy order. |
The strategy has entryPrice and/or entryConfig, and also has exitConfig. |
ENTRY_AND_EXIT |
Entry multi-leg strategy order with attached stop-loss, target, trailing stop-loss, or timed exit. |
Multi-leg execution mode
executionMode is still required for the strategy order. The difference from single order is that isMultiLeg=True moves instrument direction into legs[], while executionMode still describes whether the strategy payload is defining entry, exit, or both.
Strategy side and leg direction
The top-level side is the strategy-level side required by the Trading API V3 flexi order shape. Individual leg direction is controlled by signed legs[].unitQty: positive values are buy legs and negative values are sell legs.
Python SDK Payload Shape¶
Pass one strategy dictionary to trader.create_order().
{
"isMultiLeg": true,
"qty": 1,
"side": "BUY",
"deliveryType": "CNC",
"priceType": "LIMIT",
"validityType": "DAY",
"executionMode": "ENTRY",
"entryPrice": 0,
"legs": [
{"refId": 111111, "unitQty": 65},
{"refId": 222222, "unitQty": -65}
]
}
Strategy Order Fields¶
| Field | Type | Required | Allowed values / shape | Meaning |
|---|---|---|---|---|
isMultiLeg |
bool |
yes | True |
Enables the leg-based order validation path. |
legs |
list[LegRequest] |
yes | non-empty list | FNO legs inside this one strategy order. |
legs[].refId |
int |
yes | instrument ref ID | FNO instrument reference ID for that leg. |
legs[].unitQty |
int |
yes | signed lot quantity | Per-strategy-unit leg quantity. Use positive values for buy legs and negative values for sell legs, such as 65 or -65 for one NIFTY lot. |
qty |
int |
yes | positive integer | Strategy multiplier. Use 1 for one strategy unit; do not use this field for the option lot size. |
side |
str |
yes | BUY |
Strategy-level order side required by the current flexi strategy placement path. Leg buy/sell direction is still represented by signed unitQty. |
deliveryType |
str |
yes | CNC |
Product / delivery type for the flexi FNO strategy examples. Current Trading API V3 flexi placement expects CNC for this strategy shape. |
priceType |
str |
no | LIMIT |
Price behavior for the strategy order. |
validityType |
str |
no | DAY, GTE |
Order validity. |
goodTillDate |
str |
no | date/time string | Good-till date for supported good-till workflows. |
executionMode |
str |
yes | ENTRY, EXIT, ENTRY_AND_EXIT |
Execution mode for the strategy order. Match this to the entry and exit fields in the payload. |
entryPrice |
int |
conditional | price integer | Strategy entry price or net price, as expected by Trading API V3. Required for price-based ENTRY and ENTRY_AND_EXIT payloads. Omit for EXIT-only payloads. |
entryConfig |
object |
no | see below | Delayed or trigger-based strategy entry conditions. |
exitConfig |
object |
no | see below | Strategy stop-loss, target, trailing stop, or time exit settings. |
algoId |
str |
no | string | Algo identifier when applicable. |
stratTags |
list[str] |
no | strings | Strategy or tracking tags. |
echoFields |
str |
no | string | Free-form metadata echoed back by Trading API V3. |
orderId |
int |
no | integer | Present in the SDK model but not normally sent for new create requests. |
refId |
int |
no | omit | Must be absent when isMultiLeg=True. |
icebergInfo |
object |
no | omit unless Trading API V3 enables it for this strategy | Iceberg fields exist on the SDK model, but are not part of the normal leg-based strategy shape. |
Condition Fields¶
| Field | Type | Required | Allowed values / shape | Meaning |
|---|---|---|---|---|
entryConfig.entryTime |
str |
no | date/time string | Time at which the strategy entry can activate. |
entryConfig.triggers |
list[object] |
no | trigger objects | One or more LTP trigger conditions. |
entryConfig.triggers[].kind |
str |
yes for trigger | ABOVE, BELOW, AT_OR_ABOVE, AT_OR_BELOW |
Trigger comparison. |
entryConfig.triggers[].value |
int |
yes for trigger | price integer | Trigger threshold. |
exitConfig.stoplossParams.stoplossTriggerPrice |
object |
no | {"value": int} or {"disabled": true} |
Stop-loss trigger price wrapper. |
exitConfig.stoplossParams.stoplossLimitPrice |
object |
no | {"value": int} or {"disabled": true} |
Stop-loss limit price wrapper. |
exitConfig.stoplossParams.stoplossTrailJump |
float |
no | number | Trailing stop jump. |
exitConfig.targetParams.targetProfitTriggerPrice |
object |
no | {"value": int} or {"disabled": true} |
Target trigger price wrapper. |
exitConfig.targetParams.targetProfitLimitPrice |
object |
no | {"value": int} or {"disabled": true} |
Target limit price wrapper. |
exitConfig.exitTime |
str |
no | date/time string | Time-based exit. |
Response Fields¶
| Field | Type | Meaning |
|---|---|---|
orders |
list[IntentOrderResponse] |
Created Trading API V3 strategy orders. This request normally returns one item. |
orders[].intentOrderId |
int |
Trading API V3 strategy order identifier. |
orders[].status |
str |
Current order status. |
orders[].isMulti |
bool |
True for leg-based strategy orders. |
orders[].exchange |
str |
Exchange. |
orders[].legs |
list[IntentOrderLeg] |
Leg details returned by Trading API V3. |
orders[].legs[].refId |
int |
Leg instrument reference ID. |
orders[].legs[].unitQty |
int |
Signed leg unit quantity. |
orders[].legs[].orderQty |
int |
Expanded leg order quantity. |
orders[].legs[].filledQty |
int |
Filled quantity for the leg. |
orders[].legs[].filledPrice |
int |
Fill price for the leg. |
orders[].legs[].refData |
RefData |
Leg instrument metadata. |
orders[].orderQty |
int |
Strategy quantity. |
orders[].deliveryType |
str |
Delivery type. |
orders[].priceType |
str |
Price type. |
orders[].validityType |
str |
Validity type. |
orders[].executionMode |
str |
Execution mode. |
orders[].entryConfig |
IntentOrderEntryConfig |
Entry conditions as returned by Trading API V3. |
orders[].exitConfig |
list[IntentOrderExitTrigger] |
Exit triggers as returned by Trading API V3. |
orders[].stratTags |
list[str] |
Strategy tags. |
orders[].echoFields |
str |
Echo metadata. |
orders[].entryPrice |
int |
Strategy entry price. |
orders[].ltp |
int |
Latest traded price. |
orders[].orderPrice |
int |
Order price. |
orders[].filledPrice |
int |
Fill price. |
orders[].rejectionMsg |
str |
Rejection reason when rejected. |
orders[].timestamps |
IntentOrderTimestamps |
Lifecycle timestamps. |
orders[].positionId |
str |
Position identifier when available. |
orders[].intentOrderType |
str |
Trading API V3 intent order type. |
Important Rules¶
Important Rules
- This is one strategy order, not multiple independent orders.
isMultiLegmust beTrue.legsmust be non-empty.- Top-level
refIdmust be absent. - Top-level
sideshould beBUYfor the strategy shape; leg direction is represented by signedlegs[].unitQty. - Use FNO
refIdvalues inlegs[]. - Use
deliveryType: "CNC"for the flexi FNO strategy payload. - Use
qtyas the strategy multiplier andlegs[].unitQtyas the per-leg signed lot quantity. - Use
ENTRY_AND_EXITwhen the same strategy payload has both entry fields andexitConfig. - Use Get Margin before placement when margin impact matters.