27 আগস্ট, 2026 · ডেটা ইঞ্জিনিয়ারিং

আপনার সিম্বল ইউনিভার্স একটি টাইম মেশিন: ক্রিপ্টো পার্প ব্যাকটেস্টে সারভাইভারশিপ বায়াস

আপনার সিম্বল ইউনিভার্স একটি টাইম মেশিন: ক্রিপ্টো পার্প ব্যাকটেস্টে সারভাইভারশিপ বায়াস

রবিবার রাতে আপনি নোটবুকটা পাঠিয়েছিলেন, তারপর থেকে দ্বিতীয় মনিটরে খোলাই আছে। ক্রস-সেকশনাল মোমেন্টাম, 30-দিনের ডলার ভলিউমে শীর্ষ 150 Binance USDⓈ-M পার্প, সাপ্তাহিক রিব্যালান্স, শীর্ষ ডেসাইল লং ও নিচের ডেসাইল শর্ট, 2021-01 থেকে 2026-06। Sharpe 2.31, সর্বোচ্চ ড্রডাউন 14.2%, আর কস্ট মডেলটাও আমার কাছে বিশ্বাসযোগ্য লেগেছিল: taker-এ ঢোকা, taker-এ বেরোনো, প্রতি ইন্টারভ্যালে ফান্ডিং জমা, অর্ডারবুকের তুলনায় আপনার সাইজ অনুযায়ী বাড়ে এমন স্লিপেজ টার্ম। কঠিন কাজগুলো আপনি ঠিকই করেছিলেন। তারপর জিজ্ঞেস করলেন, ছয় সপ্তাহের পেপার ট্রেডিং কেন সমতল ফল দিয়েছে, আর এজ কি ক্ষয় হয়ে গেছে।

ক্ষয় হয়নি। ব্যাকটেস্টে এজটা কখনো ছিলই না। সেল 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"]

আপনি 2026 সালের জুনে ওই এন্ডপয়েন্ট ডেকে, 2021 সালের মার্চে কী ট্রেড করা যেত তা নির্ধারণ করতে সেই উত্তর ব্যবহার করেছেন। ওই তালিকার প্রতিটি সিম্বল 2026 সালের জুন পর্যন্ত টিকে ছিল—তালিকাটি এভাবেই তৈরি। এটাই পুরো বাগ, আর আপনার বাকি কস্ট মডেলের সম্মিলিত মূল্যের চেয়েও এর প্রভাব বেশি।

2.31 → 0.74Sharpe, টিকে থাকা সিম্বলের তালিকা বনাম পয়েন্ট-ইন-টাইম
প্রায় 1 in 5আপনার 2021 ইউনিভার্সের আর অস্তিত্ব নেই
380 KBদৈনিক exchangeInfo স্ন্যাপশট, gzip করা

এন্ডপয়েন্ট যা জানাবে না

exchangeInfo-তে কোনো ইতিহাস নেই। কোনো asOf প্যারামিটার নেই, আর্কাইভ নেই, চেঞ্জলগ নেই। এটি এই মুহূর্তের একটি ছবি, আর Binance কখনো এর বেশি কিছু দেওয়ার প্রতিশ্রুতি দেয়নি। কোনো কন্ট্রাক্ট ডিলিস্ট হলে, তার এন্ট্রি রেসপন্স থেকে মুছে যায় এবং API-র হিসাবে টিকারটির আর অস্তিত্ব থাকে না। 2019 সাল থেকে Binance 600-এরও বেশি USDⓈ-M পার্পেচুয়াল তালিকাভুক্ত করেছে, আর তার শতাধিকেরও বেশি বাতিল করেছে। BTS, COCOS, TOMO, RAY, FTT, SC—2021 সালের অল্ট-সিজনের দীর্ঘ লেজের এমন সব কন্ট্রাক্ট, যেগুলোর এক দুর্দান্ত কোয়ার্টার ছিল, তারপর ভলিউম কমতে কমতে একসময় ভেন্যু সেগুলো সরিয়ে দিয়েছে।

নিজেকে জিজ্ঞেস করুন, 30-দিনের মোমেন্টাম স্ক্রিন কোন নামগুলো পছন্দ করে। BTC নয়। স্ক্রিন পছন্দ করে সেই জিনিসটিকে, যেটি লিস্টিং পাম্প আর Twitter চক্রে এইমাত্র তিন গুণ হয়েছে। ওই গোষ্ঠী আর শেষ পর্যন্ত ডিলিস্ট হওয়া গোষ্ঠীর মধ্যে বড়সড় মিল আছে, আর আপনার ইউনিভার্স ফিল্টার সেই মিলটাই মুছে দিয়েছে।

