یکشنبهشب نوتبوک را برایم فرستادی و از آن موقع روی نمایشگر دوم باز مانده است. مومنتوم مقطعی، 150 پرپ Binance USDⓈ-M برتر بر اساس حجم دلاری 30روزه، بازتوازن هفتگی، خرید دهک برتر و فروش استقراضی دهک پایین، از 2021-01 تا 2026-06. شارپ 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"]
این endpoint را در ژوئن 2026 فراخوانی کردی و از پاسخ آن برای تعیین نمادهای قابل معامله در مارس 2021 استفاده کردی. طبق تعریف، همهٔ نمادهای آن فهرست تا ژوئن 2026 دوام آورده بودند. کل ایراد همین است و اثرش از مجموع باقی مدل هزینههایت بیشتر است.
چیزی که endpoint به شما نمیگوید
exchangeInfo هیچ سابقهای ندارد. نه پارامتر asOf، نه آرشیو، نه گزارش تغییرات. تصویری از همین لحظه است و Binance هیچوقت چیز دیگری وعده نداده. وقتی قراردادی از فهرست خارج میشود، ورودیاش از پاسخ حذف میشود و از دید API دیگر نمادی وجود ندارد. Binance از 2019 تاکنون بیش از 600 قرارداد دائمی USDⓈ-M فهرست کرده و خیلی بیش از صدتای آنها را بازنشسته کرده است. BTS، COCOS، TOMO، RAY، FTT، SC و دنبالهای بلند از قراردادهای فصل آلتکوینهای 2021 که یک فصل درخشان داشتند و بعد کمرمق شدند تا صرافی آنها را حذف کرد.
از خودت بپرس فیلتر مومنتوم 30روزه عاشق کدام نمادهاست. نه BTC؛ عاشق چیزی است که تازه با جهش زمان عرضه و موج توییتری سه برابر شده. این گروه همپوشانی زیادی با نمادهایی دارد که سرانجام از فهرست خارج میشوند و فیلتر جهان معاملاتی تو همین همپوشانی را حذف کرده است.
اجرایت را با آرشیو تصویرهای روزانهٔ ما، جهان معاملاتی نقطهدرزمان، همان سیگنال و همان هزینهها از نو اجرا کردم؛ شارپ 0.74 و افت سرمایهٔ 31٪ شد. حدود دوپنجم فاصله مربوط به نمادهای حذفشدهای است که اصلاً اجازه نداشتی نگه داری. یکچهارم دیگر از مسئلهٔ وارونه میآید؛ ظریفتر است و گمان میکنم کمتر خوشت بیاید.
سر دیگر ماشین زمان: نمادهایی که هنوز وجود نداشتند
ویژگی شما بازده 90روزه است. پنجرهٔ گردشت min_periods=20 دارد، چون یکبار آن را طوری تنظیم کردی که دورهٔ گرمشدن، سهماههٔ اول نمونه را از بین نبرد و دیگر سراغش نرفتی. پس قراردادی که 21 روز پیش فهرست شده، امتیاز مومنتومش را بر اساس سه هفته حرکت قیمت پس از عرضه میگیرد، تقریباً هر وقت عرضه خوب پیش رفته در دهک برتر قرار میگیرد و وارد پرتفویات میشود.
میشود گفت این بخش قابلقبول است. اما این یکی نیست: ارائهدهندهٔ دادهات تاریخچهٔ بعضی از این نمادها را با دادهٔ اسپات یا شاخصی از پیش از وجود پرپت آنها پُر کرده است، بنابراین تاریخچهٔ کندل چند قرارداد از onboardDate خودشان قدیمیتر است. بررسیاش حدود یک دقیقه طول میکشد. جدول قیمت را به تاریخهای عرضه وصل کن و ردیفهای قبل از فهرستشدن را بشمار. در دادههایت 41 نماد کندل پیش از عرضه دارند و یکی از آنها در تابستان 2023 از موقعیتی در قراردادی که تا 9 روز دیگر هم وجود نداشت، 6٪ سود در یک هفته به منحنی سرمایه اضافه میکند.
رشتهٔ نماد شناسه نیست؛ برچسبی است که صرافی اجاره میدهد، گاهی هم دوبار.
اینجا تغییر نامها هم مطرح میشوند. MATICUSDT به POLUSDT تبدیل شد. FTMUSDT با تبدیل 1:1 به SUSDT تبدیل شد. ماجرای LUNA در مه 2022 به LUNCUSDT و بعدتر LUNAUSDT کاملاً جدیدی انجامید که ریشهٔ نمادش با چیزی مشترک است که کمابیش همهچیزش را از دست داد. اگر بارگذار دادهات با رشتهٔ نماد کلیدگذاری میکند و هر فایلی را که پیدا کند به هم میچسباند، دستکم یک سری داری که در آن ناپیوستگیای هست که حرکت قیمت نیست و ویژگی مومنتوم آن را بهعنوان قویترین سیگنال مقطعی میخواند.
بقیهٔ چیزهایی که زیر پایتان تغییر میکنند
وقتی پذیرفتی که فهرست نمادها با زمان تغییر میکند، همین استدلال دربارهٔ همهٔ فیلدهای دیگر آن پاسخ هم صدق میکند. برای همهشان از مقادیر امروز استفاده میکنی.
| فیلد | نحوهٔ تغییر | پیامد |
|---|---|---|
| status | از TRADING به SETTLING و بعد حذف | سوگیری بقا؛ خروجهای خیالی با قیمت بستهشدنی که هرگز معامله نشده |
| onboardDate | هر هفته فهرستهای جدید؛ برای نمادهای مرده موجود نیست | معاملهٔ قراردادها پیش از وجودشان |
| tickSize / stepSize | با تغییر سطح قیمت دوباره تنظیم میشوند | گردکردن سفارش و قیمتهای محدودی که رد میشدند |
| minNotional | بهمرور در دفترهای کمعمق افزایش مییابد | موقعیتهای کوچک را مسیریاب زندهٔ شما رد میکند |
| fundingIntervalHours | سالها 8h بود و بعد برای نمادهای زیادی 4h یا 1h شد | محاسبهٔ بازده نگهداری 2–3× خطا دارد، دقیقاً برای آلتکوینهایی که فیلترتان نگه میدارد |
| نردبانهای اهرم | سطوح و مارجین نگهداری بازبینی شدند | مدلسازی لیکوییدشدن و ظرفیت مارجین |
در مورد تو، فاندینگ بیشترین آسیب را میزند. حلقهٔ انباشتت در تمام تاریخچه فرض میکند روزی سه پرداخت انجام میشود. بخش قابلتوجهی از پرتفوی آلتکوین به فاندینگ چهارساعته تغییر کرد و موقعیتهای فروش استقراضی در نمادهای با فاندینگ بالا منبع بخش بزرگی از سود و زیان شبیهسازیشدهٔ تو هستند. اینجا خطایت در حد اختلاف ناشی از گردکردن نیست؛ ضریبی از مقدار درست است.
خود حذف از فهرست یک رویداد است و تو آن را مدل نمیکنی
در اجرای دوبارهٔ نقطهدرزمان، خروج سخاوتمندانهای برای راهبرد در نظر گرفتم. حذفهای واقعی طبق یک برنامه پیش میروند: اعلامیهای که معمولاً 7 تا 14 روز زودتر منتشر میشود، بعد بازهٔ کاهش صرفاً، و سپس تسویهٔ اجباری با قیمت مارک. اعلامیه اطلاعات عمومی است و میتوانی بر اساس آن اقدام کنی؛ پس شبیهسازی واقعبینانه یعنی خروج در قیمت پایانی روز اعلامیه. اما در یک حذف معمول آلتکوین، آن قیمت پایانی از هفتهٔ قبل 10-20٪ پایینتر است، دفتر سفارش کمعمق است و مؤلفهٔ لغزش باید بداند در رژیم متفاوتی کار میکند. اگر موتور اجرای سفارش قیمت تسویه را بیهیچ اثر قیمتی به تو بدهد، بیسروصدا داراییهای در حال مرگ را با ارزش منصفانه قابل معامله کردهای.
اگر هیچوقت exchangeInfo را آرشیو نکردی، هنوز کار از کار نگذشته است. مخزن عمومی data.binance.vision/data/futures/um/monthly/klines/ هنوز مدتها پس از فراموششدن نمادهای حذفشده از سوی API، پوشههایشان را نگه میدارد. فهرست پوشهها را استخراج کن؛ اولین و آخرین فایل ماهانهٔ هر نماد، بدون نیاز به هیچ فروشندهای، بازهٔ تقریبی عرضه و حذف را به دست میدهد. این بازسازی است، نه سابقهٔ ثبتشده، و اندازهٔ تیک یا بازههای فاندینگ را بازیابی نمیکند. اما میگوید چه نمادی چه زمانی وجود داشته؛ دوشنبه 80٪ چیزی است که لازم داری.
چیزی که پیش از دستزدن دوباره به سیگنال میخواهم بسازی
- یک cron که هر روز exchangeInfo را از همهٔ صرافیهایی که بررسی میکنی دریافت کند و بر اساس تاریخ در فضای ذخیرهسازی آبجکت بنویسد. نسخهٔ فشردهاش کمتر از نیم مگابایت است. ده سال هزینهای در حد خطای گردکردن در S3 دارد و توان پژوهشیای برایت میخرد که بعداً نمیتوانی تهیهاش کنی.
- یک مرجع اصلی دارایی که از آن تصویرهای روزانه ساخته شود: یک ردیف برای هر ترکیب (صرافی، نماد، valid_from، valid_to) با همهٔ فیلدها. با مقایسهٔ تصویرهای پیاپی آن را بساز و هر تغییر در هر فیلد را ردیف تازهای در نظر بگیر.
- تابعی برای جهان معاملاتی با آرگومان زمان اجباری.
universe(ts)، هرگزuniverse(). پیشفرض را طوری ناممکن کن که هیچکس، حتی خود آیندهات ساعت 1 بامداد، نتواند تصادفی سراغ فهرست بازماندگان برود. - یک assertion برای پیش از عرضه در بارگذار داده: هیچ کندلی نباید پیش از
onboard_tsمنهای یک روز وجود داشته باشد. اجرای برنامه را متوقف کن، هشدار نده. - یک شناسهٔ داخلی پایدار برای ابزار معاملاتی که با تغییر نام عوض نشود و نماد را به ویژگی تبدیل کند. POL و MATIC را به یک شناسه نگاشت کن و تغییر نامگذاریِ واحد را پرچم بزن تا منطق پیوستگی از اتصال آنها جلوگیری کند.
اینها را انجام بده و دوباره اجرا کن. حدسم این است که به 0.74 من میرسی و آنوقت پرسش جالب این میشود که آیا 0.74 با احتساب نمادهای مرده چیزی برای معاملهٔ کاغذی دارد یا نه. شاید داشته باشد. مومنتوم مقطعی در پرپتها بیاثر نیست و بخشی از چیزی که بعد از اصلاح جهان معاملاتی باقی میماند، بازده نگهداری واقعی از سمت فروش استقراضی است. همچنین میبینی که نتایج معاملات کاغذی و بکتستت با هم جور درمیآیند، چون معاملات کاغذی همیشه روی جهان معاملاتی نقطهدرزمان اجرا شده است. چارهٔ دیگری نداشت.
پینوشت: این ویژگی خاص کریپتو نیست، فقط اینجا پررنگتر است. پژوهشگران سهام از وقتی CRSP شروع به ارائهٔ داده کرده، با بازده حذف از فهرست و نمادهای بازیافتی دستوپنجه نرم میکنند و بازارهای پیشبینی این مسئله را به نهایت میرسانند: هر قرارداد طبق طراحی منقضی میشود، پس جهان معاملاتی چیزی جز عرضهها و پایانها نیست. اگر روزی این فیلتر را به Kalshi منتقل کردی، اول مرجع اصلی دارایی را بساز. آنجا نوع دیگری از تاریخچه وجود ندارد.
← همهٔ مطالب

