跳至主要內容
台股研究 約 24 分鐘閱讀

mfi 指標怎麼用才對?台股 11 年回測:動能選股+mfi 廣度擇時的純技術策略

mfi 指標怎麼用才對?台股回測:買 mfi 最低 30 檔研究段年化僅 2.1%;改當動能選股的剔除濾網加池內廣度擇時,全期年化 28.0% 勝 0050 的 21.2%,但 2022 年起與 0050 打平,換股日改到月中全期只剩 11.4% 到 18.1%。

免安裝,用 AI 重跑這篇的策略

在瀏覽器開啟 FinLab Studio,AI 依本文的條件重跑回測,接著可以改條件再測。

在 Studio 重跑
mfi 真用法 CAGR 28.0% Sharpe 1.09

mfi 指標在台股怎麼用:動能選股,配選股池內的 mfi 廣度擇時

mfi 指標台股回測的關鍵數字:

你想知道的 本文用真實台股回測的回答
mfi 指標是什麼 帶成交量的 RSI;把典型價格乘上成交量分成正、負資金流,換算成 0 到 100 的讀數,預設回看 14 日
mfi 低於 20 超賣買進有效嗎 每月買 MFI(14) 最低的 30 檔,研究段(2015–2021)年化 2.1%;月底 MFI 低於 20 的股票全部持有只有 1.6%。同期含息 0050 是 15.1%
mfi 能拿來選股嗎 當排序因子偏弱:同一個選股池挑 MFI 最高 12 檔,研究段年化 21.1%、月夏普 0.87;改挑多窗動能最高 12 檔是 28.5%、1.00。當剔除濾網,11 年多平均每月只剔掉 0.4 檔,全期年化只差 0.4 個百分點
那它在本文哪裡有用 算選股池內 MFI(21) 高於 50 的比例,月底若比 20 個交易日前低就整籃減到五成:全期最大回撤由 -50.4% 降到 -36.3%,年化由 29.5% 降到 28.0%
效果如何 資料延長到 2026-09-30,全期年化 28.0%、月夏普 1.09、月索提諾 1.97,勝含息 0050 的 21.2%、1.07、1.85;最大回撤 -36.3% 比 0050 的 -34.0% 深。2022 年起年化 30.5% 與 0050 打平,月夏普 1.04 對 1.21
最大的保留 這套規則在每月最後一個交易日換股。換股日改到每月 5、10、15、20、25 日,全期年化只剩 11.4% 到 18.1%;廣度擇時改成每天調整,全期 17.4%
最近發生什麼事 首發資料截止日 2026-06-09 之後到 9 月底,策略 -0.3%、0050 +8.9%;7 月策略 -16.1%,月初持有的 12 檔全部虧損
依本文重跑

執行這個策略

複製提示詞,讓 AI 依照上方證據的資料、條件與風險檢查重跑一次。

告訴你的AI:

幫我設定 FinLab,重現這篇文章,請讀:https://finlab.finance/setup?relatedUrl=/blog/mfi-money-flow-index-taiwan

免安裝,開啟 FinLab Studio

多窗動能選股配 mfi 廣度擇時的純技術策略與含息 0050 的台股淨值對照圖,2015 年 1 月 30 日同日起算到 2026 年 9 月

本文所有數字皆出自 finlab 套件(2.2.21)抓取的上市櫃真實價量資料(price 與 etl:adj_close 含息還原股價),MFI 以 TA-Lib MFI 計算,回測從 2015-01-30 起算、資料截至 2026-09-30,基準為同日起算的含息 0050。2026-10-28 用延長後的資料重跑,參數一個都沒改:2022 年起月夏普由首發版(資料截至 2026-06-09)的 1.06 變成 1.04,仍在我們設的 1.0 門檻之上,但只高出 0.04。這次重跑另外補做了換股日、擇時檢查頻率、逐層拆解與參數逐格掃描,結論比首發版保守很多,首發版的幾個錯誤在對應段落更正。文末附可下載的 strategy.py 與 data.csv,可自行重現。對回測的觀念還不熟,可先看回測是什麼。

mfi 指標是什麼

mfi(Money Flow Index,資金流量指標)是 Gene Quong 與 Avrum Soudack 提出的振盪指標,概念延伸自 J. Welles Wilder 的 RSI。它可以理解成「帶成交量的 RSI」:RSI 只看價格,mfi 則把每天的「典型價格(高+低+收 ÷ 3)」乘上成交量,分成上漲日的正資金流與下跌日的負資金流,再用近 N 日(預設 14 日)的正負資金流比值換算成 0 到 100 的讀數。讀數越高,代表近期帶量上漲的日子占優勢(資金流入);越低代表帶量下跌占優勢(資金流出)。各技術指標的計算與比較整理可參考 TA-Lib 158 個技術指標總覽,名詞釐清見名詞詞彙表。

教科書最常見的兩個用法是:

超買超賣:mfi > 80 視為超買(該賣)、mfi < 20 視為超賣(該買)。

背離:股價創高但 mfi 沒跟上創高,視為上漲動能轉弱的警訊;反之亦然。

mfi 和 RSI、KD 一樣屬於擺盪指標,資訊高度重疊。「超買要賣、超賣要買」這個直覺在台股橫截面上是對是錯,下面直接回測。

mfi 指標的數學定義與計算

mfi 的計算分四步:

MF=TP×V,MFR=∑正MFn∑負MFn,MFI=100−1001+MFRMF = TP\times V,\quad MFR = \frac{\sum \text{正}MF_n}{\sum \text{負}MF_n},\quad MFI = 100 - \frac{100}{1 + MFR}

逐項拆開來看每個符號的意思:

  • TPTP(typical price,典型價格):當日「最高價、最低價、收盤價」三者的平均,也就是 (H+L+C)/3(H+L+C)/3。它代表這一天大致成交在哪個價位。
  • VV:當日成交量(本文用成交股數)。
  • MFMF(money flow,資金流量):典型價格乘上成交量,衡量「今天有多少錢以什麼價位換手」:量大且價高,MFMF 就大。
  • ∑正MFn\sum \text{正}MF_n、∑負MFn\sum \text{負}MF_n:把回看 nn 天(預設 n=14n=14)分成上漲日與下跌日。當天 TPTP 比前一天高,就把它的 MFMF 計入「正資金流」;比前一天低就計入「負資金流」;一樣高則兩邊都不計。再分別把這 nn 天的正、負資金流加總。
  • MFRMFR(money flow ratio,資金流量比值):正資金流總和除以負資金流總和。流入越壓過流出,MFRMFR 越大。
  • 最後一步把 MFRMFR 用和 RSI 相同的方式壓縮到 0 到 100:MFRMFR 趨近無限大時 MFIMFI 趨近 100、MFR=1MFR=1(正負資金流相等)時 MFI=50MFI=50、MFRMFR 趨近 0 時 MFIMFI 趨近 0。

