מתי אסטרטגיית משקל שווה עדיפה על אופטימיזציה?
משקל שווה משיג ביצועים עודפים על פני הקצאת נכסים אופטימלית כאשר המדגם קצר מדי לחיזוי תשואות. סימולציית Python מראה כיצד היתרון נשחק ככל שהמדגם גדל והנתונים מתייצבים.
23.9
משקל שווה (Equal weight) משיג ביצועים עודפים על פני הקצאת נכסים אופטימלית בכל פעם שהמדגם קצר מכדי לקבוע במדויק את התשואות הצפויות, ומדגמים קצרים הם הכלל ולא היוצא מן הכלל. אופטימייזר הוא כלי אריתמטי תקין המיושם על קלט שאף אחד אינו מודד היטב. תיק ה-1/N, המבוסס על משקל שווה, אינו מעריך דבר, וזו הסיבה שהוא עמיד כאשר ההערכות שגויות.
הבעיה בחיזוי תשואות
בניית תיק השקעות מבוסס אופטימיזציה דורשת הערכות מדויקות של תשואות צפויות, תנודתיות ומתאמים. בפועל, קשה מאוד להעריך את התשואה הצפויה של נכס בודד בטווח זמן קצר. כאשר הנתונים ההיסטוריים מוגבלים, האופטימייזר נוטה להעניק משקלים קיצוניים לנכסים שהציגו ביצועי יתר במדגם, מה שמוביל לתיק לא מאוזן ורגיש מאוד לטעויות דגימה.
היתרון של אסטרטגיית 1/N
הגישה של משקל שווה, הידועה כ-1/N, נמנעת מהצורך בחיזוי תשואות. על ידי הקצאת משקל זהה לכל נכס בתיק, המשקיע מוותר על הניסיון "לנצח" את השוק באמצעות תחזיות שגויות. מחקרים מראים כי ברוב המקרים, תיק 1/N מציג ביצועים מותאמי סיכון טובים יותר מתיקים שעברו אופטימיזציה מורכבת, פשוט משום שהוא אינו סובל מהטיית הערכת-יתר של נתונים רועשים.
עמידות מול אי-ודאות
השורה התחתונה למשקיעים
לקריאה נוספת על ניהול סיכונים
הסתמכות על משקל שווה היא אסטרטגיה של ענווה סטטיסטית. היא מכירה בכך שהשוק אינו צפוי בטווח הקצר ושהערכות מודלים נוטות להישבר תחת תנאי שוק משתנים. עבור משקיעים רבים, פיזור פשוט ללא יומרות חיזוי הוא הדרך הבטוחה ביותר לשמר הון לאורך זמן.
האם משקל שווה באמת מנצח אופטימיזציה?
בתנאי אחד ספציפי, כן. נבחן את המונחים בנפרד. משקל שווה, שנכתב כ-1/N, מחלק את ההון באופן שווה בין N פוזיציות ואינו דורש שום תחזית. אופטימיזציית ממוצע-שונות (Mean variance optimization) מחשבת את המשקלים המניבים את התשואה הצפויה הטובה ביותר ליחידת שונות מוערכת. קריטריון קלי (Kelly criterion) מחשב את המשקלים שממקסמים את הצמיחה המורכבת בטווח הארוך; בנכסים שאינם מתואמים, התוצאה שלו מצטמצמת למשקל פרופורציונלי לתשואה העודפת הצפויה של כל נכס חלקי השונות שלו. המדריך שלנו ל-קביעת גודל פוזיציה לפי קריטריון קלי מפרט את הנוסחה הזו לעומק.
שני סוגי האופטימיזטורים זקוקים לאותו קלט: תשואה צפויה לכל נכס. זהו הנתון שדגימה מעריכה בצורה הגרועה ביותר. תנודתיות מתקבלת מחלון זמן קצר בדיוק סביר. הממוצע לא, והפער בין השניים גדול מספיק כדי להבחין בו בכל היסטוריית מחירים. הפאנל להלן לוקח שישה שמות מוחזקים בהרחבה, מודד כל שנה קלנדרית מ-2015 ועד 2024 בנפרד, ומדווח על המרחק בין האומדן השנתי הגבוה ביותר לנמוך ביותר. הוא עושה זאת פעמיים לכל שם: פעם אחת עבור התשואה היומית הממוצעת השנתית, ופעם אחת עבור התנודתיות השנתית.
ה-SQL המדויק מאחורי כל מספר
WITH prices AS
(
SELECT
ticker,
date,
toFloat64(max(close)) AS c
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'SPY', 'KO', 'JNJ')
AND date >= '2015-01-01'
AND date < '2025-01-01'
GROUP BY ticker, date
),
rets AS
(
SELECT
ticker,
date,
c / lagInFrame(c, 1) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
FROM prices
),
yearly AS
(
SELECT
ticker,
toYear(date) AS yr,
avg(ret) * 252 * 100 AS mean_pct,
stddevPop(ret) * sqrt(252) * 100 AS vol_pct
FROM rets
WHERE isFinite(ret)
GROUP BY ticker, yr
HAVING count() >= 200
)
SELECT
ticker,
round(max(mean_pct) - min(mean_pct), 1) AS mean_estimate_range_pct,
round(max(vol_pct) - min(vol_pct), 1) AS vol_estimate_range_pct
FROM yearly
GROUP BY ticker
ORDER BY mean_estimate_range_pct DESCעבור NVDA, אומדן הממוצע השנתי משתרע על פני 184.7 נקודות אחוז לאורך עשר השנים הללו, לעומת 28.6 נקודות בטווח אומדן התנודתיות עבור אותו שם באותן שנים. השם היציב ביותר בפאנל, KO, עדיין הזיז את אומדן הממוצע השנתי שלו בטווח של 23.9 נקודות. כל שיטה המזינה לאופטימיזטור את התשואה הממוצעת של השנה שעברה כתשואה הצפויה לשנה הנוכחית, מספקת לו נתון עם רמת תנודה כזו.
מהו אורך המדגם הדרוש להערכת תשואה צפויה?
טעות התקן של תשואה ממוצעת מוערכת היא התנודתיות של הנכס חלקי השורש הריבועי של אורך המדגם בשנים. בשנים, לא במספר תצפיות: דגימת אותם שנים-עשר חודשים על בסיס שעתי במקום יומי אינה מוסיפה דבר. אם נציב נכס בעל תנודתיות של עשרים אחוז בנוסחה זו, שנה אחת של היסטוריה תניב טעות תקן של עשרים נקודות אחוז בשנה. ארבע שנים יצמצמו אותה בחצי לעשר נקודות. כדי להגיע לרמת דיוק של נקודה אחת – הדיוק שתרצה לפני דירוג שני נכסים שהתשואה הממוצעת האמיתית שלהם נבדלת בשתי נקודות – נדרשות ארבע מאות שנים של נתונים.
תנודתיות היא מקרה שונה. הדיוק שלה משתפר עם מספר התצפיות ולא עם משך הזמן הקלנדרי, לכן כמה חודשים של נתונים יומיים מציבים אותה כבר בטווח של נקודות בודדות. הלוח להלן מחלק עשרים שנה של תשואות יומיות של קרן סל אחת לבלוקים ללא חפיפה באורך קבוע, מחשב את שתי ההערכות בתוך כל בלוק, ומדווח על מידת הפיזור של ההערכות בין בלוק לבלוק.
ה-SQL המדויק מאחורי כל מספר
WITH prices AS
(
SELECT
date,
toFloat64(max(close)) AS c
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2005-01-01'
AND date < '2025-01-01'
GROUP BY date
),
rets AS
(
SELECT
date,
c / lagInFrame(c, 1) OVER (ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
FROM prices
),
numbered AS
(
SELECT
ret,
row_number() OVER (ORDER BY date ASC) AS i
FROM rets
WHERE isFinite(ret)
),
sweep AS
(
SELECT
arrayJoin([21, 63, 126, 252, 504]) AS n,
i,
ret
FROM numbered
),
blocks AS
(
SELECT
n,
intDiv(i - 1, n) AS blk,
avg(ret) * 252 * 100 AS mean_pct,
stddevPop(ret) * sqrt(252) * 100 AS vol_pct
FROM sweep
GROUP BY n, blk
HAVING count() = n
)
SELECT
concat(toString(n), ' sessions') AS sample_length,
round(stddevPop(mean_pct), 1) AS mean_estimate_spread_pct,
round(stddevPop(vol_pct), 1) AS vol_estimate_spread_pct,
count() AS window_count
FROM blocks
GROUP BY n
ORDER BY n ASCבבלוקים של 21 sessions, פיזור הערכת הממוצע עומד על 53.7 נקודות אחוז, לעומת 10.9 נקודות עבור הערכת התנודתיות שנמדדה על אותם בלוקים בדיוק. אם נאריך את הבלוק ל-504 sessions, פיזור הממוצע יצטמצם ל-10.6 נקודות. הוא מצטמצם לפי שורש ריבועי: כל צמצום של הטעות בחצי דורש פי ארבעה נתונים.
סימולציה מבוססת זרע שניתן להריץ באופן עצמאי
שום דבר מזה לא מוכיח ששגיאת האומדן גדולה מספיק כדי להעניק את הניצחון לאסטרטגיית 1/N. הניסוי הבא מוכיח זאת. המתכון דורש התקנת Python בלבד: ללא קבצי נתונים, ללא הורדות וללא חבילות צד-שלישי. הוא מייצר תשואות משלו על בסיס פרמטרים שתבחר, כך שהתשובה האמיתית ידועה וניתן לדרג את שתי ההקצאות מולה.
- ייבא שני מודולים,
import randomו-import statistics, בתוספתfrom math import log. קבע את הזרע (seed) בשורה הבאה באמצעותrandom.seed(20260816). - הגדר חמישה נכסים עם תשואות שנתיות צפויות אמיתיות של חמישה, שישה, שבעה, שמונה ותשעה אחוזים, כאשר לכל אחד תנודתיות שנתית אמיתית של עשרים אחוזים, ללא מתאם ביניהם. המר לצעד יומי באמצעות
mu_d = mu_a / 252ו-sd_d = sd_a / (252 ** 0.5). - בחר אורך מדגם T מתוך הטווח
[60, 125, 250, 500, 1000, 2500, 5000]. - משוך T תשואות יומיות עבור כל נכס באמצעות
random.gauss(mu_d, sd_d). משיכה זו מהווה את כל ההיסטוריה העומדת לרשות מנהל ההשקעות. - אמד את הממוצע של כל נכס באמצעות
statistics.meanואת התנודתיות שלו באמצעותstatistics.stdev. שני אומדנים אלו הם כל מה שהאופטימייזר מכיר. - בנה את תיק ההשקעות במשקל שווה על ידי הקצאת 0.2 לכל אחד מחמשת הנכסים. הוא אינו משתמש באף אחד מהאומדנים.
- בנה את התיק האופטימלי על ידי קביעת כל משקל גולמי ל-
mu_hat / (sd_hat ** 2), ולאחר מכן חלוקת כל משקל בסכום הערכים המוחלטים של המשקלים הגולמיים, מה שמציב את שני התיקים על אותה חשיפה ברוטו. - משוך נתיב חדש מחוץ למדגם (out of sample) של 2520 תשואות יומיות לכל נכס מתוך הפרמטרים האמיתיים. אף אחת מההקצאות לא נחשפה אליו.
- דרג את שניהם על נתיב זה באמצעות הממוצע של
log(1 + r), כאשר r הוא הסכום המשוקלל של תשואות חמשת הנכסים באותו יום. - חזור על שלבים 4 עד 9 עבור 2000 ניסויים בלתי תלויים בכל T, ותעד את שיעור הניסויים שבהם משקל שווה משיג תוצאות טובות יותר מהמשקלים האופטימליים.
קרא את הטווח מ-T קצר ל-T ארוך. בקצה הקצר, משקל שווה מנצח ברוב ברור של הניסויים. השיעור יורד בהתמדה ככל ש-T גדל, ובקצה הארוך המשקלים האופטימליים מנצחים ברוב המקרים. איפשהו באמצע השניים מצטלבים. נקודת ההצלבה זזה בהתאם לזרע ובהתאם למרווח (spread) בין הממוצעים האמיתיים. הכיוון אינו משתנה: יותר נתונים מעדיפים את האופטימייזר, פחות נתונים מעדיפים את 1/N. כדי לשכפל, שנה את המספר השלם בתוך random.seed(20260816) והרץ את הטווח שוב.
מדוע האופטימייזר מעצים הערכת תוחלת שגויה
בחנו היכן נכנסות ההערכות לחישוב המשקל. התוחלת המוערכת נמצאת במונה, והשונות המוערכת במכנה. הכפלת הערכת התוחלת מכפילה את המשקל. הפחתה של רבע מהערכת השונות מעלה את המשקל בשליש. במדגם מוצלח, שתי הטעויות פועלות באותו כיוון: רצף של תוצאות חיוביות מעלה את התוחלת הנמדדת ולעיתים קרובות ממתן את השונות הנמדדת באותו חלון זמן. האופטימייזר מפרש נכס זה כבולט בקבוצה ומקצה לו משקל בהתאם. מחוץ למדגם, הנכס חוזר להיות חבר רגיל בקבוצה. משקל שווה מעולם לא "ראה" את המדגם המוצלח הזה.
הסימולציה היא הגרסה המתונה של בעיה זו. חמישה נכסים בלתי מתואמים מותירים מטריצת שונות משותפת אלכסונית ללא צורך בהיפוך. תיקי השקעות אמיתיים הם מתואמים, ומטריצת שונות משותפת מדגמית שנבנתה ממספר תצפיות הגדול בקושי ממספר הנכסים קרובה להיות סינגולרית. היפוך המטריצה מתרגם טעויות קטנות בקלט למשקלים גדולים מאוד; כך מגיע אופטימייזר לפוזיציה השווה פי כמה מההון העצמי בנכס אחד, כנגד פוזיציית שורט מקזזת בנכס תחליפי קרוב. הסקירה שלנו על סיכון ריכוזיות בתיק השקעות עוסקת בהשפעה של משקל כזה על ירידות ערך (drawdown).
הקלט גם הוא אינו יציב. הלוח להלן עוקב אחר ממוצע נע של תשואה יומית שנתית, הנדגמת מדי חודש, עבור קרן סל רחבה לצד מניית צריכה בסיסית גדולה.
ה-SQL המדויק מאחורי כל מספר
WITH prices AS
(
SELECT
ticker,
date,
toFloat64(max(close)) AS c
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('SPY', 'KO')
AND date >= '2015-10-01'
AND date < '2025-01-01'
GROUP BY ticker, date
),
rets AS
(
SELECT
ticker,
date,
c / lagInFrame(c, 1) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
FROM prices
),
trailing AS
(
SELECT
ticker,
date,
avg(ret) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 251 PRECEDING AND CURRENT ROW) * 252 * 100 AS trailing_mean_pct,
row_number() OVER (PARTITION BY ticker ORDER BY date ASC) AS i
FROM rets
WHERE isFinite(ret)
)
SELECT
toString(toStartOfMonth(date)) AS month,
round(avgIf(trailing_mean_pct, ticker = 'SPY'), 1) AS spy_trailing_mean_pct,
round(avgIf(trailing_mean_pct, ticker = 'KO'), 1) AS ko_trailing_mean_pct
FROM trailing
WHERE i >= 252
AND date >= '2017-01-01'
GROUP BY month
ORDER BY month ASCכל נקודה על שני הקווים הללו היא מספר שאופטימייזר היה מקבל כתשואה צפויה באותו תאריך. הקריאה החודשית הראשונה עבור SPY היא 17.7% והאחרונה היא 25.8%, עם 96 קריאות ביניהן. KO פותחת את אותו חלון זמן ב--0.4%. מודל שקלול הצורך סדרה זו חודש אחר חודש יורש כל תנודה הקיימת בה.
האם אסטרטגיית חצי-Kelly ושיטת ה-shrinkage פותרות את הבעיה?
הן ממתנות אותה. בפועל, עולים ארבעה תיקונים, וכל אחד מהם מוותר על חלק מהאופטימום התיאורטי בתמורה לרגישות נמוכה יותר לאומדן.
- אסטרטגיית חצי-Kelly חוצה כל משקל. עקומת הצמיחה של Kelly שטוחה ליד שיאה ותלולה מתחתיו, לכן השקעה בחצי מהגודל מוותרת על חלק קטן משיעור הצמיחה התיאורטי, אך מפחיתה במידה רבה יותר את הנזק הנובע מהערכת יתר של היתרון (edge). מיקוד תנודתיות (Volatility targeting) מיישם את אותו אינסטינקט על המכנה, וקובע את גודל הפוזיציה על סמך הקלט היחיד שמדגם קצר יכול לספק.
- שיטת ה-shrinkage מושכת כל ממוצע נאמד לעבר הממוצע הרוחבי של האומדנים, בשיעור הגדל ככל שהמדגם קטן. אם דוחפים זאת לקצה, כל נכס נושא את אותה תשואה צפויה; עם תנודתיות שווה, האופטימייזר יחזיר משקל שווה מעצמו. משקל שווה הוא תיק ההשקעות שעבר shrinkage מלא.
- מגבלות, כלומר איסור על מכירה בחסר (short) ותקרה לכל פוזיציה, תוחמות את המידה שבה אומדן מוצלח בודד יכול להטות משקל של נכס יחיד. מדובר בבקרת נזקים ולא בשיפור של האומדן עצמו.
- ויתור מוחלט על תשואות צפויות מוביל למינימום שונות (minimum variance) ול-risk parity, המשתמשים רק בשונות המשותפת (covariance). זהו הקלט שהמדגם אכן מסוגל לספק.
אף אחד מארבעת הכלים הללו אינו מייצר מידע שהמדגם אינו מכיל. מה שהם משנים הוא המידה שבה תיק ההשקעות נשען על מידע שייתכן שאינו ברשותך.
מתי אופטימיזציה מצדיקה את עלותה
ההצלבה פועלת בשני הכיוונים. ברגע ש-T גדל משמעותית ביחס למרווח (spread) שבין הממוצעים האמיתיים, ההקצאה האופטימלית מובילה ומשמרת את יתרונה, וככל שהמרווח רחב יותר, כך זה קורה מוקדם יותר. אופטימיזציה היא גם הכלי הנכון בכל פעם שהקלט הוא נתון שהמידע מספק: אומדני שונות משותפת (covariance) ויחסי גידור (hedge ratios) מדויקים הרבה יותר מאומדני תשואות צפויות.
משקל שווה נושא בעלות משלו. הוא מתעלם ממידע שקיים בידיך, ובתוך יקום קטן הוא מרכז פוזיציות באותה מידה שכל אופטימייזר היה עושה. התייחס אליו כאל קו הבסיס שכל שיטת שקלול מועמדת חייבת לנצח בנתונים שהמשקולות מעולם לא ראו. התאמת משקולות ודירוגן על אותה דגימה היא הטיית מבט לעתיד בבדיקות לאחור בתחפושת אחרת, והיא מחמיאה לאופטימייזר בכל פעם מחדש. עבור טווח מהימן סביב יתרון שנמדד, במקום אומדן נקודתי בודד, רווחי סמך מבוססי Bootstrapping הם הכלי הסטנדרטי.
שאלות נפוצות
האם משקל שווה באמת עדיף על אופטימיזציית ממוצע-שונות (Mean Variance Optimization)?
במדגמים קצרים, לרוב כן. אופטימיזטור זקוק לאומדן של התשואה הצפויה לכל נכס, ואומדן זה נושא טעות תקן השווה בקירוב לתנודתיות הנכס חלקי השורש הריבועי של אורך המדגם בשנים. כל עוד טעות זו גדולה מההבדלים האמיתיים בין הנכסים, האופטימיזטור ממיין רעשים. בשיטת משקל שווה אין אומדן שניתן לטעות בו.
כמה תצפיות נדרשות כדי לאמוד תשואה צפויה?
יותר ממה שיש כמעט לכל אחד. עבור נכס עם תנודתיות של עשרים אחוזים, שנה אחת של נתונים יומיים מותירה טעות תקן של כעשרים נקודות אחוז בשנה, וצמצום טעות זו בחצי דורש פי ארבעה מהטווח הקלנדרי. הוספת תצפיות תוך-יומיות בתוך אותה שנה אינה מסייעת. לעומת זאת, תנודתיות ניתנת לאמידה מנתונים של חודשים ספורים.
האם חצי קלי (Half Kelly) הוא פשוט הימור קטן יותר?
זהו הימור קטן יותר בתנאים מועדפים. עקומת הצמיחה של קלי שטוחה בקרבת שיאה, לכן צמצום ההימור בחצי מוותר על חלק קטן משיעור הצמיחה התיאורטי, תוך הפחתת התנודתיות של המסלול בקירוב בחצי וצמצום העלות של יתרון מוערך יתר על המידה.
מהו תיק 1/N?
זהו תיק המקצה חלק שווה מההון לכל אחת מ-N פוזיציות ומבצע איזון מחדש לפי לוח זמנים. הוא אינו זקוק לתחזית תשואה ואינו זקוק לאומדן שונות משותפת (covariance), וזה מה שהופך אותו למדד הייחוס הסטנדרטי לכל שיטת שקלול שכן זקוקה להם.
כיצד נבנו הלוחות
כל שלושת הלוחות קוראים שערי סגירה יומיים ומחשבים תשואות פשוטות מסגירה לסגירה, כאשר שורות כפולות מצומצמות לשער סגירה אחד לכל טיקר בכל תאריך. הממוצעים מחושבים במונחים שנתיים על ידי הכפלת התשואה היומית הממוצעת ב-252 ימי מסחר; התנודתיות מחושבת במונחים שנתיים על ידי הכפלת סטיית התקן היומית בשורש הריבועי של 252. הלוח השנתי שומר שנה קלנדרית רק אם קיימים בה לפחות 200 ימי מסחר. לוח הבלוקים משתמש בבלוקים שאינם חופפים ומשמיט את הבלוק החלקי האחרון בכל אורך, ועמודת ספירת החלונות מציגה כמה בלוקים הופקו בכל אורך. דיבידנדים אינם כלולים באף מקום, לכן מדובר בתשואות מחיר ורמת כל ממוצע מוערכת בחסר עבור משלמי דיבידנדים. הפיזור של האומדנים הוא מטרת הלוחות, לא הרמה שלהם.
כל לוח כאן נושא את שאילתת ה-SQL המדויקת מתחת לתרשים, והסימולציה נושאת את ה-seed שלה. כדי להריץ את אותה בדיקת יציבות אומדנים על רשימת השמות שלך, בקש זאת באנגלית פשוטה בטרמינל של Strasmore.