شش هفته بعد از اجرای پسآزمایی، آن را با همان کد، پیکربندی و بازه زمانی دوباره اجرا کردیم. سرمایه پایانی فرق داشت. تفاوت چشمگیری نبود، اما آنقدر بود که نسبت Sharpe را از 1.31 به 1.08 برساند و بهترین مجموعه پارامترها را تغییر دهد.
استراتژی تغییر نکرده بود؛ دادههای تاریخی تغییر کرده بودند. فروشنده چند روز از معاملات و کندلها را بازبینی کرده بود و در اجرای اول، نسخه دقیق ورودی را نگه نداشته بودیم. چند روز بعد را صرف این کردیم که بفهمیم نتیجه جدید حاصل اصلاح داده بود، اشکال خط لوله بود یا فرایند پژوهشیای که امکان بازتولیدش را نداشتیم.
دوشنبه: اجرای دوباره با نتیجه قبلی همخوان نبود
نخستین سرنخ، شکاف کوچکی در یک جفتارز نقدشونده در بازار اسپات بود. بیشینه کندل اولیه ما 62,418 بود. در اجرای دوباره، 62,431 ثبت شده بود. این تفاوت بیاهمیت به نظر میرسید تا وقتی نقطه ورود استراتژی را بررسی کردیم: آستانهاش بین این دو قیمت قرار داشت. تغییر چند کندل یعنی سیگنالهای متفاوت و در نتیجه، چند روز بعد موقعیتهای متفاوت.
تعداد معاملات روزانه را مقایسه کردیم و فهمیدیم که ناهماهنگی از یک تاریخ مشخص شروع شده است. بعد ردیفهای خامی را که مبنای دادههای آن تاریخ بودند با هم سنجیدیم. پاسخ فعلی فروشنده شامل چند معامله اصلاحشده و یک کندل تجمیعی بازبینیشده بود. پاسخی که قبلاً دریافت کرده بودیم هیچ گزارش تغییری همراه نداشت.
این رفتار عادی دادههاست. صرافیها سوابق را اصلاح میکنند؛ فروشندگان شکافها را با داده پر میکنند، معاملات ثبتشده نادرست را تصحیح میکنند و منطق تجمیع را تغییر میدهند. ممکن است پرسوجویی برای «دادههای ژانویه» در مارس پاسخ متفاوتی برگرداند.
سهشنبه: رسیدی را که گم کرده بودیم پیدا کردیم
نام فروشنده، نماد و بازه زمانی را در سابقه اجرا ثبت کرده بودیم. اما خود پاسخ یا هش محتوای هر بخش ورودی را ذخیره نکرده بودیم. یعنی میتوانستیم ثابت کنیم چه چیزی درخواست کرده بودیم، اما نه اینکه فروشنده دقیقاً چه بایتهایی برگردانده بود.
قدیمیترین فایلهای ذخیرهشدهای را که پیدا کردیم برداشتیم و با پاسخ فعلی مقایسه کردیم. تفاوت از تعدیل ناشی از تجزیه سهام یا تبدیل منطقه زمانی نبود. چند رکورد معامله اصلاحشده از سازنده کندل ما عبور کرده بودند. این بررسی یکی از فرضیهها را کنار گذاشت، اما حافظه نهان ناقص بود؛ بنابراین هنوز نمیتوانستیم همه کندلهای متأثر را دقیقاً بازسازی کنیم.
| آنچه ثبت کرده بودیم | پاسخی که میتوانستیم بگیریم | آنچه کم داشتیم |
|---|---|---|
| فروشنده، نماد، بازه زمانی | اینکه اجرا چه درخواستی فرستاده بود | محتوای پاسخ |
| نسخه خط لوله | اینکه کدام کد کندلها را ساخته بود | ردیفهای دقیق ورودی |
| زمان اجرای کار | اینکه کار را چه زمانی اجرا کرده بودیم | اینکه آن زمان کدام بازبینی فروشنده در دسترس بود |
فرض کرده بودیم «پرسوجوی یکسان» یعنی «داده یکسان». این فرض باعث شده بود آزمایش بازتولیدپذیرتر از واقعیت به نظر برسد.
چهارشنبه: اصلاح دادهها روایت را تغییر داد
تاریخهای متأثر را با هر دو نسخه دادههای در دسترس دوباره اجرا کردیم. کندلهای بازبینیشده دو نقطه ورود را حذف کردند و یک خروج را بهاندازه یک کندل جابهجا کردند. همین سه معامله بیشترِ تغییر Sharpe را توضیح میدادند. استراتژی به چند مشاهده نزدیک به آستانه فعالسازی حساس بود، هرچند نمودار کلی قیمت تقریباً یکسان به نظر میرسید.
این به آن معنا نبود که نتیجه اولیه ساختگی بود یا نتیجه بازبینیشده خودبهخود بهتر است. یعنی باید دامنه ادعایمان را مشخص میکردیم: اجرای قدیمی، نسخه دادهای را توصیف میکرد که آن زمان داشتیم و اجرای دوباره، تاریخچه فعلی فروشنده را. نمیتوانستیم صادقانه یکی را بازتولید دیگری بنامیم.
پنجشنبه: سابقه پژوهش را تغییر دادیم
برای اجراهای پژوهشی جدید، نسخههای ثابت و تغییرناپذیر ورودی را اضافه کردیم. برای هر بخش یک هش محتوا ثبت میشود و مانیفست اجرا منبع، زمان دریافت، نسخه طرحواره، سیاست تعدیل و نسخه کد تبدیل را نگه میدارد. برای مجموعهدادههای بزرگ، فایلهای واقعی را در فضای ذخیرهسازی مبتنی بر آدرس محتوا نگه میداریم تا بخشهای یکسان را بدون بازنویسی نسخههای قبلی به اشتراک بگذاریم.
وقتی قوانین ذخیرهسازی یا مجوز مانع نگهداری داده خام میشوند، قویترین رسیدی را که شرایط اجازه میدهد حفظ میکنیم: هشها، پارامترهای درخواست، شناسههای بازبینی منبع و نمونه کوچکی از ردیفهای تجزیهشده برای عیبیابی. هش نمیتواند داده را بازیابی کند، اما میتواند نشان دهد دو اجرا بایتهای یکسانی را مصرف نکردهاند.
برای بازتولیدپذیری پسآزمایی، باید ورودی هویت مشخصی داشته باشد، نه فقط یک URL داده. ثبت کنید چه چیزی دریافت شد، چه زمانی رسید و چطور به ردیفهایی تبدیل شد که استراتژی شما مصرف کرد.
جمعه: دفعه بعد چه کارهایی را کنار میگذاریم
مقایسه صرفِ معیارهای نهایی را کنار میگذاریم. تغییر Sharpe میگوید چیزی جابهجا شده، اما علت را مشخص نمیکند. با شمارش ردیفها و هش بخشها شروع کنید، بعد نخستین تاریخ ورودی متفاوت را پیدا کنید. از آنجا بهترتیب ردیفهای تبدیلشده، سیگنالها، سفارشها و معاملات اجراشده را مقایسه کنید.
جایگزینکردن بیسروصدای دادههای قدیمی با تاریخچه اصلاحشده را هم کنار میگذاریم. اصلاحات مفیدند، اما اجرای قدیمی باید به ورودی اصلی خودش وابسته بماند. مجموعهداده جدید باید اجرای تازهای بسازد که ارتباطش با اجرای قبلی آشکار باشد.
قاعده عملی ما حالا ساده است: اگر اجرای دوباره قرار است آزمایشی را بازتولید کند، نسخه داده را ثابت نگه دارید. اگر قرار است از تاریخچه اصلاحشده بهره ببرد، آن را آزمایشی تازه برچسب بزنید. یادگیری این تفاوت چند روز طول کشید و ثبتش فقط یک خط در مانیفست اجراست.
← همهٔ مطالب


