Eugen Soloviov

Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Articles

TWAP बनाम VWAP बनाम POV: एक execution benchmark चुनना (और यह जानना कि हर एक कब आपसे झूठ बोलता है)

TWAP बनाम VWAP बनाम POV: एक execution benchmark चुनना (और यह जानना कि हर एक कब आपसे झूठ बोलता है)

TWAP, VWAP और POV एक volume forecast पर लगाया गया दांव हैं। हम हर scheduler की छिपी हुई मान्यताओं को खोलकर देखते हैं, crypto intraday volume curves बनाते हैं, और तीनों को replayed L2 data पर आमने-सामने चलाते हैं।

Almgren-Chriss बिना लाग-लपेट के: ऑप्टिमल एक्जीक्यूशन जिसे आप एक दोपहर में लागू कर सकते हैं

Almgren-Chriss बिना लाग-लपेट के: ऑप्टिमल एक्जीक्यूशन जिसे आप एक दोपहर में लागू कर सकते हैं

Almgren-Chriss ऑप्टिमल एक्जीक्यूशन मॉडल का पूरा डिराइवेशन: लीनियर इम्पैक्ट, sinh/cosh ट्रैजेक्टरी, एफिशिएंट फ्रंटियर, और Binance L2 व ट्रेड डेटा से eta, gamma, और sigma को कैलिब्रेट करने के लिए काम करने वाला Python कोड।

ईमानदार नकारात्मक परिणाम: हजारों बैकटेस्ट, पांच मेजर, कोई मजबूत एज नहीं

ईमानदार नकारात्मक परिणाम: हजारों बैकटेस्ट, पांच मेजर, कोई मजबूत एज नहीं

सर्च-एंड-ओवरफिट कथानक का चरम बिंदु, और यह एक नकारात्मक परिणाम पर खत्म होता है — जो सही है। ETHUSDT पर एक सिंगल-सिंबल ड्यूल-टाइमफ्रेम सर्च ने एक ऐसा कॉन्फ़िग खोजा जो out-of-sample पर +16.35% और एक अछूते holdout पर +2.62% देता था; Deflated Sharpe Ratio ने, ~37,000 ट्रायल को ध्यान में रखते हुए, इसे घटाकर 0.00 कर दिया। पांच मेजर (ETH/BTC/SOL/BNB/XRP, प्रत्येक ~1.18M 1m बार) पर एक क्रॉस-इंस्ट्रूमेंट पास, median out-of-sample के आधार पर चयन करते हुए, इसे हमेशा के लिए खत्म कर देता है: dual DSR 0.24 / PBO 0.264, triple DSR 0.14 / PBO 0.327 — दोनों गेट फेल हो जाते हैं। चैंपियन 5 में से 1 सिंबल पर लाभदायक है और बाकी पर नकारात्मक। एंटी-ओवरफिट तंत्र इसी के लिए है: आपको शोर के सबसे अच्छे हिस्से को अल्फा के रूप में शिप करने से रोकने के लिए।

मल्टी-Timeframe Backtests में No Look-Ahead साबित करना: भविष्य को Perturb करें, साबित करें कि अतीत उसे देख नहीं सकता

मल्टी-Timeframe Backtests में No Look-Ahead साबित करना: भविष्य को Perturb करें, साबित करें कि अतीत उसे देख नहीं सकता

मल्टी-timeframe backtests एक बनते हुए higher-timeframe bar के जरिए भविष्य लीक करते हैं, जिसका final close अभी अस्तित्व में ही नहीं है। सिर्फ code review करके भरोसा नहीं जीता जा सकता — इसे टेस्ट करना ही पड़ता है। हम live bot के closed-bar rule को बिल्कुल वैसा ही reproduce करते हैं, फिर shifted-future probe से साबित करते हैं कि कोई leakage नहीं है: भविष्य के हर bar को perturb करें और assert करें कि अतीत का हर signal और trade bitwise अपरिवर्तित रहता है। 25/25 parity checks, और probe में असली पकड़ (teeth) है।

GPU कब अपनी कीमत वसूलता है: पैरामीटर-स्वीप की roofline, जहाँ सुर्खियों वाला 167x असल में 27x एल्गोरिदम गुणा 6.2x हार्डवेयर है

GPU कब अपनी कीमत वसूलता है: पैरामीटर-स्वीप की roofline, जहाँ सुर्खियों वाला 167x असल में 27x एल्गोरिदम गुणा 6.2x हार्डवेयर है

