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

均線怎麼用才對?台股 11 年回測:靠近新高選股+20 日線濾網的純技術策略

均線怎麼用才對?台股 11 年回測:黃金交叉與乖離選股研究段年化只有 5%~12%。改挑最靠近 52 週新高的 20 檔、換股日用 20 日線過濾,研究段年化 26.5% 大勝 0050;但 2022 年起 24.8% 落後 0050 的 30.5%,2026 年 7 月單月跌 24.4%,附衰退追蹤。

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

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

在 Studio 重跑
均線真用法 CAGR 25.8% Sharpe 1.09

均線在台股的正確用法:拿長均線找趨勢,短均線只當換股日的濾網

先用一張表回答你搜尋「均線」時最想知道的事:

你想知道的 本文用真實台股回測的回答
均線是什麼 N 日收盤價的算術平均;常用 20 日(月線)、60 日(季線)、120 日(半年線)、240 日(年線)
黃金交叉買進有效嗎 拿來選股不行。近 20 日剛黃金交叉的股票取 30 檔,研究段(2015-2021)年化 9.3%、最大回撤 -46.4%,含息 0050 同期 15.1%
跌破均線抄底有效嗎 不行。買 20 日乖離最負的 30 檔,研究段年化 5.4%、月夏普 0.33
均線能拿來選股嗎 能,但要換尺度:看收盤離自己過去 280 個交易日最高收盤多近(約一年多的高點),挑最靠近的 20 檔,研究段年化 25.2%、月夏普 1.33;加上換股日 20 日線濾網為 26.5%、1.34
短均線該放哪裡 當濾網:換股日收盤在自身 20 日線之下的入選股不買。它每月只檢查一次,月中跌破不會出場
效果如何 全期(2015-01~2026-09)年化 25.8% 勝含息 0050 的 21.2%;但 2022 年起年化 24.8% 落後 0050 的 30.5%,2026 年 7 月單月 -24.4%
依本文重跑

執行這個策略

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

告訴你的AI:

幫我設定 FinLab,重現這篇文章,請讀:https://finlab.finance/setup?relatedUrl=/blog/moving-average-taiwan-timing

免安裝,開啟 FinLab Studio

新高靠近度選股加 20 日線濾網的均線策略與含息 0050 同日起算的淨值對照圖,2015 年 1 月到 2026 年 9 月台股回測,策略終值較高,2024 年後差距縮小,2026 年 7 月急跌

本文所有數字皆出自 finlab 套件抓取的上市櫃真實價量資料(price 收盤價與 etl:adj_close 含息還原股價),回測區間 2015-01-30 至 2026-09-30,基準為同一天起算的含息買進持有 0050。文末附可下載的 strategy.py 與 data.csv,執行後會印出本文的主要表格。對回測的觀念還不熟,可先看回測是什麼。

均線是什麼

均線(Moving Average,MA)就是「過去 N 個交易日收盤價的算術平均」,每天往前滾動一格,所以叫「移動」平均。它平滑掉單日的雜訊,反映一段時間裡市場對價格的共識成本。台股最常用的幾條:5 日(週線)、20 日(月線)、60 日(季線)、120 日(半年線)、240 日(年線)。短均線靈敏但雜訊多,長均線平滑但反應慢,這是均線天生的取捨。技術指標的基礎名詞可參考名詞詞彙表。

從均線衍生出幾種散戶最熟的訊號:

黃金交叉:短均線由下往上穿過長均線(例如 20 日穿過 60 日),被視為轉強訊號。

死亡交叉:短均線由上往下跌破長均線,被視為轉弱訊號。

多頭排列:短均線在長均線之上(多條均線時,短 > 中 > 長),被視為趨勢向上。

乖離率:收盤價相對均線的偏離程度,公式為(收盤價 − 均線)/ 均線;本文用「收盤價對 20 日均線的乖離」。乖離率單獨成篇的回測見乖離率怎麼用才對。

這些訊號到底有沒有用?散戶最常拿它們選股:挑剛黃金交叉、挑多頭排列、挑低乖離想等反彈的股票。以下先用回測檢驗這些教科書選股法,再說明把均線換個尺度(看「離 52 週新高多近」)之後結果有什麼不同。

均線的數學定義

均線的核心只有一條算術平均,黃金交叉則是兩條不同窗長均線的相對位置:

SMAn=1n∑i=0n−1Ct−i ;黃金交叉:SMAshort>SMAlongSMA_n = \frac{1}{n}\sum_{i=0}^{n-1} C_{t-i}\,;\quad \text{黃金交叉}: SMA_{\text{short}} > SMA_{\text{long}}

把符號逐一拆開:Ct−iC_{t-i} 是第 tt 天往前數第 ii 天的收盤價,CtC_t 就是當天收盤;nn 是均線的窗長(台股常用 20、60、120、240 日);SMAnSMA_n 把最近 nn 天的收盤價相加再除以 nn,得到一條平滑後的價格線。窗長 nn 越大,納入的歷史天數越多,曲線越平滑、對最新一根 K 棒的權重越低,因此反應越慢;nn 越小則越貼近現價、越靈敏,但也越容易被單日跳動帶著走。黃金交叉的定義是把短窗均線 SMAshortSMA_{\text{short}}(例如 20 日)和長窗均線 SMAlongSMA_{\text{long}}(例如 60 日)相比:前者由下往上超過後者的那一天叫黃金交叉,反向跌破叫死亡交叉。這個公式裡每一天的權重都相同(都是 1/n1/n),這是 SMA 和 EMA(指數移動平均,近期權重較高)最大的差別,也是它反應偏慢的根源。

一張圖看懂黃金交叉、死亡交叉,以及它為什麼會「甩巴掌」