আমাদের স্ন্যাপশট আর্কাইভে আপনার রানটি আবার তৈরি করলাম—পয়েন্ট-ইন-টাইম ইউনিভার্স, একই সিগনাল, একই খরচ—আর Sharpe এল 0.74, ড্রডাউন 31%। ব্যবধানের মোটামুটি দুই-পঞ্চমাংশ এসেছে ডিলিস্ট হওয়া সিম্বল থেকে, যেগুলো আপনি কখনোই ধরে রাখতে পারতেন না। আরেক-চতুর্থাংশ এসেছে এর উল্টো সমস্যাটি থেকে—যেটি একটু সূক্ষ্ম, আর আমার ধারণা, আপনার আরও কম পছন্দ হবে।

টাইম মেশিনের অন্য প্রান্ত: যে সিম্বলগুলোর তখনো অস্তিত্ব ছিল না

আপনার ফিচারটি 90-দিনের রিটার্ন। আপনার রোলিং উইন্ডোতে আছে min_periods=20, কারণ স্যাম্পলের প্রথম কোয়ার্টারের ওয়ার্মআপ যাতে সবকিছু মুছে না দেয়, সে জন্য একবার সেট করেছিলেন, তারপর আর ফিরে দেখেননি। ফলে 21 দিন আগে অনবোর্ড হওয়া একটি কন্ট্রাক্টের মোমেন্টাম স্কোর হিসাব হয় লিস্টিং-পরবর্তী তিন সপ্তাহের দামের ওঠানামা থেকে; লিস্টিং ভালো হলে প্রায়ই সেটি শীর্ষ ডেসাইলে উঠে যায়, আর আপনার পজিশনে ঢুকে পড়ে।

এই অংশটিকে যুক্তিসঙ্গত বলা যায়। কিন্তু যেটি যুক্তিসঙ্গত নয় তা হলো: আপনার ডেটা প্রোভাইডার কিছু সিম্বলের পার্পের অস্তিত্বের আগের স্পট বা ইনডেক্স ডেটা দিয়ে পেছনের ইতিহাস পূরণ করেছে, ফলে কয়েকটি কন্ট্রাক্টের kline ইতিহাস তাদের নিজেদের onboardDate-এরও আগের। প্রায় এক মিনিটেই যাচাই করতে পারবেন। আপনার প্রাইস টেবিলের সঙ্গে অনবোর্ড তারিখ মিলিয়ে লিস্টিংয়ের আগের সারি গুনুন। আপনার ডেটায় 41টি সিম্বলের প্রি-লিস্টিং বার আছে, আর সেগুলোর একটি 2023 সালের গ্রীষ্মে ইকুইটি কার্ভে এক সপ্তাহে 6% লাভ যোগ করেছে—এমন একটি কন্ট্রাক্টে পজিশন থেকে, যার অস্তিত্ব শুরু হতে তখনো আরও 9 দিন বাকি ছিল।

টিকারের স্ট্রিং কোনো শনাক্তকারী নয়। এটি এমন একটি লেবেল, যা এক্সচেঞ্জ ভাড়া দেয়—কখনো একই লেবেল দুবারও।

এতে নাম বদলের প্রসঙ্গও আসে। MATICUSDT হয়েছে POLUSDT। FTMUSDT, 1:1 রূপান্তরের পর হয়েছে SUSDT। 2022 সালের মে মাসের LUNA পরিস্থিতিতে তৈরি হয়েছে LUNCUSDT, পরে একেবারে নতুন LUNAUSDT—যার টিকার মূলাংশ এমন কিছুর সঙ্গে মেলে, যা প্রায় সব মূল্য হারিয়েছিল। আপনার লোডার যদি সিম্বল স্ট্রিংকে কী ধরে এবং পাওয়া ফাইলগুলো জুড়ে দেয়, তাহলে আপনার ডেটায় অন্তত একটি সিরিজ আছে যার বিচ্ছিন্নতা দামের ওঠানামা নয়; আর আপনার মোমেন্টাম ফিচার সেই বিচ্ছিন্নতাকেই পুরো ক্রস-সেকশনের সবচেয়ে শক্তিশালী সিগনাল হিসেবে পড়বে।

আপনার অগোচরে বদলে যাওয়া বাকি সবকিছু

সিম্বল তালিকা যে সময়ের সঙ্গে বদলায়, এটা মেনে নিলে রেসপন্সের অন্য প্রতিটি ফিল্ডেও একই যুক্তি প্রযোজ্য। আপনি সবগুলোর জন্যই আজকের মান ব্যবহার করছেন।

