ट्रेडिंग बॉट के लिए सर्किट ब्रेकर कैसे काम करते हैं
सर्किट ब्रेकर खराब सत्र के बढ़ने से पहले ट्रेडिंग बॉट रोकते हैं। जानें daily loss limit कितनी बार सक्रिय होती है और volatility scaling position size को कैसे बदलती है।
Trading bots के लिए circuit breakers ऐसे नियम होते हैं जो तय सीमा पहुंचते ही automated strategy को orders भेजने से रोक देते हैं। ये strategy और broker के बीच risk layer में काम करते हैं। ये हर order पर लागू होते हैं, चाहे strategy उनसे सहमत हो या नहीं। Strategy यह तय करती है कि क्या trade करना है। Risk layer यह तय करती है कि trading होनी भी चाहिए या नहीं।
यही इस design का मूल विभाजन है। जो strategy खुद की निगरानी करती है, उसके पास उस क्षण कोई स्वतंत्र जांच नहीं होती जब उसकी अपनी धारणाएं टूटती हैं। और यही वह क्षण होता है जब स्वतंत्र जांच सबसे जरूरी होती है।
ट्रेडिंग बॉट में सर्किट ब्रेकर क्या करता है
जोखिम-नियंत्रण परत के चार हिस्से होते हैं। हर हिस्सा एक खास और सामान्य विफलता को रोकने के लिए होता है।
- पोजीशन आकार, प्रत्येक symbol का notional exposure और orders की दर पर कठोर सीमाएँ। ये उस bug से होने वाले नुकसान को सीमित करती हैं, जो अन्यथा बिना सीमा के बढ़ सकता है।
- Drawdown circuit breaker, जो सत्र के दौरान account में तय राशि की गिरावट होने पर या equity के उच्चतम स्तर से तय राशि नीचे आने पर नए orders रोक देता है।
- स्केल किया हुआ order sizing, जिसे हाल की volatility या fixed share count के बजाय Kelly bet के एक हिस्से के आधार पर तय किया जाता है। इससे बाजार की range बदलने पर भी प्रत्येक trade का जोखिम लगभग स्थिर रहता है।
- हर decision का append-only audit log, जिसमें वे orders भी शामिल होते हैं जिन्हें risk layer ने अस्वीकार किया। यही एकमात्र रिकॉर्ड है जो यह स्पष्ट करता है कि “strategy गलत थी” या “जाँच चली ही नहीं।”
नीचे दिया गया पूरा विवरण इन्हीं चार हिस्सों में से एक को व्यावहारिक रूप में समझाता है।
ट्रेडिंग bot के लिए उचित दैनिक नुकसान सीमा क्या है?
दैनिक नुकसान सीमा तब नए ऑर्डर रोक देती है, जब उस सत्र का नुकसान तय सीमा से अधिक हो जाता है। यह संख्या पसंद का मामला नहीं, बल्कि calibration का विषय है। सीमा सामान्य market noise के भीतर रखेंगे, तो bot अधिकांश सप्ताह halted रहेगा। इसे बहुत दूर रखेंगे, तो यह कभी सक्रिय नहीं होगा। शुरुआत इस बात से होती है कि बाजार स्वयं किसी निश्चित आकार का गिरावट वाला दिन कितनी बार देता है।
हर आंकड़े के पीछे का पूरा SQL
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2017-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
with_prev AS (
SELECT d,
close_px,
any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT toYear(d) AS year,
countIf(close_px / prev_close - 1 <= -0.01) AS down_1pct_days,
countIf(close_px / prev_close - 1 <= -0.02) AS down_2pct_days,
countIf(close_px / prev_close - 1 <= -0.03) AS down_3pct_days
FROM with_prev
WHERE prev_close > 0
AND d >= toDate('2018-01-01')
GROUP BY year
ORDER BY year1% या उससे अधिक गिरावट वाले सत्रों की संख्या 15 थी, 2019 में, और 45 थी, 2020 में। एक वर्ष में लगभग 250 trading days होते हैं। 3% या उससे अधिक गिरावट वाले सत्रों की तस्वीर अलग है: 0, 2019 की तुलना में 16, 2020 में। 9 की अंतिम पंक्ति में केवल 31 जुलाई 2026 तक के सत्र शामिल हैं।
यह रेखा लगातार नहीं, बल्कि असमान रूप से आगे बढ़ती है। यही इस सीमा-निर्धारण का मुख्य बिंदु है। कठिन trading days समूहों में आते हैं। यदि bot किसी समूह के पहले दिन halt हो जाए और दूसरे दिन फिर शुरू हो जाए, तो वह वास्तव में halt नहीं हुआ।
दो सीमाएँ अलग-अलग काम करती हैं। दैनिक नुकसान सीमा, जो आमतौर पर account equity के 2% पर रखी जाती है, सत्र समाप्त कर देती है। Equity के high-water mark से मापी जाने वाली trailing drawdown limit, जो आमतौर पर लगभग 10% होती है, human review तक strategy को रोक देती है। पहली नियमित सुरक्षा है, जबकि दूसरी दुर्लभ स्थिति के लिए होती है। केवल पहली सीमा वाला bot किसी account को हर बार 2% घटाते हुए लगातार नीचे ले जा सकता है और फिर भी कभी कोई सुरक्षा सक्रिय नहीं होगी।
अस्थिरता स्केलिंग पोजीशन आकार को कैसे बदलती है?
अस्थिरता लक्ष्यीकरण हाल की वास्तविकीकृत अस्थिरता के उलटे अनुपात में पोजीशन का आकार तय करता है: जब दैनिक रेंज दोगुनी हो जाती है, तो पोजीशन लगभग आधी रह जाती है। इससे प्रति ट्रेड डॉलर जोखिम लगभग स्थिर रहता है। यहां वास्तविकीकृत अस्थिरता दैनिक रिटर्न के वार्षिकीकृत मानक विचलन को दर्शाती है। यह अधिकांश लोगों की अपेक्षा से अधिक तेजी से बदलती है।
हर आंकड़े के पीछे का पूरा SQL
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2023-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
rets AS (
SELECT d,
close_px / any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) - 1 AS ret
FROM daily
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(stddevSamp(ret) * sqrt(252) * 100, 1) AS realized_vol_pct,
round(least(100.0, 1200.0 / (stddevSamp(ret) * sqrt(252) * 100)), 1) AS vol_target_size_pct
FROM rets
WHERE d >= toDate('2024-01-01')
AND isFinite(ret)
GROUP BY toStartOfMonth(d)
HAVING count() >= 15
ORDER BY toStartOfMonth(d)वास्तविकीकृत अस्थिरता को 11.1% के दौरान 2024-01 में वार्षिकीकृत और 12% में 2026-07 के पार 31 महीनों में मापा गया। दूसरा कॉलम प्रत्येक रीडिंग को उस पोजीशन में बदलता है, जिसे 12% अस्थिरता लक्ष्य वाली रणनीति रखेगी। इसकी अधिकतम सीमा पूरी लाइन पर है: 100%, जबकि 2024-01 के मुकाबले 99.7% 2026-07 है। रणनीति वही है और विश्वास का स्तर भी वही है, लेकिन शेयरों की संख्या बहुत अलग है।
Kelly criterion इसी समस्या को दूसरे छोर से देखता है। इसमें आकार केवल अस्थिरता के आधार पर नहीं, बल्कि अनुमानित बढ़त और variance के आधार पर तय किया जाता है। अधिकांश systematic operators इसका एक अंश इस्तेमाल करते हैं—आधा या एक-चौथाई Kelly—क्योंकि दोनों इनपुट सीमित नमूने से प्राप्त अनुमान होते हैं। Kelly criterion के आधार पर पोजीशन का आकार इसी गणना को समझाता है।
स्टॉप के बाद ट्रेडिंग बॉट बार-बार दोबारा एंट्री क्यों करता है?
स्टॉप ट्रिगर होता है। पोजीशन बंद हो जाती है। नब्बे सेकंड बाद एंट्री की शर्त फिर से पूरी हो जाती है। बॉट दोबारा एंट्री करता है, वही नुकसान उठाता है और यह सिलसिला दोहराता रहता है। कोई एक घटक खराब नहीं है। रणनीति ने वही किया जिसके लिए उसे लिखा गया था। स्टॉप ने भी वही किया जिसके लिए उसे लिखा गया था। फिर भी खाते में हर राउंड-ट्रिप पर थोड़ा-थोड़ा नुकसान होता रहता है।
यह आवृत्ति सीधे प्राइस पाथ से आती है। यह पैनल हर सत्र में गिनता है कि SPY अपने शुरुआती मूल्य से 0.1% से अधिक ऊपर जाने के बाद 0.1% से अधिक नीचे कितनी बार गया, या इसके उलट कितनी बार हुआ।
हर आंकड़े के पीछे का पूरा SQL
WITH mins AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
window_start AS ts,
toFloat64(close) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2025-08-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
),
opens AS (
SELECT d, argMin(px, ts) AS open_px
FROM mins
GROUP BY d
),
zoned AS (
SELECT m.d AS d,
m.ts AS ts,
multiIf(m.px >= o.open_px * 1.001, 1,
m.px <= o.open_px * 0.999, -1,
0) AS zone
FROM mins AS m
INNER JOIN opens AS o ON m.d = o.d
),
flips AS (
SELECT d,
zone,
any(zone) OVER (PARTITION BY d ORDER BY ts ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_zone
FROM zoned
WHERE zone != 0
),
per_day AS (
SELECT d, countIf(prev_zone != 0 AND zone != prev_zone) AS crossings
FROM flips
GROUP BY d
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(avg(crossings), 1) AS avg_crossings_per_session,
max(crossings) AS max_crossings_in_a_session
FROM per_day
GROUP BY toStartOfMonth(d)
ORDER BY toStartOfMonth(d)2025-08 और 2026-07 में SPY ने उस बैंड को प्रति सत्र औसतन क्रमशः 0.7 और 1.5 बार पार किया। 2026-07 के एक सत्र में 5 क्रॉसिंग दर्ज हुईं। किसी स्तर के एक ओर खुलने और दूसरी ओर स्टॉप होने वाली हर rule को एक ही दिन में उतनी बार ट्रिगर होने का अवसर मिलता है।
चार उपाय इसे नियंत्रित करते हैं।
- हर स्टॉप के बाद cooldown रखें। इसे मिनटों या bars में मापा जाए। इस अवधि में उस symbol के लिए कोई नया order risk layer से आगे न जाए।
- प्रति symbol दैनिक trade-count cap रखें। इससे अनियंत्रित loop सीमित हो जाता है।
- ऐसा halt flag रखें जो latch हो जाए। दैनिक नुकसान की सीमा पार होने के बाद यह flag तब तक सक्रिय रहे, जब तक कोई व्यक्ति इसे manually clear न करे।
- इस flag को process memory के बाहर persist करें। क्रैश हुए bot को restart करने वाला supervisor उसे नई स्थिति से शुरू कर सकता है। यही वह स्थिति है जिसे रोकने के लिए flag बनाया गया है।
आखिरी उपाय उन लोगों के लिए महत्वपूर्ण है जिन्होंने बाकी सब सही किया हो। Grid trading bots डिजाइन के अनुसार orders की ladders लगाते हैं। इसलिए trade-count cap केवल दिखावटी नियंत्रण नहीं, बल्कि एक आवश्यक सुरक्षा है।
जब कोई bot पुराने price feed पर ट्रेड करता है तो क्या होता है?
जो quote अपडेट होना बंद हो गया है, वह अब भी एक संख्या जैसा दिखता है। bot उसे पढ़ता है, उसी के आधार पर order का price तय करता है और उस order को ऐसे market में भेज देता है जो आगे बढ़ चुका है। यह failure बिना किसी स्पष्ट संकेत के होता है: कुछ भी exception नहीं देता, कोई error log नहीं बनता और fills केवल बाद में असामान्य दिखते हैं।
इसे साफ़ तौर पर मापने का तरीका overnight gap है। इसमें कोई ज्ञात price घंटों तक बिना बदले रहता है, जबकि tradable price बदलता रहता है।
हर आंकड़े के पीछे का पूरा SQL
WITH daily AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMin(toFloat64(open), window_start) AS open_px,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'KO', 'MSFT', 'AAPL', 'NVDA', 'TSLA')
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2024-01-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, d
),
gaps AS (
SELECT ticker,
d,
open_px,
any(close_px) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT ticker,
round(quantileDeterministic(0.5)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS median_gap_pct,
round(quantileDeterministic(0.95)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS p95_gap_pct,
round(max(abs(open_px / prev_close - 1) * 100), 2) AS max_gap_pct
FROM gaps
WHERE prev_close > 0
GROUP BY ticker
ORDER BY p95_gap_pct DESC95th-percentile gap के आधार पर सबसे बड़ा gap TSLA में था, जो 4.41% रहा। इसकी तुलना में KO का gap 1% था। सामान्य रातें कहीं शांत थीं: median gap क्रमशः 1.01% और 0.24% रहे। Risk layer tail events से निपटने के लिए बनाई जाती है। मापी गई अवधि में TSLA का सबसे बड़ा single gap 14.57% था। ये वे price distances हैं जिन पर कोई bot कुछ समय पहले पढ़े गए price के आधार पर कार्रवाई कर सकता है। शेयर रातोंरात gap क्यों करते हैं में इसकी प्रक्रिया समझाई गई है।
इनसे बचाव के उपाय सस्ते हैं। हर quote के लिए अधिकतम age तय करें, जिसके आधार पर risk layer price तय करेगी। Intraday strategy में यह सीमा आमतौर पर कुछ seconds होती है। Feed से heartbeat को data से अलग प्राप्त करें। इससे silent socket और शांत market के बीच अंतर पता चलता है। Missing data को hold के बजाय halt मानें, क्योंकि बिना prices वाला bot अपने exits का भी मूल्यांकन नहीं कर सकता।
जोखिम परत में कौन-सी कठोर सीमाएँ होनी चाहिए?
- खाते की इक्विटी के अनुपात के रूप में प्रत्येक symbol का अधिकतम notional। 10% की सीमा यह सुनिश्चित करती है कि किसी एक खराब symbol से पूरा खाता प्रभावित न हो।
- सभी खुले positions का अधिकतम सकल notional। इसे इक्विटी के 100% पर निर्धारित करने का अर्थ है कि leverage नहीं होगा। इस निर्णय को broker की default setting से विरासत में लेने के बजाय स्पष्ट रूप से करना चाहिए।
- प्रति मिनट और प्रति दिन orders की अधिकतम संख्या। अधिकांश retail strategies के लिए प्रति मिनट ten orders पर्याप्त उदार सीमा है। फिर भी यह एक मिनट के भीतर चलने वाले अनियंत्रित loop को सीमित करती है।
- symbol के average daily volume के अनुपात के रूप में order का अधिकतम आकार। 1% की सीमा bot को उस कीमत को प्रभावित करने से रोकती है, जिस पर वह trade करने की कोशिश कर रहा है। average daily volume इसका denominator है।
इनमें से हर सीमा strategy के बजाय risk layer में होनी चाहिए। हर सीमा backtest, paper और live में एक ही code path के माध्यम से लागू होनी चाहिए। जो limit केवल live में मौजूद हो, वह ऐसी limit है जिसका किसी ने परीक्षण नहीं किया है।
ट्रेडिंग बॉट के ऑडिट लॉग में क्या होना चाहिए?
Append-only लॉग हर निर्णय के लिए एक रिकॉर्ड लिखता है और उसे कभी संपादित या हटाता नहीं है। हर रिकॉर्ड में timestamp, इस्तेमाल किया गया quote और उसकी age, चलाए गए हर limit check का verdict, भेजा गया order और broker का जवाब शामिल होता है। Rejected orders को filled orders के समान महत्व के साथ दर्ज किया जाता है।
पुनर्निर्माण ही इसका उद्देश्य है। खराब trading session के छह सप्ताह बाद सवाल यह नहीं होता कि P&L क्या था। सवाल यह होता है कि कौन-सा check पास हुआ और किस input पर हुआ। दर्ज input के बिना आप bot की स्थिति को market की स्थिति से दोबारा निकालने लगते हैं। यह वही गलती है जो backtesting में look-ahead bias में होती है: ऐसे information का इस्तेमाल करना जो निर्णय के समय system के पास उपलब्ध नहीं थी।
riskguard project इस separation का एक open-source implementation है। इसमें limit checks strategy के भीतर बिखरे हुए logic के बजाय उस component में रहते हैं जिसे strategy call करती है। यह कई designs में से एक है। इसे बिना जाँच अपनाने के बजाय पढ़ना उपयोगी है। आप जिस भी चीज़ पर निर्भर हों, default branch के बजाय tagged release को pin करें। एक ही backtest के दो runs के बीच branch बदल सकती है। चुपचाप बदली हुई risk layer, risk layer न होने से भी बदतर होती है।
पहली तैनाती paper broker पर क्यों चलती है
Broker adapter का default paper पर होता है। Live trading जानबूझकर एक स्पष्ट flag सेट करने पर ही सक्रिय होती है। इससे एक सामान्य लेकिन गंभीर गलती रोकी जाती है: कॉपी की गई config file या ऐसा environment variable जिसे override नहीं किया गया, वास्तविक धन से वास्तविक orders भेज सकता है।
Paper run वह महत्वपूर्ण artifact भी तैयार करता है: live prices पर उसी risk layer से बना decision log। इससे पता चलता है कि कौन-सी सीमाएँ सक्रिय हुईं और कौन-सी नहीं। यह risk layer के बारे में प्रमाण है। यह इस अलग प्रश्न का उत्तर नहीं देता कि strategy पैसा कमाती है या नहीं। वास्तविक धन लगाने से पहले paper trading बताता है कि paper record क्या साबित करता है और क्या नहीं। multi-agent AI trading systems दिखाता है कि जब कई agents orders दे सकते हों, तो halt authority हर agent से बाहर क्यों रखनी चाहिए।
Trading bot circuit breaker FAQ
Trading bot में circuit breaker क्या होता है?
यह risk layer में लगा ऐसा नियम है, जो तय सीमा पार होने पर bot को नए orders भेजने से रोक देता है। यह सीमा आमतौर पर दैनिक नुकसान की threshold या account equity के उच्चतम स्तर से drawdown होती है। यह हर order पर strategy से स्वतंत्र रूप से लागू होता है और तब तक सक्रिय रहता है, जब तक कोई प्रक्रिया इसे clear न कर दे।
बाजार में 2% की गिरावट वाला दिन कितनी बार आता है?
2019 में SPY में 5 sessions ऐसे रहे, जिनमें गिरावट 2% या उससे अधिक थी। 2020 में यह संख्या 25 रही। हर वर्ष लगभग 250 trading days होते हैं। शांत वर्ष और तनावपूर्ण वर्ष के बीच यह अंतर बताता है कि loss limit को अनुमान के बजाय ऐतिहासिक आंकड़ों के आधार पर calibrate करना चाहिए।
Stop के बाद bot को दोबारा entry लेने से कैसे रोकते हैं?
हर stop के बाद cooldown window और प्रत्येक symbol के लिए दैनिक trade cap लगाने से अनियंत्रित loop सीमित हो जाता है। Halt flag को process memory के बाहर भी latch और persist करना जरूरी है। ऐसा न होने पर crashed bot को restart करने वाला supervisor उसे फिर से सक्रिय, बिना halt वाला state दे सकता है।
Bot कैसे पहचान सकता है कि price feed पुराना हो गया है?
Order की pricing करने से पहले हर quote की age जांचकर और data से अलग feed के heartbeat पर नजर रखकर। Overnight gaps बताते हैं कि stale price कितना बड़ा जोखिम छिपा सकता है। जनवरी 2024 से जुलाई 2026 के बीच TSLA को 95th-percentile overnight move 4.41% तक पहुंचा।
क्या छोटे trading bot को वास्तव में audit log की जरूरत होती है?
Fills का log बताता है कि क्या हुआ। Decisions का log बताता है कि bot को लगा कि उसे क्या करने की अनुमति थी। यही गलत strategy और ऐसे risk check के बीच अंतर बताने का एकमात्र तरीका है, जो कभी चला ही नहीं। Append-only log, जिसमें rejections भी शामिल हों, उपयोगी न्यूनतम संस्करण है।
ऊपर दिया गया हर आंकड़ा minute bars पर चलाए गए stored query से लिया गया है। हर panel में उसके पीछे का SQL खुलता है। इन्हीं queries को Strasmore terminal पर अपनी symbol list के लिए चलाएं।