理論講完,直接把公式畫到真實個股上。下面兩張圖用台積電(2330)與聯發科(2454)2023 年 7 月到 2024 年 6 月的還原前收盤價,疊上 20 日與 60 日兩條 SMA,並在價格線上標出黃金交叉(向上三角)與死亡交叉(向下三角)。均線先用完整歷史算好再切出這一年,所以窗口開頭的 60 日線也有值:

台積電 2330 股價疊加 20 日與 60 日均線的黃金交叉死亡交叉示意圖,2023 年 7 月到 2024 年 6 月,一年內只有一次死亡交叉與一次黃金交叉

台積電這一年走的是一段乾淨的上升趨勢,20×60 均線只交叉了 2 次:2023-08-14 死亡交叉、2023-11-06 黃金交叉,之後一路在多頭排列裡走完主升段。這是黃金交叉派最理想的情境。同一套規則換到聯發科就變樣了:

聯發科 2454 股價疊加 20 日與 60 日均線的黃金交叉死亡交叉示意圖,2023 年 7 月到 2024 年 6 月,一年內三次黃金交叉、三次死亡交叉來回甩巴掌

同樣一年、同樣的 20×60 規則,聯發科觸發了 6 次交叉(3 次黃金交叉、3 次死亡交叉)。看圖就懂問題在哪:2023 年 7、8 月與 2024 年 1 月、4 月那幾段整理裡,兩條均線黏在一起反覆穿越,2024-01-25 死亡交叉賣在 943 元,一個月後 2024-02-23 又在 1,100 元黃金交叉買回;2024-04-30 再賣在 992 元,2024-05-28 又在 1,310 元買回。這就是「甩巴掌」(whipsaw):均線交叉在趨勢明確時有用,在盤整時會被雜訊頻繁觸發,買賣點常落在小波段的錯誤一端。

這兩張圖用的是下面這段程式碼,你可以換成任何股票自己重畫,直觀感受不同個股的訊號密度:

顯示程式碼
import finlab
from finlab import data
import matplotlib.pyplot as plt
 
# finlab 會在需要資料時自動引導登入
finlab.login()
 
# 均線先用完整歷史算好,再切出要看的一年,窗口開頭的均線才不會是空值
close = data.get("price:收盤價")
stock_id = "2454"          # 換成你想看的股票代號
window = slice("2023-07-01", "2024-06-30")
ma_short = close[stock_id].rolling(20).mean()
ma_long = close[stock_id].rolling(60).mean()
 
# 黃金交叉:短均由下穿上長均的那一天;死亡交叉:由上跌破的那一天
above = ma_short > ma_long
was_above = above.shift(1, fill_value=False)
golden = (above & ~was_above)[window]
death = (~above & was_above)[window]
px = close[stock_id][window]
 
print(f"黃金交叉 {golden.sum()} 次,死亡交叉 {death.sum()} 次")
 
# 畫價格 + 兩條均線,標出交叉點
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(px.index, px, label=f"{stock_id} 收盤", color="#111827")
ax.plot(px.index, ma_short[window], label="20 日均線", color="#7C3AED")
ax.plot(px.index, ma_long[window], label="60 日均線", color="#F59E0B")
ax.scatter(px.index[golden], px[golden], marker="^", s=90, label="黃金交叉")
ax.scatter(px.index[death], px[death], marker="v", s=90, label="死亡交叉")
ax.legend()
plt.show()

stock_id 為 "2454" 時會印出「黃金交叉 3 次,死亡交叉 3 次」,換成 "2330" 是各 1 次。多換幾檔盤整股自己看一次,就能體會「均線交叉的有效性取決於個股當下是趨勢還是盤整」,這也是它不適合無差別套到全市場選股的直觀原因。

散戶最常見的均線選股,在台股 11 年都沒贏過大盤

我們在可交易宇宙(60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 大,排除 ETF、金融保險股、處置股)裡,把四種「均線選股」各跑一次月再平衡的回測,每月等權持有 30 檔:

均線選股用法 研究段年化 研究段月夏普 2022 年起年化 全期最大回撤
多頭排列(20 日線在 60 日線上)取 60 日漲幅前 30 15.2% 0.70 17.4% -45.2%
近 20 個交易日剛黃金交叉,取 60 日漲幅前 30 9.3% 0.50 10.9% -46.4%
追高乖離:20 日乖離最高 30 檔 11.7% 0.62 20.0% -50.0%
跌破均線抄底:20 日乖離最低 30 檔 5.4% 0.33 17.7% -43.0%
新高靠近度+20 日線濾網(本文策略,20 檔) 26.5% 1.34 24.8% -34.1%
對照:含息買進持有 0050 15.1% 1.00 30.5% -34.0%

均線常見選股用法與含息 0050 的研究段與 2022 年起年化報酬分組長條圖:多頭排列 15.2% 與 17.4%、剛黃金交叉 9.3% 與 10.9%、乖離最高 11.7% 與 20.0%、乖離最低 5.4% 與 17.7%、新高靠近度策略 26.5% 與 24.8%、含息 0050 15.1% 與 30.5%

四種常見用法的月夏普,研究段與 2022 年起都輸含息 0050;年化報酬只有多頭排列在研究段與 0050 打平(15.2% 對 15.1%),但它的月夏普只有 0.70(0050 是 1.00)、全期最大回撤深達 -45.2%:報酬差不多,波動與回撤大得多。把條件收緊成「近 20 天剛發生黃金交叉」反而更差,研究段年化掉到 9.3%,年換手 11.2 次也是四種裡最高。「跌破均線抄底」研究段只有 5.4%,接近無效。

