SAHI DOCS

Python SDK

Orders

Place, modify and cancel orders, and read the order book and trades from Python.

These methods wrap the Orders endpoints one for one. Prices are paise, quantities are units, and each returns the endpoint's JSON as a dict.

Each segment takes only some products; any other raises SahiValidationException.

Segment Products
NSE C delivery, I intraday, F MTF
BSE C delivery, I intraday
NFO, BFO M carry-forward, I intraday

Live order updates are on Live streams.

Place order#

method api.place_order(...)
api.place_order(*, exchange_segment: str, symbol: str, txn_type: str, qty: int, order_type: str, product: str, validity: str, price: int, trigger_price: int | None = None, disclosed_qty: int | None = None, market_protection: float | None = None, variant: str | None = None, timeout: float | None = None) -> dict

Calls POST /v1/orders · Scope: orders.write

Sends one order. All arguments are keyword-only.

exchange_segment str Required
NSE, NFO, BSE or BFO.
symbol str Required
The scrip master's symbol, e.g. RELIANCE, NIFTY29DEC26C24500. Look it up; don't build it.
txn_type str Required
B buy, S sell.
qty int Required
Units. For F&O, a multiple of lot_size. At most the freeze quantity.
order_type str Required
LMT, MKT, SL-LMT or SL-MKT.
product str Required
C, I, M or F; see the table above.
validity str Required
DAY or IOC.
price int Required
Paise. 0 for MKT and SL-MKT; otherwise a multiple of the tick size.
trigger_price int for SL
Paise. Required for SL-LMT and SL-MKT.
disclosed_qty int Optional
Units shown to the market at once.
market_protection float Optional
MKT / SL-MKT only. Omit or -1 for auto; else 0.01 to 100 percent.
variant str Optional
AMO for an after-market order; default REGULAR.
timeout float Optional
Seconds, overriding the client default.

Returns#

{"order_ids": [...]}, always a list.

Raises#

Notes#

  • Accepted is not placed. Tick size and price band are checked after the order id is returned; a failing order then shows status Rejected with a rejection_reason. Read the status before relying on an order.
  • Market orders read back as limits. MKT and SL-MKT are converted once to protected LMT and SL-LMT, and the order book shows the converted type and price.
  • After-market orders. Send variant=SahiAPI.VARIANT_AMO only while the market is closed; it goes out at the next open. See Market hours.

Example — a stop-loss buy#

Triggers if the price rises to trigger_price, then sends a limit at price.

Find the order after a timeout#

There is no client order id, so match the order book on what you sent. Treat more than one match as a case to resolve by hand.

Modify order#

method api.modify_order(...)
api.modify_order(order_id: str, *, qty: int | None = None, price: int | None = None, order_type: str | None = None, validity: str | None = None, trigger_price: int | None = None, disclosed_qty: int | None = None, market_protection: float | None = None, timeout: float | None = None) -> dict

Calls PUT /v1/orders/{order_id} · Scope: orders.write

Changes an Open or OpenPartial order. Pass only the fields you change.

order_id str Required
From place_order or the order book.
qty int Optional
New total quantity, in units.
price int Optional
New limit price, in paise.
order_type str Optional
New order type.
validity str Optional
DAY or IOC.
trigger_price int Optional
Paise, for stop orders.
disclosed_qty int Optional
Units.
market_protection float Optional
Only with a change to MKT or SL-MKT.
timeout float Optional
Seconds.

Returns#

{"order_id": "..."}.

Raises#

Cancel order#

method api.cancel_order(...)
api.cancel_order(order_id: str, *, timeout: float | None = None) -> None

Calls DELETE /v1/orders/{order_id} · Scope: orders.write

Cancels an Open or OpenPartial order. Returns None.

order_id str Required
The order to cancel.
timeout float Optional
Seconds.

Raises#

Order book#

method api.get_order_list(...)
api.get_order_list(*, timeout: float | None = None) -> dict

Calls GET /v1/orders · Scope: orders.read

Every order on the account today, in any status.

Returns#

{"orders": [...]}; fields are on the endpoint.

Raises#

Order details#

method api.get_order_detail(...)
api.get_order_detail(order_id: str, *, timeout: float | None = None) -> dict

Calls GET /v1/orders/{order_id} · Scope: orders.read

One order, with the same fields as an order-book entry. Right after placing, wait a second before reading it.

Raises#

Trades for an order#

method api.get_trade_list_for_order(...)
api.get_trade_list_for_order(order_id: str, *, timeout: float | None = None) -> dict

Calls GET /v1/orders/{order_id}/trades · Scope: orders.read

The fills behind one order; empty if it has not traded.

Returns#

{"trades": [...]}.

Raises#

  • Rate limit as for get_order_list.