תשואת דיבידנד בתיק: ממוצע משוקלל
כך מחשבים תשואת דיבידנד בתיק לפי הכנסה שנתית ושווי שוק, ומבינים מדוע ממוצע פשוט של עמודת התשואה מטעה ואיך לתקן את החישוב בפועל.
תשואת הדיבידנד של התיק שלך היא נתון אחד: סך הכנסות הדיבידנד השנתיות שהחזקותיך צפויות לשלם, חלקי שווי השוק הכולל שלהן. בניסוח הפוך, מדובר בממוצע משוקלל לפי שווי שוק של התשואות של כל החזקה, כאשר המשקל של כל החזקה הוא שוויה בדולרים כחלק מהשווי הכולל. הממוצע של עמודת התשואה במסך הברוקר הוא נתון אחר, וברוב התיקים בפועל זהו הנתון המחמיא יותר.
כיצד לחשב את תשואת הדיבידנד של התיק
עבור כל פוזיציה, הכפל את מספר המניות בדיבידנד השנתי למניה. כך מתקבלת ההכנסה השנתית של הפוזיציה בדולרים. חבר את ההכנסות האלה, חלק את הסכום בסכום המכפלות של מספר המניות במחיר בכל הפוזיציות, והכפל ב־100. זהו החישוב המלא, בין אם מדובר בארבע החזקות ובין אם בארבעים.
אפשר לכתוב את הנוסחה בשתי דרכים שקולות:
- סך ההכנסה השנתית חלקי שווי השוק הכולל של התיק.
- הסכום, על פני כל ההחזקות, של משקל כפול תשואה, כאשר המשקל הוא שווי הפוזיציה חלקי שווי התיק.
הצורה השנייה מראה היכן הממוצע הפשוט משתבש. כל החזקה מופיעה בשתי הגרסאות, אך בגרסה הנכונה כל אחת נושאת משקל לפי הדולרים שלה, ולא קול אחד בלבד. אם אתה מחשיב מזומן כחלק מהתיק, יש לכלול אותו גם במכנה. השמטתו מעלה את התשואה המוצגת בלי להוסיף אפילו סנט להכנסה. לגרסה המתייחסת למניה בודדת, התחל ב־כיצד לחשב תשואת דיבידנד.
מדוע ממוצע עמודת התשואה מגדיל את ההכנסה המוצגת
את הפער בין שתי השיטות קל ביותר לראות בדוגמה מחושבת. הסקריפט שלהלן הוא קוד Python 3 פשוט, ללא ייבוא של חבילות. הוא ירוץ בכל מחשב עם python3. חמש הפוזיציות הן מספרים עגולים והיפותטיים, שנבחרו כדי להמחיש את ההשפעה: שם, מספר מניות, מחיר ודיבידנד שנתי למניה.
#!/usr/bin/env python3
# each row: (name, shares, price, annual dividend per share)
holdings = [
('A', 200, 50.00, 1.50),
('B', 150, 100.00, 2.00),
('C', 100, 80.00, 0.80),
('D', 300, 20.00, 1.00),
('E', 100, 10.00, 0.90),
]
total_value = sum(sh * px for _, sh, px, _ in holdings)
total_income = sum(sh * dps for _, sh, _, dps in holdings)
naive = sum(100 * dps / px for _, _, px, dps in holdings) / len(holdings)
print(f'market value : ${total_value:,.2f}')
print(f'annual income : ${total_income:,.2f}')
print(f'portfolio yield : {100 * total_income / total_value:.2f}%')
print(f'average of yields : {naive:.2f}%')
for name, sh, px, dps in holdings:
value = sh * px
income = sh * dps
print(
f'{name} weight {100 * value / total_value:5.1f}%'
f' yield {100 * dps / px:5.2f}%'
f' income ${income:8,.2f}'
f' share of income {100 * income / total_income:5.1f}%'
)
הריצו אותו, ושתי השורות המרכזיות לא יסכימו זו עם זו. התיק מחזיק מניות בשווי של $40,000 ומשלם $1,070 בשנה, כלומר תשואה משוקללת של 2.68%. הממוצע הפשוט של חמש התשואות מציג 4.00%, בערך פי one and a half מהנתון הנכון.
פוזיציה E מספרת את הסיפור כולו. התשואה שלה היא 9.00%, הגבוהה ביותר בתיק, אך היא מבוססת על מניות בשווי $1,000 בלבד. אלה 2.5% משווי התיק ו־8.4% מהכנסתו. בממוצע הפשוט היא מקבלת חמישית מהקולות, בדיוק כמו הפוזיציה בשווי $15,000 שלצדה. נתון תשואה מקבל משמעות רק כאשר מצרפים אליו את הדולרים שעומדים מאחוריו.
כיצד נראה שקלול בין החזקות בפועל
מניות שמחלקות דיבידנד למשקי בית מציגות טווח רחב של תשואות, ולכן לבחירת שיטת השקלול יש חשיבות. הפאנל שלהלן מחשב את תשואת העבר של כל חברה, לפי הדיבידנדים למניה שהוכרזו ב־twelve months האחרונים, חלקי שער הסגירה היומי האחרון.
ה-SQL המדויק מאחורי כל מספר
WITH
last_px AS
(
SELECT
ticker,
toFloat64(argMax(close, date)) AS px,
formatDateTime(max(date), '%b %e, %Y') AS priced_through
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('AAPL', 'MSFT', 'HD', 'KO', 'PG', 'PEP', 'JNJ', 'XOM', 'CVX', 'VZ')
AND date >= today() - 30
GROUP BY ticker
),
ttm_dps AS
(
SELECT
ticker,
sum(amount) AS dps
FROM
(
SELECT
ticker,
id,
toFloat64(any(cash_amount)) AS amount
FROM global_markets.stocks_dividends
WHERE ticker IN ('AAPL', 'MSFT', 'HD', 'KO', 'PG', 'PEP', 'JNJ', 'XOM', 'CVX', 'VZ')
AND ex_dividend_date > today() - 365
AND ex_dividend_date <= today()
GROUP BY ticker, id
)
GROUP BY ticker
)
SELECT
p.ticker AS symbol,
round(d.dps, 2) AS ttm_dividend_usd,
round(100 * d.dps / p.px, 2) AS yield_pct,
p.priced_through AS priced_through
FROM last_px AS p
INNER JOIN ttm_dps AS d ON d.ticker = p.ticker
ORDER BY yield_pct DESCבין 10 החברות האלה, שמחיריהן מחושבים עד Aug 7, 2026, התשואות נעות מ־5.96% בשיעור VZ ועד 0.34% בשיעור AAPL. תיק שנבנה מתמהיל כזה לא יתקרב בהכרח לנקודת האמצע של העמודה, אלא אם הפוזיציות שוות בגודלן בדולרים.
כעת נכניס חמש מהן לתיק עם מספרי מניות קבועים ונבחן זה לצד זה שני נתונים: חלקה של כל החזקה בשווי השוק וחלקה בהכנסה השנתית.
ה-SQL המדויק מאחורי כל מספר
WITH
positions AS
(
SELECT
tupleElement(p, 1) AS ticker,
toFloat64(tupleElement(p, 2)) AS shares
FROM
(
SELECT arrayJoin([('MSFT', 30.), ('PG', 60.), ('XOM', 80.), ('KO', 100.), ('VZ', 60.)]) AS p
)
),
last_px AS
(
SELECT
ticker,
toFloat64(argMax(close, date)) AS px
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('MSFT', 'PG', 'XOM', 'KO', 'VZ')
AND date >= today() - 30
GROUP BY ticker
),
ttm_dps AS
(
SELECT
ticker,
sum(amount) AS dps
FROM
(
SELECT
ticker,
id,
toFloat64(any(cash_amount)) AS amount
FROM global_markets.stocks_dividends
WHERE ticker IN ('MSFT', 'PG', 'XOM', 'KO', 'VZ')
AND ex_dividend_date > today() - 365
AND ex_dividend_date <= today()
GROUP BY ticker, id
)
GROUP BY ticker
),
holding AS
(
SELECT
pos.ticker AS ticker,
pos.shares * lp.px AS value_usd,
pos.shares * d.dps AS income_usd
FROM positions AS pos
INNER JOIN last_px AS lp ON lp.ticker = pos.ticker
INNER JOIN ttm_dps AS d ON d.ticker = pos.ticker
)
SELECT
h.ticker AS symbol,
round(100 * h.value_usd / t.total_value, 1) AS weight_pct,
round(100 * h.income_usd / t.total_income, 1) AS income_share_pct,
round(100 * h.income_usd / h.value_usd, 2) AS yield_pct
FROM holding AS h
CROSS JOIN
(
SELECT
sum(value_usd) AS total_value,
sum(income_usd) AS total_income
FROM holding
) AS t
ORDER BY weight_pct DESCהתבנית מהסקריפט חוזרת על עצמה במחירי שוק עדכניים. MSFT היא הפוזיציה הגדולה ביותר, עם 31.4% משווי השוק, ובמקביל היא מספקת 10% מההכנסה, בתשואה של 0.72%. בצד השני, VZ מהווה 5.9% מהשווי ומשלמת 15.7% מההכנסה, בתשואה של 5.96%. המשקל וחלקה של ההחזקה בהכנסה נפרדים זה מזה בכל פעם שהתשואות שונות.
בחישוב ממוצע בשתי הדרכים, אותן חמש החזקות נותנות שתי תשובות שונות.
ה-SQL המדויק מאחורי כל מספר
WITH
positions AS
(
SELECT
tupleElement(p, 1) AS ticker,
toFloat64(tupleElement(p, 2)) AS shares
FROM
(
SELECT arrayJoin([('MSFT', 30.), ('PG', 60.), ('XOM', 80.), ('KO', 100.), ('VZ', 60.)]) AS p
)
),
last_px AS
(
SELECT
ticker,
toFloat64(argMax(close, date)) AS px
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('MSFT', 'PG', 'XOM', 'KO', 'VZ')
AND date >= today() - 30
GROUP BY ticker
),
ttm_dps AS
(
SELECT
ticker,
sum(amount) AS dps
FROM
(
SELECT
ticker,
id,
toFloat64(any(cash_amount)) AS amount
FROM global_markets.stocks_dividends
WHERE ticker IN ('MSFT', 'PG', 'XOM', 'KO', 'VZ')
AND ex_dividend_date > today() - 365
AND ex_dividend_date <= today()
GROUP BY ticker, id
)
GROUP BY ticker
),
holding AS
(
SELECT
pos.shares * lp.px AS value_usd,
pos.shares * d.dps AS income_usd
FROM positions AS pos
INNER JOIN last_px AS lp ON lp.ticker = pos.ticker
INNER JOIN ttm_dps AS d ON d.ticker = pos.ticker
)
SELECT
tupleElement(m, 1) AS method,
round(tupleElement(m, 2), 2) AS yield_pct
FROM
(
SELECT arrayJoin([
('Market-value weighted portfolio yield', weighted_yield),
('Simple average of the five yields', naive_yield)
]) AS m
FROM
(
SELECT
100 * sum(income_usd) / sum(value_usd) AS weighted_yield,
avg(100 * income_usd / value_usd) AS naive_yield
FROM holding
)
)
ORDER BY yield_pct DESCהקו הגבוה יותר, בשיעור 2.93%, הוא נתון ה־Simple average of the five yields. הקו האחר מציג 2.24%. רק אחד מהם תואם את תזרים המזומנים. הכפל את הנתון המשוקלל בשווי השוק של התיק, ותקבל את ההכנסה השנתית. בצע את אותה פעולה עם הממוצע הפשוט, ותקבל מספר שאף דוח לא יציג. הכיוון נובע ממבנה החישוב: כאשר המניות בעלות התשואה הגבוהה יותר הן הפוזיציות הקטנות, הממוצע הפשוט גבוה מתשואת התיק האמיתית; כאשר המניות בעלות התשואה הגבוהה הן הפוזיציות הגדולות, הוא נמוך ממנה.
תשואה על בסיס העלות אינה תשואת התיק
תשואה על בסיס העלות מחלקת את הדיבידנד השנתי הנוכחי במחיר ששילמת, ולא בשווי הפוזיציה כיום. פוזיציה שנרכשה ב־$20 ונסחרת כעת ב־$80, ועדיין משלמת $1.00 למניה בשנה, מציגה תשואה על בסיס העלות של 5.00%, לעומת תשואה נוכחית של 1.25%. הדיבידנד הוא אותו סכום בדולרים. רק המכנה השתנה.
שני הנתונים לגיטימיים, והם עונים על שאלות שונות. שווי השוק הנוכחי במכנה אומר לך מהי תשואת התיק כיום — הנתון שניתן להשוות ל־תשואת דיבידנד טובה או ל־Treasury bill. בסיס העלות במכנה אומר לך משהו על רכישה שביצעת בעבר. הבעיה מתחילה כאשר מערבבים בין השניים בתוך נתון כולל אחד של התיק: תשואה נוכחית על רכישות חדשות, ותשואה על בסיס העלות על החזקות שנשמרו במשך עשור. שילוב כזה מכפיל באופן שגרתי את התשואה הנראית של תיק הכנסה, ואינו תואם שום נתון שברוקר מדווח. מלכודות תשואת דיבידנד עוסק באשליה ההפוכה — תשואה שנראית גבוהה לאחר ירידה חדה במחיר.
נתוני עבר או נתונים קדימה משנים את התשובה
כל נתון לעיל תלוי במספר הדיבידנד שנכנס למונה. תשואת עבר מסכמת את התשלומים שהוכרזו בפועל במהלך twelve months האחרונים. תשואה קדימה משנתת את התשלום האחרון, בדרך כלל באמצעות הכפלת הסכום הרבעוני האחרון בארבע. שני הנתונים שונים בכל חברה ששינתה את החלוקה שלה או שילמה חלוקה מיוחדת במהלך השנה, והחזקה גדולה אחת יכולה לשנות לבדה את נתון התיק במידה משמעותית. הפאנלים כאן משתמשים בנתוני עבר. תשואת דיבידנד על בסיס נתוני עבר לעומת נתונים קדימה מסביר מתי נכון להשתמש בכל אחת מהשיטות.
התשואה היא שיעור, והמזומן מגיע בתשלומים מרוכזים
תשואה משוקללת היא שיעור שנתי, לא לוח תשלומים. אותן חמש פוזיציות מחלקות את המזומן לאורך קומץ חודשים מרוכזים, משום שרוב החברות בארה״ב עוברות ex-dividend מדי רבעון ופועלות לפי לוחות זמנים דומים.
ה-SQL המדויק מאחורי כל מספר
WITH
positions AS
(
SELECT
tupleElement(p, 1) AS ticker,
toFloat64(tupleElement(p, 2)) AS shares
FROM
(
SELECT arrayJoin([('MSFT', 30.), ('PG', 60.), ('XOM', 80.), ('KO', 100.), ('VZ', 60.)]) AS p
)
),
payments AS
(
SELECT
ticker,
id,
any(ex_dividend_date) AS ex_date,
toFloat64(any(cash_amount)) AS amount
FROM global_markets.stocks_dividends
WHERE ticker IN ('MSFT', 'PG', 'XOM', 'KO', 'VZ')
AND ex_dividend_date > today() - 365
AND ex_dividend_date <= today()
GROUP BY ticker, id
)
SELECT
formatDateTime(toStartOfMonth(pay.ex_date), '%Y-%m') AS month,
formatDateTime(toStartOfMonth(pay.ex_date), '%b %Y') AS month_label,
round(sum(pos.shares * pay.amount), 2) AS income_usd
FROM payments AS pay
INNER JOIN positions AS pos ON pos.ticker = pay.ticker
GROUP BY month, month_label
ORDER BY monthהמזומן התקבל במהלך 12 חודשים שונים בשנה האחרונה, כשהאחרון שבהם היה Jul 2026 ובו התקבלו $107.76. תשואת תיק של כמה אחוזים אינה אומרת דבר על החודש שבו הכסף יתקבל. לכן תוכנית הכנסה המבוססת על נתון חודשי צריכה לכלול גם את לוח התשלומים לצד השיעור. לרמת השוק הכולל שאליה מושווים נתוני התיק האלה, ראו תשואת הדיבידנד של S&P 500.
שאלות נפוצות
כיצד מחשבים את תשואת הדיבידנד של התיק כולו?
חבר את ההכנסה השנתית של כל החזקה מדיבידנדים — מספר המניות כפול הדיבידנד השנתי למניה. לאחר מכן חבר את שווי השוק של כל החזקה — מספר המניות כפול המחיר. חלק את סך ההכנסה בסך השווי והכפל ב־100. התוצאה היא הממוצע המשוקלל לפי שווי שוק של תשואות ההחזקות בתיק.
מדוע הממוצע של תשואות ההחזקות שלי גבוה מתשואת התיק?
ממוצע פשוט מעניק לכל פוזיציה קול אחד. תשואת תיק מעניקה לכל פוזיציה משקל בהתאם לדולרים שלה. כאשר המניות בעלות התשואה הגבוהה ביותר הן הפוזיציות הקטנות ביותר, הממוצע הפשוט גבוה מתשואת התיק בפועל, ולעיתים גבוה ממנה ב־half again as much.
האם מזומן נכלל בתשואת הדיבידנד של התיק?
אם אתה מחשיב מזומן כחלק מהתיק, יש לכלול אותו במכנה, עם דיבידנד אפס, ולכן הוא מוריד את התשואה. אם משמיטים אותו, מדווחים על תשואת החלק המושקע בלבד. שתי השיטות תקפות, כל עוד משתמשים באותה שיטה בכל מדידה.
האם תשואה על בסיס העלות זהה לתשואת התיק שלי?
לא. תשואה על בסיס העלות מחלקת את הדיבידנד הנוכחי במחיר ששילמת לפני שנים, ולכן היא עולה בכל פעם שהמניה עולה. תשואת התיק משתמשת בשווי השוק הנוכחי, וזהו הנתון שמתאים להכנסה שההחזקות הנוכחיות שלך מייצרות.
האם הוספת מניה אחת בעלת תשואה גבוהה תעלה במידה רבה את תשואת התיק?
רק בהתאם לדולרים המושקעים בה. מניה עם תשואה של 9% המוחזקת במשקל של 2.5% מהתיק מוסיפה בערך 0.2 נקודות אחוז לתשואה המשוקללת — 0.09 כפול 0.025 — בלי קשר להשפעתה על ממוצע עמודת התשואה.
כל פאנל כאן כולל את שאילתת ה־SQL המדויקת שהפיקה אותו, ולכן ניתן לבדוק את השקלול שורה אחר שורה. כדי לבצע את אותו חישוב על רשימת החברות ומספרי המניות שלך, בקש זאת באנגלית פשוטה במסוף Strasmore.