1 בנובמבר 2026 · מחקר

איך מחממים בקטסט בלי לספור את המבט-לאחור כביצועים?

איך מחממים בקטסט בלי לספור את המבט-לאחור כביצועים?

Donchian של 20 יום נראה תמים במפרט. הסוכן כותב מקסימום נע של 20 ברים, הבקטסט מתחיל בשורה הראשונה של קובץ ה-parquet, ובשבועיים הראשונים ה"שיא של 20 יום" הוא בסך הכול המקסימום הרץ של הברים שכבר קיימים. ביום הרביעי זה שיא של 4 ימים. האסטרטגיה שחשבתם שאתם בודקים אינה זו שהפיקה את תריסר המילויים הראשונים.

יש לי מחברת על ברים יומיים של ETHUSDT שבה ה-Sharpe על כל המדגם הוא 1.4. חותכים את 20 הסשנים הראשונים והוא יורד ל-0.6. משאירים את 20 האלה וזורקים את שאר השנה הראשונה, והוא מדפיס 3.1. אף אחד לא הדליף את המחר. האסטרטגיה השתמשה בעבר, פשוט לא במספיק ממנו, והדוח התייחס לעסקאות החצי-מגובשות האלה כאל ראיה.

1.4Sharpe על כל המדגם, כולל חלון לא-גמור
0.6אותו קוד אחרי 20 סשנים שהושלמו
3.1Sharpe אם משאירים רק את עסקאות החימום

לתת לחלון לסחור כשהוא עוד מתמלא

ההרס הרגיל הוא min_periods=1. Pandas יחשב ממוצע נע על בר בודד אם נותנים לו. סוכנים עושים את זה כל הזמן, כי NaN בראש הפריים מרגיש כמו באג, ומילוי שלו צובע את בדיקת היחידה בירוק.

יעד realized-vol של 20 יום עם 2 תצפיות תשואה הוא פיצוץ גודל. השונות של 2 מספרים היא הטלת מטבע, הופכים אותה, והפוזיציה הראשונה היא פי כמה מהסיכון המתוכנן. z-score מול סטיית תקן כמעט-אפס עושה את אותו תעלול עם סימן: נראה שלאסטרטגיה יש כניסה חדה כתער שאינה מופיעה שוב ברגע שהחלון כנה.

פריצות גרועות יותר, כי הן נראות כמו הכלל האמיתי. ערוץ של 20 ברים בבר השישי הוא ערוץ של 6 ברים. מקבלים מקבץ עסקאות ממש בהתחלה, לעיתים קרובות בקטע שקט שלא היה מפעיל את האינדיקטור המושלם. שווקים שקטים נסחפים מעט. ערוץ הדוק יורה. עקומת ההון מקבלת יתרון התחלתי שאף שנה מאוחרת יותר לא חוזרת עליו.

מילוי-אפס ו-forward-fill ממציאים שקר אחר. RSI ב-0 נקרא כמכירת-יתר. ATR חסר של 0 מפוצץ את גודל היחידה, והבקטסט קונה באדיקות מחסן שלם. אני מעדיף ש-NaN יהרוג את הפקודה מאשר ש-0 ימציא אחת.

אני עדיין תופס את עצמי מצייר משורה 0 כי חודש ריק בצד שמאל של הגרף נראה לא-גמור. החודש הריק הוא החלק הכנה.

לגזור את עקומת ההון, להשאיר את הפוזיציה

הזו עוברת ביקורת קוד. מחשבים את הפיצ'רים של 20 יום כמו שצריך, זורקים את 20 השורות הראשונות מהעקומה המצוירת, ומפרסמים מ-21 בינואר. הפוזיציה ב-21 בינואר נפתחה ב-14 בינואר. קו המים הגבוה של הסטופ הנגרר, ספירת הפירמידה, המזומן אחרי אותם שריפות: הכול צעד אל תוך המדגם ה"נקי".

ההרס הוא אסטרטגיית נייר שאי אפשר להתחיל בתאריך שבכתבה. מפעילים מחדש ממצב שטוח בתאריך ההתחלה המדווח ופקודות השבוע הראשון לא מסכימות. לפעמים הבקטסט כבר בעסקה שלמערכת הנייר אין סיבה להיכנס אליה. לפעמים מערכת הנייר נכנסת כי המבט-לאחור שלה קר, והבקטסט יושב בחוץ כי החודש המוסתר שלו כבר לקח את הפריצה. שני ספרי פתיחה, תאריך התחלה מפורסם אחד.