RSI 是把「平均上漲幅」對「平均下跌幅」做同一個 100−100/(1+RS)100 - 100/(1+RS) 的壓縮;mfi 把「漲跌幅」換成「帶量的資金流量」,等於成交量加權版的 RSI。要注意 mfi 只看 TPTP 比前一天高或低來分類,不看漲跌幅大小,所以一天小漲但爆量,也會被算成一大筆正資金流。本文的 mfi 讀數都由 finlab 套件 data.indicator("MFI") 在未還原的價量上算出;我們用上式手算台積電(2330)與聯發科(2454)2015 年起每一天的 MFI(14),和套件讀數完全相同。要注意的是沒有成交的日子:聯發科 2016-05-13 沒有成交,套件把它當成價格不變、成交量 0 的一天放進 14 日視窗;手算時若直接刪掉這一天,之後 13 個交易日的讀數會不同(最大差 17.8),照套件的方式補上這一天就完全一致。

在單股上看兩派 mfi 訊號:同一條規則,兩檔股票結果相反

公式講完,把訊號畫在真實股價上看。下圖取台積電(2330)2023-07 到 2024-06 約一年的走勢:上半部是未還原的收盤價,標出兩個教科書派別的買賣點;下半部是 MFI(14) 讀數與 20/50/80 三條線。

台積電 2330 的 mfi 超賣派與資金流入派買賣訊號示意圖,價格面板以三角形標出超賣派、以圓點與叉號標出資金流入派,下方面板為 MFI 指標讀數與 20 50 80 三條線

圖上畫的是兩派最常見的單股用法:

  • 超賣派(三角形):mfi 跌破 20 買進、升破 80 賣出。這一年台積電收盤從 579 元漲到 966 元(+66.8%),超賣買點只出現 3 次(2023 年 7 月 7 日、8 月 4 日、8 月 16 日),每一次買進後 20 個交易日內都再跌了 1.1% 到 3.1%,20 日後的報酬是 -1.2%、-1.1%、-0.2%。超買賣點 2 次(2023 年 11 月 21 日、12 月 27 日),都在 2024 年那段大漲之前就賣掉了。
  • 資金流入派(圓點與叉號):mfi 上穿 50 買、跌破 50 賣。這一年買 11 次、賣 10 次,平均一個多月就進出一輪;盤整段(如 2023 年下半年)mfi 在 50 上下反覆穿梭,買了又賣、賣了又買,來回的交易成本會把報酬磨掉。

聯發科(2454)同一段期間的結果相反:

聯發科 2454 的 mfi 超賣派與資金流入派買賣訊號示意圖,兩次超賣買點都落在波段低點,六次超買賣點多數在上漲途中

聯發科收盤從 691 元漲到 1,400 元(+102.6%)。超賣買點 2 次(2024 年 1 月 17 日、4 月 22 日)剛好都買在波段低點,20 個交易日後分別 +25.1% 與 +21.6%;但超買賣點有 6 次,多數在上漲途中,資金流入派買 8 次、賣 7 次,兩派合計 23 個訊號。同一條規則,在台積電是接刀,在聯發科是抄到底部。單股的例子挑哪一檔都講得通,所以下一節改用全市場橫截面回測,看這些用法平均下來賺不賺錢。

想自己重畫這張圖,下面這段程式碼用 finlab 的 data.indicator 取 mfi、再用穿越邏輯標訊號:

顯示程式碼
import matplotlib.pyplot as plt
import finlab
from finlab import data
 
finlab.login()  # finlab 會在需要資料時引導登入
 
# 取收盤價與 MFI(14)
close = data.get("price:收盤價")
mfi = data.indicator("MFI", timeperiod=14)
 
sid = "2330"
start, end = "2023-07-01", "2024-06-30"
m = mfi[sid]
prev = m.shift(1)  # 用完整歷史的前一天判斷穿越,窗內第一天也不會漏判
 
# 超賣派:MFI 由上跌破 20 = 買、由下升破 80 = 賣
oversold_buy = ((m < 20) & (prev >= 20)).loc[start:end]
overbought_sell = ((m > 80) & (prev <= 80)).loc[start:end]
 
# 資金流入派:MFI 上穿 50 = 買、跌破 50 = 賣
moneyflow_buy = ((m > 50) & (prev <= 50)).loc[start:end]
moneyflow_sell = ((m < 50) & (prev >= 50)).loc[start:end]
 
px = close[sid].loc[start:end]
mw = m.loc[start:end]
 
# 上下兩個面板:上畫價格與買賣點、下畫 MFI 與 20 / 50 / 80 三條線
fig, (ax_px, ax_mfi) = plt.subplots(
    2, 1, figsize=(12, 7), sharex=True, gridspec_kw={"height_ratios": [2, 1]}
)
ax_px.plot(px.index, px, color="#333", label=sid)
ax_px.scatter(px.index[oversold_buy], px[oversold_buy], marker="^", label="oversold buy")
ax_px.scatter(px.index[overbought_sell], px[overbought_sell], marker="v", label="overbought sell")
ax_px.scatter(px.index[moneyflow_buy], px[moneyflow_buy], marker="o", label="money flow buy")
ax_px.scatter(px.index[moneyflow_sell], px[moneyflow_sell], marker="x", label="money flow sell")
ax_px.legend()
 
ax_mfi.plot(mw.index, mw, color="#06b6d4", label="MFI(14)")
for level in (20, 50, 80):
    ax_mfi.axhline(level, ls="--", color="#888")
plt.tight_layout()
plt.show()

首發版的示意圖只用窗內的前一天判斷穿越,台積電資金流入派寫成賣 11 次、聯發科兩派合計 24 次;改用完整歷史判斷後是賣 10 次、合計 23 次。

散戶最常見的 mfi 用法,在台股 11 年幾乎沒賺到錢

在可交易宇宙(60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 大,排除 ETF、金融保險股、處置與全額交割股)裡,把幾種教科書用法各跑一次:MFI(14)、等權、月底換股、不擇時,從 2015-01-30 起算。

mfi 用法 研究段年化 / 月夏普 2022 年起年化 全期最大回撤
每月買 MFI 最低的 30 檔 2.1% / 0.20 10.4% -39.8%
月底 MFI < 20 的股票全部持有 1.6% / 0.18 7.3% -47.4%
最近 20 個交易日內曾由 20 以下上穿 20 -6.4% / -0.22 8.0% -61.0%
月底當天剛由 20 以下上穿 20 -1.9% / 0.00 18.8% -44.4%
每月買 MFI 最高的 30 檔 11.2% / 0.60 12.8% -43.2%
月底 MFI > 80 的股票全部持有 8.9% / 0.52 5.9% -46.6%
含息 0050 15.1% / 1.00 30.5% -34.0%

mfi 指標四種裸用法的研究段與 2022 年起年化報酬長條圖,mfi 最低 30 檔研究段 2.1%、月底 mfi 低於 20 全部持有 1.6%、近 20 日由 20 以下上穿 -6.4%、mfi 最高 30 檔 11.2%,兩段都低於含息 0050

最多人用的「mfi 低於 20 超賣就買」,研究段年化只有 1.6% 到 2.1%;等它由 20 以下翻上來再買,研究段反而虧錢。買 mfi 最高的 30 檔研究段 11.2%,是幾種用法裡最好的,但仍落後 0050 的 15.1%,2022 年起 12.8% 更遠低於 0050 的 30.5%。每一種裸用法在兩段都輸給 0050。

