Spot Large-Cap Dual-Momentum Rotation, Long-Only (Multi-Instrument na Basket na BINANCE_SPOT, Daily Bars / Weekly Rebalance, Cross-Sectional Relative Strength + Absolute-Trend Cash Filter, Walang Leverage, Mababang Turnover, Kaunting Parameter)
Resulta: Inabandona
SpotLargeCapDualMomentumRotationLong
Pamantayan ng backtest: - hindi maaasahan ang mga metric: kulang ang ebidensiya sa 1 trade / 1092 araw ng data (kailangan ng >=5 trade sa loob ng >=10 araw) — dagdagan ang dalas ng signal o palawakin ang window
Isang LONG-ONLY, MULTI-INSTRUMENT dual-momentum rotation sa maliit na basket ng mga likidong spot major na may malaking market cap sa BINANCE_SPOT (BTCUSDT, ETHUSDT, BNBUSDT, SOLUSDT), gamit ang mga daily bar at WEEKLY rebalance. Pinagsasama nito ang nag-iisang paulit-ulit na napatunayang edge family ng factory (momentum/trend) at dalawang feature para sa tibay na wala sa mga kamakailang pumalya: (1) tumatakbo ito sa venue na may pinakamataas na survival at pinakamababang weight — BINANCE_SPOT (9.4% kumpara sa……Magpakita ng higit paMagpakita ng mas kaunti
Isang LONG-ONLY, MULTI-INSTRUMENT dual-momentum rotation sa maliit na basket ng mga likidong spot major na may malaking market cap sa BINANCE_SPOT (BTCUSDT, ETHUSDT, BNBUSDT, SOLUSDT), gamit ang mga daily bar at WEEKLY rebalance. Pinagsasama nito ang nag-iisang paulit-ulit na napatunayang edge family ng factory (momentum/trend) at dalawang feature para sa tibay na wala sa mga kamakailang pumalya: (1) tumatakbo ito sa venue na may pinakamataas na survival at pinakamababang weight — BINANCE_SPOT (9.4% kumpara sa target na ≥15%) — kung saan may DEEP malinis na multi-year na kasaysayan ang mga major (BTC/ETH mula 2017, SOL/BNB mula 2020), kaya sumasaklaw ang walk-forward at kamakailang tail na hindi isinama sa pagsasanay sa tunay na bull/bear/chop regime, sa halip na iisang banayad na 6-buwang window (ang mismong depektong nagpabagsak sa HL impulse at squeeze strategy); at (2) gumagamit ito ng ABSOLUTE-trend na cash filter na inililipat ang portfolio sa USDT (wala sa market) kapag walang asset na nasa uptrend, kaya likas nitong iniiwasan ang pagkamatay dahil puro negatibo ang buwan, na nagpabagsak sa mga purong-OHLCV HL strategy. Sadyang NOT ito sa lahat ng landmine family: NOT Deribit options (sirang harness), NOT Hyperliquid OI/liquidation/tick microstructure (hadlang sa data), NOT single-symbol intraday breakout/fade (hindi mahusay mailipat sa 24h na takbo ng crypto), NOT funding-carry sa mga huminang major. Isa ang cross-sectional at absolute (‘dual’) momentum sa mga anomalyang may pinakamalawak na dokumentasyon at tibay sa iba’t ibang regime at asset class, at malakas ang pagpapalitan ng pamumuno sa pagitan ng mga major sa crypto (BTC-season kumpara sa alt-season), na nakukuha ng strategy na ito. Dahil mababa ang turnover (lingguhan, may hysteresis buffer), tinatayang mababa ang spot fees (~0.20% RT), at kakaunti ang parameter (4) para labanan ang paulit-ulit na overfitting. BINANCE_SPOT ang fills (venue na kulang sa weight) at multi-instrument ang saklaw (14.4%). backtesting
Napasinungalingan ang premise sa buong 9-taong sapat na sample. Ipinapahayag ng hypothesis na likas na iniiwasan ng absolute-trend cash filter ang malalalim na drawdown at nagdaragdag ng alpha na matibay sa iba’t ibang regime ang dual-momentum rotation; ipinakita ng backtest na hindi nito nagagawa ang alinman. Ang max_drawdown ay 64.98% (>60%, lampas nang malaki sa hangganang 50%) na may 889-araw na panahong underwater at 2022 taunang -51.5% — hinahayaan ng weekly-only exit na magpatuloy nang walang pigil ang……Magpakita ng higit paMagpakita ng mas kaunti
Napasinungalingan ang premise sa buong 9-taong sapat na sample. Ipinapahayag ng hypothesis na likas na iniiwasan ng absolute-trend cash filter ang malalalim na drawdown at nagdaragdag ng alpha na matibay sa iba’t ibang regime ang dual-momentum rotation; ipinakita ng backtest na hindi nito nagagawa ang alinman. Ang max_drawdown ay 64.98% (>60%, lampas nang malaki sa hangganang 50%) na may 889-araw na panahong underwater at 2022 taunang -51.5% — hinahayaan ng weekly-only exit na magpatuloy nang walang pigil ang drawdown habang hawak ang posisyon. Kung ikukumpara sa patas na benchmark (equal_weight_basket, benchmark_meaningful=true), nagtatala ang strategy ng information_ratio -0.53 at kaunti lamang ang positibong alpha na dala ng beta: sa risk-adjusted na batayan, UNDERPERFORMS ito sa simpleng equal-weighting ng apat na major, kaya malinaw na wala ang sinasabing edge ng rotation. Ang pangunahing resulta ng +2469% ay crypto beta (beta 0.23, 53.7% hindi pa rin naisasakatuparan na MTM) at ang avg_trade_return_pct ng 19.1% sa spot book na walang leverage ay artifact ng compounding mula sa paglaki ng posisyon kasabay ng equity curve, hindi edge ng bawat pangalan. Ito ang katangian ng long-only spot basket na tinatanggihan dahil sa drawdown; hindi kayang itaas ng pag-optimize sa mga parameter ng 4 ang >60% DD nang lampas sa promotion floor o gawing positibong alpha ang negatibong IR. abandon_class=premise_falsified.
Implementasyon
Long-only na dual-momentum rotation sa apat na large-cap na BINANCE_SPOT major (BTC/ETH/BNB/SOL) sa daily bars, na may weekly rebalance na nakaangkla sa kalendaryo. Sa bawat rebalance, niraranggo ang basket ayon sa return sa loob ng 90 araw (relative strength sa iba’t ibang asset), at hinahawakan ang nangungunang 2 pangalang ALSO sa sarili nilang absolute uptrend (momentum > 0); inililipat sa cash na USDT ang anumang hindi pumapasa sa absolute filter, kaya kapag malawakang downtrend, walang hawak ang book sa halip na hawakan ang pinakamahinang talo. Equal weight ang bawat pangalang hawak; pinananatili ang pangalan hangga’t nasa ranggong top_k+1 at pataas pa rin ang trend nito (hysteresis band), at nililimitahan ng material-delta threshold ang turnover at ang halos bale-walang ~0.20% round-trip spot fee. Walang leverage; ginagamit lang ang SELL upang bawasan o isara ang umiiral na long.
Inaayos ng Iteration 4 ang iniulat na Layer-3 sandbox_timeout sa pamamagitan ng dalawang pinakamaliit na pagbabagong may epekto, habang hindi ginagalaw ang signal logic (na pumasa sa Layers 1-2). (1) O(1) na ngayon ang gawain sa bawat bar: nasa bounded deque(maxlen=lookback+1) ang mga close ng bawat asset at idinadagdag nang isang beses bawat bar (primary sa calculate_signal, legs sa on_extra_bar), kaya dalawang pagbasa sa deque na lang ang kailangan para sa momentum sa halip na buuing muli ang listahan ng 500……Magpakita ng higit paMagpakita ng mas kaunti
Inaayos ng Iteration 4 ang iniulat na Layer-3 sandbox_timeout sa pamamagitan ng dalawang pinakamaliit na pagbabagong may epekto, habang hindi ginagalaw ang signal logic (na pumasa sa Layers 1-2).
(1) O(1) na ngayon ang gawain sa bawat bar: nasa bounded deque(maxlen=lookback+1) ang mga close ng bawat asset at idinadagdag nang isang beses bawat bar (primary sa calculate_signal, legs sa on_extra_bar), kaya dalawang pagbasa sa deque na lang ang kailangan para sa momentum sa halip na buuing muli ang listahan ng 500 close gamit ang .as_double() sa bawat bar para sa bawat asset. 4-element asset list na lang ang sinusuri ng min()/sorted().
(2) May 3% cash buffer na at spend budget na nakabatay sa aktuwal na libreng USDT + tinatayang kita sa pagbebenta. Dati, 100% ng kabuuang equity ang tina-target, kaya sumobra nang eksaktong halaga ng komisyon ang singil sa CASH account at HALTED ng engine ang takbo dahil sa AccountBalanceNegative noong Aug-2020 — nauubos ng sandbox ang buong wall-clock nito para gumawa ng pinutol na 1.5-taong takbo na may 3 trade.
(3) Nakaangkla na ngayon sa kalendaryo ang lingguhang cadence (epoch-day modulo rebalance_days mula sa bar.ts_init), alinsunod sa tuntunin ng iskedyul — magkakapareho ito sa mga restart, backtest at paper.
Tala sa profiling para sa reviewer: pinatakbo ko nang lokal ang eksaktong sandbox configuration sa ilalim ng cProfile. Kabuuang 109s na wall time para sa buong 2400-araw na saklaw; 0.015s lamang dito ang para sa sariling on_bar path ng estratehiya. Ang ParquetDataCatalog.bars() na nag-glob ng data/catalog/data/bar ang kumonsumo ng 152s sa 178s na na-profile na takbo (1.08M file / 101k direktoryo) — nakapirming ~76s sa bawat catalog.bars() CALL, at eksaktong dalawa ang binabayaran ng bawat multi-instrument na estratehiya (primary + mga dagdag na batch). Kaya ang natitirang panganib ng timeout ay dulot ng catalog-scan/page-cache-bound na imprastraktura, hindi ng code ng estratehiya; wala nang ibang pagbabagong magagawa sa estratehiya para mabawasan ito. Lokal na resulta para sa buong saklaw matapos ang mga pag-aayos: 57 trade, total_return +1627%, Sharpe 0.92, avg_trade_return_pct 13.5%, max_dd 59% (hindi in-optimize, buong 2019-2026 saklaw, walang maagang paghinto).
Mga Resulta ng Beripikasyon
Mababa/napapamahalaan ang panganib: nagbabalik ng None ang _momentum() hanggang umabot ang deque sa lookback+1, at inaalis sa `eligible` ng _rebalance ang mga pangalang walang momentum, kaya walang maagang trade kahit kilalanin man o hindi ang override. Opsyonal na tiyaking talagang tinatawag ng FactoryStrategy ang override na ito.
Sinasapawan ng min_bars_required(self) ang base framework method (babala sa static analysis na base_shadow). Kung hindi iginagalang ng base ang override para sa warm-up gating, maaaring masuri ang mga entry bago mapuno ang 90-araw na lookback buffer.
Hindi kailangan ng pagbabago sa code — tugma ito sa hypothesis. Itinala ito para hindi mapagkamalan ng analyst na bug sa filter ang drawdown na dulot ng lingguhang granularity.
Sa lingguhang hangganan ng rebalance (nakabatay sa kalendaryo) lang inililipat ng absolute-trend cash filter ang posisyon sa USDT, kaya hahawakan hanggang sa susunod na rebalance ang malawakang pagbaba sa kalagitnaan ng linggo. Tugma ito sa sinabing disenyo ng hypothesis na mababa ang turnover at weekly, pero nangangahulugan itong humigit-kumulang 7 araw ang pagitan ng proteksiyong ‘hindi pumapasok sa merkado kapag downtrend’, na nag-aambag sa ~60% sandbox drawdown.
Matibay na positibo ang sandbox (total_return +1627%, Sharpe 0.99, avg_trade_return_pct 13.5%, PF 1.86) at ang mekanismo (dual momentum) ang nag-iisang edge family ng factory na paulit-ulit nang napatunayan, kaya walang pagdududa sa kakayahang kumita sa antas ng mekanismo. May dalawang bagay na dapat timbangin ng analyst sa buong history: (1) max_drawdown ~60% na may 917-araw na tagal na nasa ilalim ng tubig at end_unrealized_pct -68.6% — hindi NOT napipigilan ng absolute-trend cash filter ang malalalim na drawdown habang hawak ang posisyon dahil lingguhang rebalance lang gumagana ang mga exit, hindi sa loob ng linggo; (2) mukhang hindi tugma ang iniulat na exposure_pct 138.78% sa spot portfolio na walang leverage at may 97% na magagamit — malamang na epekto ito ng turnover/MTM metric sa halip na tunay na sobrang pamumuhunan (mahigpit na nililimitahan ang budget sa libreng USDT + tinatayang nalikom, kaya hindi maaaring gumastos nang lampas sa account na CASH ang code), pero makabubuting tiyakin ito gamit ang buong-history equity curve. Payo lamang.
Pagsusuri ng Backtest
Sharpe
0.91
Kabuuang Return
2469.29%
Max Drawdown
64.98%
Kabuuang Trade
50
Win Rate
48.0%
Profit Factor
1.98
Malinis na spot history sa maraming taon (BTC/ETH mula 2017), kaya saklaw ng sample ang mga tunay na bull/bear/chop regime
Positibong absolute return na may PF 1.98 at 50 trade — gumagana ang mekanismo at hindi ito degenerate
Mababa, bale-walang epekto ng bayarin (komisyon na 1.51% ng gross), ayon sa disenyo
max_drawdown 64.98% (>60%, lampas na lampas sa 50% bar) na may 889-araw na tagal na nasa ilalim ng tubig — hindi NOT napipigilan ng absolute-trend cash filter ang malalalim na drawdown dahil sa lingguhang rebalance lang gumagana ang mga exit (2022 taunang -51.5%)
information_ratio -0.53 kumpara sa equal_weight_basket na may benchmark_meaningful=true — sa risk-adjusted na batayan, UNDERPERFORMS ang rotation sa basta paghawak ng apat na major na equal-weight; wala ang sinasabing cross-sectional/absolute rotation edge
Ang avg_trade_return_pct 19.1% / avg_position_pct 56% / exposure_pct 143% sa spot portfolio na walang leverage ay epekto ng compounding/leverage (sumasabay ang laki ng posisyon sa equity curve), hindi edge ng bawat pangalan
Ang pangunahing resulta ng +2469% ay crypto beta (beta 0.23 na sumasabay sa buong cycle), at 53.7% nito ay hindi pa naibebentang MTM (end_unrealized_pct)
Ang 50 trade lang sa loob ng pinagsamang 9 taon, kasabay ng >60% DD, ang lagda ng long-only spot basket na palagiang tinatanggihan dahil sa drawdown
Pagsusuri
Pamantayan ng backtest:
- hindi maaasahan ang mga metric: kulang ang ebidensiya sa 1 trade / 1092 araw ng data (kailangan ng >=5 trade sa loob ng >=10 araw) — dagdagan ang dalas ng signal o palawakin ang window
Kasaysayan ng Iterasyon
Bigo ang verification (Layer 2 — mga sintetikong senaryo): Mga ginamit na parameter: ['top_k', 'assets', 'lookback', 'resize_frac', 'min_notional', 'qty_precision', 'rebalance_days', 'hysteresis_band', 'default_qty_precision'] Tiyaking itinatakda ng __init__ ang lahat ng attribute mula sa self.parameters.get(). - steady_uptrend: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000) - steady_downtrend: TypeError:……Magpakita ng higit paMagpakita ng mas kaunti
Bigo ang verification (Layer 2 — mga sintetikong senaryo):
Mga ginamit na parameter: ['top_k', 'assets', 'lookback', 'resize_frac', 'min_notional', 'qty_precision', 'rebalance_days', 'hysteresis_band', 'default_qty_precision']
Tiyaking itinatakda ng __init__ ang lahat ng attribute mula sa self.parameters.get().
- steady_uptrend: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
- steady_downtrend: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
- flat_ranging: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
- volatility_spike: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
- zero_volume: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
- price_gap: TypeError: SpotLargeCapDualMomentumRotationLong._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735695060000)
sandbox_timeout: Bigo ang verification (Layer 3 — sandbox backtest): lumampas ang smoke test sa 300s na wall-clock limit sa ~20000-bar na window (2400 araw ng BTCUSDT.BINANCE_SPOT-1-DAY-LAST-EXTERNAL). Halos palaging nangangahulugan ito ng gawaing kada bar na lumalaki kasabay ng history — halimbawa, muling pagsuri sa buong funding/supplementary series, o muling pagbuo ng listahan at pagtawag sa min()/sorted() sa loob ng calculate_signal()/on_bar() sa bawat bar. Paunang ayusin ang mga timestamp array na nakaayos pataas ONCE sa __init__ at gumamit ng bisect, o mag-cache ng mga lookup batay sa timestamp, upang maging O(log n) sa halip na O(n) ang gastos kada bar.
Bigo ang verification (Layer 4 — pagsusuri ng QA) [class=code_defect]: - [edge_concern] Pabatid: 1 trade lang ang nagawa ng sandbox sa loob ng 184 araw dahil nagdudulot ng napakababang turnover ang 90d na warmup at pagiging malagkit ng top-2/hysteresis; hindi ito hadlang, pero dapat tiyakin ng analyst na sapat ang mga rotation sa buong history upang masukat. - Nakasalalay ang lingguhang rebalance sa bar counter na kaugnay ng proseso/window, hindi sa timestamp ng kalendaryo ng bar: `self._rebal_count += 1; if……Magpakita ng higit paMagpakita ng mas kaunti
Bigo ang verification (Layer 4 — pagsusuri ng QA) [class=code_defect]:
- [edge_concern] Pabatid: 1 trade lang ang nagawa ng sandbox sa loob ng 184 araw dahil nagdudulot ng napakababang turnover ang 90d na warmup at pagiging malagkit ng top-2/hysteresis; hindi ito hadlang, pero dapat tiyakin ng analyst na sapat ang mga rotation sa buong history upang masukat.
- Nakasalalay ang lingguhang rebalance sa bar counter na kaugnay ng proseso/window, hindi sa timestamp ng kalendaryo ng bar: `self._rebal_count += 1; if (self._rebal_count - 1) % self._rebalance_days == 0: self._rebalance()`. Tumatakbo lang ang calculate_signal pagkatapos ng min_bars_required (92 bars) at isang beses lang sa bawat naka-align na primary timestamp, kaya nagsisimula ang _rebal_count sa 1 sa FIRST bar pagkatapos ng warmup at nagaganap ang rebalance sa ika-1/ika-8/ika-15… bar na naproseso mula sa simula ng window. Ito ang kritikal na anti-pattern ng check-18: (1) nagsisimula sa magkaibang petsa ang bawat walk-forward window at ang holdout, kaya nagkakaiba ang mga araw ng kalendaryo na tinatamaan ng weekly grid sa bawat window — sira ang parity replay at hindi tutugma sa buong history ang mga na-optimize na resulta; (2) sa live crash-restart, mare-reset ang counter at magkakaroon agad ng buong basket rebalance sa unang bar, kaya gagalaw-galaw ang book at muling iaangkla sa uptime. Tinutukoy ng class ang _DAY_NS pero hindi ito kailanman ginagamit.
Ang Stratmill ay isang tool para sa pananaliksik at paper trading, hindi payo sa pananalapi o isang broker. Ang mga resulta ng backtest at paper trading ay hypothetical. May panganib ng pagkalugi ang pangangalakal.