एक-दूसरा, गहरा-Phantom-Fill-Bug मिला असली-Discovery: friend के-established-fix (occurrence-check-per-k_atr) को-implement-करने-के-बाद, मैंने-genuinely-अपने-controlled-test-में एक-दूसरा-bug पकड़ा — occurrence-check-genuinely-pullback_zone_high=breakout+k×A
1) `max(target_level, actual_touched_price)` वाला fix कितना सही है?
- Bullish case में आप असल में ये enforce कर रहे हैं:
- आप एक pre-defined limit/target level तय करते हैं (e.g. `entry_limit = breakout - k_atr * ATR` जैसा कुछ)।
- Bar के अंदर price path कुछ भी हो, fill price कभी भी उस limit से बेहतर (यानी buy के लिए उससे नीचे) नहीं हो सकता।
- अगर price उस level तक नहीं पहुँचा तो fill ही नहीं होगा; अगर पहुँचा, तो fill को ज़्यादा से ज़्यादा उस limit पर मानेंगे, उससे नीचे नहीं।
- अगर `actual_touched_price` = उस bar का low (bullish buy के लिए), तो:
- अगर `low <= target_level`:
- `max(target_level, low) = target_level` → fill यहीं पर; “limit पर भरा” model होता है।
- अगर `low > target_level`:
- मतलब target छुआ ही नहीं; अच्छी implementation में trade ही नहीं होना चाहिए। (आपने अगर कोई अलग logic रखा है तो बस ये ensure करें कि ‘fill’ तभी माने जब `low <= target_level`)
- Standard backtest practice में limit-order मॉडल प्रैक्टिकली यही करता है:
- Pre-decided limit price तय करो।
- अगर bar का low (buy के लिए) उस limit से नीचे/बराबर गया, तो मानो order fill हो गया, और execution price = limit price (ना इससे बेहतर, ना worse, जब तक slippage model अलग से न लगाएँ)।
इस नज़र से देखें तो आपका `entry_price = max(target_level, actual_touched_price)` एक defensible, conservative fix है — बशर्ते:
- आप पहले ये चेक कर रहे हों कि “price ने target_level छुआ ही या नहीं” (e.g. `if low <= target_level` for buy)।
- और उसके बाद ही `entry_price` assign कर रहे हों।
इसका फायदा:
- Phantom “super-deep” fills गायब हो जाते हैं।
- Entry logic deterministic और parameter-stable रहता है (k_atr बढ़ाने से fills खुद-ब-खुद better नहीं होते)।
तो, established quant/backtest practice के हिसाब से:
- हाँ, `max(target_level, actual_touch)` जैसा construct (सही touch-check के साथ) बिल्कुल ठीक और defensible approach है।
---
2) क्या target_level को हटाकर सिर्फ़ actual_touched_price को entry मानें?
इसे दो angle से देखिए:
A. अगर आप कह रहे हैं: “k_atr सिर्फ़ occurrence zone define करेगा, entry हमेशा ‘bar के अंदर जहाँ तक price गया उसके best point’ पर होगी”
- Bullish pullback buy में इसका मतलब होगा:
- Zone: `[breakout, breakout - k_atr*ATR]`
- Occurrence: जैसे ही price इस zone में कहीं भी आया, trade माना गया।
- Entry: हमेशा उस zone के अंदर सबसे low price पर (i.e. bar का low अगर zone में है)।
- ये असल में “ex-post best fill” है — practically realizable नहीं, क्योंकि:
- Real life में आप पहले से ये तय करके order लगा सकते हैं:
- या तो fixed limit (e.g. `breakout - 0.5*ATR`)
- या कोई rule-based dynamic execution (जैसे VWAP, TWAP, या “first touch” आदि)
- लेकिन आप कभी भी ये नहीं जानते कि बार के अंदर future path में आगे सबसे नीचे कौन-सा point आएगा; backtest जो सबसे अच्छा low चुन रहा है, वह hindsight है।
- इस तरह का model backtest को optimistically biased बना देगा:
- आप हर बार zone के अंदर “सबसे best possible” fill ले रहे हैं, जो practically किसी भी realistic order-model से better है।
- Sharpe, win-rate, drawdown सब over-optimistic लगेंगे।
B. Standard practice क्या कहती है?
- Signal/occurrence और execution को अलग रखते हैं:
1. Signal / Occurrence Rule
- e.g. “Breakout के बाद price X ATR के अंदर pullback करे” → ये सिर्फ़ trade की eligibility define करता है।
2. Execution Rule
- Fixed limit (e.g. `breakout - k_entry*ATR`), या
- Next-bar open market order, या
- stop/stop-limit का कोई clear deterministic rule।
- Execution rule हमेशा forward-looking और pre-specified होना चाहिए; backtest bar की अंदरूनी path से ex-post “सबसे अच्छा” price नहीं चुन सकता।
इसलिए:
- Target/limit level को पूरी तरह हटाकर “सिर्फ़ actual_touched_price = best low” को entry बनाना standard / defensible practice नहीं है (जब तक आप कोई बहुत specific, realistic execution algorithm detail नहीं करते, और तब भी “best low” लगभग कभी भी justified नहीं होगा)।
- Better है:
- k_atr से या तो target/limit को ही define कीजिए,
- या zone और limit दोनों के लिए अलग-अलग deterministic functions रखिए, लेकिन execution हमेशा किसी explicit order price पर हो (जैसे `entry_limit`), न कि बाद में चुना गया “सबसे अच्छा low/high”।
आपका वर्तमान `max(target_level, actual_touch)` approach ठीक इसी conservative principle पर बैठता है, इसलिए ये ज्यादा standard-aligned है बनिस्बत “pure actual_touched_price (best low)” वाले model के।
---
3) पुराने Parameter Perturbation (n=87, rising Sharpe) results का status क्या है?
आपने जो double-bug identify किया, उसमें core problem ये थी कि:
- Occurrence condition और entry-price formula दो अलग-अलग levels यूज़ कर रहे थे।
- k_atr बढ़ाने से:
- Occurrence easier होती गई (zone expand या shift हो रहा था),
- Entry price गहरी होती गई (phantom-improvement in fill),
- यानी higher k_atr पर systematically “better-than-realistic” fills, जो पूरी तरह bug-induced edge है।
इससे दो serious biases आते हैं:
1. Parameter-dependent optimism:
- जैसे-जैसे k_atr बढ़ रहा था, आपका model कृत्रिम रूप से better fills दे रहा था।
- Sharpe का उठना बहुत संभावना से इसी phantom fill की वजह से था, न कि असली strategy robustness की वजह से।
2. Comparability का टूटना:
- Low k_atr vs high k_atr runs अब apples-to-apples comparison नहीं रहे, क्योंकि execution model practically अलग-अलग हो गया था (एक तरफ कम artificial improvement, दूसरी तरफ ज़्यादा)।
इसलिए, research-standard/established standpoint से:
- पहले के सारे parameter-perturbation नतीजों को genuinely invalid / contaminated मानना चाहिए।
- उन्हें सिर्फ़ “bugged v1 experiment log” की तरह archive कर दीजिए, लेकिन किसी भी serious inference (optimal k_atr, robustness, Sharpe improvements) के लिए use नहीं करना चाहिए।
- Strategy को अब bug-fixed execution model के साथ पूरा experiment दोबारा चलाना चाहिए:
- Same universe, same sample period, same costs और slippage assumptions,
- लेकिन नए, correct fill logic के साथ।
इसके बाद ही:
- नए Sharpe vs k_atr curve पर भरोसा करना logical होगा।
- अगर bug-fixed runs में भी वही qualitative pattern (e.g. Sharpe monotonic या hump-shaped) दिखे, तो उसे real effect मानने की कुछ credibility मिलेगी; वरना मानना होगा कि पहले का “edge” असल में bug था।
---
संक्षिप्त actionable summary:
1. `entry_price = max(target_level, actual_touched_price)`
- अगर आप पहले सही तरीके से “did price touch target?” चेक कर रहे हैं (e.g. `if low <= target_level` for buy), तो ये limit-order style implementation है और standard, defensible, और conservative है।
2. Target_level हटाकर pure “best actual_touched_price” को entry बनाना
- Practically ex-post optimization है, standard नहीं है, और over-optimistic bias लाएगा।
- Recommended नहीं है, जब तक आप कोई बहुत स्पष्ट, realistic execution algorithm define न कर दें — और तब भी “best low/high” approach गलत है।
3. पुराने parameter-perturbation (n=87) results
- Double-bug के बाद इन्हें research-grade standpoint से invalid मानिए।
- Strategy को corrected fill logic के साथ पूरी तरह re-run करना चाहिए; पुराने Sharpe improvements को सिर्फ़ bug-artefact के तौर पर archived रखिए, conclusions के लिए नहीं।
If you have any further queries, please connect with us on 022-6290-10141 (Timings : 09.00 AM to 05.00 PM) or you can email us on info@cniinfoxchange.com