ফিল্ডযেভাবে বদলায়কী ভাঙে
statusTRADING → SETTLING → নেইসারভাইভারশিপ; এমন ক্লোজ প্রাইসে ভুয়া এক্সিট, যে দামে কখনো ট্রেডই হয়নি
onboardDateপ্রতি সপ্তাহে নতুন লিস্টিং; মৃত সিম্বলের তারিখ অনুপস্থিতঅস্তিত্বের আগেই কন্ট্রাক্ট ট্রেড করা
tickSize / stepSizeদামের স্তর বদলালে নতুন করে সমন্বয়অর্ডার রাউন্ডিং, আর এমন লিমিট প্রাইস যা প্রত্যাখ্যাত হতো
minNotionalপাতলা অর্ডারবুকে সময়ের সঙ্গে বাড়ানো হয়েছেছোট লেগ, যা আপনার লাইভ রাউটার গ্রহণই করত না
fundingIntervalHoursবছরের পর বছর 8h, তারপর বহু সিম্বলে 4h বা 1hঠিক সেই অল্টগুলোতে ক্যারি 2–3× ভুল, যেগুলো আপনার স্ক্রিন ধরে রাখে
leverage bracketsটিয়ার ও মেইনটেন্যান্স মার্জিন সংশোধিত হয়েছেলিকুইডেশন মডেলিং ও মার্জিন ধারণক্ষমতা

আপনার ক্ষেত্রে ফান্ডিংয়ের ব্যাপারটাই সবচেয়ে বেশি ক্ষতি করছে। আপনার অ্যাক্রুয়াল লুপ ধরে নিচ্ছে পুরো ইতিহাসজুড়ে প্রতিদিন তিনটি পেমেন্ট হয়েছে। অল্ট বুকের উল্লেখযোগ্য অংশ চার ঘণ্টা অন্তর ফান্ডিংয়ে গেছে, আর উচ্চ-ফান্ডিং সিম্বলের শর্ট লেগ থেকেই আপনার সিমুলেটেড PnL-এর বড় অংশ আসছে। এখানে রাউন্ডিংয়ের সামান্য ভুল হয়নি। ভুল হয়েছে গুণিতকে।

ডিলিস্টিং নিজেই একটি ঘটনা, অথচ আপনি সেটি মডেল করছেন না

আপনার পয়েন্ট-ইন-টাইম পুনরায় চালানো পরীক্ষায় আমি স্ট্র্যাটেজিকে সুবিধাজনক এক্সিট দিয়েছি। বাস্তবে ডিলিস্টিং চলে নির্দিষ্ট ধাপে: ঘোষণা, সাধারণত 7 থেকে 14 দিন আগে; তারপর শুধু পজিশন কমানোর সময়সীমা; শেষে মার্ক প্রাইসে জোরপূর্বক সেটলমেন্ট। ঘোষণা জনসমক্ষে আসে, তাই আপনি ব্যবস্থা নিতে পারেন; সৎ সিমুলেশনে ঘোষণার দিনের ক্লোজে এক্সিট দেখানো উচিত। কিন্তু সাধারণ অল্ট ডিলিস্টিংয়ে সেই ক্লোজ আগের সপ্তাহের চেয়ে ইতিমধ্যেই 10-20% নিচে থাকে, অর্ডারবুক পাতলা থাকে, আর আপনার স্লিপেজ টার্মকে বুঝতে হবে যে এটি অন্য রকম বাজার পরিস্থিতিতে কাজ করছে। আপনার ফিল ইঞ্জিন যদি কোনো ইমপ্যাক্ট ছাড়া সেটলমেন্ট প্রাইস দিয়ে দেয়, তাহলে নীরবে মরে যাওয়া অ্যাসেটকে ন্যায্য দামে ট্রেডযোগ্য বানিয়ে ফেলেছেন।

আপনি exchangeInfo কখনো আর্কাইভ না করলেও, সব শেষ হয়ে যায়নি। সর্বজনীন ডাম্পটি data.binance.vision/data/futures/um/monthly/klines/-এ API ভুলে যাওয়ার অনেক পরও ডিলিস্ট হওয়া সিম্বলের ডিরেক্টরি রেখে দেয়। ডিরেক্টরি তালিকা দেখুন; প্রতিটি সিম্বলের প্রথম ও শেষ মাসিক ফাইল থেকে কোনো ভেন্ডার ছাড়াই লিস্টিং ও ডিলিস্টিংয়ের ব্যবহারযোগ্য সময়সীমা বের করা যায়। এটি রেকর্ড নয়, পুনর্গঠন; আর এতে tick size বা funding interval উদ্ধার করা যাবে না। তবে কে কখন ছিল, তা বলে দেবে—সোমবারের মধ্যে আপনার যা দরকার তার 80% এটাই।

