IOC & Auto-Reversal
Why IOC?
DAY limit orders can sit pending indefinitely. For a box spread, all 4 legs must fill or none — a partial box is unhedged. IOC forces the exchange to fill immediately or cancel. No stuck pending orders ever.
Bid/ask anchor (not LTP)
The scanner already stores the correct side of the book:
ce_ask / pe_ask for BUY legs,
ce_bid / pe_bid for SELL legs.
The executor now uses these as its price anchor.
LTP is compared only to detect if the market moved past
the scanner price since the scan, in which case LTP becomes the
new anchor. A 0.2% drift buffer covers order-arrival latency.
Why the old LTP+0.4% failed
LTP sits between bid and ask. On BANKNIFTY ATM options the half-spread is often 0.5–0.8%, so LTP + 0.4% still landed below the ask — BUY legs consistently missed. SELL legs hit the bid easily, creating the "2 SELLs filled, 2 BUYs missed" pattern seen in live metrics. Each abort cost ₹500–1000.
Why tick_round (₹0.05)?
NSE rejects orders whose price is not a multiple of ₹0.05 (error EXCH:16283). BUYs round up, SELLs round down to the nearest valid tick.
ORDER_SLIPPAGE_PCT (0.2%), the bot retries
once — re-fetching fresh LTP and using LEG_RETRY_SLIPPAGE_PCT (0.8%) as a wider
buffer (LTP-based, not bid/ask, since scanner price is now too stale to trust).
Only if the retry also fails does _auto_reverse() run — and even then it tries
IOC LIMIT at REVERSAL_LIMIT_SLIPPAGE_PCT (0.1%) first to capture more of the
bid-ask spread, falling back to MARKET only for legs that don't fill on LIMIT. You get a
Telegram "ABORTED" alert if reversal runs. All orders count toward daily_order_count.