低 mfi 代表近期帶量下跌的日子占多數,在台股橫截面上,這群股票之後並沒有比較會反彈。Jegadeesh & Titman (1993) 發現過去 3 到 12 個月的贏家在之後幾個月傾向繼續贏、輸家繼續輸;mfi 衡量的是近期帶量的強弱,研究段「買最高」勝過「買最低」,方向和動能效應一致。延伸閱讀:技術面與基本面選股的差異。

首發版這一段有兩個數字要更正。一是「裸用全宇宙的最大回撤高達 -74.2%」:那是沒有切 2015 起評、從 2007 年開始持股(含 2008 年金融海嘯)的回撤,2015 年起買 mfi 最高 30 檔的最大回撤是 -43.2%。二是低 mfi 30 檔研究段寫成 1.1%,用新版 finlab 從同一天起算重跑是 2.1%。

我們也照首發研究的做法測了多空:在站上季線的股票裡,做多 MFI(14) 最高 30 檔、放空最低 30 檔。研究段多頭年化 12.3%、空頭 6.1%,價差每年約 +6.1%;2022 年起翻轉,空頭那一籃 19.6% 反而勝過多頭的 11.1%,價差每年約 -6.8%(未計放空成本與借券限制)。mfi 的高低排序撐不起多空組合。

mfi 在這套策略裡的兩個位置

把 mfi 當買賣訊號失效之後,首發版把它放進一套動能策略的兩個位置。這次重跑逐一檢查,兩個位置的作用大小差很多。

零件一:在動能前 12 檔裡剔除 mfi 偏低的股票

選股的主力是動能。先從可交易宇宙裡留下站上 60 日均線的股票,取其中 60 日報酬波動最低的 150 檔(不足 150 檔就全留),再要求站上 120 日均線,這就是選股池;池內用 20、60、120 日報酬的百分位平均(多窗動能)取最高 12 檔。mfi 在這裡只負責剔除:12 檔裡 MFI(21) 落在整個選股池最低 20% 的拿掉,其餘等權。

首發版寫「剔除池內波動最高的一半」與「剔除這 12 檔中 mfi 最低 20%」,和程式不符:程式是保留波動最低的 150 檔,141 個月底裡有 96 個月站上季線的股票本來就不到 150 檔,這一步沒有剔除任何股票;mfi 濾網比的是「在整個池子裡的排名」,不是 12 檔內部排名。動能前 12 名多半本來就在帶量上漲:每個月底入選股 MFI(21) 的中位數,141 個月再取中位數是 74.0(約在池內第 80 百分位),所以濾網很少動手:141 個月底一共只剔掉 57 檔次,42 個月有剔除,單月最多 3 檔,平均每月 0.4 檔。

版本 研究段年化 / 月夏普 2022 年起年化 / 月夏普 全期年化 全期最大回撤
完整策略 26.49% / 1.24 30.49% / 1.04 28.03% -36.33%
拿掉 mfi 濾網(動能前 12 檔全留) 25.76% / 1.23 30.60% / 1.02 27.64% -35.98%
池內改挑 MFI 最高 12 檔(不擇時) 21.08% / 0.87 21.18% / 0.79 20.94% -46.02%
池內挑多窗動能最高 12 檔(不擇時) 28.47% / 1.00 31.11% / 0.93 29.42% -49.68%

濾網讓全期年化多 0.4 個百分點、研究段多 0.7 個百分點,2022 年起反而少 0.1 個百分點。把剔除門檻從 0 掃到 50%(每 5% 一格),全期年化 25.3% 到 28.0%、研究段月夏普 1.14 到 1.24、2022 年起 0.94 到 1.04,20% 剛好是研究段與全期最高的那一格。拿 mfi 當主排序更差:同一個池子挑 MFI 最高的 12 檔,兩段年化都只有 21% 左右,回撤 -46.0%。

零件二:選股池內的 mfi 廣度當擇時開關

第二個位置才是 mfi 真正改變結果的地方。每天計算選股池內 MFI(21) 高於 50 的股票比例,本文稱為 mfi 廣度;月底換股時,如果廣度比 20 個交易日前低,整籃曝險乘 0.5、其餘放現金,否則滿倉,全程不加槓桿。

首發版把它寫成「全市場站上 mfi 中位的比例」,實際上只算選股池內的股票,而選股池本身就是站上季線與半年線的股票,所以廣度平常就很高:2015 年起的中位數 88.2%,九成的日子落在 77.3% 以上。真正用到的是它 20 日的變化,這個變化很常翻轉:日頻訊號一年轉向 38.8 次,只有 47.9% 的交易日是滿倉狀態。

選股池內 mfi 21 日指標高於 50 的股票比例與策略淨值的雙軸時序圖,2015 年 1 月到 2026 年 9 月,比例多數時間在 77% 到 96% 之間

回測只在月底讀一次。141 個月底有 78 個月判定減碼,平均曝險 72.3%。月底讀到的判定和下個月的報酬確實有關:判定減碼的 77 個月,不擇時的選股籃下個月平均 +1.0%(中位數 +1.3%),28 個月虧損;判定滿倉的 63 個月平均 +4.7%(中位數 +5.6%),18 個月虧損。同期 0050 是 +1.0% 對 +2.7%。

但這個關係離開月底就不成立:

  • 改成每天依廣度調整(同一個月底選股籃,月中一轉弱就減到五成):全期年化 17.35%、研究段 14.99%、2022 年起 21.05%,最大回撤 -38.70%,年換手由 7.4 倍升到 16.2 倍。
  • 不看廣度、每月換股時把部位固定設成 72.3%(和月底平均曝險相同):全期 22.01%、最大回撤 -39.15%。月底讀廣度的完整策略比它多賺 6.0 個百分點,所以月底的判定有內容,不只是降低平均持股。
  • 廣度改算整個流動性宇宙(比較接近首發版寫的「全市場」):研究段 26.77%、月夏普 1.28,2022 年起只剩 20.23%、0.87。
  • 改用 0050 年線擇時(0050 還原價站上 200 日均線才滿倉,同樣減到五成):全期 26.20%、最大回撤 -44.22%。

首發版用 Moreira & Muir (2017) 支撐這個開關。他們的波動管理組合在近期波動升高時減碼,前提是訊號能分出高波動的日子;這個廣度訊號分不出來:訊號轉弱的日子,0050 隔天報酬的年化波動 20.1%,滿倉的日子 19.4%,往後 20 個交易日的平均報酬 1.84% 對 1.61%。它的效果不是來自避開高波動。

減碼要減多少,下圖把廣度轉弱時保留的曝險從 0(全部轉現金)掃到 1(不擇時):

mfi 廣度轉弱時保留曝險比例從 0 到 1 的逐格掃描折線圖,比例越高全期年化越高、最大回撤越深,0 到 0.3 之間最大回撤都是負 30.6%

