4 בספטמבר 2026 · בק-טסט

גם הסטופ וגם היעד היו בתוך אותו נר. באיזה מהם בחר הבקטסט שלך?

גם הסטופ וגם היעד היו בתוך אותו נר. באיזה מהם בחר הבקטסט שלך?

לונג מ-84,120. סטופ ב-84,036, יעד ב-84,271. הנר של הדקה הבאה מגיע: פתיחה 84,118, שיא 84,290, שפל 84,010, סגירה 84,240.

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

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

הדרך השגויה הראשונה: לתת לשרשרת ה-if להחליט

הצורה הנפוצה:

if bar.high >= target:
    exit(target, "tp")
elif bar.low <= stop:
    exit(stop, "sl")

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

הרצתי סקאלפר רגרסיה לממוצע רגיל במכוון על חוזה BTCUSDT, שלושה חודשים של נרות בני 1-minute, 4,812 עסקאות, סטופ של 0.10% ויעד של 0.18% ממחיר הכניסה. אותם אותות, אותן עמלות, רק כלל הכרעת התיקו השתנה.

12.6%מהעסקאות נגעו בשתי הרמות בתוך נר אחד
2.31Sharpe, היעדים מתבצעים קודם
0.18Sharpe, הסטופים מתבצעים קודם
0.94Sharpe, ההכרעה לפי נרות של 1-second

שמינית מהעסקאות קובעת את כל התוצאה. זו האריתמטיקה של צמד סטופ ויעד צמודים: העסקאות העמומות הן אלה שבהן המחיר נע לשני הכיוונים, וזה נכון לרוב העסקאות המעניינות, וכל אחת מהן שווה את מלוא המרחק בין הסטופ ליעד, בהתאם להטלת המטבע. 12.6% מהעסקאות × טווח של 0.28% הם 3.5% ממחזור הנומינלי ברוטו ליחידת מדגם, הרבה מעבר ליתרון האמיתי של האסטרטגיה.

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

מרווח בין נרותעסקאות ששתי הרמות היו בתוכן בנר אחדSharpe (היעד קודם)
1s0.3%0.91
1m12.6%2.31
5m34%3.60
15m49%4.42
1h71%5.88

שימו לב למה שהטבלה הזאת באמת אומרת. נרות גסים יותר שיפרו את הבקטסט. האינסטינקט של כל חוקר הוא שנרות שעתיים הם הבחירה השמרנית: פחות רעש ופחות התאמת יתר למיקרו-מבנה. אבל כשמשתמשים בכלל תוך-נרי שמכריע לטובתך, נר גס יותר הוא פשוט קופסה גדולה יותר שבתוכה אפשר להניח שהיה לך מזל. בנרות 1h, שבע מכל עשר עסקאות מוכרעות לפי מוסכמה בלבד. הבקטסט הזה לא בוחן אסטרטגיה; הוא בוחן את סדרן של שתי פקודות `if` 3,400 פעמים.

הדרך השגויה השנייה: להניח שהסטופ התמלא במחיר הסטופ

נניח שתיקנתם את הסדר. הסטופ מוכרע ראשון, אתם רושמים הפסד מדויק של 0.10% ועוד עמלת taker, ומרגישים קפדניים. עדיין יש כאן שתי טעויות נפרדות.

הראשונה היא שסטופ הוא טריגר, לא מילוי. ב-Binance USDⓈ-M, פקודת STOP_MARKET הופכת לפקודת שוק ברגע שתנאי ההפעלה מתקיים, ואז היא צורכת את הנזילות הזמינה בספר הפקודות. בדקה שקטה מדובר בטיק או שניים של החלקה. בדקה שהפעילה בפועל את הסטופ — זו עם נר של 40 נקודות ומפל ликווידציות מתחתיו — ספר הפקודות דליל בדיוק בצד שבו אתם חוצים. במדגם שלי, בהשוואת טריגרים של סטופים לנתוני הטיקים, המילוי החציוני היה 1.4 bps מעבר לטריגר והאחוזון ה-95 היה 11 bps. בסטופ של 10 bps, הקצה הזה עולה לכם עוד עשירית מהסיכון שחשבתם שהגדרתם.

השנייה עדינה יותר וייחודית לחוזים תמידיים: איזה מחיר מפעיל אותו. ב-Binance, ברירת המחדל לפקודות סטופ היא מחיר mark, שנבנה מהמדד בתוספת בסיס מוחלק, ולא מהעסקה האחרונה באותה זירה. סדרת ה-OHLC שלכם מבוססת על המחיר האחרון. אלה סדרות שונות, והן סוטות זו מזו במיוחד באירועים שמפעילים סטופים.

מחיר אחרון (נתוני ה-klines שלכם)מחיר mark (טריגר ברירת המחדל)
מקורעסקאות בזירה הזאתמדד ממספר זירות + בסיס
התנהגות הפתילמהלך מלאריכוך משמעותי
סטייה טיפוסית1–3 bps בשוק רגוע, 20–35 bps בדקת מפל ликווידציות
השלכה על הבקטסטסטופים שהופעלו שלא לצורך, ולהפך