原因不難理解:「對 20 日均線的乖離」是個雙義訊號。高乖離可能是強勢延續、也可能是過熱準備回檔;低乖離可能是落底反彈、也可能是趨勢轉空的起點。我們把 20 日乖離的五種橫截面取法(最高、最低、5 日變化量、5 日加速度、60 日 z-score)都跑過,研究段月夏普落在 0.33~0.62,全部輸給同期含息 0050 的 1.00。問題出在「拿哪一條均線、衡量哪一段的偏離」。延伸閱讀:技術面與基本面選股的差異、動能策略。

換個尺度用均線:看收盤離 52 週新高多近

散戶的均線選股之所以失靈,在於訊號太短、太雙義。把觀察尺度拉長到一整年,再把短均線降級成換股時的濾網,結果就不一樣了。本文的純技術策略由兩個零件組成。

零件一:靠近 280 日滾動最高價,當選股因子

第一個零件是看「收盤價 ÷ 自身過去 280 個交易日的最高收盤」,我們稱為新高靠近度(prox)。這個比值越接近 1,代表收盤越貼近自己過去約 13 個月(280 個交易日,略長於 52 週)的高點;越低代表離高點越遠、結構越弱。每月底在可交易宇宙裡,挑 prox 最高的 20 檔,也就是挑「最靠近自己 52 週新高」的一籃強勢股。收盤剛好等於 280 日最高收盤的股票 prox 都是 1,名次並列時會全部入選,所以有 6 個月選出超過 20 檔,最多是 2021 年 3 月的 31 檔。

這和散戶用的短均線乖離差在哪?20 日乖離問的是「現在離近一個月的平均成本多遠」,只反映一兩週的波動;新高靠近度問的是「現在離一整年的高點多近」,捕捉的是中長期趨勢結構。學術上,George & Hwang (2004) 在美股發現「收盤 ÷ 52 週最高價」對未來報酬的預測力,強過單純的過去報酬動能。他們的解釋是錨定效應:投資人把 52 週高點當參考價,股價逼近高點時不敢追,好消息反映得慢,之後才補漲。這個結果也與 Jegadeesh & Titman (1993) 的中期動能效應同方向。本文的新高靠近度就是 George & Hwang 那個比值換成 280 個交易日的台股版本。

零件二:換股日用 20 日均線過濾

選出最靠近新高的 20 檔之後,第二個零件用個股自己的 20 日均線過濾:換股日收盤在自身 20 日均線之下的入選股,這個月不買。執行上有兩點要先講清楚:

  1. 只在換股日檢查一次。 回測在每月最後一個交易日讀訊號、下一個交易日成交,均線也只在那天讀取;持有期間月中跌破 20 日線,要等到下一個換股日才處理。統計全期 141 個換股月共 2,628 筆持股,其中 2,080 筆(79.1%)到下一個換股日(含當天)為止曾收在自身 20 日線下。換句話說,強勢股在一個月裡跌破月線是常態,這個濾網擋掉的只是「換股日當天已經轉弱」的那幾檔。
  2. 被濾掉的名額不是轉成現金。 布林部位在 sim() 裡是等權,濾掉 5 檔就由剩下 15 檔平分(2026-07-31 換股日就是 15 檔各 6.67%)。全期 141 個月裡有 60 個月因為濾網不滿 20 檔,最少 6 檔(單檔權重 16.7%),另有 6 個月因為名次並列超過 20 檔;從來沒有全部被濾掉而空手的月份。

如果改成「月中一跌破就賣」會不會比較好?我們統計了其中 2,032 筆在換股日之前就跌破的持股(另 48 筆剛好在換股日當天才跌破,不列入),從第一次跌破當天收盤到下一個換股日,報酬中位數 +0.6%、平均 +1.7%,54.0% 是正的:跌破後立刻賣掉,平均反而會少賺一點。真正的日頻停損牽涉補位與交易成本,屬於另一個策略,本文沒有拿它替換。

下圖比較「不加濾網」(同宇宙、同新高靠近度選 20 檔等權)與不同窗長的換股日均線濾網:

換股日均線濾網的窗長對照雙軸圖:不加濾網全期年化 24.9%、最大回撤 -31.5%,10 日線 25.4% 與 -34.2%,20 日線 25.8% 與 -34.1%,60 日線 25.5% 與 -33.0%,120 日線 25.2% 與 -31.9%

不加濾網全期年化 24.9%、最大回撤 -31.5%;加 20 日線濾網年化 25.8%,但最大回撤加深到 -34.1%。換成 10、60、120 日線,全期年化都落在 25.2%~25.8%,彼此只差 0.6 個百分點。濾網對報酬的貢獻不到 1 個百分點,也沒有壓低回撤:這個策略的報酬幾乎全部來自零件一的新高靠近度。

完整策略:靠近新高選股+換股日 20 日線濾網

把兩個零件組成一套可執行、可重現、完全不含基本面的純技術策略:

  1. 選股因子:在可交易宇宙裡,每檔算「收盤 ÷ 自身過去 280 個交易日最高收盤」的新高靠近度,每月底取最高的 20 檔(名次並列時全部入選)。
  2. 均線濾網:換股日收盤在自身 20 日均線之下的入選股不買。
  3. 持股與權重:剩下的股票等權持有,月再平衡;月中不檢查均線、不補倉。
  4. 全程不使用槓桿 ETF、不含任何財報或月營收輸入。

選股端的核心程式碼(可直接交給你的 AI 助理改寫、或下載完整版執行):

顯示程式碼
import finlab
from finlab import data
from finlab.backtest import sim
 
# finlab 會在需要資料時自動引導登入
finlab.login()
data.truncate_end = "2026-09-30"   # 與文章同一個資料截止日
 
# 1) 載入價量資料
close = data.get("price:收盤價")
amount = data.get("price:成交金額")
 