保留比例越高,全期年化由 24.3% 一路升到 29.5%,最大回撤也由 -30.6% 加深到 -50.4%;研究段月夏普在 0.2 到 0.3 最高(1.29),不擇時是 1.01,2022 年起在 0.93 到 1.07 之間。首發版說「把這個係數在合理區間內微調,Sharpe 只在小數點後一兩位移動」,掃完是研究段 1.01 到 1.29。

完整策略:mfi 濾網+廣度擇時純技術選股

把上面的規則寫完整,是一套可執行、完全不含基本面的純技術策略:

  1. 可交易宇宙:60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 名;代號剛好 4 碼數字,排除 00 開頭的 ETF、金融保險股、處置與全額交割股。
  2. 選股池:宇宙內站上 60 日均線的股票,取 60 日報酬波動最低的 150 檔(不足全留),再要求站上 120 日均線。
  3. 主排序(多窗動能):20、60、120 日報酬各自取池內百分位後平均,取最高 12 檔。
  4. mfi 濾網:12 檔裡 MFI(21) 落在選股池最低 20% 的剔除,其餘等權。
  5. 擇時(mfi 廣度):選股池內 MFI(21) 高於 50 的比例,若比 20 個交易日前低,整籃乘 0.5、其餘現金;否則滿倉。
  6. 換股:每月最後一個交易日換股一次,選股與擇時都只在換股日讀取,月中不檢查。

選股與擇時的完整程式碼:

顯示程式碼
import numpy as np
import pandas as pd
import finlab
from finlab import data
from finlab.backtest import sim
 
finlab.login()  # finlab 會在需要資料時引導登入
data.truncate_end = "2026-09-30"  # 文章數字的資料截止日
 
# 1) 載入價量資料
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
amount = data.get("price:成交金額")
 
# 2) 可交易宇宙:60 日均量 > 100 萬股、收盤 > 10 元、成交金額前 300 大,
#    排除 ETF、非 4 碼代號、金融保險股、處置與全額交割股
cat = data.get("security_categories")
financial = set(cat.loc[cat["category"].astype(str).str.contains("金融|保險|銀行", na=False), "stock_id"].astype(str))
common_cols = [
    sid for sid in close.columns
    if len(sid) == 4 and sid.isdigit() and not sid.startswith("00") and sid not in financial
]
flagged = data.get("etl:is_flagged_stock")
universe = (
    (volume.rolling(60, min_periods=20).mean() > 1_000_000)
    & (close > 10)
    & amount.rolling(60, min_periods=20).mean().is_largest(300)
)[common_cols]
universe = universe & ~flagged.reindex_like(universe).fillna(False).astype(bool)
 
# 3) 選股池:站上季線的股票裡,60 日波動最低 150 檔,再要求站上半年線
uptrend = universe & (close > close.rolling(60).mean())
vol60 = close.pct_change().rolling(60, min_periods=30).std()
lowvol150 = vol60.where(uptrend).rank(axis=1) <= 150
pool = uptrend & lowvol150 & (close > close.rolling(120).mean())
 
# 4) 多窗動能:20 / 60 / 120 日報酬各取池內百分位後平均,取最高 12 檔
ranks = [(close / close.shift(w) - 1).where(pool).rank(axis=1, pct=True) for w in (20, 60, 120)]
momentum = (ranks[0] + ranks[1] + ranks[2]) / 3
top12 = momentum.rank(axis=1, ascending=False) <= 12
 
# 5) MFI 濾網:12 檔裡 MFI(21) 落在整個選股池最低 20% 的剔除,其餘等權
mfi = data.indicator("MFI", timeperiod=21)
mfi_rank = mfi.where(pool).rank(axis=1, pct=True)
basket = top12 & (mfi_rank > 0.20)
weights = basket.astype(float)
weights = weights.div(weights.sum(axis=1).replace(0, np.nan), axis=0).fillna(0.0)
 
# 6) 擇時:選股池內 MFI(21) > 50 的比例比 20 個交易日前低,整籃乘 0.5
breadth = (mfi > 50).where(pool).sum(axis=1) / pool.sum(axis=1).replace(0, np.nan)
scale = np.where(breadth >= breadth.shift(20), 1.0, 0.5)
weights = weights.mul(pd.Series(scale, index=weights.index), axis=0)
 
# 7) 每月最後一個交易日換股(手續費打三折,另扣賣出證交稅 0.3%)
report = sim(weights.loc["2015-01-01":], resample="M", fee_ratio=1.425 / 1000 * 0.3, upload=False)

這段程式碼和文末可下載的 strategy.py 是同一套規則;資料截到 2026-09-30 實跑,研究段、2022 年起與全期的年化、月夏普和最大回撤都和下一節的表相同。下載版另外印出逐層建構(5 層加每天調整擇時的對照)、換股日比較、逐年報酬與首發後的逐月報酬。

完整策略的真實績效

所有數字從同一天(2015-01-30,策略第一個淨值日)起算:

指標 研究段(2015–2021) 2022 年起 全期 含息 0050 研究段 含息 0050 2022 年起 含息 0050 全期
年化報酬 26.49% 30.49% 28.03% 15.09% 30.51% 21.17%
月夏普 1.24 1.04 1.09 1.00 1.21 1.07
月索提諾 2.34 1.83 1.97 1.47 2.44 1.85
最大回撤 -30.62% -36.33% -36.33% -28.22% -33.96% -33.96%

研究段年化、月夏普與月索提諾勝 0050,最大回撤較深。2022 年起年化 30.49% 對 30.51% 打平,月夏普、月索提諾與最大回撤都輸 0050。全期年化領先 0050 6.9 個百分點,月索提諾 1.97 對 1.85 較好,月夏普 1.09 對 1.07 差不多,最大回撤 -36.3% 比 -34.0% 深;年化波動 25.9%,0050 是 19.8%。年換手約 7.4 倍,11 年多共 1,615 筆交易。

「2022 年起」這一段,首發時挑參數的門檻就包含它的表現,看過這段才定案,所以本文不把它稱為樣本外。真正選完參數才出現的資料,是首發資料截止日 2026-06-09 之後的四個月,見後面「2026-06-09 之後」一節。

下面是完整互動式回測:月報酬熱力圖、權益曲線、年度績效都可以直接在文章裡操作:

逐層拆開:趨勢閘、mfi 濾網與廣度擇時各自的作用

從宇宙內最單純的動能 12 檔開始,一次加一個條件;再從完整策略各拿掉一個零件。其餘設定不變,同一天起算:

版本 研究段年化 / 月夏普 2022 年起年化 / 月夏普 全期年化 全期最大回撤
宇宙內多窗動能最高 12 檔(等權、不擇時) 25.84% / 0.94 11.92% / 0.58 19.95% -50.53%
再限站上季線 23.30% / 0.88 14.74% / 0.64 19.70% -49.67%
再加低波 150 檔與站上半年線 28.47% / 1.00 31.11% / 0.93 29.42% -49.68%
再加 mfi 濾網(不擇時) 29.34% / 1.01 30.02% / 0.93 29.51% -50.37%
再加 mfi 廣度擇時(完整策略) 26.49% / 1.24 30.49% / 1.04 28.03% -36.33%
完整策略拿掉低波 150 檔 21.85% / 1.06 23.53% / 0.89 22.49% -41.18%
完整策略拿掉半年線 27.31% / 1.29 26.65% / 0.95 26.98% -36.44%
選股池全部持有(等權、不擇時) 14.32% / 0.78 19.65% / 0.84 16.37% -36.93%

