4 सितंबर 2026 · बैकटेस्टिंग

आपका स्टॉप और लक्ष्य, दोनों एक ही बार के भीतर थे। आपके बैकटेस्ट ने किसे चुना?

आपका स्टॉप और लक्ष्य, दोनों एक ही बार के भीतर थे। आपके बैकटेस्ट ने किसे चुना?

84,120 पर लॉन्ग। स्टॉप 84,036 पर, लक्ष्य 84,271 पर। अगले मिनट का बार आता है: ओपन 84,118, हाई 84,290, लो 84,010, क्लोज़ 84,240।

दोनों स्तर उस बार के भीतर हैं। स्टॉप भी छुआ गया और लक्ष्य भी, और OHLC के 4 नंबरों में यह जानने की बिल्कुल भी जानकारी नहीं है कि पहले कौन-सा छुआ गया। फिर भी आपके बैकटेस्ट ने एक नतीजा दिया। लूप में कहीं एक लाइन ने फैसला कर लिया — शायद ऐसी लाइन, जिसे लिखते समय आपने मॉडलिंग की धारणा नहीं माना होगा।

कम अवधि की रणनीतियों में मुझे नकली प्रदर्शन का सबसे बड़ा कारण यही दिखता है — फीस और स्लिपेज से भी बड़ा — क्योंकि यह किसी धारणा जैसा नहीं दिखता। यह तो बस कोड का जोड़-तोड़ लगता है।

गलत तरीका 1: फैसला if-चेन पर छोड़ देना

आम तौर पर कोड कुछ ऐसा होता है:

if bar.high >= target:
    exit(target, "tp")
elif bar.low <= stop:
    exit(stop, "sl")

किसी ने यह नहीं चुना था कि “लक्ष्य का फैसला स्टॉप से पहले होगा।” लक्ष्य की जाँच पहले लिखी गई, क्योंकि वही मनचाहा रास्ता था और उसी के बारे में आप सोच रहे थे। दोनों ब्रांच की जगह बदलते ही इक्विटी कर्व बदल जाता है; इससे ही पता चल जाना चाहिए कि आपकी रणनीति का P&L कुछ हद तक इस बात पर निर्भर है कि आपने एडिटर में क्या पहले टाइप किया।

मैंने BTCUSDT perp पर एक जान-बूझकर साधारण मीन-रिवर्ज़न स्कैल्पर चलाया: 1-मिनट बार के 3 महीने, 4,812 ट्रेड, एंट्री से 0.10% पर स्टॉप और 0.18% पर लक्ष्य। सिग्नल वही, फीस वही — सिर्फ टाई-ब्रेक का नियम बदला।

12.6%ट्रेड में एक ही बार के भीतर दोनों स्तर छुए गए
2.31Sharpe, लक्ष्य का फैसला पहले
0.18Sharpe, स्टॉप का फैसला पहले
0.94Sharpe, 1-सेकंड बार पर फैसला

आठ में से एक ट्रेड पूरे नतीजे को अपने साथ ले जाता है। टाइट स्टॉप-और-लक्ष्य जोड़ी का गणित यही है: अस्पष्ट ट्रेड वे होते हैं जिनमें कीमत दोनों तरफ गई — यानी ज़्यादातर दिलचस्प ट्रेड — और सिक्का उछालने जैसे इस फैसले के आधार पर हर ट्रेड का मूल्य पूरे स्टॉप-से-लक्ष्य अंतर जितना होता है। ट्रेड का 12.6% × 0.28% का अंतर = सैंपल की हर इकाई पर ग्रॉस नॉशनल टर्नओवर का 3.5%, जो रणनीति के असली एज से कहीं बड़ा है।

यह दर आपके बार के आकार और स्तरों के बीच की दूरी पर निर्भर करती है, और बार जितने लंबे होते हैं, उतनी ही तेज़ी से बिगड़ती है। स्टॉप और लक्ष्य वही, सिग्नल वही, बस अलग-अलग अंतराल पर री-सैंपल किया:

बार का अंतरालएक बार के भीतर दोनों स्तर वाले ट्रेडSharpe (लक्ष्य पहले)
1s0.3%0.91
1m12.6%2.31
5m34%3.60
15m49%4.42
1h71%5.88

देखिए, यह तालिका असल में क्या कह रही है। मोटे बार ने बैकटेस्ट को बेहतर बना दिया। हर रिसर्चर को लगता है कि घंटे वाले बार ज़्यादा सतर्क विकल्प हैं: कम शोर, माइक्रोस्ट्रक्चर के हिसाब से कम ओवरफिटिंग। लेकिन जब इंट्राबार का नियम आपके पक्ष में फैसला करता है, तो मोटा बार बस एक बड़ा डिब्बा है जिसके भीतर आप मान सकते हैं कि किस्मत आपके साथ थी। 1h बार पर 10 में से 7 ट्रेड सिर्फ नियम के भरोसे तय होते हैं। वह बैकटेस्ट रणनीति नहीं जाँच रहा; वह 3,400 बार दो `if` स्टेटमेंट के क्रम को परख रहा है।

गलत तरीका 2: मान लेना कि स्टॉप, स्टॉप की कीमत पर भरा गया

मान लें कि आपने क्रम ठीक कर लिया। स्टॉप का फैसला पहले होता है, आप ठीक 0.10% के नुकसान के साथ taker fee जोड़कर हिसाब दर्ज करते हैं, और आपको लगता है कि आपने सावधानी बरती। फिर भी 2 अलग-अलग बातें गलत हैं।

पहली बात यह कि स्टॉप एक ट्रिगर है, फिल नहीं। Binance USDⓈ-M पर STOP_MARKET ऑर्डर ट्रिगर की शर्त पूरी होते ही मार्केट ऑर्डर बन जाता है, फिर वह ऑर्डर बुक में जो भी हो उसे खा जाता है। शांत मिनट में स्लिपेज 1 या 2 टिक का होता है। जिस मिनट आपका स्टॉप सचमुच ट्रिगर हुआ — 40 पॉइंट की कैंडल बॉडी और उसके नीचे लिक्विडेशन की तेज़ लहर वाला मिनट — उसमें जिस तरफ आप ऑर्डर पार कर रहे हैं, उसी तरफ ऑर्डर बुक पतली होती है। अपने सैंपल में टिक टेप से स्टॉप ट्रिगर का मिलान करने पर मीडियन फिल ट्रिगर से 1.4 bps आगे था और 95वाँ परसेंटाइल 11 bps था। 10 bps के स्टॉप पर, इस आखिरी हिस्से की कीमत उस जोखिम का एक अतिरिक्त दसवाँ हिस्सा है जिसे आपने तय समझा था।

दूसरी बात थोड़ी पेचीदा है और perps के लिए खास है: इसे ट्रिगर कौन-सी कीमत करती है। Binance डिफ़ॉल्ट रूप से स्टॉप ऑर्डर को mark price पर ट्रिगर करता है, और mark price इंडेक्स और स्मूद किए गए बेसिस से बनती है, उस एक्सचेंज के आखिरी ट्रेड से नहीं। आपका OHLC सिलसिला last price का है। ये अलग-अलग सिलसिले हैं, और ठीक उन्हीं घटनाओं में सबसे ज़्यादा अलग होते हैं जो स्टॉप ट्रिगर करती हैं।

Last price (आपकी klines)Mark price (डिफ़ॉल्ट ट्रिगर)
स्रोतइस एक्सचेंज के ट्रेडकई एक्सचेंजों का इंडेक्स + बेसिस
विक की चालपूरी हलचलकाफी सीमित
आम तौर पर अंतरशांत समय में 1–3 bps, लिक्विडेशन की तेज़ लहर वाले मिनट में 20–35 bps
बैकटेस्ट पर असरऐसे स्टॉप जो ट्रिगर हुए पर होने नहीं चाहिए थे, और इसके उलट भी