CPU पर GPU की बढ़त batch size के साथ बढ़ती है — हमारे मल्टी-टाइमफ्रेम इंडिकेटर precompute पर प्रति कॉल एक combo पर 54.5x से लेकर 61 पर 359.6x तक — क्योंकि छोटा स्वीप kernel-launch और transfer overhead की भरपाई नहीं कर पाता। हम सुर्खियों वाले 167x को 27x की एल्गोरिदमिक जीत (जो CPU को भी उतना ही तेज़ करती है) गुणा 6.2x की हार्डवेयर जीत में तोड़ते हैं, दिखाते हैं कि GPU बनाम सर्वश्रेष्ठ-CPU की असली बढ़त सिंगल-टाइमफ्रेम पर सिर्फ़ 3.2x और मल्टी पर 6.2x है, और एक निर्णय-गाइड देते हैं कि GPU खरीदने लायक बनने से पहले स्वीप कितना चौड़ा होना चाहिए।

GPU प्रिसिजन ट्रैप: Apple Metal पर fp32 बैकटेस्ट चुपचाप गार्बेज नतीजे कैसे देता है

GPU प्रिसिजन ट्रैप: Apple Metal पर fp32 बैकटेस्ट चुपचाप गार्बेज नतीजे कैसे देता है

Apple के Metal GPU में float64 होता ही नहीं। किसी vectorized बैकटेस्ट को उस पर भोलेपन से पोर्ट कर दीजिए, और वह लुभावना prefix-sum WMA fp32 में overflow कर जाता है — अधिकतम relative error 211× — फिर भी वह चलता रहता है और plausible दिखने वाले नंबर लौटाता है। इसका फिक्स ज्यादा precision नहीं है; यह एक अलग formulation है: एक direct windowed convolution, जो fp32 में 8×10⁻⁷ तक सुरक्षित है और single-thread numba से 55.9× तेज है। यह लेख इसी ट्रैप, उसके पीछे के arithmetic, और यह साबित करने के तरीके पर है कि आप खुद उसमें फंसे तो नहीं।

फिडेलिटी गेट: कोर्स-टू-फाइन बैकटेस्टिंग आपको और तेज़ी से बेवकूफ बनाती है, जब तक कि सस्ता प्रॉक्सी वैसे ही रैंक न करे जैसे महंगा वाला करता है

फिडेलिटी गेट: कोर्स-टू-फाइन बैकटेस्टिंग आपको और तेज़ी से बेवकूफ बनाती है, जब तक कि सस्ता प्रॉक्सी वैसे ही रैंक न करे जैसे महंगा वाला करता है

ड्रिल-डाउन / मल्टी-फिडेलिटी सर्च (ASHA, successive halving, Hyperband) हज़ारों कॉन्फ़िग्स को सस्ते में स्क्रीन करती है और केवल बचे हुए (survivors) को महंगे फुल इवैल्यूएशन के लिए आगे बढ़ाती है। यह एक असली स्पीडअप है — लेकिन अगर लो-फिडेलिटी रैंकिंग हाई-फिडेलिटी रैंकिंग से असहमत हो, तो यह चुपचाप ध्वस्त हो जाती है। हमने फोल्ड-रैंक कोरिलेशन को मापा: एक फोल्ड पर Spearman ρ 0.03 तक हो सकता है (लगभग रैंडम रैंकिंग), और जैसे-जैसे फोल्ड्स बढ़ते हैं यह 0.43, 0.67, 0.78, 0.91 तक चढ़ता जाता है। इसका समाधान एक अनिवार्य गेट है — पहले ρ(cheap, full) मापें, और न्यूनतम फिडेलिटी को ऑटोमैटिक रूप से उस पहले रंग (rung) तक बढ़ा दें जहाँ ρ ≥ 0.5 हो।

रैंडम बनाम स्मार्ट सर्च: क्रॉसओवर इवैल कॉस्ट से तय होता है, एल्गोरिदम से नहीं

रैंडम बनाम स्मार्ट सर्च: क्रॉसओवर इवैल कॉस्ट से तय होता है, एल्गोरिदम से नहीं

जब एक बैकटेस्ट सस्ता होता है, तो डम्ब स्क्रैम्बल्ड Sobol रॉ थ्रूपुट पर जीत जाता है — स्मार्ट सैंपलर (TPE, CMA-ES, ASHA) एक Python ask/tell टैक्स चुकाते हैं जो उन्हें 20x धीमा कर देता है, इसलिए बराबर वॉल-क्लॉक में वे बहुत कम पॉइंट्स इवैल्यूएट करते हैं और हार जाते हैं। हर eval को महंगा बनाइए (multi-TF + walk-forward folds) और क्रॉसओवर पलट जाता है। हमने दोनों रीजीम मापे, और क्यों fold-rank fidelity (ρ@1 का 0.03→0.43 तक बढ़ना) pruning के फायदेमंद होने की पूर्वशर्त है।

दो-अक्षीय पैरामीटर स्पेस: आपके स्वीप का ज्यादातर हिस्सा लगभग मुफ्त क्यों होना चाहिए