mfi 策略逐層建構長條圖,比較宇宙內動能 12 檔、再限站上季線、再加低波與半年線、再加 mfi 濾網與再加廣度擇時五個版本的全期年化、全期最大回撤與研究段及 2022 年起月夏普

從這張表讀出的事:

  • 報酬來自「選股池內的動能」。 宇宙內直接挑動能最高 12 檔,2022 年起只有 11.9%;限定在站上季線、低波、站上半年線的池子裡再挑,2022 年起是 31.1%,全期由 20.0% 升到 29.4%。池子全部持有只有 16.4%,所以池子和動能排序兩者都需要。
  • 低波 150 檔是最重要的一刀。 完整策略拿掉它,全期年化由 28.0% 掉到 22.5%、2022 年起月夏普 0.89。保留檔數也很敏感:改成 100 檔全期 19.1%、125 檔 23.8%、175 檔 23.2%,150 檔是研究段月夏普最高的那一格。
  • mfi 濾網幾乎沒有作用,數字見前面「零件一」。
  • mfi 廣度擇時用報酬換回撤。 加上擇時,全期年化由 29.5% 降到 28.0%,最大回撤由 -50.4% 降到 -36.3%,研究段月夏普由 1.01 升到 1.24、2022 年起由 0.93 升到 1.04。這套策略的月夏普能站上 1.0,靠的是這一層。
  • 半年線讓 2022 年起變好、研究段變差。 拿掉半年線研究段月夏普 1.29 較高,2022 年起 0.95 跌破 1.0。

換股日挪到月中,結果差很多

同一套規則、同一個部位,只把讀取部位的日子從月底改到每月 5、10、15、20、25 日(遇假日取該月在這天以前的最後一個交易日;該月在這天以前沒有交易日就不換股,5 日有 3 個月、10 日有 1 個月因此沒換),其餘完全不變:

換股日 研究段年化 / 月夏普 2022 年起年化 / 月夏普 全期年化 全期最大回撤
每月 5 日 9.51% / 0.51 32.03% / 0.98 18.08% -50.95%
每月 10 日 13.34% / 0.65 10.22% / 0.54 12.02% -47.83%
每月 15 日 12.02% / 0.52 17.14% / 0.70 14.04% -43.95%
每月 20 日 8.18% / 0.42 16.19% / 0.77 11.38% -37.07%
每月 25 日 13.50% / 0.63 22.18% / 0.76 16.89% -51.33%
月底(本文) 26.49% / 1.24 30.49% / 1.04 28.03% -36.33%

mfi 策略換股相位長條圖,每月 5 日到 25 日換股的研究段年化 8.2% 到 13.5%,月底換股 26.5%,另列 2022 年起年化與不擇時的研究段年化

(月底那一列用「只在月底讀取部位」的寫法重算,全期年化與主表相同,用來確認這個比較的做法沒有偏差。)

月底以外的五個換股日,全期年化 11.4% 到 18.1%,全部輸給 0050 的 21.2%;研究段 8.2% 到 13.5%,月夏普都低於 0.7;2022 年起只有 5 日的 32.0% 比月底高,其餘 10.2% 到 22.2%。

把擇時拿掉再比一次,可以看出差距從哪裡來。不擇時的籃子,月底換股全期 29.51%、研究段 29.34%,每月 5 到 25 日是全期 16.0% 到 24.7%、研究段 14.3% 到 20.6%,選股本身就有換股日的落差;套上 mfi 廣度擇時後,月底只少 1.5 個百分點(29.51% → 28.03%),其他五個日子少 3.7 到 10.6 個百分點(15 日由 24.67% 降到 14.04%)。廣度擇時只有在月底讀取時代價很小,在月中讀取都明顯拖累報酬;改成每天調整也一樣差(全期 17.35%)。

這叫換股時點運氣(rebalance timing luck)。Hoffstein, Faber & Braun (2020) 分析 smart beta 指數時指出,規則完全相同、只差換股日的組合,績效可以有明顯落差。本文的參數是在研究段用月底換股挑出來的,優勢又只出現在月底這一組,所以研究段 26.5% 應該看成「月底換股這一組」的結果。我們沒有找到月底換股特別有效的原因。同系列的 KD 指標回測、RSI 指標回測與 CCI 指標回測也有同樣的問題,這個檢查是首發版沒有做的。

參數最佳化:mfi 週期、剔除門檻與廣度參數

mfi 週期與剔除門檻排成 4 × 3 網格(和首發版同一組軸),每一格都跑完整策略;改 mfi 週期時,選股濾網與廣度用的是同一個 mfi,會一起換。研究段月夏普:

mfi 週期乘以剔除門檻四乘三網格的研究段月夏普色溫圖,12 格在 1.02 到 1.24 之間,mfi 21 剔最低 20% 最高

同一張網格的 2022 年起月夏普:

同一張 mfi 週期乘以剔除門檻網格的 2022 年起月夏普色溫圖,只有 mfi 21 那一列三格在 1.0 以上,mfi 28 那一列只有 0.55 到 0.60

研究段 12 格在 1.02 到 1.24 之間,看起來是一片高原;2022 年起只有 mfi 21 那一列三格站上 1.0(1.02 到 1.04),mfi 9 是 0.83 到 0.89、mfi 14 是 0.87 到 0.96、mfi 28 只剩 0.55 到 0.60(年化 12.1% 到 13.8%)。首發版寫「12 格研究段 0.98 到 1.20、整片高原」,只看了研究段。首發版拿來當「相鄰高原格」的 mfi 9、剔 30%,重跑後研究段 1.18、2022 年起 0.89、最大回撤 -39.0%。

再把 mfi 週期從 9 到 35 逐格掃一遍,分成兩種:選股濾網與廣度一起換,以及只換選股濾網、廣度維持 MFI(21):

mfi 週期 9 到 35 日逐格掃描的月夏普折線圖,選股與廣度同步換週期時研究段與 2022 年起都大幅跳動,只換選股濾網週期時研究段 1.16 到 1.37、2022 年起 0.96 到 1.07

  • 只換選股濾網的週期:研究段月夏普 1.16 到 1.37、2022 年起 0.96 到 1.07(27 格有 19 格高於 1.0,另 2 格是 0.999),全期年化 26.5% 到 31.9%。濾網本來就很少動手,換週期影響不大。
  • 選股與廣度一起換:研究段 0.89 到 1.24,2022 年起 0.58 到 1.11,27 格只有 19、20、21、23 日四格在 1.0 以上;相鄰兩格常差 0.2 以上(21 日 1.04、22 日 0.91,12 日只有 0.58)。
  • 廣度回看天數 5 到 40 日:研究段 0.95 到 1.41、2022 年起 0.81 到 1.16,36 格有 11 格高於 1.0(另 2 格是 0.997),全期年化 19.9% 到 30.2%。
  • 廣度門檻 30 到 70:50 的研究段月夏普 1.24 是 9 格裡最高,次高的 55 只有 1.13,最低 0.73。
  • 持股 6 到 24 檔:研究段 0.98 到 1.30、2022 年起 0.92 到 1.07;檔數越多回撤越淺(24 檔 -29.5%)、全期年化越低(24 檔 20.4%)。

