הסבר על פקודות Bracket ו-OCO במסחר
מהי פקודת Bracket וכיצד היא פועלת? המדריך מסביר את הקשר בין יעד רווח לפקודת Stop בתצורת OCO, מה קורה בביצוע חלקי ואיך המערכת מנהלת את הקישור בין הפקודות.
פקודת Bracket היא הוראה אחת המשגרת שלוש פקודות בקשר מוגדר: פקודת כניסה, וזוג פקודות יציאה מקושרות משני צדי הכניסה. הזוג הוא OCO, קיצור של One Cancels the Other (אחת מבטלת את השנייה). פקודת Limit ליעד רווח ממוקמת מעל מחיר הכניסה, ופקודת Stop להגנה ממוקמת מתחתיו; ביצוע של אחת מהן מבטל אוטומטית את השנייה. פקודת Bracket היא למעשה מכונת מצבים קטנה, ורוב ההפתעות מתרחשות ברגעים שבין המצבים.
מהי פקודת Bracket?
דמיינו סוחר שרוצה לקנות 200 מניות סביב מחיר של 50$, לסגור את הפוזיציה סביב 53$ אם העסקה תצליח, ולצאת סביב 48.50$ אם לא. כתיבת הפקודות בנפרד משמעה שלוש הוראות ומטלה ידנית: לבטל את ה-Stop ברגע שהיעד מתבצע, אחרת מסתכנים במכירת 200 מניות פעמיים. פקודת Bracket מאגדת את אותה כוונה בהגשה אחת. הכניסה היא פקודת שוק או פקודת לימיט רגילה. שתי פקודות היציאה הן ה"ילדים" שלה: פקודת Limit לסגירה ביעד, ופקודת Stop או Stop Limit לסגירה ברמת ההגנה.
המינוחים משתנים. Bracket, פקודה משורשרת (Attached order), OCO bracket ו-OTOCO מתארים כולם מבנה זה. OTOCO, קיצור של One Triggers a One-Cancels-the-Other, הוא השם המדויק ביותר לרצף: הכניסה מפעילה את הזוג, ואז הזוג מבטל את עצמו עד להיוותרות פקודה אחת.
מה המשמעות של OCO בפקודת Bracket?
פקודת OCO היא שתי פקודות ממתינות עם קישור ביטול ביניהן. שתיהן נמצאות בספר הפקודות בו-זמנית. כאשר אחת מתבצעת, השנייה נמשכת. כאשר אחת מתבצעת חלקית, השנייה מצומצמת בהתאם לכמות שבוצעה במקום להימשך כליל; צמצום זה הוא ששומר על התאמה בין הפוזיציה להגנה עליה, מניה מול מניה.
הרצף המלא עבור Bracket של 200 מניות לונג פועל כך:
- פקודת הכניסה עובדת לבדה. היעד וה-Stop קיימים בתוך מערכת הברוקר אך אינם פקודות פעילות, לכן ביצוע (print) במחיר היעד בזמן שהכניסה לא בוצעה אינו גורם לדבר.
- הכניסה מתבצעת עבור 200 מניות. שני ה"ילדים" הופכים לפעילים, כל אחד עבור 200 מניות.
- המסחר מגיע למחיר ה-Stop. ה-Stop הופך לפקודת מכירה פעילה ונכנס לספר הפקודות.
- ה-Stop מבצע 120 מניות לפני שהשוק נע הרחק משם. פקודת ה-Limit ליעד מצטמצמת מ-200 ל-80, בהתאמה לפוזיציה שנותרה.
- 80 המניות האחרונות מתבצעות ביעד מאוחר יותר באותו יום מסחר. יתרת ה-80 של ה-Stop מבוטלת וה-Bracket נסגר.
ביצועים חלקיים בכניסה הם הנקודה שבה פלטפורמות נבדלות זו מזו ביותר. יש ברוקרים שמפעילים את ה"ילדים" עבור הכמות שבוצעה מיד ומגדילים אותם ככל ששאר הכניסה מושלמת. אחרים ממתינים לביצוע מלא של הכניסה, מה שמותיר את הפוזיציה ללא הגנה בפרק הזמן הזה. הסמנטיקה משתנה בין ברוקרים באופן שאינו קוסמטי בלבד: האם ה"ילדים" מופעלים בביצוע חלקי, והאם עריכת "ילד" אחד שוברת את קישור הביטול של השני.
מה המרחק בין שתי הרגליים?
על שתי הרגליים להימצא מחוץ ל"רעש" שהמניה מייצרת ביום רגיל, ובתוך הטווח שהיא מסוגלת לעבור בפועל. הטווח היומי הוא המדד הגס הראשון לכך. הטבלה להלן מציגה שישה שמות מוכרים לאורך השנה האחרונה: טווח החציון בין הגבוה לנמוך כאחוז מהפתיחה, לצד התנועה המוחלטת החציונית מהפתיחה לסגירה.
ה-SQL המדויק מאחורי כל מספר
SELECT
ticker,
round(quantileDeterministic(0.5)(
(toFloat64(high) - toFloat64(low)) / toFloat64(open) * 100,
toUInt32(date)), 2) AS median_range_pct,
round(quantileDeterministic(0.5)(
abs(toFloat64(close) - toFloat64(open)) / toFloat64(open) * 100,
toUInt32(date)), 2) AS median_open_to_close_pct
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'KO', 'JNJ')
AND date >= today() - 370
AND date < today() - 2
GROUP BY ticker
ORDER BY median_range_pct DESCNVDA נושא בטווח היומי הטיפוסי הרחב ביותר מבין השישה ב-2.72%, ו-SPY בצר ביותר ב-0.86%. שימו לב כמה רחוק העמודה השנייה נמצאת מתחת לראשונה בכל שורה. מניה טיפוסית עוברת מרחק רב יותר במהלך יום המסחר מאשר הנטו מהפתיחה לסגירה, ושתי רגלי ה-Bracket חיות בתוך טווח תנועה זה. יעד ו-Stop יכולים שניהם להיות ברי-השגה באותו יום מסחר רגיל.
באיזו תדירות רגל של Bracket ננגעת?
המרחק מהכניסה הוא החוגה שהסוחר שולט בה בפועל. הטבלה הבאה בוחנת את השאלה על פני שלוש שנים קבועות של ימי מסחר ב-SPY, ובודקת עבור מרחקים מוגדרים ממחיר הפתיחה, איזה חלק מימי המסחר הגיע עד לשם כלפי מטה ואיזה חלק הגיע עד לשם כלפי מעלה בנקודה כלשהי ביום.
ה-SQL המדויק מאחורי כל מספר
SELECT
concat(toString(d.dist), '%') AS distance_from_open,
round(100 * countIf(
(toFloat64(a.open) - toFloat64(a.low)) / toFloat64(a.open) * 100 >= d.dist
) / count(), 1) AS reached_below_pct,
round(100 * countIf(
(toFloat64(a.high) - toFloat64(a.open)) / toFloat64(a.open) * 100 >= d.dist
) / count(), 1) AS reached_above_pct
FROM global_markets.stocks_daily_aggs AS a
CROSS JOIN
(
SELECT arrayJoin([0.25, 0.5, 1.0, 1.5, 2.0, 3.0]) AS dist
) AS d
WHERE a.ticker = 'SPY'
AND a.date >= '2023-08-01'
AND a.date < '2026-08-01'
GROUP BY d.dist
ORDER BY d.distברבע אחוז מהפתיחה, 62.3% מימי המסחר נסחרו עד לשם כלפי מטה בנקודה כלשהי, ו-64.7% נסחרו עד לשם כלפי מעלה. הרחבת המרחק ל-3% מורידה את הנתון כלפי מטה ל-0.5%. שני העקומים דועכים יחד, וזוהי כל המתיחות בתכנון גודל ה-Bracket. Stop צמוד הוא Stop שייפגע בימים לא יוצאי דופן. יעד רחוק הוא יעד שלרוב יפוג ללא ביצוע.
האם פקודת Stop Loss תמיד מתבצעת במחיר ה-Stop?
לא. Stop הוא הוראה לשלוח פקודה ברגע שמחיר טריגר מסוים מתבצע. Stop רגיל שולח פקודת שוק, והביצוע נוחת היכן שהספר נמצא באותו רגע. Stop Limit שולח פקודת לימיט במחיר שקבעת, מה שמגן על המחיר ומקבל את הסיכון לאי-ביצוע כלל. פשרה זו היא נושא הדיון ב-פקודת Stop לעומת Stop Limit.
הפער במסחר של לילה (Overnight gap) הוא המקרה הברור ביותר. פקודת Stop להגנה ממתינה בשעות שבהן הבורסה סגורה, והביצוע הראשון (opening print) יכול לנחות הרחק מעבר לטריגר. עשר דוגמאות מ-AAPL לאורך שלוש שנים וחצי:
ה-SQL המדויק מאחורי כל מספר
SELECT
formatDateTime(session_date, '%b %e, %Y') AS gap_label,
round((day_open / prev_close - 1) * 100, 2) AS overnight_gap_pct
FROM
(
SELECT
session_date,
day_open,
lagInFrame(day_close) OVER (
ORDER BY session_date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW
) AS prev_close
FROM
(
SELECT
date AS session_date,
toFloat64(any(open)) AS day_open,
toFloat64(any(close)) AS day_close
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2023-01-01'
AND date < '2026-07-01'
GROUP BY date
)
)
WHERE prev_close > 0
ORDER BY overnight_gap_pct ASC
LIMIT 10הגדול שבהם נמדד ב--9.45% ב-Aug 5, 2024, והעשירי ברשימה עדיין נמדד ב--2.96%. פקודת Stop להגנה שהמתינה בכל מקום בתוך פערים אלו הומרה בביצוע הפתיחה, לא במחיר הטריגר שלה. תכנון גודל ה-Bracket על בסיס טווח תוך-יומי בלבד מותיר מרחק זה ללא מודל.
היכן נמצא קישור ה-OCO בפועל?
כמעט לעולם לא בבורסה. קישור הביטול בין שני ה"ילדים" מוחזק במערכת ניהול הפקודות של הברוקר, או שכבה אחת החוצה בפלטפורמת מסחר הרצה על המחשב שלך. הבורסה רואה שתי פקודות רגילות ובלתי תלויות.
מיקום זה קובע מה שורד תקלה. Bracket בצד הברוקר ממשיך לעבוד גם כשהמחשב כבוי, שכן שרתי הברוקר מחזיקים את שתי הרגליים ואת לוגיקת הביטול. Bracket בצד הפלטפורמה, מהסוג שיישומי גרפים מסוימים מיישמים מקומית, דורש שהאפליקציה תהיה פעילה ומחוברת. פלטפורמות מסוימות מחזיקות Stop מדומה שקיים רק בזיכרון המקומי עד שמחיר הטריגר מתבצע. סגור את המחשב וה-Stop הזה לעולם לא יישלח.
אותה שאלה חלה על הקוד שלך. Stop שחי רק בתוך תהליך רץ לא מותיר דבר בספר הפקודות ברגע שהתהליך נעצר. מפסקי זרם (Circuit breakers) לבוטים של מסחר מכסה את התבנית למערכות אוטומטיות: הנח שהתהליך קורס ברגע הגרוע ביותר, ואז שאל מה עדיין עובד אצל הברוקר.
זמן תוקף (Time in force) חל על כל רגל
כל רגל נושאת הגדרת זמן תוקף משלה. כניסה יומית (Day) המשולבת עם "ילדים" מסוג GTC היא שילוב נפוץ ומביך: הכניסה פגה בסגירה בעוד ה"ילדים" לעולם לא מופעלים, מה שמותיר Bracket שלא עושה דבר בבוקר למחרת. השילוב ההפוך מותיר הגנה שפגה בשעה 16:00 שעון מזרח ארה"ב על פוזיציה שמוחזקת ללילה.
מחוץ לשעות המסחר הרגילות, הספר עצמו משנה את אופיו. הטבלה להלן מחלקת את דקות המסחר של SPY לפי זמן שעון מזרח ארה"ב לאורך כל היום וקוראת שני דברים לכל חצי שעה: הגודל הממוצע של תנועה בדקה אחת, בנקודות בסיס (נקודת בסיס אחת היא מאית האחוז), והחציון של הווליום שבוצע בדקה.
ה-SQL המדויק מאחורי כל מספר
SELECT
formatDateTime(
toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE),
'%H:%i') AS et_time,
round(avg(abs(toFloat64(close) - toFloat64(open)) / toFloat64(open) * 10000), 1) AS avg_move_bps,
round(quantileDeterministic(0.5)(toFloat64(volume), toUInt64(window_start)), 0) AS median_volume
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= today() - 120
AND window_start < today() - 2
GROUP BY et_time
ORDER BY et_timeהטבלה מחזירה 32 דליי חצי שעה, מ-04:00 ועד 19:30 שעון מזרח ארה"ב. קראו משמאל לימין והמבנה מלמד את עצמו. שתי הסדרות נמצאות קרוב לרצפה שלהן בשעות טרום-המסחר, מטפסות בתלילות לקראת הפתיחה ב-09:30, וצונחות שוב אחרי 16:00. פקודת Stop מסוג GTC הממתינה ב-5 בבוקר ממתינה בחלק הדליל של עקומה זו, וביצוע Stop-market בספר דליל כל כך יכול לנחות רחוק מאוד מהטריגר.
שאלות נפוצות
מה ההבדל בין פקודת Bracket לפקודת OCO?
OCO הוא הזוג עצמו: שתי פקודות ממתינות עם קישור ביטול, שבו ביצוע של אחת מסיר את השנייה. Bracket הוא פקודת כניסה עם זוג OCO מצורף, והזוג הופך לפעיל רק ברגע שהכניסה מתבצעת. כל Bracket מכיל OCO. זוגות OCO רבים משמשים בפני עצמם.
האם פקודת Bracket עדיין עובדת אם המחשב שלי כבוי?
זה תלוי היכן הקישור נמצא. Bracket בצד הברוקר ממתין בשרתי הברוקר וממשיך לעבוד כשהפלטפורמה סגורה. Bracket בצד הפלטפורמה או מדומה דורש שהאפליקציה תהיה פעילה ומחוברת, ופקודות ה"ילדים" עלולות לעולם לא להגיע לשוק בלעדיה.
מה קורה ל-Stop אם יעד הרווח מתבצע חלקית?
ה-Stop מצומצם לפי הכמות שבוצעה במקום להתבטל. אם יעד של 200 מניות מבצע 60 מניות, ה-Stop יורד ל-140 מניות, בהתאמה לפוזיציה שעדיין פתוחה. הביטול מופעל רק כאשר האחרון מהפוזיציה נסגר.
האם אני יכול להשתמש בפקודת Bracket במסחר טרום-פתיחה או אחרי הסגירה?
ההתנהגות משתנה בין ברוקרים, ורבים מנתבים "ילדי" Bracket רק במהלך שעות המסחר הרגילות. פקודות Stop בפרט נדחות לעיתים קרובות או מוחזקות מחוץ לשעות 09:30 עד 16:00 שעון מזרח ארה"ב במניות ארה"ב. הגדרת זמן התוקף על כל רגל קובעת האם אותה רגל זכאית למסחר מורחב כלל.
האם הבורסות יודעות ששתי הפקודות שלי מקושרות?
לא. במניות ארה"ב קישור הביטול מוחזק על ידי הברוקר או הפלטפורמה, והבורסה מקבלת שתי פקודות עצמאיות. הודעת הביטול עבור הרגל שנותרה נשלחת על ידי המערכת שמחזיקה את הקישור, לאחר שהרגל השנייה מדווחת על ביצועה.
כל טבלה כאן מגיעה עם ה-SQL המדויק שמתחתיה. כדי למדוד את הטווח ואת סיכון הפער במניה שאתם עוקבים אחריה, שאלו את השאלה באנגלית פשוטה במסוף Strasmore.