# 2) 可交易宇宙:成交額前 300 大、收盤 > 10 元,只留代號剛好 4 碼數字的股票
#    (完整版另有 60 日均量 > 100 萬股門檻,並排除金融保險與處置股,見文末 strategy.py)
liquidity = amount.rolling(60, min_periods=20).mean()
common_cols = [s for s in close.columns
               if len(str(s)) == 4 and str(s).isdigit() and not str(s).startswith("00")]
universe = (liquidity.is_largest(300) & (close > 10))[common_cols]
 
# 3) 選股因子:收盤對自身 280 日最高收盤的靠近度,越接近 1 越貼近 52 週新高
prox = close / close.rolling(280).max()
 
# 4) 每月底取池內 prox 最高的 20 檔
basket = prox.where(universe).rank(axis=1, ascending=False) <= 20
 
# 5) 20 日均線濾網:換股日收盤在自身 20 日線之下的入選股不買
ma20 = close.rolling(20).mean()
position = basket & (close > ma20)
 
# 6) 每月換股回測(sim 只在每月最後一個交易日讀部位)
report = sim(position.loc["2015":], resample="M", fee_ratio=1.425 / 1000 * 0.3, upload=False)
stats = report.get_stats()
print(f"年化 {stats['cagr']:.1%},最大回撤 {stats['max_drawdown']:.1%}")

這段簡化版用 finlab 2.2.16 實跑,印出「年化 21.3%,最大回撤 -38.4%」,比完整版的 25.8%/-34.1% 差。差距來自簡化版少了 60 日均量 > 100 萬股、排除金融保險股與處置股三道篩選,可交易宇宙裡多了流動性較差、事件風險較高的股票。要對上文中數字,請下載文末的 strategy.py。

這套策略研究段(2015-01-30~2021-12)年化 26.5%、月夏普 1.34、月索提諾 2.13、最大回撤 -34.1%;2022 年起(2022-01~2026-09)年化 24.8%、月夏普 0.99、月索提諾 1.48;全期年化 25.8%、月夏普 1.09、月索提諾 1.63、最大回撤 -34.1%、年化波動 26.0%。同一天起算的含息 0050:研究段 15.1%、2022 年起 30.5%、全期 21.2%/月夏普 1.07/月索提諾 1.85/最大回撤 -34.0%/年化波動 19.8%。全期勝 0050 的只有年化報酬(多 4.6 個百分點);月夏普 1.09 對 1.07 接近打平,最大回撤相當,月索提諾與波動都輸。年換手約 8.9 次。

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

研究段大勝,2022 年起落後 0050

判斷一套策略是不是只靠某一段行情湊出來,最直接的方法是把回測切成兩段、各自結算。本文把 2015-2021 當研究段(涵蓋 2015 股災、2018 中美貿易戰急跌、2020 疫情崩跌與反彈),2022 年起另列(涵蓋 2022 升息熊市與其後的強多頭,資料截至 2026-09-30):

區間 對象 年化 月夏普 月索提諾 最大回撤
研究段 2015-01-30~2021 策略 26.5% 1.34 2.13 -34.1%
研究段 2015-01-30~2021 含息 0050 15.1% 1.00 1.47 -28.2%
2022-01~2026-09 策略 24.8% 0.99 1.48 -33.6%
2022-01~2026-09 含息 0050 30.5% 1.21 2.44 -34.0%
全期 2015-01-30~2026-09 策略 25.8% 1.09 1.63 -34.1%
全期 2015-01-30~2026-09 含息 0050 21.2% 1.07 1.85 -34.0%

新高靠近度均線策略與同日起算含息 0050 的三段年化報酬分組長條圖:研究段 26.5% 對 15.1%、2022 年起 24.8% 對 30.5%、全期 25.8% 對 21.2%

研究段策略的年化、月夏普、月索提諾都大幅領先(年化 26.5% 對 15.1%),靠的是「靠近新高」選股在震盪市裡持續挑到趨勢明確向上的強勢股;但研究段最大回撤 -34.1% 比 0050 的 -28.2% 深。2022 年起情況反轉:0050 年化 30.5%,2024 年後單年漲幅 37%~74%,策略年化 24.8%,月夏普 0.99、月索提諾 1.48 也都低於 0050 的 1.21、2.44。

這裡有一個口徑要交代:參數(280 日、20 檔、20 日線)是 2026 年 6 月定案的,當時已經看得到 2022 年之後的資料,選參數的標準也包含 2022 年起的表現。所以 2022 年起只能算「選參數時看過的驗證段」,真正沒看過的新資料只有 2026-06-09 之後的近四個月,結果在下一節。

策略衰退追蹤:2026-06-09 之後的新資料

本文首發版的資料截至 2026-06-09。從那天到 2026-09-30,策略下跌 11.8%,同期含息 0050 上漲 8.9%:

首發資料截止日之後新高靠近度均線策略與含息 0050 的淨值對照圖,2026 年 6 月 9 日到 9 月 30 日,策略 6 月下旬創高後 7 月急跌、8 月反彈,期末 -11.8%,0050 期末 +8.9%

期間 策略 含息 0050
2026-06-09~06-30 +7.3% +4.2%
2026-07 -24.4% -4.0%
2026-08 +7.1% +3.3%
2026-09 +1.5% +5.5%
合計 06-09~09-30 -11.8% +8.9%

2026 年 7 月單月 -24.4% 是全期最差的一個月,研究段最差月是 2015 年 7 月的 -14.0%,2022 年起在此之前最差是 -11.5%。拆開來看:6 月 30 日換股日選進的 20 檔,7 月 1 日進場、持有到 8 月 3 日換股,其中 18 檔虧損,中位數 -19.9%,最差的 8261 富鼎 -41.7%、6271 同欣電 -41.6%。這 20 檔在 7 月裡全部都曾收在自己的 20 日線下,最早的 7 月 2 日、最晚的 7 月 23 日,但濾網每月只讀一次,回測照樣抱到月底。7 月 31 日換股日重新選股,當天入選的 20 檔裡有 5 檔仍在月線下被濾掉,8 月只持 15 檔。策略淨值在 2026-06-22 創高,2026-07-30 回落 31.5%,到 9 月底仍比高點低 20.2%。