קיפולי walk-forward עושים את זה בשקט. לכל חלון בדיקה יש זנב מבט-לאחור שלא מציירים. מדלגים על סימולציה של הזנב והעסקאות הראשונות בבדיקה הן שוב עסקאות של חלון לא-גמור. מסמלצים אותו ומדווחים רק על ימי הבדיקה, והפוזיציה ביום הבדיקה מותנית במילויים שלא מציגים. הגרסה השנייה יכולה להיות בחירת מחקר לגיטימית. לכנות את הבוקר הראשון של הקיפול התחלה קרה, בזמן שסטופ נגרר כבר חי מהזנב, זה איך שני חוקרים מקבלים שני ערכי Sharpe מתצורה אחת.

אם הפעלה מחדש ממצב שטוח בתאריך ההתחלה המפורסם משנה את ה-P&L, החימום נמצא בתיעוד הביצועים. נתוני המבט-לאחור יכולים להיות נוכחים. עסקאות המבט-לאחור לא יכולות.

לחמם בימי לוח כשהפיצ'ר אינו יום

"תנו לו 30 יום" משאיר את הפיצ'ר לא-מוגדר דיו. 30 ימי לוח על Donchian של 5 דקות הם אלפי ברים מעבר למבט-לאחור של 20 תקופות. 30 יום על פיצ'ר יומי שצריך 20 סשנים הוא או שמן או רזה, תלוי בסופי שבוע ובחורים.

z-score של שיעור מימון באחת מזירות ה-perp שלנו קיבל חימום של 30 יום כי המפרט אמר 30 תקופות ומישהו תרגם תקופות ללוח שנה. המימון שם מודפס כל 8 שעות. 30 יום הם בערך 90 סליקות. 30 תקופות הן 10 ימים. שני חודשי החימום העודפים במקרה כללו שבוע של דה-פג. השמטה שלהם גרמה לחלון החי להיראות רגוע יותר מההיסטוריה האמיתית של האסטרטגיה. אנשים האשימו רגישות לתאריך התחלה. החימום אכל את המשטר.

וקריפטו מול מניות גורם לאותו מספר לשנות משמעות בלי שאף אחד יערוך פרמטר. 20 "ימים" של ETH כוללים שבתות. 20 סשני מניות הם כמעט חודש לוח. מעתיקים מבט-לאחור של 20 יום ממחברת מניות אל נרות תמידיים שעתיים ומקבלים ערוץ של 20 שעות עם שם של 20 יום. הבר התקף הראשון הוא אז או 20 שעות פנימה, או 20 ימים פנימה אם פונקציה מאוחרת יותר עושה resample, וראיתי את שניהם באותו diff של סוכן.

לנעוץ את חותמת-הזמן הראשונה לסחירות

החימום הוא דרישת נתונים, לא מדגם בונוס. כל פיצ'ר מציין את מספר התצפיות המושלמות שהוא צריך, ביחידות שבהן הוא מחושב. חותמת-הזמן הראשונה לסחירות היא הבר הראשון שבו כל אלה מתקיימים וחשבון שטוח היה מורשה לשלוח פקודה.

פיצ'רמה שהמפרט בדרך כלל אומרמה שבאמת חייב להתקייםתחליף שקט
Donchian של 20 יום20 שיאים יומיים20 סשנים שהושלמומקסימום רץ עם min_periods=1
realized vol של 30 יוםחלון של 30 יום30 תשואות סגירה-לסגירהשונות של 2 ימים, הפוכה לגודל
z-score מימון של 20 הדפסות20 ימים20 סליקות מימון20 ימי לוח (~90 הדפסות), או 20 ברים של מסגרת הזמן הלא נכונה
RSI של 14 תקופות על 5m14 תקופות14 ברים סגורים של 5 דקות14 ימים, או 14 ברים עם חורים שמולאו קדימה

P&L לפני חותמת-הזמן הזו נשאר מחוץ לתיעוד הביצועים. מצב לפני חותמת-הזמן הזו עדיין עשוי להזדקק לסימולציה, כך שסטופ נגרר או צינון אמיתיים כשהשעון פוגע בבר הסחיר הראשון, אבל המילויים האלה לא נכנסים ל-Sharpe, לספירת העסקאות או לחשבון הקיבולת. ואז מריצים את הבדיקה המכוערת: הפעלה מחדש ממצב שטוח בחותמת-הזמן הזו, עם המבט-לאחור זמין כנתונים בלבד. אם הפקודות משתנות, שילחתם עסקאות מוסתרות.

מסחר על נייר מתחיל לפי אותו חוזה. כך גם כל חלון בדיקה של walk-forward. אם הגרף נראה כאילו חסר לו חודש, השאירו אותו חסר.

בקטסטינגהנדסת נתוניםwalk-forwardסוכני AIמסחר על נייר
← כל הפוסטים