Ipinadala mo sa akin ang notebook noong Linggo ng gabi, at mula noon ay nakabukas na ito sa pangalawang monitor ko. Cross-sectional momentum, nangungunang 150 Binance USDⓈ-M perp ayon sa 30-araw na dollar volume, lingguhang rebalance, long sa nangungunang decile at short sa pinakailalim, mula 2021-01 hanggang 2026-06. Sharpe 2.31, maximum drawdown na 14.2%, at cost model na mukhang makatotohanan sa akin: taker sa pagpasok, taker sa paglabas, naipon ang funding sa bawat interval, at slippage term na tumataas kasabay ng laki ng posisyon mo kumpara sa order book. Tama ang pagkakagawa mo sa mahihirap na bahagi. Pagkatapos, tinanong mo kung bakit flat ang naging resulta ng anim na linggong paper trading, at kung humina na ba ang edge.
Hindi ito humina. Wala talaga ito sa backtest. Tingnan ang cell 4:
info = requests.get(BASE + "/fapi/v1/exchangeInfo").json()
symbols = [s["symbol"] for s in info["symbols"]
if s["status"] == "TRADING" and s["quoteAsset"] == "USDT"]
Tinawag mo ang endpoint na iyon noong Hunyo 2026 at ginamit ang sagot para tukuyin kung ano ang puwedeng i-trade noong Marso 2021. Bawat simbolo sa listahang iyon ay nakaligtas hanggang Hunyo 2026, dahil ganoon mismo ang pagkakabuo ng listahan. Iyan ang buong bug, at mas malaki ang epekto nito kaysa sa pinagsama-samang iba pang bahagi ng cost model mo.
Ang hindi sinasabi sa iyo ng endpoint
Walang history sa exchangeInfo. Walang parameter na asOf, walang archive, walang changelog. Larawan lang ito ng kasalukuyang sandali, at wala nang ibang ipinangako sa iyo ang Binance. Kapag inalis sa listahan ang isang kontrata, binubura ang entry nito sa response at hindi na umiiral ang ticker ayon sa API. Mahigit 600 USDⓈ-M perpetual na ang inilista ng Binance mula pa noong 2019 at mahigit isang daan na ang itinigil nila. BTS, COCOS, TOMO, RAY, FTT, SC, at marami pang kontrata mula sa alt-season noong 2021 na nagkaroon ng maningning na isang quarter, saka unti-unting naubusan ng aktibidad hanggang alisin sila ng venue.
Tanungin mo ang sarili mo kung aling mga pangalan ang gustong piliin ng 30-araw na momentum screen. Hindi BTC. Ang gusto nito ay ang coin na katatlong beses lang tumaas ang halaga dahil sa listing pump at siklo sa Twitter. Malaki ang pagkakasapawan ng populasyong iyan at ng mga tuluyang inaalis sa listahan, at inalis ng universe filter mo ang mismong mga coin na iyon.
Inulit ko ang run mo gamit ang snapshot archive namin, point-in-time universe, parehong signal at parehong gastos, at 0.74 ang lumabas na Sharpe na may 31% drawdown. Tinatayang dalawang ikalima ng agwat ay dahil sa mga inalis na simbolong hindi mo kailanman puwedeng hawakan. Isa pang sangkapat ay mula sa kabaligtarang problema, na mas mahirap mapansin at pinaghihinalaan kong mas hindi mo magugustuhan.
Ang kabilang dulo ng time machine: mga simbolong hindi pa umiiral noon
90-araw na return ang feature mo. min_periods=20 ang rolling window mo, dahil minsan mo lang ito itinakda para hindi masira ng warmup ang unang quarter ng sample at hindi mo na ito binalikan. Kaya nakakakuha ng momentum score ang kontratang 21 araw pa lang mula nang ilista, batay sa tatlong linggong galaw ng presyo matapos itong ilista; pumapasok ito sa top decile halos tuwing naging maganda ang listing, at napapasama sa portfolio mo.
Maaaring katanggap-tanggap ang bahaging iyon. Pero ito ang hindi: nag-backfill ang provider mo ng spot o index data para sa ilan sa mga simbolong iyon bago pa umiral ang perp, kaya may ilang kontratang may kline history na mas maaga pa sa sarili nilang onboardDate. Mga isang minuto lang ang kailangan para masuri ito. I-join ang price table mo sa mga onboard date at bilangin ang mga row na mas maaga sa listing. Sa data mo, may 41 simbolong may bar bago ilista, at isa sa mga ito, noong tag-init ng 2023, ang nagdagdag ng 6% na kita sa equity curve sa loob ng isang linggo mula sa posisyon sa kontratang hindi pa iiral sa loob ng siyam na araw.
Hindi identifier ang ticker string. Label ito na ipinapagamit ng exchange, minsan pa nga ay dalawang beses.
Dito pumapasok ang mga rename. Naging POLUSDT ang MATICUSDT. Naging SUSDT ang FTMUSDT sa 1:1 conversion. Nag-iwan ang pangyayari sa LUNA noong Mayo 2022 ng LUNCUSDT at kalaunan ay ng bagong LUNAUSDT na kapareho ang ugat ng ticker ng coin na halos nawalan na ng lahat ng halaga. Kung symbol string ang susi ng loader mo at pinagdudugtong nito ang anumang file na makita, may kahit isang serye ka roon na may discontinuity na hindi galaw ng presyo. Babasahin ng momentum feature mo ang discontinuity na iyon bilang pinakamalakas na signal sa cross-section.
Iba pang mga bagay na unti-unting nagbabago nang hindi mo namamalayan
Kapag tinanggap mong pabago-bago sa paglipas ng panahon ang listahan ng mga simbolo, ganoon din ang masasabi para sa bawat iba pang field sa response na iyon. Mga value ngayon ang ginagamit mo para sa lahat ng iyon.
| Field | Paano ito nagbabago | Ano ang nasisira |
|---|---|---|
| status | TRADING → SETTLING → wala na | Survivorship; mga pekeng exit sa closing price na hindi kailanman na-trade |
| onboardDate | May mga bagong listing bawat linggo; walang value para sa mga patay na simbolo | Pag-trade sa mga kontrata bago pa umiral ang mga ito |
| tickSize / stepSize | Inaayos habang nagbabago ang mga antas ng presyo | Pag-round ng order at mga limit price na sana ay tinanggihan |
| minNotional | Itinataas sa paglipas ng panahon sa mga manipis na order book | Mga maliit na leg na tatanggihan ng live router mo |
| fundingIntervalHours | 8h sa loob ng maraming taon, saka naging 4h o 1h sa maraming simbolo | Mali nang 2–3× ang carry para mismo sa mga alt na hawak ng screen mo |
| leverage brackets | Binago ang mga tier at maintenance margin | Pagmomodelo ng liquidation at kapasidad ng margin |
Pinakamalaking problema sa kaso mo ang funding. Ipinapalagay ng accrual loop mo na may tatlong bayad bawat araw sa buong history. Lumipat sa apat na oras na funding ang malaking bahagi ng alt book, at sa mga short leg ng mga coin na mataas ang funding nanggagaling ang malaking bahagi ng simulated PnL mo. Hindi lang ito kaunting diperensiya dahil sa pag-round. Mali ito nang ilang ulit.
Pangyayari ang mismong pag-alis sa listahan, at hindi mo ito namo-modelo
Sa point-in-time rerun mo, binigyan ko ng paborableng exit ang strategy. May takbo ang totoong delisting: may anunsyo, karaniwang pitong hanggang labing-apat na araw bago mangyari, kasunod ang reduce-only window, saka sapilitang settlement sa mark price. Pampublikong impormasyon ang anunsyo at puwede kang kumilos batay rito, kaya ang patas na simulation ay mag-exit sa closing price sa araw ng anunsyo. Pero karaniwang 10-20% na itong mas mababa kaysa noong nakaraang linggo, manipis ang order book, at dapat alam ng slippage term mo na nagbago ang market regime. Kung ibinibigay ng fill engine mo ang settlement price nang walang market impact, tahimik mong ginagawang posibleng i-trade sa patas na halaga ang mga asset na mamamatay na.
Kung hindi ka kailanman nag-archive ng exchangeInfo, hindi pa huli ang lahat. Napananatili pa rin sa pampublikong dump sa data.binance.vision/data/futures/um/monthly/klines/ ang mga direktoryo ng mga inalis na simbolo kahit matagal nang nakalimutan na ng API ang mga ito. Ilista ang mga direktoryo; nagbibigay ng magagamit na palugit ng listing at delisting ang una at huling buwanang file para sa bawat simbolo, kahit walang vendor. Rekonstruksiyon ito, hindi opisyal na rekord, at hindi nito mababawi ang tick size o funding interval. Pero sasabihin nito kung aling mga simbolo ang umiral at kung kailan, na siyang 80% ng kailangan mo sa Lunes.
Mga ipagawa ko sa iyo bago mo galawin ulit ang signal
- Gumawa ng cron na kumukuha ng exchangeInfo mula sa bawat venue na sinasaliksik mo araw-araw, at isinusulat ito sa object storage na nakaayos ayon sa petsa. Mas mababa ito sa kalahating megabyte kapag naka-gzip. Magkakahalaga lang ng halos wala sa S3 ang sampung taon, at magkakaroon ka ng kakayahan sa pananaliksik na hindi mo na mabibili sa hinaharap.
- Gumawa ng asset master mula sa mga snapshot na iyon: isang row bawat (venue, symbol, valid_from, valid_to) na may kumpletong set ng mga field. Ikumpara ang magkakasunod na snapshot para mabuo ito, at ituring na bagong row ang bawat pagbabago ng field.
- Gumawa ng universe function na laging nangangailangan ng timestamp argument.
universe(ts), huwaguniverse(). Gawing imposibleng default ito para walang sinuman, pati ikaw sa hinaharap nang 1am, ang aksidenteng makapili ng survivor list. - Maglagay ng pre-listing assertion sa data loader: walang bar ang puwedeng umiral bago ang
onboard_tsminus one day. Itigil ang run; huwag magbabala lang. - Gumamit ng matatag na internal instrument ID na hindi nagbabago kahit mag-rename, at gawing attribute na lang ang ticker. I-map ang POL at MATIC sa iisang ID, at markahan ang redenomination para mapigilan ng continuity logic ang pagdugtong ng mga ito.
Gawin mo ang mga iyon at ulitin ang run. Tingin ko ay malapit ka sa 0.74 na nakuha ko, at ang kawili-wiling tanong ay kung may saysay bang i-paper trade ang 0.74 na kasama ang mga patay na coin. Posible. May saysay ang cross-sectional momentum sa perps, at tunay na carry mula sa short side ang bahagi ng natitira matapos ayusin ang universe. Mapapansin mo ring magtutugma na ang paper results at backtest mo, dahil point-in-time universe na talaga ang gamit ng paper trading. Wala naman itong ibang mapagpipilian.
P.S. Hindi ito natatangi sa crypto, mas litaw lang dito. Matagal nang hinaharap ng mga equity researcher ang delisting returns at mga ticker na ipinapagamit muli mula nang simulang ipadala ng CRSP ang mga ito, at mas sukdulan pa ang prediction markets: sadyang nag-e-expire ang bawat kontrata, kaya puro listing at pag-expire ang uniberso. Kung ililipat mo ang screen na ito sa Kalshi, unahin mong buuin ang asset master. Wala roong ibang uri ng history.
← Lahat ng post