我們對這一系列技術指標策略設了一條檢查線:2022 年起的月夏普要在 1.0 以上、年化在 15% 以上。資料延長到 2026-09-30 後,2022 年起年化 24.8% 還在線上,月夏普 0.99 跌破了 1.0。依照我們的刷新規則,跌破就不回頭改參數,改為公開逐季追蹤。後面參數段會看到,不加濾網或換成 10、60、120 日線濾網,2022 年起月夏普是 1.02~1.06,剛好在線上;挑這種格子讓策略「重新過關」,等於用看過的資料調參,我們不這麼做。

逐年攤開,策略 12 年裡勝 0050 的有 6 年,2024 年起連三年落後:

年份 策略 含息 0050 勝負
2015(自 01-30) 9.1% -7.9% 勝
2016 9.4% 19.6% 負
2017 36.7% 18.1% 勝
2018 -6.7% -4.9% 負
2019 49.0% 33.5% 勝
2020 55.5% 31.1% 勝
2021 44.5% 21.9% 勝
2022 -29.6% -21.4% 負
2023 85.6% 27.5% 勝
2024 35.1% 48.6% 負
2025 18.5% 36.8% 負
2026(至 09-30) 36.3% 74.3% 負

全期年化的領先主要來自 2017、2019~2021 與 2023 年。落後的六年裡,2016 與 2024~2026 年是 0050 大漲、策略漲得較少;2018、2022 年是兩者都跌、策略跌得較多。

月營收 YoY 是選配,不在主策略內

本文的主策略是完全不含基本面的純技術策略:選股只用「收盤對 280 日最高收盤的靠近度」這個純價格因子,濾網只用個股自身的 20 日均線,沒有任何財報或月營收輸入。這是刻意的設計:純技術訊號每日可得、無財報公布延遲與對齊問題,回測口徑乾淨、可重現性高。

常見的延伸問題是:在選股端疊一層月營收年增率(YoY)過濾,績效會不會更好?站內創新高策略就是這個方向:價格創新高再加營收確認。本文不把它納入主策略,原因有二:其一,主策略只取 20 檔、集中度已高,再加營收過濾會大幅縮小可選池;其二,月營收公布有時間落差,要正確對齊「當期(含)以前已公布」的資料才不會用到未來資訊。想實驗的讀者可在下載的程式碼裡,於新高靠近度排名前加一層 monthly_revenue:去年同月增減(%) 的過濾自行對照,記得只用已公布的資料。

回測方法與口徑

量化結論的可信度取決於方法,以下逐項交代:

  • 交易成本:策略使用 finlab sim(),台股預設已內扣手續費(本文以 0.1425% 打三折計)與賣出證交稅 0.3%。
  • 滑價:未額外假設滑價,實際成交衝擊取決於資金規模與流動性。
  • 股票池:上市櫃普通股,60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 名。
  • 排除類別:只留代號剛好 4 碼數字的股票(排除權證、特別股與 6 碼代號),再排除 ETF(00 開頭)、金融保險股、處置與全額交割股。KY 股的代號也是 4 碼數字,沒有被排除。改用首發版「前 4 碼是數字就放行」的口徑重跑,所有數字完全相同。
  • 執行頻率:每月最後一個交易日讀訊號、下一個交易日成交,新高靠近度與 20 日線濾網都只在這天讀取;月中不出場、不補倉。被濾掉的名額由其餘入選股等權平分,持股最少時 6 檔,單檔權重最高 16.7%。
  • 價格口徑:新高靠近度與 20 日均線用的是未還原收盤價(price:收盤價),除權息、減資會讓股價跳空,可能影響選股;績效則由 sim() 以還原價計算。
  • 前視偏差:新高靠近度與 20 日均線只使用當日(含)以前的價格;完全不使用財報或月營收,沒有公布日對齊問題。
  • 生存者偏差:宇宙每天依當時資料篩選。2015-01-30 有收盤價、2026-09-30 已無收盤價的 4 碼普通股有 142 檔,這些後來下市或停止交易的股票在當時都可能被選入。
  • 起算日:所有變體與 0050 都從策略第一個淨值日 2015-01-30 起算;2022 年起的分段固定自 2022-01-01。
  • 周轉率:年換手約 8.9 次,成本敏感度較高,已在 sim() 內扣手續費與證交稅下計算。
  • 套件版本:finlab 2.2.16,資料截止日釘在 2026-09-30。

穩健度與參數最佳化:研究段是高原,2022 年起整片變平

策略有兩個關鍵參數:新高靠近度的滾動最高視窗(看多長一段的高點)與等權持股檔數(決定集中度)。最危險的做法是把參數掃一遍、挑研究段最好的那一格就上線。正確的看法是把整片參數空間畫成色溫圖,看高夏普是連成一片,還是只有一格孤峰。

下面把視窗(240/252/280 日)× 持股檔數(15/20/25 檔)共 9 組各跑一次(20 日線濾網固定),每格標的是研究段月夏普:

新高靠近度視窗與持股檔數參數網格的研究段月夏普色溫圖,九格從 1.12 到 1.34,持 20 檔、280 日視窗為最高格

研究段九格月夏普 1.12~1.34,持 20 檔那一列 1.24/1.30/1.34 最高,持 25 檔那一列最低(1.12~1.25),三列都是視窗越長越好。要注意的是:本文預設的 280 日 × 20 檔就是研究段最高的那一格,參數是在這張圖上挑出來的。同一張網格換成 2022 年起的月夏普:

