跳至主要內容

回測視窗 2019-02-11 〜 2026-10-30 · 資料截至 2026-10-30

月營收動能+現金股利調高優先

月營收動能選股(近三月平均營收高於近十二月平均、站上 20/60/120 日均線、五日平均漲跌幅最強 10 檔,每月營收公布後換股、10% 停損),近 60 個交易日內董事會決議每股現金股利比去年同期多 10% 以上的候選股優先入選。2019 年至 2026 年台股回測年化報酬 59.9%、日夏普 1.83、最大回撤 -27.8%;同視窗原版月營收動能 54.3%、1.52,0050 含息 28.5%、1.30。

投資警語:本文僅供教學參考,不構成投資建議。過去績效不代表未來表現,投資有風險。

回測績效

年化報酬率
59.9%
日夏普
1.83
最大回撤
-27.9%
總報酬率
3642%
平均持股
10.0 檔

回測含手續費 0.1425% 與賣出證交稅 0.3%(finlab 套件 sim() 預設成本),日夏普未扣無風險利率。策略淨值自資料可得日(2019-02-11)起算。

淨值曲線(對數座標)

月營收動能+現金股利調高優先 vs 0050 買進持有(含息)
1x2x3x5x8x12x20x30x2019-02-112020-05-282021-09-072022-12-162024-04-162025-07-312026-10-30
月營收動能+現金股利調高優先0050 買進持有(含息)

與 0050 買進持有(含息)對照

對象年化報酬率日夏普最大回撤統計視窗
月營收動能+現金股利調高優先59.9%1.83-27.9%2019-02-11 〜 2026-10-30
0050 買進持有(含息)28.5%1.30-34.0%2019-02-11 〜 2026-10-30

完整策略程式碼

安裝 finlab 套件後即可直接執行重現(finlab.login() 會自動引導登入,不需手動填 token)。想用 AI 輔助安裝與跑第一次回測,可以走安裝教學。

展開程式碼(strategy.py)
"""現金股利調高選股:月營收動能選股,近 60 個交易日內董事會調高現金股利的候選股優先。

與 https://finlab.finance/blog/cash-dividend-increase-stock-selection 同一份程式。
回測從 2019-01 起(FinLab 的董事會股利決議日從 2019 年開始收錄)到最新資料。

執行前先安裝 finlab,需要資料時 finlab 會自動引導登入:

    pip install finlab
    python strategy.py
"""
import numpy as np
import pandas as pd
from finlab import data
from finlab.backtest import sim

close = data.get("price:收盤價")
rev = data.get("monthly_revenue:當月營收")
board = pd.DataFrame(data.get("board_dividend_announcement"))

# 1. 月營收動能:近三個月平均營收高於近十二個月平均營收
rev_up = rev.average(3) > rev.average(12)

# 2. 股價趨勢:收盤價同時站上 20、60、120 日均線
trend = (
    (close > close.average(20))
    & (close > close.average(60))
    & (close > close.average(120))
)

# 3. 董事會決議的每股現金股利,比去年同一期(年度、上下半年或同一季)多 10% 以上
period = board["股利所屬年(季)度"].astype(str)
board["year"] = period.str.extract(r"^(\d+)年")[0].astype(float)
board["part"] = period.str.replace(r"^\d+年", "", regex=True)
board["cash"] = (
    board["盈餘分配之現金股利(元/股)"].fillna(0)
    + board["法定盈餘公積發放之現金(元/股)"].fillna(0)
    + board["資本公積發放之現金(元/股)"].fillna(0)
)
board = board.dropna(subset=["year"]).sort_values("key_date")
board = board.drop_duplicates(["stock_id", "股利所屬年(季)度"], keep="last")
last_year = board.set_index(["stock_id", "year", "part"])["cash"]
board["last_year_cash"] = last_year.reindex(
    list(zip(board["stock_id"], board["year"] - 1, board["part"]))
).to_numpy()
decided = board["董事會決議(擬議)股利分派日"]
raised = board[(decided >= "2019-01-01") & (board["last_year_cash"] > 0)
               & (board["cash"] > board["last_year_cash"] * 1.1)]

# 決議日當天(假日公告算前一個交易日)起 60 個交易日內,算「近期調高股利」
recent = np.zeros(close.shape, dtype=bool)
start = close.index.searchsorted(raised["董事會決議(擬議)股利分派日"], side="right") - 1
for stock_id, i in zip(raised["stock_id"], start):
    if stock_id in close.columns and i >= 0:
        recent[i:i + 60, close.columns.get_loc(stock_id)] = True
recent = pd.DataFrame(recent, index=close.index, columns=close.columns)

# 4. 五日平均漲跌幅排名,近期調高股利的候選股排前面,取前 10 檔
momentum = (close / close.shift() - 1).rolling(5).mean()
score = momentum + recent * 1000
position = score[trend & rev_up].is_largest(10).loc["2019-01-01":]

# 每月營收公布後(月初第 11 天)換股,單檔 10% 停損,手續費與證交稅用 sim 預設
report = sim(
    position,
    resample="M",
    resample_offset="11D",
    stop_loss=0.1,
    upload=False,
    name="月營收動能+現金股利調高優先",
)
print(report.get_stats())

下載 strategy.py 下載 data.csv(淨值曲線)

到 FinLab Studio 重現這支策略

在 Studio 裡用同一套真實資料調整條件、重跑回測。

本頁策略與回測結果僅供教學與研究用途,詳見服務條款。