इसलिए last-price टेप पर 25 bps की विक बैकटेस्ट में आपको स्टॉप आउट कर देती है, जबकि लाइव mark price आपके ट्रिगर से 10 bps के भीतर भी नहीं आई। या इसका उलटा होता है, उस दिन जब इंडेक्स चलता है और आपका एक्सचेंज पीछे रह जाता है। अगर आप workingType को CONTRACT_PRICE पर सेट करते हैं, तो कम से कम लाइव व्यवहार आपके डेटा के अनुरूप हो जाता है। रिसर्चर के लिए आम तौर पर यही सही विकल्प है, क्योंकि mark-price ट्रिगर का ईमानदार सिमुलेशन करने के लिए आपको अपने पूरे fill engine में दूसरी प्राइस सीरीज़ साथ रखनी होगी।

इसका जो उदाहरण मुझे सबसे अच्छी तरह याद है: हमारी टीम के किसी व्यक्ति ने टेक-प्रॉफिट को 0.18% से 0.21% करके एक रणनीति को “बेहतर” बनाया। Sharpe 2.3 से 3.1 हो गया। कोई नया एज नहीं था। लक्ष्य बस 1-मिनट विक के वितरण के घने हिस्से से बाहर चला गया था, इसलिए कम ट्रेड उस अस्पष्ट समूह में आए जहाँ कोड चुपचाप उन्हें जीत दे रहा था। उन्होंने टाई-ब्रेकर को ऑप्टिमाइज़ किया था।

गलत तरीका 3: हमेशा सबसे बुरा मानकर उसे सतर्कता कहना

तुरंत सूझने वाला हल है निराशावाद। अगर दोनों स्तर छुए गए, तो स्टॉप मान लो। बस, अब कोई आशावाद नहीं, इसे जारी करो।

मैं पहले ऐसा किया करता था। यह दूसरे विकल्प से बेहतर है, फिर भी 2 वजहों से गलत है।

इससे ठीक-ठाक रणनीतियाँ भी खत्म हो जाती हैं। 12.6% ट्रेड पर निराशावादी फैसला मानने से इस रणनीति का Sharpe, टिक के हिसाब से तय हुए 0.94 के मुकाबले 2.1 पॉइंट घट गया। अगर असली संख्या 0.94 है और आपका नियम 0.18 दिखाता है, तो आप यह आइडिया छोड़कर किसी बदतर चीज़ पर काम करने लगेंगे। 2 Sharpe पॉइंट से चूकने वाली सतर्कता, सतर्कता नहीं; नैतिकता का लिबास पहने शोर है।

इससे भी बुरा, यह ऑप्टिमाइज़ेशन को दूषित करता है। पैरामीटर स्वीप को निराशावादी टाई-ब्रेकर दें, तो ऑप्टिमाइज़र अस्पष्टता से बचना सीखता है, क्योंकि अब अस्पष्टता का मतलब सिर्फ नुकसान है। वह चौड़े स्टॉप और पास के लक्ष्य, या धीमे बार चुनने लगेगा जहाँ दोनों स्तर एक साथ कम ही आते हैं। फिर वह ऐसे पैरामीटर दिखाएगा जो बाज़ार के बजाय आपके fill नियम के आधार पर चुने गए हैं। उदार नियम में भी यही नाकामी होती है, बस दिशा उलटी और tearsheet में उतनी ही अदृश्य।

हमारा शुरुआती मोटा नियम: अगर stop_distance + target_distance आपके बार-अंतराल के 75वें परसेंटाइल रेंज से छोटी है, तो आपके P&L में इंट्राबार की धारणा का योगदान आपके सिग्नल से बड़ा है। दोनों संख्याएँ निकालें। इसमें 4 लाइन लगती हैं और इस एक जाँच ने किसी भी दूसरी जाँच से ज़्यादा रणनीति समीक्षाएँ खत्म की हैं।

जो सचमुच काम आता है