同一張新高靠近度參數網格的 2022 年起月夏普色溫圖,九格都落在 0.96 到 1.01

視窗 \ 檔數 15 檔(研究/2022 起) 20 檔(研究/2022 起) 25 檔(研究/2022 起)
240 日 1.17/0.97 1.24/0.97 1.12/0.96
252 日 1.19/1.01 1.30/0.98 1.19/0.97
280 日 1.27/1.00 1.34/0.99 1.25/1.00

2022 年起九格全部落在 0.96~1.01,研究段那種「20 檔、長視窗最好」的形狀已經消失。這張表說明兩件事:一是參數選擇本身沒有造成孤峰,換到哪一格都差不多;二是 2022 年起的落後是整個策略的問題,換參數救不回來。

再看一次只動一個參數的 10 個鄰格(視窗 200/240/252/320、檔數 15/25/30、濾網均線 10/60/120 日):

一次只動一個參數的新高靠近度均線策略鄰格月夏普分組長條圖,研究段 1.19 到 1.34,2022 年起 0.87 到 1.06,視窗 200 日的 2022 年起只有 0.87

10 個鄰格的研究段月夏普 1.19~1.33,都低於預設的 1.34;2022 年起 0.87~1.06,有 6 格在 1.0 以上(濾網 10 日 1.06、持 30 檔 1.05、濾網 60 與 120 日各 1.02、持 15 檔與 25 檔各 1.00)。最敏感的是把視窗縮到 200 日:研究段 1.19、2022 年起 0.87、全期年化 21.5%,視窗太短會混進太多短期反彈股。方向性結論是「視窗別短於 240 日」,持股檔數在測過的 15~30 檔之間差異不大;至於精確該設 280 還是 252,資料給不出差別。

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

這裡驗證本文的完整策略:取收盤除以 280 日最高收盤最高的 20 檔,換股日收盤在 20 日均線之下的不買,其餘等權,每月換股。兩個鄰近參數是均線濾網天數與新高回看天數。我們在 2026-10-27 用本文附的 strategy.py(把 DATA_END 改成 None,finlab 2.2.20,資料截至 2026-10-27)把它重跑到最新,再做三項檢查。三項檢查的「贏」都是同一個意思:日夏普高於同一段期間的 0050 含息買進持有(etl:adj_close 還原價、純算術計算、不扣成本)。兩邊的日夏普用同一個公式:日報酬平均除以標準差、乘上 √252,不扣無風險利率。三項都用 sim() 預設的手續費 0.1425% 與證交稅 0.3%;原文手續費三折的結果另列於成本對照表。

檢查 標準 結果
鄰近參數 均線濾網天數(15、20、25)乘上新高回看天數(240、280、320),9 組至少 7 組贏 0/9 組贏,不過
前後兩段 2015-01-30 到 2020-12-11、2020-12-14 到 2026-10-27 兩段都贏 前段 1.00 對 0.89,後段 0.95 對 1.24,不過
交易成本 原參數、sim() 預設成本 日夏普 0.96 對 1.08,不過

新高靠近度+20 日線策略鄰近參數 9 組日夏普熱圖:0 組高於同期 0050 含息,原參數日夏普 0.96

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

新高回看天數 \ 均線濾網天數 15 20 25
320 0.88(年化 21.0%) 0.91(年化 21.6%) 0.91(年化 21.6%)
280 0.95(年化 22.9%) 0.96(年化 23.2%) 0.96(年化 23.2%)
240 0.90(年化 21.2%) 0.90(年化 21.3%) 0.90(年化 21.0%)

前後兩段與全期:

期間 策略年化 策略日夏普 0050 含息年化 0050 日夏普
前段 2015-01-30 到 2020-12-11 20.3% 1.00 13.5% 0.89
後段 2020-12-14 到 2026-10-27 25.9% 0.95 28.0% 1.24
全期 2015-01-30 到 2026-10-27 23.2% 0.96 20.5% 1.08

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

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

成本設定 年化 日夏普 最大回撤
不扣成本 29.9% 1.17 -33.6%
sim() 預設:手續費 0.1425%、證交稅 0.3% 23.2% 0.96 -35.0%
原文設定:手續費打三折 25.5% 1.03 -34.1%
0050 含息買進持有(同期) 20.5% 1.08 -34.0%

9 組鄰近參數的日夏普都在 0.88 到 0.96 之間,均線濾網 15 到 25 日、新高回看 240 到 320 日都差不多,但沒有一組追上 0050。前段(2015 到 2020 年)日夏普 1.00 贏 0050 的 0.89,後段 0.95 輸 1.24,三項都不成立,跟上文「研究段大勝,2022 年起落後 0050」一致。上文的年化 25.8% 是資料到 2026-09-30、手續費打三折的結果;照三折跑到 2026-10-27 是 25.5%,換成 sim() 預設成本是 23.2%。

「均線趨勢過濾」也一起重跑

曾列在策略庫的均線趨勢過濾也是均線策略:市值前 200 大、近 60 日成交額在前半的股票裡,收盤站上 120 日均線且 20 日均線在 60 日均線之上,取 6 個月動能前 20 檔等權,每月換股。鄰近參數是長均線天數與持股檔數,我們用同樣的三項檢查把它重跑到 2026-10-27。檢查方法與口徑同上。

檢查 標準 結果
鄰近參數 長均線天數(100、120、140)乘上持股檔數(16、20、24),9 組至少 7 組贏 0/9 組贏,不過
前後兩段 2018-01-31 到 2022-06-14、2022-06-15 到 2026-10-27 兩段都贏 前段 0.69 對 0.75,後段 0.88 對 1.47,不過
交易成本 原參數、sim() 預設成本 日夏普 0.79 對 1.15,不過