以月夏普看,選股端(剔除門檻、持股檔數、mfi 濾網週期)不太敏感;敏感的是廣度那一層的參數與換股日,2022 年起能站上 1.0 的組合集中在目前這組參數附近。依季度刷新的規則,參數不因事後看到的鄰格而更換。

2026-06-09 之後:首發後的新資料

首發版資料截止日 2026-06-09 之後的四個月,是這套參數選定後才出現的資料:

區間 策略 不擇時 廣度每天調整(對照) 含息 0050
2026 年 7 月 -16.1% -32.2% -26.5% -4.0%
2026 年 8 月 +6.1% +13.2% +9.8% +3.3%
2026 年 9 月 +6.3% +6.7% +2.5% +5.5%
06-09 → 09-30 合計 -0.3% -9.2% -9.1% +8.9%

6 月 9 日到 6 月 30 日策略 +5.4%、0050 +4.2%。

首發資料截止日 2026-06-09 之後 mfi 策略、廣度每天調整的對照組與含息 0050 的淨值走勢圖,策略 7 月下跌、8 月與 9 月部分收復

這四個月發生的事:

  • 6 月 30 日換股時廣度判定減碼(廣度 73.8%,比 20 個交易日前低 15.4 個百分點),7 月只有五成部位。7 月 1 日進場的 12 檔持有到 8 月 3 日全部虧損,中位數 -29.8%,最差的國巨(2327)-51.6%,表現最好的藥華藥(6446)也 -5.0%。不擇時的籃子 7 月 -32.2%,策略 -16.1%,這是 2015 年以來減碼少賠最多的一個月。同期 0050 從 7 月 1 日高點跌到 7 月 30 日 -14.0%,整月 -4.0%。
  • 7 月 31 日仍判定減碼(廣度 59.3%),8 月同樣五成部位,策略 +6.1%,不擇時的籃子 +13.2%。8 月 31 日廣度回到 97.7%,9 月滿倉;9 月 30 日又判定減碼,2026-09-30 換股日持有 11 檔、五成部位。
  • 淨值從 7 月 3 日高點到 7 月 30 日回落 20.2%,9 月底距高點 -7.4%。2026 年 7 月 -16.1% 不是這套策略最差的單月,2025 年 3 月是 -16.8%。

2022 年起的月夏普因此從同截止日的 1.10 降到 1.04。同截止日比對:首發程式在首發用的 finlab 2.0.13 截到 2026-06-09,研究段 25.25%、2022 年起 31.72% / 1.06、全期 27.68%,和首發版逐位相同;同一支程式換成 finlab 2.2.21 是 26.49%、33.03% / 1.10、28.93%(第一個淨值日也由 2015-02-26 提前到 01-30),新版程式截到同一天的數字和它完全相同。所以首發版到本文的差距分成兩塊:套件版本讓三段都高出約 1.2 到 1.3 個百分點(原因沒有逐項查明),新資料讓 2022 年起由 33.03% / 1.10 降到 30.49% / 1.04。

回測方法與口徑

  • 交易成本:finlab sim(),手續費 0.1425% 打三折,賣出另扣證交稅 0.3%。改用 sim() 預設手續費(不打折),全期年化 26.14%、2022 年起月夏普 0.99;原設定的三折手續費再加倍、賣出稅率拉到 0.6%,全期 24.42%、2022 年起月夏普 0.94。兩種成本設定下,2022 年起月夏普都跌破 1.0。
  • 滑價:未額外假設,實際成交衝擊取決於資金規模與流動性,本文未估算容量。
  • 股票池:上市櫃普通股,60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 名;代號必須剛好是 4 碼數字(排除權證、特別股與 6 碼代號),排除 00 開頭的 ETF、金融保險股、處置與全額交割股。KY 股的代號也是 4 碼數字,沒有排除;首發版寫「排除 KY」與程式不符。首發版的宇宙寫法(代號前 4 碼是數字就放行)跑出來的結果與本文完全相同,換股日從來沒有持有過非 4 碼代號。
  • 前視偏差:均線、60 日波動、多窗動能、個股 MFI 與廣度都只用當天(含)以前的價量,月底收盤後決定部位,下一個交易日成交。完全不用財報或月營收。
  • mfi 計算:MFI(21) 用 finlab data.indicator("MFI")(TA-Lib,未還原的價格與成交股數)。未還原價格遇到除權息,當天典型價格下跌,會被算成負資金流。我們在看任何回測結果之前先檢查了廣度:選股池內沒有缺值,2025 年 6 月 0050 一拆四那段期間廣度沒有跳動(ETF 不在選股池內),但 7、8 月除權息旺季,未還原版的廣度平均比還原版低 1.0 到 1.4 個百分點,141 個月底有 3 個月的判定不同(2016-06、2018-08、2023-05)。本文維持首發的未還原價;選股濾網與廣度都改用還原價時,全期 27.19%、2022 年起 28.95% / 1.00,只有廣度改還原價時全期 27.65%、2022 年起同樣 1.00。
  • 權重:等權,單一個股不另設上限;每個月底名單中位數 12 檔,141 個月有 58 個月不到 12 檔(最少 9 檔)。減碼月份整籃乘 0.5,其餘放現金。
  • 周轉率:年換手約 7.4 倍,11 年多共 1,615 筆交易。
  • 研究段與 2022 年起:研究段 2015–2021;2022 年起這段在首發選參數時已經看過。選定後才出現的資料只有 2026-06-09 之後的四個月。
  • 生存者偏差:宇宙每天依當時的資料篩選,2015-01-30 有收盤價、到 2026-09-30 已經沒有收盤價的 4 碼普通股共 142 檔,在當時都可能被選入。
  • 首發後補做的檢查:換股日(每月 5 到 25 日,含不擇時的版本)、每天調整擇時與固定曝險的對照組、逐層建構與零件拆除、mfi 濾網實際剔除檔數、mfi 週期 9 到 35 日(兩種換法)與剔除門檻、持股檔數、廣度回看天數、減碼比例、廣度門檻、低波保留檔數的逐格掃描、還原價對照、多空價差、月營收過濾與年線擇時對照。

不同年度的表現:12 年贏 8 年

年度 策略 含息 0050 不擇時 廣度每天調整
2015(1/30 起) 18.0% -7.9% -1.2% -2.8%
2016 3.4% 19.6% 7.6% -0.2%
2017 30.6% 18.1% 36.8% 15.8%
2018 -1.1% -4.9% -11.1% -14.3%
2019 23.9% 33.5% 38.4% 24.5%
2020 59.6% 31.1% 111.3% 52.5%
2021 62.8% 21.9% 56.6% 43.5%
2022 -13.4% -21.4% -20.1% -16.5%
2023 66.4% 27.5% 84.3% 58.8%
2024 7.9% 48.6% 0.4% -0.5%
2025 10.8% 36.8% 23.0% 23.8%
2026(至 9/30) 104.0% 74.3% 89.5% 50.8%