बार के भीतर कीमत का रास्ता डेटा है। उसे हासिल करें, या जो डेटा नहीं मिल सकता उसकी सीमा तय करें।

  1. सबसे बारीक उपलब्ध सीरीज़ से फैसला करें। संबंधित मिनटों के Binance aggTrades में कुछ सौ रो आते हैं और वे सवाल का सीधा जवाब दे देते हैं: पहले कौन-सा स्तर छुआ गया और स्विप किस कीमत पर भरा। पूरे बैकटेस्ट के लिए टिक डेटा की ज़रूरत नहीं, सिर्फ अस्पष्ट बार के लिए चाहिए। मेरे सैंपल में 129,600 में से सिर्फ 606 मिनट ऐसे थे। यह छोटा-सा डाउनलोड है, कोई इन्फ्रास्ट्रक्चर प्रोजेक्ट नहीं।
  2. टिक डेटा उपलब्ध न हो, तो सिर्फ फैसला करने के लिए टाइमफ़्रेम 1 या 2 स्तर नीचे करें। 15m पर सिग्नल लें, और एग्ज़िट का फैसला 1s या 1m बार से करें। अस्पष्टता 49% से घटकर प्रतिशत के छोटे-से हिस्से तक आ जाती है, और बाकी इतना कम होता है कि उसे ईमानदारी से नज़रअंदाज़ किया जा सके।
  3. हमेशा नतीजों की रेंज बताएँ। हर बैकटेस्ट 2 बार चलाएँ — आशावादी और निराशावादी फैसले के साथ — और दोनों Sharpe को तय नतीजे के साथ दिखाएँ। यह अंतर आपकी इंट्राबार अनिश्चितता है, और इसे tearsheet में Sharpe के कॉन्फिडेंस इंटरवल के पास दिखाना चाहिए। जब रेंज 0.2–2.3 हो, तो उसके भीतर का कोई नतीजा असली नहीं है।
  4. अस्पष्टता दर को एक अहम मेट्रिक की तरह ट्रैक करें। हमारी हर रणनीति कार्ड में यह सबसे ऊपर, ट्रेड संख्या और टर्नओवर के पास दिखती है। करीब 5% से ऊपर की दर का मतलब है कि एंट्री लॉजिक नहीं, एग्ज़िट लॉजिक की परीक्षा हो रही है।
  5. ट्रिगर को फिल से अलग मॉडल करें। जिस प्राइस सीरीज़ का एक्सचेंज सच में इस्तेमाल करता है, उसी पर ट्रिगर करें; फिर टेप से कैलिब्रेट किए गए स्लिपेज ड्रॉ के साथ भरें, ट्रिगर की कीमत पर नहीं।

इक्विटी में भी यही समस्या अलग रूप में आती है। जिस शेयर की कीमत रातोंरात गिरकर 58.40 हो जाए, उस पर 62.00 का स्टॉप 62.00 पर नहीं भरेगा; वह ओपन प्रिंट से नीचे कहीं भरेगा। और गैप के पार हुए स्टॉप पर −$0.00 स्लिपेज दर्ज करने वाला डेली-बार बैकटेस्ट खुशी से बताएगा कि स्टॉप-लॉस ओवरले ने आपका ड्रॉडाउन घटाया। ऐसा नहीं हुआ। जिन दिनों की अहमियत थी, उन दिनों यह आज़माया ही नहीं गया। ट्रेडिंग रोक दिए जाने पर भी यही होता है: रीओपनिंग ऑक्शन में आपका स्टॉप असल में क्लियर होता है, ऐसी कीमत पर जिसे बार का लो कभी दिखाता ही नहीं।

यह सब कोई अनोखी बात नहीं है। बस यह समझना है कि बार एक सारांश है, और स्टॉप-और-लक्ष्य रणनीति उन घटनाओं के क्रम पर दाँव लगाती है जिन्हें उस सारांश ने हटा दिया। जब पेपर-ट्रेडिंग इंजन आखिरकार लाइव टेप पर रणनीति चलाता है, तो टेप उस क्रम पर अपनी राय देता है — और उसे इस बात की कभी परवाह नहीं रही कि आपने if-स्टेटमेंट की कौन-सी ब्रांच पहले टाइप की थी।

इंट्राबार फिलस्टॉप ऑर्डरबैकटेस्टिंगक्रिप्टो फ्यूचर्समार्केट माइक्रोस्ट्रक्चर
साझा करेंXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← सभी पोस्ट