fix: resolve exchange from trading symbol in doOrder (SENSEX AB4046) - #104
Merged
Conversation
added 5 commits
August 20, 2026 10:52
SENSEX orders were failing with AB4046 'Symbol token not found in scrip master cache for the given exchange' because doOrder defaulted to 'NFO'. SENSEX trades on BFO. Derive exchange from the symbol via getIndexFromSymbol/getExchangeForIndex when not explicitly provided, and remove the hardcoded 'NFO' in placeStoplossForAllSells.
SENSEX symbols use a different date format (SENSEX2682077400CE, numeric
YYMDD) than NIFTY (NIFTY26AUG24200CE, DDMMMYY), and some SENSEX expiries
even use SENSEX26AUG76800PE. The old anchored regex only matched NIFTY
format, so SENSEX strikeprice fell back to '0' — which made the roll
logic (|ATM - prevStrike| >= strikeDiff) fire every tick and duplicate
the straddle at the same strike (20-Aug live incident: 77400 sold twice).
Strike is always the last 5 digits before CE/PE in both formats, so the
regex is now /(\d{5})([CP]E)$/ in positions.ts and paperTrade.ts.
Previously setStraddleOpenedToday ran unconditionally after the SELL
attempts, even when both orders were rejected (e.g. AB4046). The next
tick then skipped the entry ('Straddle already opened once in this
session') while positions.json was empty — no position, but the flag
blocked retries. Now capture both doOrderByStrike results and only set
the flag when ceSell.status && peSell.status are both true; otherwise
log and leave the flag false so the next tick retries.
31 strategy tests pass, tsc clean.
doOrderByStrike returns OrderData | boolean | undefined (boolean when hedge LTP>3 skip, undefined under mocks). Only treat a real object with status===true as filled. tsc clean, 31/31 strategy tests pass.
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
SENSEX orders were failing with AB4046
Symbol token not found in scrip master cache for the given exchangeon the first SENSEX expiry day (20-Aug-2026). The algo identified the right ATM/hedge strikes, fetched correct LTPs (BFO), but everyplaceOrderwas rejected.Root cause
doOrder(src/helpers/apiService/orders.ts) defaulted toexchange = 'NFO'and most call sites (doOrderByStrike, shortStraddle, closeTrade, placeStopLossOrder) never passedexchange. NIFTY trades on NFO so the bug was invisible; SENSEX trades on BFO so every order went to the wrong exchange segment → AB4046.Fix
doOrdernow resolves the exchange from the trading symbol when not explicitly provided:exchange || getExchangeForIndex(getIndexFromSymbol(tradingsymbol))→ NIFTY→NFO, SENSEX→BFOexchange: 'NFO'inplaceStoplossForAllSellsexchangein doOrder now useresolvedExchangeVerification (live, 20-Aug 10:50 IST)
After the hotfix + dist rebuild:
First live SENSEX short straddle executed: ATM 77400, hedges ±1500, lot 20.
Note
Hotfixed directly on the VPS during market hours (user-approved) — this PR formalizes it.