সিগনাল আবার হাত দেওয়ার আগে যে জিনিসগুলো বানাতে বলব

  1. একটি cron, যা আপনার গবেষণার প্রতিটি ভেন্যু থেকে প্রতিদিন exchangeInfo টেনে এনে তারিখ অনুযায়ী কী করা অবজেক্ট স্টোরেজে লিখবে। gzip করলে আকার আধা মেগাবাইটেরও কম। দশ বছরের খরচ S3-তে রাউন্ডিংয়ের ভুলমাত্র, আর এতে এমন গবেষণার সামর্থ্য পাবেন যা পরে কিনতে পারবেন না।
  2. সেই স্ন্যাপশট থেকে তৈরি একটি অ্যাসেট মাস্টার: (venue, symbol, valid_from, valid_to) অনুযায়ী প্রতি সারিতে সব ফিল্ডের মান। পরপর স্ন্যাপশটের পার্থক্য বের করে এটি তৈরি করুন, আর যেকোনো ফিল্ড বদলালেই নতুন সারি ধরুন।
  3. একটি ইউনিভার্স ফাংশন, যাতে টাইমস্ট্যাম্প দেওয়া বাধ্যতামূলক। universe(ts), কখনো universe() নয়। ডিফল্টটি এমনভাবে অসম্ভব করে রাখুন, যাতে কেউ—রাত 1am-এ ভবিষ্যতের আপনিও—ভুল করে টিকে থাকা সিম্বলের তালিকা ব্যবহার করতে না পারেন।
  4. ডেটা লোডারে প্রি-লিস্টিং অ্যাসারশন: কোনো বার থাকতে পারবে না onboard_ts থেকে এক দিন আগে। রান ব্যর্থ করুন, শুধু সতর্কবার্তা দেবেন না।
  5. নাম বদলালেও টিকে থাকে এমন স্থিতিশীল অভ্যন্তরীণ ইনস্ট্রুমেন্ট ID, আর টিকার থাকবে অ্যাট্রিবিউট হিসেবে। POL ও MATIC-কে একটি ID-তে ম্যাপ করুন, আর রিডিনোমিনেশন চিহ্নিত রাখুন, যাতে কন্টিনিউটি লজিক সেগুলো জুড়ে দিতে না পারে।

এগুলো করে আবার চালান। আমার ধারণা, ফল আমার পাওয়া 0.74-এর কাছাকাছি আসবে; তখন আসল প্রশ্ন হবে, মৃত সিম্বলসহ 0.74-এর মধ্যে পেপার-ট্রেড করার মতো কিছু আছে কি না। থাকতে পারে। পার্পে ক্রস-সেকশনাল মোমেন্টাম একেবারে অর্থহীন নয়, আর ইউনিভার্স ঠিক করার পর যা থাকে তার একটি অংশ শর্ট দিকের প্রকৃত ক্যারি। আপনার পেপার ফল আর ব্যাকটেস্টও মিলতে শুরু করবে, কারণ পেপার ট্রেডিং সব সময় পয়েন্ট-ইন-টাইম ইউনিভার্সেই চলেছে। তার বিকল্প ছিল না।

পুনশ্চ: এটি ক্রিপ্টোর বিশেষ বৈশিষ্ট্য নয়, এখানে শুধু বিষয়টা বেশি চোখে পড়ে। CRSP থেকে ডেটা পাওয়া শুরু হওয়ার পর থেকেই ইকুইটি গবেষকেরা ডিলিস্টিং রিটার্ন আর পুনর্ব্যবহৃত টিকার নিয়ে লড়ছেন; আর প্রেডিকশন মার্কেটে বিষয়টি চরমে—প্রতিটি কন্ট্রাক্টের মেয়াদ নিয়মমাফিক শেষ হয়, তাই ইউনিভার্স বলতে শুধু লিস্টিং আর অবসান। কখনো এই স্ক্রিন Kalshi-তে নিয়ে গেলে, আগে অ্যাসেট মাস্টার বানাবেন। সেখানে ইতিহাসের আর কোনো ধরন নেই।

সারভাইভারশিপ বায়াসপয়েন্ট-ইন-টাইম ডেটাক্রিপ্টো ফিউচার্সব্যাকটেস্টিংডেটা ইঞ্জিনিয়ারিং
শেয়ার করুনXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← সব পোস্ট