均線趨勢過濾鄰近參數 9 組日夏普熱圖:0 組高於同期 0050 含息,原參數日夏普 0.79

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

持股檔數 \ 長均線天數 100 120 140
24 0.82(年化 21.5%) 0.83(年化 21.9%) 0.80(年化 20.9%)
20 0.77(年化 20.4%) 0.79(年化 21.2%) 0.76(年化 20.2%)
16 0.79(年化 22.3%) 0.83(年化 23.6%) 0.81(年化 23.1%)

原參數年化 21.2%、日夏普 0.79、最大回撤 -48.8%,同期 0050 含息年化 23.9%、日夏普 1.15。9 組鄰近參數全部輸,前段(2018 到 2022 年中)0.69 對 0.75、後段 0.88 對 1.47,前後兩段也都輸,三項都不成立,策略頁已撤下。頁面最後顯示的是資料到 2026-06-09 的版本(日夏普 0.95 對 0050 的 1.22),當時日夏普就已經輸 0050。通過三項驗證的策略見營收篩選創新高策略。

策略的限制與取捨

  • 2022 年起落後大盤:2022-01~2026-09 年化 24.8% 對 0050 的 30.5%,2024 年起連三年落後。0050 單年大漲 37%~74% 的這三年,多半等權持有 20 檔的策略都沒跟上。
  • 月中不處理轉弱:濾網每月只讀一次,2026 年 7 月 20 檔持股全部在月中跌破 20 日線,回測照樣抱到月底,單月 -24.4%。
  • 集中度帶來較深回撤:持股多半是 20 檔、全期最大回撤 -34.1%、年化波動 26.0%,波動比 0050 的 19.8% 高三成以上。
  • 高周轉、成本敏感:年換手約 8.9 次,已扣手續費與證交稅,但實單滑價會進一步侵蝕,資金規模越大越明顯。
  • 崩盤型態涵蓋有限:回測從 2015 年起算,未對 2008、2011 年的崩盤型態做測試;首發版下載檔從 2008 年起跑的那一版,最大回撤是 2008~2009 年的 -48.7%。
  • 容量:選股多半 20 檔、宇宙限前 300 大,大資金部署需重估流動性衝擊;回測未逐筆估算滑價與借券成本。

用均線最常踩的五個坑

把這篇的回測結論整理成五個一上手就容易犯、而且資料證明會傷績效的錯誤:

  1. 拿均線交叉去選股。 近 20 天剛黃金交叉的股票取 30 檔,研究段年化 9.3%、月夏普 0.50,比單純多頭排列(15.2%)還差,年換手 11.2 次也最高。

  2. 在盤整股上盲信交叉訊號。 前面聯發科那張圖一年觸發 6 次交叉,兩次在一個月內「賣在 943 元、買回 1,100 元」這類位置來回甩巴掌。判斷不出個股當下是趨勢還是盤整,就會被雜訊一刀刀磨掉獲利。

  3. 拿 20 日乖離當選股訊號。 五種橫截面取法研究段月夏普 0.33~0.62,全部輸 0050。要讓均線變成有效的選股因子,得把尺度拉長到「離一整年的高點多近」,新高靠近度研究段月夏普 1.34。

  4. 以為月線濾網會幫你停損。 回測裡的 20 日線只在換股日檢查,持股到下一個換股日為止曾跌破月線的比例高達 79.1%;加了濾網全期最大回撤反而從 -31.5% 加深到 -34.1%。真要日頻停損,得另外設計補位與成本,那是另一個策略。

  5. 挑研究段最漂亮的那一格參數。 本文預設格就是研究段最高格(1.34),但 2022 年起九格全部擠在 0.96~1.01。研究段的高原不保證之後的表現,只代表參數沒有過度敏感。

這五個坑的共同根源,是把均線放到它不擅長的角色,或高估了每月檢查一次的濾網能做的事。對指標家族的整體差異與正確分工,可參考RSI、MACD、KD 比較與如何挑選台股。

2026-10 更新與更正

資料延長到 2026-09-30,2026-10-24 用 finlab 2.2.16 重跑。把資料截止日設回上一版的 2026-06-09,用同一版套件算出研究段 26.5%/月夏普 1.34、2022 年起 30.4%/1.21、全期 28.0%/1.21;改用首發時的 finlab 2.0.13 重跑則是 27.4%/1.35、30.6%/1.21、28.6%/1.22,與上一版完全相同。研究段由 27.4% 變成 26.5%,來自套件版本更新(第一個淨值日由 2015-02-26 提前到 2015-01-30,持股路徑也略有不同);2022 年起與全期的下滑則來自新增的資料。另有以下更正:

  • 「個股跌破 20 日線就清空、降為現金」與回測不符。 回測每月換股一次,20 日線只在換股日讀取,月中跌破不會出場;被濾掉的名額由其餘入選股平分,不是轉成現金。本文已改寫為「換股日 20 日線濾網」,並補上月中跌破的統計。
  • 「三段都勝含息 0050」不再成立。 2022 年起策略 24.8% 落後 0050 的 30.5%(上一版 30.6% 對 30.4% 只差 0.2 個百分點)。
  • 教科書表重寫。 上一版的「跌破均線抄底」與「超賣接刀」是同一個籃子,重複列出;「黃金交叉+多頭排列」實際規則是「多頭排列取 60 日漲幅前 30」,沒有交叉條件。本版改名並新增真正限定「近 20 天剛黃金交叉」的一列。
  • 示意圖的交叉次數。 上一版寫台積電 3 次(2 黃金、1 死亡)、聯發科 7 次(4 黃金、3 死亡),把窗口第一天已在多頭排列算成一次黃金交叉;正確是台積電 2 次、聯發科 6 次。
  • 頁內第一段程式碼。 上一版只用窗內資料算均線(前 59 天沒有 60 日線),而且 ~above.shift(1).fillna(False) 在目前的 pandas(3.1)會把多頭排列期間的每一天都標成黃金交叉(台積電 157 天)。已改為完整歷史計算與 shift(1, fill_value=False)。
  • 頁內第二段與下載檔的宇宙。 上一版以「前 4 碼是數字」判斷普通股,會放進 124 個非 4 碼代號(如 01001T);已改為剛好 4 碼。重跑確認這些代號從未被選入,數字不受影響。
  • 下載的 strategy.py 重現不出文中數字。 上一版沒有釘資料截止日、從 2008-06-30 開始持股,2015-2021 段是 26.3%/1.33。新版釘在 2026-09-30、從 2015 起評,印出的三段績效、教科書四列、零件拆解、逐年、首發後的區間與逐月報酬,逐格等於本文。
  • 0050 起算日與「排除 KY」。 0050 改從策略第一個淨值日 2015-01-30 起算(上一版自 2015-01-05);宇宙說明拿掉「排除 KY」。