לכן פתיל של 25 bps בנתוני המחיר האחרון עוצר אתכם בבקטסט, אף שמחיר ה-mark החי לא התקרב אפילו למרחק 10 bps מהטריגר. או להפך, ביום שבו המדד זז והזירה שלכם מפגרת אחריו. אם תגדירו workingType ל-CONTRACT_PRICE, לפחות תתאימו את ההתנהגות בפועל לנתונים שלכם. לרוב זו הבחירה הנכונה לחוקר, כי סימולציה מדויקת של טריגר לפי מחיר mark מחייבת להעביר סדרה שנייה בכל מנוע המילוי.

המקרה שאני זוכר הכי טוב: מישהו אצלנו "שיפר" אסטרטגיה בכך שהעלה את ה-take-profit מ-0.18% ל-0.21%. ה-Sharpe עלה מ-2.3 ל-3.1. לא היה יתרון חדש. היעד פשוט זז אל מעבר לחלק הצפוף של התפלגות הפתילים של 1-minute, ולכן פחות עסקאות הגיעו לקבוצה העמומה, שבה הקוד העניק להן בשקט את הניצחון. הם ביצעו אופטימיזציה לכלל הכרעת התיקו.

הדרך השגויה השלישית: תמיד להניח את הגרוע ביותר ולקרוא לזה שמרנות

התגובה האינסטינקטיבית היא פסימיות. אם שתי הרמות נגעו, רושמים את הסטופ. סיימנו, אין יותר אופטימיות, אפשר לפרסם.

פעם נהגתי לעשות את זה. זה עדיף על החלופה, ועדיין שגוי, משתי סיבות.

כך פוסלים אסטרטגיות טובות. הכרעה פסימית ב-12.6% מהעסקאות עלתה לאסטרטגיה הזאת 2.1 נקודות Sharpe לעומת 0.94 כשההכרעה נעשתה לפי טיקים. אם המספר האמיתי הוא 0.94 והשיטה שלכם מציגה 0.18, אתם זונחים את הרעיון ועובדים על משהו גרוע יותר. שמרנות שגויה ב-2 נקודות Sharpe היא לא שמרנות; היא רעש שמתחזה לעיקרון.

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

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

מה באמת עובד

המסלול בתוך הנר הוא נתון. השיגו אותו, או תחמו את מה שאי אפשר להשיג.

  1. הכריעו לפי הסדרה ברזולוציה הגבוהה ביותר שיש לכם. נתוני aggTrades של Binance לדקות הרלוונטיות כוללים כמה מאות שורות ומכריעים את השאלה באופן חד-משמעי: באיזו רמה נגעו קודם, ובאיזה מחיר בוצעה העסקה במהלך התנועה. לא צריך נתוני טיקים לכל הבקטסט, אלא רק לנרות העמומים. במדגם שלי מדובר ב-606 דקות מתוך 129,600. זו הורדה קטנה, לא פרויקט תשתיות.
  2. אם אין נתוני טיקים, רדו בפרק זמן אחד או שניים לצורך ההכרעה בלבד. אותות על 15m, יציאות מוכרעות לפי נרות של 1s או 1m. העמימות יורדת מ-49% לשבריר אחוז, והיתרה קטנה דיה כדי להתעלם ממנה ביושר.
  3. הציגו תמיד את הטווח. הריצו כל בקטסט פעמיים, עם הכרעה אופטימית ופסימית, והציגו את שני ערכי ה-Sharpe לצד הערך שהתקבל לפי הנתונים. הפער הזה הוא אי-הוודאות התוך-נרית שלכם, והוא שייך לדוח הביצועים לצד רווח הסמך שהייתם מציגים עבור ערך ה-Sharpe עצמו. כשהטווח הוא 0.2–2.3, שום מסקנה שנמצאת בתוכו אינה אמיתית.
  4. עקבו אחר שיעור העמימות כמדד מרכזי. אצלנו הוא מופיע בראש כל כרטיס אסטרטגיה, לצד מספר העסקאות והמחזור. שיעור של יותר מ-5% בערך פירושו שמנגנון היציאה, ולא מנגנון הכניסה, הוא הדבר שנבחן.
  5. מדלו את הטריגר בנפרד מהמילוי. הפעילו את הטריגר לפי סדרת המחירים שהזירה משתמשת בה בפועל; בצעו את המילוי בטריגר בתוספת החלקה שנדגמה לפי נתוני המסחר, ולא במחיר הטריגר עצמו.

גם במניות יש אותה בעיה, רק בלבוש אחר. סטופ ב-62.00 במניה שפותחת אחרי פער לילי ב-58.40 לא מתמלא ב-62.00; המילוי יהיה איפשהו מתחת למחיר הפתיחה. בקטסט לפי נרות יומיים שרושם החלקה של −$0.00 במקרים שבהם הפער חוצה את הסטופ ישמח לספר לכם שמנגנון הסטופ-לוס צמצם את הירידה. הוא לא. הוא פשוט לא נבחן בימים החשובים. גם עצירות מסחר גורמות לכך: המכירה הפומבית עם חידוש המסחר היא הרגע שבו הסטופ שלכם מתבצע בפועל, במחיר שהשפל של הנר לא מציג.

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

מילויים תוך-נרייםפקודות סטופבק-טסטחוזים עתידיים בקריפטומיקרו-מבנה שוק
← כל הפוסטים