🛡️ Algo-Trading on NSE: Beating the Strategy ≠Everything Myth
6/13/2025
đź§© 1 | Strategy Is Just One Piece#
Everyone obsesses over the edge: latency-arb between NSE & BSE, iron-fly gamma scalps—pick your poison.
What most retail coders skip is the other half of the equation:
Layer | Gotcha |
---|---|
Exchange timing | No orders before 09 : 15 / after 15 : 30 (unless it’s a special Mahurat). |
TOPS limit | NSE Circular NSE/INVG/67858 (05-May-2025) caps unregistered algos at 10 order submissions and 10 cancels per second. |
Circuit validation | Every price must sit inside live upper/lower circuit. |
Symbol bans | GSM series, invalid tokens, “Check Holdings” rejections—all get flagged by broker RMS. |
Crack a strategy and ignore these and you’ll be throttle-killed or even blocked.
🛠️ 2 | Our Compliance Toolkit#
2.1 Market-Timing Gatekeeper#
MarketTiming
utility lazily fetches today’s timetable (handles Muhurat, Saturday Budget day, etc.).BuyArbitrage
refuses to submit beforemarket_open_time
or aftermarket_close_time
.- Price snapshots taken in pre-open are logged but never traded.
2.2 Token-Bucket Limiter (10 TPS)#
class TokenBucket:
def __init__(self, rate=10):
self.rate, self.cap = rate, rate
self.tok, self.ts = self.cap, time.monotonic()
self.lock = asyncio.Lock()
async def acquire(self):
async with self.lock:
now = time.monotonic()
self.tok = min(self.cap, self.tok + (now - self.ts) * self.rate)
self.ts = now
if self.tok < 1:
await asyncio.sleep((1 - self.tok) / self.rate)
self.tok -= 1
- One instance for submits, one for cancels → cannot bust 10 / sec.
- Latency impact ≤ 1 ms in normal flow, < 100 ms in overload bursts.
2.3 Drift Band Before Cancel#
drift = abs(live_price - order_price) / order_price * 100
if drift < 0.10: # 10 bp tolerance
keep_alive()
else:
schedule_cancel()
Eliminated ~70 % of our cancels that were previously spammed for 1-tick moves.
2.4 Symbol Black-Lists#
Trigger text in broker rejection | Action |
---|---|
Invalid Trading Symbol | Add symbol to runtime blacklist; skip for rest of day. |
SCRIP BELONGS TO GSM | Ditto. |
Check Holdings | Ditto. |
🏛️ 3 | What If You Need > 10 TPS?#
- Register the strategy via your broker → obtain an Algo ID.
- Broker files risk-control checklist with NSE Algo Cell.
- Exchange can lift your limit (20–50 TPS common), but you must tag every order with that Algo ID and keep audit logs for three years.
See Zerodha’s note on Algo approval & throughput and TrueData’s summary of the 05-May-2025 circular here.
🔬 4 | Results#
Metric | Pre-fix | Post-fix |
---|---|---|
Average cancels / sec | 117 | 3.5 |
OTR (Order-to-Trade) | 42 : 1 | 11 : 1 |
Exchange warnings | Weekly calls from RMS | 0 since 01-June-2025 |
Fill-rate stayed flat at 96 % within our 0.3 % spread threshold.
🚀 5 | Takeaways#
- Speed without compliance is useless—exchange will strand you.
- A 50-line token bucket and a 10-bp drift band fix 90 % of cancel spam.
- Register the algo only if you really need > 10 TPS; most edges don’t.
- Keep circuit, timing and blacklist logic isolated—you’ll sleep better during upgrades.