自己跑一次

把下面這句話交給你的 AI 助理,它會引導你安裝 FinLab Skill、抓台股資料、重現這篇的回測:

裝好之後,下載本文的 strategy.py 與 data.csv,即可在自己的環境重跑、改參數、換選股因子。data.csv 兩欄(策略、含息 0050)都從 2015-01-30 起歸一,與文中統計同一個起點。strategy.py 的資料截止日寫在 DATA_END,改成 None 就會用最新資料重跑,可以自己延續本文的衰退追蹤。登入只需在程式裡寫 finlab.login(),套件會在需要資料時引導你完成登入。想延伸成更完整的量化流程,可參考量化交易總覽與程式交易是什麼。其餘常用技術指標的台股實測結論,匯整在13 個技術指標回測總覽。

常見問題

Q:均線參數要設多少?20 日、60 日、240 日哪個最好? 看用途。拿來選股時,本文看的是收盤離 280 日最高收盤多近,視窗在 240~320 日之間研究段月夏普 1.23~1.34,短到 200 日就明顯變差。拿來當換股日濾網,10、20、60、120 日全期年化都在 25.2%~25.8%,差別不大。拿 20 日乖離去選股,測過的五種取法都贏不過大盤,那是用法的問題。

Q:黃金交叉買進真的會賺嗎? 拿來選股的話,台股 11 年回測站不住。近 20 天剛黃金交叉的股票取 30 檔,研究段年化 9.3%、月夏普 0.50、全期最大回撤 -46.4%;同期含息 0050 是 15.1%、1.00、-34.0%。黃金交叉在盤整期還會反覆觸發、來回甩巴掌。

Q:什麼是「新高靠近度」?為什麼比黃金交叉好用? 新高靠近度是「收盤價 ÷ 自身過去 280 個交易日的最高收盤」,越接近 1 代表越貼近自己約 52 週的高點。黃金交叉看的是兩條短均線剛交叉的那一瞬間;新高靠近度看的是離一整年高點多近,反映中長期趨勢結構。本文用它選最靠近高點的 20 檔,研究段月夏普 1.34,黃金交叉選股是 0.50。

Q:跌破均線就該停損嗎? 本文的回測沒有日頻停損。20 日線只在每月換股日檢查一次,換股日在月線下的入選股不買。統計全期持股,79.1% 到下一個換股日為止曾跌破月線;在換股日之前就跌破的那些,從第一次跌破到換股日的報酬中位數 +0.6%:對這種靠近新高的強勢股,一跌破月線就賣,平均並沒有少虧。日頻停損要另外處理補位與成本,屬於另一個策略。

Q:均線可以單獨拿來當買賣訊號嗎? 拿 20 日乖離或均線交叉橫截面排名選股不建議,研究段月夏普都不超過 0.70,輸給含息 0050 的 1.00。把均線的尺度拉長成「對 280 日高點的靠近度」當選股因子,研究段才有明顯超額報酬;但 2022 年起這套策略也落後 0050,要搭配逐季追蹤。

Q:均線和布林通道、肯特納通道有什麼關係? 布林通道的中軌就是均線(常用 20 日),上下軌是中軌加減標準差;肯特納通道則用 ATR 定義通道寬度。均線是它們共同的骨幹。各指標的正確用法可參考肯特納通道與 ATR 指標。

Q:均線和 KD、RSI、MACD 一起用會更好嗎? 這些大多是同性質的價格衍生指標,資訊高度重疊,硬疊在一起通常沒有加分。比較有效的組合是讓均線各司其職:長尺度的新高靠近度負責選股、短均線負責換股日過濾。各指標的差異可參考RSI、MACD、KD 比較。

Q:這套策略適合誰? 適合想主動選股、能接受 -34% 等級回撤與 26% 年化波動、也能接受某些年份大幅落後大盤的人:全期年化 25.8% 勝 0050 的 21.2%,但 2024 年起連三年落後,2026 年 7 月單月 -24.4%。偏好低周轉、不想承受單月 -20% 以上跌幅的人,直接買進持有含息 0050 更省心。延伸閱讀:如何挑選台股。


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

本文僅供量化研究與教學用途,所有回測數字均由 finlab 套件在真實台股資料上產出,過去績效不代表未來表現,不構成投資建議。本文均線選股純技術策略全期最大回撤 -34.1%,2026 年 7 月單月下跌 24.4%,實際交易前請自行評估風險、滑價與交易容量。

FinLab AI

想建立自己的策略?

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

免費開始

更多技術指標研究

查看全部