月報酬率怎麼算
收盤至收盤、開盤至收盤、計入股利與分割調整,同一檔股票同一個月會得出不同數字。以NVDA與SPY真實行情並列對照。
詢問某檔股票「6 月表現如何」,不同來源會給出不同數字——而且每一種都正確。
月報酬的定義,取決於多數人從未留意的選擇:用哪兩個價格標定月份的起訖、是否計入股利,以及價格序列是否經過股票分割調整。
本頁將這些互相競爭的計算慣例,放在真實行情上並列對照,讓差異不再難以理解。
收盤至收盤:標準慣例
指數供應商、基金月報及多數報價頁面採用的慣例:月度回報率從前月最後一個常規交易時段收盤價計算至本月最後一個收盤價。5月的最後收盤價是6月的起點。計算方式只有一條算式——期末價格減去期初價格,再除以期初價格。先用簡化例子說明:一隻股票在5月底收於$50.00,6月底收於$53.50,當月回報率為 (53.50 − 50.00) ÷ 50.00 = 0.07,即7%。本頁的每一種慣例都是將不同輸入值代入同一條公式。以下是2026年6月實際數據的呈現,並與主要替代方案並列:
每個數據背後的精確 SQL 語法
SELECT ticker,
round(argMaxIf(cl, day, day <= '2026-05-31'), 2) AS may_final_close,
round(argMinIf(op, day, day >= '2026-06-01'), 2) AS june_first_open,
round(argMaxIf(cl, day, day <= '2026-06-30'), 2) AS june_final_close,
round(100 * (argMaxIf(cl, day, day <= '2026-06-30') - argMaxIf(cl, day, day <= '2026-05-31'))
/ argMaxIf(cl, day, day <= '2026-05-31'), 2) AS close_to_close_pct,
round(100 * (argMaxIf(cl, day, day <= '2026-06-30') - argMinIf(op, day, day >= '2026-06-01'))
/ argMinIf(op, day, day >= '2026-06-01'), 2) AS open_to_close_pct,
round(abs(100 * (argMaxIf(cl, day, day <= '2026-06-30') - argMinIf(op, day, day >= '2026-06-01'))
/ argMinIf(op, day, day >= '2026-06-01')
- 100 * (argMaxIf(cl, day, day <= '2026-06-30') - argMaxIf(cl, day, day <= '2026-05-31'))
/ argMaxIf(cl, day, day <= '2026-05-31')), 2) AS convention_gap_points
FROM (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMinIf(toFloat64(open), window_start, rth) AS op,
argMaxIf(toFloat64(close), window_start, rth) AS cl
FROM (
SELECT ticker, window_start, open, close,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('NVDA', 'SPY')
AND window_start >= '2026-05-28 04:00:00'
AND window_start < '2026-07-01 08:00:00'
)
GROUP BY ticker, day
)
GROUP BY ticker
ORDER BY tickerNVDA的6月收盤至收盤回報率為-5.39%——但若從6月第一個常規交易時段開盤價計算至最後一個收盤價,則為-7.4%。同一隻股票,同一個月份,兩個誠實的答案之間相差2.01個百分點。整個差異來自一個隔夜加週末的窗口:NVDA在5月收於$211.15,並在6月以$215.73開盤——這段跳升在開盤至收盤慣例中歸屬於「6月」,而在收盤至收盤慣例中則歸屬於邊界。SPY以較溫和的方式展現相同的結構:收盤至收盤為-1.33%,開盤至收盤則為-1.2%。
這兩個數字都沒有錯。收盤至收盤回答的是「持續持有者在跨越月份邊界時經歷了什麼?」開盤至收盤回答的是「對於在6月開盤時買入的人,該月份自身的交易帶來了什麼?」每當市場在邊界處出現跳空,兩者就會產生差異——而隔夜跳空是常態,並非罕見。
股息:價格回報 vs 總回報
第二個選擇:股票在當月派發的現金是否計入?價格回報忽略它;總回報則將其加回。對大多數單一月份而言,差距很小——每季派息的公司每季大約只分配其殖利率的四分之一——但經年累月複利下來,差距會變成鴻溝,而2026年6月恰好是SPY的除息月份:
每個數據背後的精確 SQL 語法
WITH px AS (
SELECT argMaxIf(cl, day, day <= '2026-05-31') AS may_close,
argMaxIf(cl, day, day <= '2026-06-30') AS jun_close
FROM (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMinIf(toFloat64(open), window_start, rth) AS op,
argMaxIf(toFloat64(close), window_start, rth) AS cl
FROM (
SELECT ticker, window_start, open, close,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('NVDA', 'SPY')
AND window_start >= '2026-05-28 04:00:00'
AND window_start < '2026-07-01 08:00:00'
)
GROUP BY ticker, day
)
WHERE ticker = 'SPY'
),
dv AS (
SELECT sum(cash_amount) AS div_per_share
FROM global_markets.stocks_dividends
WHERE ticker = 'SPY'
AND ex_dividend_date >= '2026-06-01'
AND ex_dividend_date <= '2026-06-30'
)
SELECT round(may_close, 2) AS may_final_close,
round(jun_close, 2) AS june_final_close,
round(div_per_share, 4) AS june_dividend_per_share,
round(100 * (jun_close - may_close) / may_close, 2) AS price_return_pct,
round(100 * div_per_share / may_close, 2) AS dividend_contribution_pct,
round(100 * ((jun_close + div_per_share) - may_close) / may_close, 2) AS total_return_pct
FROM px CROSS JOIN dvSPY的6月價格回報為-1.33%;加上當月每股$1.9035的除息分配後,總回報提升至-1.08%——現金貢獻了0.25%。指數系列會同時發布兩種版本(你看到的「標普500」報價通常是價格指數),基金績效頁面依法須顯示總回報,而選股器則隨意混用兩者。當兩個來源對某檔配息股某月的回報差了幾十分之一個百分點時,股息就是首要嫌疑對象——除息日決定了該筆款項歸屬於哪個月份。
單一個6月只是百分之零點幾的差距。時間跨度才是區分這兩種慣例的關鍵——以下是將同樣的算術拉長到五年的結果:
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMaxIf(toFloat64(close), window_start,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York')) AS cl
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND ((window_start >= '2021-06-28 04:00:00' AND window_start < '2021-07-01 08:00:00')
OR (window_start >= '2026-06-26 04:00:00' AND window_start < '2026-07-01 08:00:00'))
GROUP BY day
),
px AS (
SELECT argMaxIf(cl, day, day <= '2021-06-30') AS start_close,
argMaxIf(cl, day, day <= '2026-06-30') AS end_close
FROM daily
),
dv AS (
SELECT round(sum(cash_amount), 2) AS divs_per_share,
count() AS payments
FROM global_markets.stocks_dividends
WHERE ticker = 'SPY'
AND ex_dividend_date >= '2021-07-01'
AND ex_dividend_date <= '2026-06-30'
)
SELECT round(start_close, 2) AS june_2021_close,
round(end_close, 2) AS june_2026_close,
divs_per_share AS dividends_paid_per_share,
payments AS dividend_payments,
round(100 * (end_close - start_close) / start_close, 2) AS five_year_price_return_pct,
round(100 * ((end_close + divs_per_share) - start_close) / start_close, 2) AS five_year_return_with_divs_pct,
round(100 * divs_per_share / start_close, 2) AS dividend_points_added
FROM px CROSS JOIN dv從2021年6月收盤價$428.07到2026年6月收盤價$746.32,SPY的五年價格回報為74.35%。同期它進行了20次分配,合計每股$34.07;將這些現金計入後,數字升至82.3%——在尚未將任何一筆股息再投資之前,差距已達7.96個百分點。真正的總回報指數會在每個除息日將款項再投資,而再投資所得的份額會進一步擴大差距。對一檔成熟的配息標的而言,「巨大差距」並非修辭手法,而是長年逐季累積現金的必然結果。
調整後收盤價 vs. 原始收盤價:股票分割的陷阱
大多數圖表工具——Yahoo Finance、Google Finance、多數券商 App——報價採用的是調整後收盤價:一種歷史價格序列,其中過去的成交價已因股票分割而下調(部分平台也會針對股利進行調整),讓價格線在時間軸上具有可比性。我們的資料庫儲存的是實際成交的原始數據。在一般月份,兩者一致。但在包含股票分割的月份,兩者會呈現截然不同的走勢——以 NVDA 在 2024 年 6 月 10 日執行的 10 拆 1 分割為例,該事件發生在當月內:
每個數據背後的精確 SQL 語法
WITH px AS (
SELECT argMaxIf(cl, day, day <= '2024-05-31') AS may_close,
argMaxIf(cl, day, day <= '2024-06-30') AS jun_close
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMaxIf(toFloat64(close), window_start,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York')) AS cl
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'NVDA'
AND window_start >= '2024-05-29 04:00:00'
AND window_start < '2024-07-01 08:00:00'
GROUP BY day
)
),
sp AS (
SELECT split_to / split_from AS ratio
FROM global_markets.stocks_splits
WHERE ticker = 'NVDA'
AND execution_date >= '2024-06-01'
AND execution_date <= '2024-06-30'
)
SELECT round(may_close, 2) AS may_final_close_raw,
round(jun_close, 2) AS june_final_close_raw,
toInt32(ratio) AS shares_after_split_per_old_share,
round(100 * (jun_close - may_close) / may_close, 2) AS raw_price_change_pct,
round(may_close / ratio, 2) AS may_close_split_adjusted,
round(100 * (jun_close - may_close / ratio) / (may_close / ratio), 2) AS adjusted_return_pct
FROM px CROSS JOIN sp若以原始數據解讀,NVDA 在該年 6 月從 $1097.46「跌」至 $123.41——跌幅達 -88.75%。實際上完全沒有這回事:在執行日,每一股舊股變成 10 股新股,價格也等比例下調,每位持有人的美元價值維持不變。將 5 月收盤價除以相同比例——在分割調整基礎上為 $109.75——則 2024 年 6 月測得的報酬率為 12.45%,是一個上漲的月份。任何引用調整後數據的來源,回報的數字都會接近第二種結果;而對原始成交價進行天真計算,則會得出第一種結果。調整後收盤價是兩個來源在歷史月度報酬率上出現巨大分歧最常見的原因——當某個數字無論漲跌方向都大到不合理時,請先查閱股票分割行事曆,再進行其他判斷。
哪個「收盤價」才是真正的收盤價?
慣例中還藏著另一個邊界:收盤價本身。每份資料表使用的數字,都是官方收盤集合競價的成交價——也就是美東時間下午4:00由收盤集合競價決定的單一價格。但盤後交易仍在繼續,延長交易時段的最後一筆成交價,可能與官方收盤價產生偏離:
每個數據背後的精確 SQL 語法
SELECT round(argMaxIf(toFloat64(close), window_start, rth), 2) AS regular_session_close,
round(argMax(toFloat64(close), window_start), 2) AS last_extended_print,
round(100 * (argMax(toFloat64(close), window_start) - argMaxIf(toFloat64(close), window_start, rth))
/ argMaxIf(toFloat64(close), window_start, rth), 3) AS after_hours_drift_pct
FROM (
SELECT window_start, close,
toTimeZone(window_start, 'America/New_York') >= toDateTime('2026-06-30 09:30:00', 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime('2026-06-30 16:00:00', 'America/New_York') AS rth
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2026-06-30 04:00:00'
AND window_start < '2026-07-01 08:00:00'
)6月30日當天,兩者相差了-0.003%——當晚差距不大,但若遇到個股財報發布的夜晚,延長交易時段可能出現數個百分點的波動,而官方月度報酬率會將這些波動歸入下一個月份。盤後與盤前交易詳細說明了這個邊界。一個相關的特殊情況是:月底邊界偶爾會落在假日縮短交易時段,當天常規交易在美東時間下午1:00結束,官方收盤價會在提前的收盤集合競價中產生——市場休市日曆列出了這些日期。
將十二個月複合成一年
年報酬率不是十二個月報酬率的總和,而是它們的乘積。連結公式:將每個月轉換為成長因子(1 + 報酬率),將十二個因子相乘,再減去 1。一個 −5% 的月份後接一個 +5% 的月份,相加為零,但複合後為 0.95 × 1.05 − 1 = −0.25%。以下是 SPY 在截至 2026 年 6 月的十二個月期間的實際月度走勢:
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMaxIf(toFloat64(close), window_start,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York')) AS cl
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2025-06-24 04:00:00'
AND window_start < '2026-07-01 08:00:00'
GROUP BY day
),
monthly AS (
SELECT toStartOfMonth(day) AS month_start,
argMax(cl, day) AS month_close
FROM daily
GROUP BY month_start
),
rets AS (
SELECT month_start,
formatDateTime(month_start, '%Y-%m') AS month,
round(month_close, 2) AS month_final_close,
100 * (month_close / lagInFrame(month_close) OVER (ORDER BY month_start) - 1) AS r
FROM monthly
)
SELECT month,
month_final_close,
round(r, 2) AS simple_return_pct,
round(100 * log(1 + r / 100), 2) AS log_return_pct
FROM rets
WHERE isFinite(r)
ORDER BY month_start從 2.28% 的 2025-07 到 2026-06 的 -1.33%,共十二個收盤至收盤的月份——最後一列與第一個面板所衡量的 2026 年 6 月 SPY 數值相同。正確連結這十二個月份,並與單純加總百分比的捷徑進行比較:
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
argMaxIf(toFloat64(close), window_start,
toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York')) AS cl
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2025-06-24 04:00:00'
AND window_start < '2026-07-01 08:00:00'
GROUP BY day
),
monthly AS (
SELECT toStartOfMonth(day) AS month_start,
argMax(cl, day) AS month_close
FROM daily
GROUP BY month_start
),
rets AS (
SELECT month_start,
100 * (month_close / lagInFrame(month_close) OVER (ORDER BY month_start) - 1) AS r
FROM monthly
),
ends AS (
SELECT argMin(month_close, month_start) AS base_close,
argMax(month_close, month_start) AS final_close
FROM monthly
)
SELECT count() AS months_linked,
round(sum(r), 2) AS simple_sum_pct,
round(100 * (exp(sum(log(1 + r / 100))) - 1), 2) AS geometric_compound_pct,
round(100 * (any(final_close) / any(base_close) - 1), 2) AS direct_twelve_month_pct,
round(100 * (exp(sum(log(1 + r / 100))) - 1) - sum(r), 2) AS compounding_gap_points,
round(sum(100 * log(1 + r / 100)), 2) AS sum_of_monthly_log_returns_pct,
round(100 * log(any(final_close) / any(base_close)), 2) AS twelve_month_log_return_pct
FROM rets CROSS JOIN ends
WHERE isFinite(r)這十二個月的總和為 19.83%,但複合後為 20.79%——而直接計算,從 2025 年 6 月的收盤價直接到 2026 年 6 月的收盤價,得出 20.79%,與複合後的數字相符,而非總和。這裡的差距在一個相對平穩的年份是 0.96 個點;隨著波動性和時間跨度增加,差距會擴大。將月度百分比相加是常見的試算表習慣,而這在不知不覺中是錯誤的。
最後兩欄顯示了為加法而建立的慣例:對數報酬率,即成長因子的自然對數,ln(1 + 報酬率)。月度對數報酬率加總為 18.89%——與十二個月對數報酬率的 18.89% 相同,這正是分析師和風險模型使用它們的原因。對於波動較小的月份,兩種慣例幾乎沒有差異(2025-11:簡單報酬率 0.21%,對數報酬率 0.21%);月份波動越大,兩者分歧越大(2026-04:簡單報酬率 10.49%,對數報酬率 9.97%)。基金概況說明書引用簡單報酬率;對數報酬率則存在於研究論文和波動性數學中。
讓任何兩個數據來源達成一致的四項檢查清單
當兩組月度回報數字不一致時,差異幾乎都出在以下四個開關的其中一個:
- 端點 — 收盤價對收盤價(標準做法),或開盤價對收盤價(當月自身的交易區間)。只要邊界出現跳空缺口,兩者就會不同。
- 股息 — 價格回報或總回報。只要當月包含除息日,兩者就會不同。
- 調整 — 原始報價或調整後收盤價序列。只要當月發生股票分割,兩者就會天差地遠。
- 收盤價本身 — 官方集合競價撮合價(標準做法),對比可能涵蓋盤後交易的最後一筆成交價。
對兩個數據來源套用相同的開關設定,分歧就會消失 — 而基金與指數的比較,只有在兩組數字採用相同四項設定時才有效;只要有一項設定不同,比較結果就會悄悄衡量設定差異,而非績效表現。我們自家的2026年6月回顧正是為此,開頭就明確說明其慣例 — 該篇的每一項月度數字,都是收盤價對收盤價、官方撮合價、價格回報。
月度報酬常見問答
什麼是收盤價對收盤價報酬?
從前一期間最後一筆常規交易時段收盤價,到本期最後一筆收盤價的百分比變動。這是概況說明書和指數報告中,計算每日、每月和每年股票報酬的標準慣例。
為什麼兩個網站對同一檔股票和同一個月份顯示不同的報酬?
幾乎總是以下四種慣例之一:不同的端點(收盤價對收盤價與開盤價對收盤價)、是否計入股息、原始價格與經股票分割調整後的價格,或是不同的收盤價來源。僅在第一種轉換下,輝達(NVDA)2026年6月的衡量結果就可能是 -5.39% 或 -7.4%。
股票分割會改變月度報酬的計算嗎?
不應該——股票分割同時改變股數和價格,使持倉價值保持不變——但任何基於原始價格進行的計算都會被破壞。輝達(NVDA)2024年6月在原始收盤價上看起來像是 -88.75%,而在針對10比1分割進行調整後,衡量結果為 12.45%。
月度股票報酬包含股息嗎?
只有總報酬才會包含。價格報酬——包括標普500指數的整體水準——則排除股息。2026年6月,股息為SPY的月度表現貢獻了 0.25%,這就是其價格報酬與總報酬之間的差距。
我個人投資組合的月度報酬也是用同樣方式計算的嗎?
一旦有現金進出,就不是了。像本頁面上的這類單一證券報酬是時間加權的;一個有存款和提款的帳戶需要採用資金加權(內部報酬率)的計算方式,否則現金流會偽裝成投資績效。大多數券商報告時間加權數字,正是為了將你的存款從數字中剝離出來。
以上每個數字都是基於真實交易資料儲存、帶有版本的查詢結果——展開任何一個面板的SQL,或在Strasmore終端機上以任何慣例衡量任何股票的月度表現。