策略 12 年裡贏 0050 的有 8 年,輸的是 2016、2019、2024 與 2025 年;2024、2025 年分別落後 40.7 與 26.0 個百分點,2024 年連不擇時的籃子都只有 0.4%,落後來自選股。2022 年 0050 跌 21.4%,策略 -13.4%,那一年 12 個月底有 10 個判定減碼;不擇時的籃子 -20.1%。和不擇時相比,廣度擇時在 2015 年多賺 19.2 個百分點、2018 年 10.0 個百分點、2026 年至 9 月底 14.5 個百分點,在 2020 年少賺 51.7 個百分點、2019 年 14.5 個百分點、2023 年 17.9 個百分點。2020 年差距最大的一筆是 3 月底判定減碼,4 月不擇時的籃子漲 35.4%,策略只有 17.6%。每天調整的版本只有 2019 與 2025 年比月底讀取好。

加上月營收 YoY 會更好嗎:實跑結果兩段都較差

首發版這一段說加營收過濾「會大幅縮小可選池,反而犧牲動能的爆發力」,沒有放回測數字。這次用本文的策略實跑:選股前先限定月營收年增率大於 0 的股票(用 finlab 月營收資料的公布日索引對齊,只用當時應已公布的數字),其餘不變。研究段年化 22.27%、月夏普 1.06,2022 年起 24.60%、0.90,全期 23.16%、最大回撤 -33.13%。兩段都比純技術版差,最大回撤淺 3.2 個百分點;「縮小可選池」是不是原因,本文沒有逐段驗證。本文主策略維持純技術面。基本面與技術面如何分工,可延伸看技術面與基本面怎麼分工選股。

用 mfi 指標最常踩的四個陷阱

把前面的回測整理成可操作的避雷清單:

  1. 把 20/80 當進出開關。 月底 MFI 低於 20 的股票全部持有,研究段年化 1.6%;由 20 以下翻上來再買,研究段 -6.4%。單股上同一條規則有時接刀、有時抄到底,平均下來贏不了 0050。
  2. 拿 mfi 當選股排序。 在同一個選股池挑 MFI 最高的 12 檔,兩段年化都只有 21% 左右、回撤 -46.0%;換成多窗動能是 28.5% 與 31.1%。
  3. 以為廣度擇時隨時在保護。 回測只在月底看一次,日頻訊號一年轉向近 39 次;照字面每天調整,全期年化降到 17.4%。換股日從月底挪到月中,全期只剩 11.4% 到 18.1%。
  4. 拿 mfi 建多空。 研究段價差每年 +6.1%,2022 年起翻成 -6.8%。

前兩個陷阱是把 mfi 用在個股進出或排序,全期年化都沒贏 0050;第三個是擇時的讀取方式,換股日或檢查頻率一改,全期年化就少約 10 到 17 個百分點;第四個是方向,多空價差在 2022 年起翻成負的。各擺盪指標的用法差異,可再看 RSI、MACD、KD 三個指標的比較。

三項穩健性驗證:重跑到 2026 年 10 月

這裡驗證本文的完整策略:站上季線與半年線、波動較低的股票裡,取多窗動能最強 12 檔,剔除其中 MFI(21) 池內分位最低 20% 後等權,MFI 廣度 20 日變化轉負時減碼到五成,每月換股。我們在 2026-10-27 用本文附的 strategy.py 重跑三項檢查;2026-10-28 修正下載程式與文章引擎的差異後,用和新版 strategy.py 相同的規則同口徑重跑(finlab 2.2.21,資料截至 2026-10-27),下面是修正後的數字;把新版 strategy.py 的 DATA_END 改成 "2026-10-27"、FEE 改成 1.425 / 1000,可以重現下表「全期」那一列。三項檢查統一採 sim() 預設手續費 0.1425% 與證交稅 0.3%;原程式手續費三折的結果另列於成本對照表。「贏」指日夏普高於同期 0050 含息買進持有(etl:adj_close 還原價、純算術計算、不扣成本)。兩邊日夏普皆為日報酬平均除以標準差、乘上 √252,不扣無風險利率。

檢查 標準 結果
鄰近參數 MFI 週期(17、21、25)乘上動能前幾檔(10、12、14),9 組至少 7 組贏 0/9 組贏,不過
前後兩段 2015-01-30 到 2020-12-11、2020-12-14 到 2026-10-27 兩段都贏 前段 0.90 對 0.89,後段 1.17 對 1.24,不過
交易成本 原參數、sim() 預設成本 日夏普 1.05 對 1.08,不過

mfi 策略鄰近參數 9 組日夏普熱圖:0 組高於同期 0050 含息的 1.08,原參數日夏普 1.05,mfi 25 那一欄只有 0.76 到 0.82

9 組參數的日夏普(括號內是年化報酬,粗體是原文參數):

動能前幾檔 \ MFI 週期 17 21 25
14 0.87(年化 19.7%) 1.00(年化 23.8%) 0.76(年化 17.6%)
12 0.94(年化 22.1%) 1.05(年化 25.7%) 0.82(年化 19.9%)
10 0.90(年化 21.5%) 1.03(年化 25.9%) 0.79(年化 19.4%)

前後兩段與全期:

期間 策略年化 策略日夏普 0050 含息年化 0050 日夏普
前段 2015-01-30 到 2020-12-11 18.0% 0.90 13.5% 0.89
後段 2020-12-14 到 2026-10-27 33.7% 1.17 28.0% 1.24
全期 2015-01-30 到 2026-10-27 25.7% 1.05 20.5% 1.08

前後兩段是把整段期間從中點對半切。上文的研究段與 2022 年起以 2022 年初為界,照這個切法,2015 到 2021 年日夏普 1.06 對 0050 的 0.96,2022 年起 1.04 對 1.22。上文多用月夏普,跟這裡的日夏普算法不同,數字不能直接比。

交易成本對照(原參數):

成本設定 年化 日夏普 最大回撤
不扣成本 31.3% 1.22 -34.9%
sim() 預設:手續費 0.1425%、證交稅 0.3% 25.7% 1.05 -37.0%
原文設定:手續費打三折 27.6% 1.11 -36.3%
0050 含息買進持有(同期) 20.5% 1.08 -34.0%

策略年化領先 0050 約 5.2 個百分點,風險調整後小輸。9 組鄰近參數全部輸,MFI 週期拉長到 25 日時日夏普掉到 0.76 到 0.82,和上一節廣度參數敏感的結果一致;前段(2015 到 2020 年)日夏普 0.90 對 0.89 小贏,後段 1.17 輸 1.24,三項都沒過。照原文手續費三折,日夏普 1.11 略高於 0050 的 1.08。