दो-अक्षीय पैरामीटर स्पेस: आपके स्वीप का ज्यादातर हिस्सा लगभग मुफ्त क्यों होना चाहिए

सभी पैरामीटर खोजने में एक जैसे महंगे नहीं होते। स्ट्रैटेजी के पैरामीटर दो अक्षों में बंट जाते हैं: महंगा अक्ष (इंडिकेटर — पूरी सीरीज पर दोबारा गणना) और सस्ता अक्ष (डिसीजन थ्रेशोल्ड — पहले से गणना किए गए सिग्नलों पर एक O(n) पास)। चूंकि इंडिकेटर थ्रेशोल्ड से अपरिवर्तित रहते हैं, आप उन्हें एक बार गणना करके हजारों थ्रेशोल्ड कॉन्फिग ~5,600 cfg/s की रफ्तार से स्वीप कर सकते हैं — हर कॉन्फिग पर दोबारा गणना करने से करीब 1,600 गुना सस्ता। यह डाइमेंशनैलिटी के अभिशाप की कीमत का पुनर्मूल्यांकन है।

फ्रेमवर्क टैक्स: जब आपकी बैकटेस्ट लाइब्रेरी एक भोले pandas लूप से भी धीमी होती है

फ्रेमवर्क टैक्स: जब आपकी बैकटेस्ट लाइब्रेरी एक भोले pandas लूप से भी धीमी होती है

हमने आठ बैकटेस्ट इंजनों को एक ही समान पैरामीटर स्वीप पर बेंचमार्क किया — 150k बार, 80 HMA-क्रॉस संयोजन, ट्रेड-गिनती की पैरिटी 2707 पर लॉक। दो सबसे लोकप्रिय इवेंट-ड्रिवन फ्रेमवर्क हाथ से लिखे pandas लूप से भी धीमे निकले, जबकि एक वेक्टराइज़्ड/कंपाइल्ड इंजन ने वही काम लगभग 13,000× तेज़ी से चलाया। उस प्रति-बार ओवरहेड का अध्ययन जिसे लोकप्रिय लाइब्रेरियाँ कभी अमॉर्टाइज़ करने के लिए बनी ही नहीं थीं।

The Probability of Backtest Overfitting: Did Your Search Beat a Coin Flip?

The Probability of Backtest Overfitting: Did Your Search Beat a Coin Flip?

The Deflated Sharpe Ratio prices the winning strategy; PBO prices the search that picked it. Combinatorially Symmetric Cross-Validation runs C(16,8) = 12,870 train/test splits over a 1000x200 performance matrix and asks: does the in-sample winner land in the bottom half out of sample? The catch almost everyone misses — PBO's null is 0.5, not 1. On 200 zero-edge strategies the best in-sample annualized Sharpe of 1.98 collapses to 0.06 out of sample and PBO = 0.476: a coin flip, fully overfit. Plant a real edge (annualized Sharpe 2.38) and PBO drops to 0.001, the in-sample 3.73 surviving to an out-of-sample 2.34. A moving-average grid on a pure random walk has no out-of-sample skill either — PBO 0.463 averaged over 60 matrices, statistically indistinguishable from the null — and on one representative matrix the mirage is vivid: a best in-sample Sharpe of 2.33 collapses to a median out-of-sample -0.22, PBO 0.573, a 63% chance of a loss.

IPC टैक्स: बैकटेस्ट इंजन को सॉकेट के पीछे रखें और 13% गंवाएं — जिसमें से लगभग कुछ भी सॉकेट की वजह से नहीं

IPC टैक्स: बैकटेस्ट इंजन को सॉकेट के पीछे रखें और 13% गंवाएं — जिसमें से लगभग कुछ भी सॉकेट की वजह से नहीं

हमने एक numba बैकटेस्ट कर्नेल को लाइन-दर-लाइन Rust में पोर्ट किया और उसे एक प्रोसेस बाउंड्री के पार चार तरीकों से कॉल किया, एक इक्विवैलेंस गेट के साथ जो अंतिम ट्रेड तक समान PnL की पुष्टि करता है। पूरी 1.2 MB प्राइस सीरीज़ को Unix सॉकेट के जरिए भेजने में ~2 ms लगते हैं — जॉब का लगभग 0.1%। उसी पेलोड को JSON-एनकोड करने में रॉ बाइट्स से 1348 गुना ज्यादा लागत आती है, प्रति-कॉम्बो chatty कॉल्स डेटा को 80 बार दोबारा भेजते हैं, और प्रति-बार कॉल पैटर्न 2.0 सेकंड के जॉब पर 2.1 सेकंड शुद्ध IPC खर्च करेगा। बाउंड्री सस्ती है; टैक्स इस बात में है कि आप उसे कैसे पार करते हैं।