這一段 2026-10-27 第一次上線時,用的是當時可下載的 strategy.py。它和文章的回測引擎有一處不同:季線用 rolling(60, min_periods=20),上市不到 60 個交易日的新股也有季線,會擠進「波動最低 150 檔」的排名。當時的數字是原參數年化 25.0%、日夏普 1.02,鄰近參數 9 組 0.77 到 1.03,前段 0.88 對 0.89、後段 1.14 對 1.24;我們用同一支舊程式逐格重現了這些數字,換成和引擎相同的季線後就是上面的表,三項的結論都沒有改變。照三折手續費跑到首發的 2026-06-09,新版是全期年化 28.9%、月夏普 1.12,舊版是 28.2%、1.09。

策略的限制與取捨

  • 換股日運氣:研究段 26.5% 只出現在月底換股這一組,挪到每月 5 到 25 日研究段只剩 8.2% 到 13.5%,全期 11.4% 到 18.1%,全部輸給 0050。實際操作若無法固定在月底最後一個交易日換股,不應期待接近本文的數字。
  • 廣度擇時的參數很敏感:廣度的 mfi 週期、回看天數與門檻稍微一動,2022 年起月夏普就在 0.6 到 1.2 之間跳動;這次重跑的三項驗證裡,9 組鄰近參數也全部輸給 0050。
  • mfi 的作用集中在擇時:剔除濾網平均每月只拿掉 0.4 檔,報酬的主要來源是選股池內的多窗動能;擇時讓回撤由 -50.4% 降到 -36.3%,代價是每年少賺約 1.5 個百分點。
  • 近年落後大盤:2022 年起年化 30.5% 與 0050 打平,月夏普 1.04 對 1.21;2024、2025 年連續兩年大幅輸 0050;首發之後四個月 -0.3% 對 +8.9%。
  • 回撤比 0050 深:全期最大回撤 -36.3%,0050 是 -34.0%;年化波動 25.9% 對 19.8%。
  • 高周轉、成本敏感:年換手約 7.4 倍,改用 sim() 預設手續費全期年化 26.1%、2022 年起月夏普 0.99;實單滑價會進一步侵蝕。
  • 容量:每月只持有約 12 檔,宇宙限前 300 大成交金額,回測未逐筆估算滑價與市場衝擊。

自己跑一次

FinLab Skill 可以讓你的 AI 助理一步步帶你安裝、抓台股資料、重現這篇的回測:

裝好之後,下載本文的 strategy.py 與 data.csv,即可在自己的環境重跑、改參數、換選股基底。strategy.py 會印出本文的主表、逐層建構、換股日比較、逐年報酬與首發後的逐月報酬;data.csv 除了策略與 0050 的淨值,也附上每天的 mfi 廣度與滿倉/減碼判定。把 DATA_END 改成 None 就能用最新資料重跑。登入只需在程式裡寫 finlab.login(),套件會在需要資料時引導你完成登入。想延伸成更完整的量化流程,可參考量化交易總覽與程式交易是什麼。同樣把成交量放進指標的還有 OBV 能量潮回測;想一次看完常用技術指標在台股的回測結論,可讀技術指標台股回測總覽。籌碼面的資金動向,可以用三大法人買賣超資料與分點主力買超交叉驗證。

常見問題

Q:mfi 指標是什麼?和 RSI 差在哪? mfi(資金流量指標)是「帶成交量的 RSI」。RSI 只看價格漲跌,mfi 把每天的典型價格乘上成交量,依典型價格比前一天高或低分成正、負資金流,再換算成 0 到 100 的讀數。它只看典型價格的漲跌方向,不看漲跌幅大小,所以爆量的小漲日也會被算成一大筆正資金流。

Q:mfi 低於 20 真的代表超賣、會反彈嗎? 在台股橫截面上不一定。月底 MFI(14) 低於 20 的股票全部持有,研究段(2015–2021)年化 1.6%;每月買 MFI 最低的 30 檔是 2.1%,同期含息 0050 是 15.1%。2022 年起這兩種寫法是 7.3% 與 10.4%,仍遠輸 0050 的 30.5%。單股上有時有效(聯發科 2024 年兩次超賣都買在低點),有時是接刀(台積電 2023 年三次超賣買進後都再跌)。

Q:那 mfi 高於 80 就一定要賣嗎? 回測不支持。月底 MFI 高於 80 的股票全部持有,研究段年化 8.9%,比低於 20 的 1.6% 好;每月買 MFI 最高的 30 檔是 11.2%。不過兩者都輸 0050,也不建議把高 mfi 當買進理由。

Q:mfi 可以單獨拿來當買賣訊號嗎? 不建議。超賣買、超買賣、由 20 以下翻上來買,或用 mfi 高低排序選股,在台股回測都輸 0050(研究段年化 -6.4% 到 11.2%)。本文的用法是把 mfi 放在一套動能策略裡:剔除動能前 12 檔裡 mfi 偏低的股票(作用很小),以及用選股池內的 mfi 廣度在月底決定滿倉或五成部位。

Q:mfi 的參數(timeperiod)要設多少?14 是最好的嗎? 14 是 TA-Lib 預設值,本文用 21。只換選股濾網的週期,9 到 35 日的研究段月夏普都在 1.16 到 1.37,結果不太敏感;但廣度也跟著換週期時,2022 年起月夏普在 0.58 到 1.11 之間跳動,只有 19、20、21、23 日四格站上 1.0。21 日不是穩定高原上的一點,換別的週期要先自己重跑。

Q:mfi 和 KD、RSI 一起用會更好嗎? mfi、RSI、KD 都是擺盪指標,mfi 多算了成交量,三者資訊高度重疊。本文沒有測試把它們疊在一起的效果;各指標在台股的用法可參考RSI、MACD、KD 的差異與用法與同系列的單篇回測。

Q:為什麼擇時用選股池內的 mfi 廣度,不用全市場? 首發版就是用選股池內的比例,文章誤寫成全市場。實測改算整個流動性宇宙的版本,研究段月夏普 1.28,但 2022 年起只剩 0.87、年化 20.2%。選股池內的廣度平常就在 77% 到 96% 之間,策略看的是它比 20 個交易日前高還是低。

Q:這套 mfi 策略適合誰? 適合想主動選股、能固定在每月最後一個交易日換股、接受 -36% 等級回撤與較高換手成本的人:全期年化 28.0%、月索提諾 1.97,勝含息 0050 的 21.2%、1.85。要注意三件事:2022 年起年化與 0050 打平、月夏普較低;換股日挪到月中,全期只剩 11.4% 到 18.1%;廣度那一層的參數很敏感。偏好低周轉、被動持有的人,買進持有含息 0050 更省心。


最後更新:2026-10|回測區間:2015-01-30 ~ 2026-09-30|作者:FinLab 量化研究團隊(經量化研究員審閱)

本文僅供量化研究與教學用途,所有回測數字均由 finlab 套件在真實台股資料上產出,過去績效不代表未來表現,不構成投資建議。mfi 剔除濾網加廣度擇時策略全期最大回撤 -36.3%,換股日改到每月 5 到 25 日時全期年化只剩 11.4% 到 18.1%,實際交易前請自行評估風險、滑價與交易容量。

FinLab AI

想建立自己的策略?

用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案

免費開始

更多技術指標研究

查看全部