
執行這個策略
複製提示詞,讓 AI 依照上方證據的資料、條件與風險檢查重跑一次。
告訴你的AI:
幫我設定 FinLab,在我的選股策略上加大盤半年線濾網,比較加之前和加之後的日夏普與最大回撤,請讀:https://finlab.finance/setup?relatedUrl=/blog/taiex-moving-average-market-filter
大盤跌破均線就空手,能讓選股策略更好嗎?我們把這個做法疊在站上 31 支驗證過的台股選股策略上:加權報酬指數跌破半年線(120 日均線)再低 2% 就全部賣出,回到均線之上再買回。31 支裡 27 支最大回撤變淺,年化報酬 31 支全部變少,日夏普 17 支上升、14 支下降。條件在看結果前寫定,三項驗證都過、又贏過原策略的只有 3 支:極小型股 30 檔、核心衛星 60/40、營業利益率三因子。只看「跌破季線」(60 日均線)而且不留緩衝的版本最差,31 支只有 2 支贏原策略。
會不會變好,看的是原策略在大盤跌破均線那段時間還賺不賺。2007 年 10 月到 2026 年 11 月,加權報酬指數有 24.8% 的交易日處在濾網空手的狀態,那些日子平均年化仍有 +1.2%。原策略在這些日子日夏普低於 0.5 的 9 支,加濾網後全部變好;高於 0.9 的 8 支全部變差,其中營收創新高、營收動能這類策略在大盤弱的時候照樣賺錢,濾網讓它們錯過這段報酬。
大盤濾網實測關鍵數字
| 項目 | 大盤均線濾網(120 日、緩衝 2%) | 波動度控管(63 日、1.0 倍) |
|---|---|---|
| 測試的策略 | 31 支台股 | 31 支台股 |
| 平均在場比例 | 80%(75% 到 83%) | 86%(81% 到 91%) |
| 最大回撤變淺 | 27 支,中位數淺 6.1 個百分點 | 31 支,中位數淺 4.7 個百分點 |
| 年化報酬變少 | 31 支,中位數少 4.3 個百分點 | 31 支,中位數少 4.9 個百分點 |
| 日夏普上升 | 17 支,中位數 +0.004 | 5 支,中位數 -0.055 |
| 9 組參數至少 7 組贏原策略 | 7 支 | 2 支 |
| 週報酬跟原策略相關 ≥0.95 | 0 支 | 31 支 |
| 全部過關 | 3 支 | 0 支 |
季線、半年線、年線是什麼
均線是過去 N 個交易日收盤價的平均。台股習慣把 60 日均線叫季線(一季大約 60 個交易日),120 日叫半年線,240 日叫年線。「大盤跌破季線」指加權指數收盤低於自己的 60 日均線,常被當成短中期轉弱的訊號;它跟個股停損不同,停損看的是手上每一檔股票的價格,大盤濾網只看指數,觸發時整個組合一起出場。
本文用的大盤是「發行量加權股價報酬指數」,它把配息加回指數,長期比一般看到的加權指數高。規則有兩條線:收盤低於 N 日均線再往下 b%(緩衝)才出場,收盤回到 N 日均線以上才進場,介於兩條線之間維持前一天的狀態。緩衝是為了避免指數在均線附近來回時一直進出。原參數是 120 日、緩衝 2%,鄰近參數是 60、120、240 日乘上 0、2%、4%,共 9 組。

原參數在這 19 年出場 31 次,平均一年 1.6 次。2008 年、2022 年這種長空頭,濾網大多躲掉;2020 年 3 月的急跌,等指數跌破均線時已經跌了一大段,隨後的 V 型反彈又要等指數站回均線才買回。這套做法參考 Faber(2007) 的 10 個月均線擇時:他用在美股與其他資產類別的指數上,回撤明顯變小,報酬接近買進持有。
測試設計:31 支驗證過的策略、兩種濾網
原策略: 站上 策略庫 裡所有台股選股策略,排除本身就是擇時的國安基金正 2,共 31 支。每支都用策略頁提供下載的 strategy.py 原封不動執行,期間起點跟策略頁相同,資料截到 2026-11-06。在策略頁統計的同一段期間內,重跑的年化與策略頁差不到 0.2 個百分點、日夏普差不到 0.01。下文的「原策略」就是這 31 支,圖表裡標為「底策略」。
怎麼疊: 原策略每次換股的權重延用到下次換股。濾網切換的那天,用原策略當天實際持有的股票與權重乘上曝險重新下單,其餘放現金;原策略本來的換股日、停損、單檔上限與成本都不變。曝險固定為 1 時,這套做法每天的淨值都跟原策略完全相同,我們拿這點檢查疊法沒有寫錯。
濾網 A,大盤均線: 上一節的規則。訊號用當天收盤算,sim() 在下一個交易日收盤成交。
濾網 B,波動度控管: 參考 Moreira 與 Muir(2017) 的波動度管理,以及 Barroso 與 Santa-Clara(2015) 用在動能策略的版本。每月最後一個交易日算原策略過去 L 天的實現波動 σ,下個月的曝險設成 min(1, 目標 ÷ σ);目標是到那天為止 σ 的中位數乘上 m,只用到過去的資料。原參數 L 63 日、m 1.0,鄰近參數 L 21、63、126 日乘上 m 0.8、1.0、1.2。
過關條件(開跑前寫在案件裡,之後沒改):
- 三項驗證:9 組參數至少 7 組的日夏普贏同期 0050 含息;原參數把期間對半切,前後兩段都贏;用
sim()預設的手續費與證交稅。 - 比原策略好:9 組至少 7 組的日夏普高於同期、同成本的原策略,原參數前後兩段也都高於原策略。夏普比率不受固定比例縮放影響,所以贏原策略也代表贏「平均持股比例相同、一直持有」的版本。
- 是不同的策略:原參數的週報酬跟原策略、跟每支已上線策略的相關都要低於 0.95。
第 2 項才是這篇真正要回答的問題。31 支原策略本來就是驗證過、贏 0050 的策略,加了濾網贏 0050 不難,難的是比原策略好。
結果一:回撤幾乎都變淺,年化全部變少
大盤均線濾網平均讓策略有 20% 的時間空手。最直接的效果是回撤:31 支裡 27 支最大回撤變淺,中位數淺 6.1 個百分點;代價是年化報酬 31 支全部變少,中位數少 4.3 個百分點。風險調整後的日夏普就有升有降,17 支上升、14 支下降,中位數幾乎是 0。

上升最多的是極小型股 30 檔(+0.23)、金控高殖利率前 5 名(+0.20)、核心衛星 60/40(+0.18)、營業利益率三因子(+0.18);下降最多的是營收連續成長創新高(-0.26)、營收篩選創新高(-0.25)、月營收驚喜(-0.15)。
結果二:空手期間還在賺的策略,加濾網就變差
為什麼同一個濾網,有的策略變好、有的變差?我們把每支原策略的日報酬拆成兩組:濾網空手的那些日子,和在場的日子。濾網只會改變前一組,所以原策略在空手日子裡表現越差,濾網的幫助越大。首圖就是這個關係:橫軸是原策略在空手日子的日夏普,縱軸是加濾網後的日夏普變化,31 支的相關係數是 -0.88。
- 空手日子日夏普低於 0.5 的 9 支,加濾網後全部變好。 例如營業利益率三因子,空手日子年化只有 1.0%、日夏普 0.05,在場日子年化 24.0%、日夏普 1.74。避開那 19% 的日子,等於丟掉一段只有波動、沒有報酬的時間。
- 空手日子日夏普高於 0.9 的 8 支,加濾網後全部變差。 營收連續成長創新高在空手日子年化 47.7%、日夏普 1.91,比在場日子的 1.47 還高。這類策略挑的是營收剛創新高、股價也強的公司,大盤轉弱時它們常常照樣漲,濾網讓它們在最好的時候空手,年化從 46.2% 掉到 33.2%。
- 原本就有大盤濾網的策略,再加一層沒有差別。 營收動能低波三因子本身已經用大盤 120 日線決定要不要持股,空手日子日夏普只有 0.05,再疊一層濾網,日夏普只多 0.008。
大盤本身也一樣。加權報酬指數在空手日子年化 +1.2%、年化波動 26.2%,在場日子年化 +17.1%、波動 16.4%。跌破半年線之後平均還是小漲,只是波動大很多,所以均線濾網的效果主要來自少承受那段波動,躲掉下跌只是一部分。
過關的 3 支:極小型股、核心衛星、營業利益率三因子
三項驗證都過、9 組參數多數贏原策略、前後兩段也都贏原策略的有 3 支。原策略都是每月換股、持股 20 到 30 檔、偏低波動或小型股,空手日子的日夏普在 0.05 到 0.47 之間。
| 策略(期間) | 版本 | 年化報酬 | 日夏普 | 最大回撤 | 9 組贏原策略 |
|---|---|---|---|---|---|
| 極小型股 30 檔(2013-04 起) | 加濾網 | 33.6% | 2.53 | -13.3% | 9/9 |
| 原策略 | 36.4% | 2.30 | -24.0% | ||
| 0050 含息 | 18.4% | 1.01 | -34.0% | ||
| 核心衛星 60/40(2018-02 起) | 加濾網 | 20.4% | 1.46 | -17.5% | 8/9 |
| 原策略 | 21.7% | 1.28 | -26.5% | ||
| 0050 含息 | 22.7% | 1.10 | -34.0% | ||
| 營業利益率三因子(2018-01 起) | 加濾網 | 18.6% | 1.49 | -14.3% | 8/9 |
| 原策略 | 19.5% | 1.31 | -25.9% | ||
| 0050 含息 | 21.8% | 1.06 | -34.0% |
前後兩段的日夏普(加濾網/原策略/0050 含息):極小型股 2.67/2.53/0.89 與 2.40/2.11/1.13,核心衛星 1.14/1.06/0.78 與 1.73/1.48/1.36,營業利益率三因子 1.15/1.05/0.71 與 1.78/1.55/1.34。三支的週報酬跟原策略的相關在 0.84 到 0.86 之間,跟已上線策略的最高相關是 0.79 到 0.87(都是跟自己的原策略頁),彼此之間是 0.27 到 0.67。

要注意兩點。第一,3 支加了濾網年化都變少,核心衛星與營業利益率三因子的年化也低於 0050 含息,贏的是日夏普與回撤:核心衛星的最大回撤從 -26.5% 變成 -17.5%,大約是 0050 的一半。第二,極小型股 30 檔的原策略沒有流動性門檻,這些股票成交量很小,資金一大就買不到回測的價格,加了濾網一年平均多進出 1.4 次,實際報酬會比回測低。
3 支都放上策略頁每天更新,程式跟本文下載的同一份:極小型股+大盤半年線濾網、核心衛星+大盤半年線濾網、營業利益率三因子+大盤半年線濾網。策略頁從第一次買進那天起算,核心衛星濾網版因為 2018 年 2 月一開始就在空手,策略頁從 2018-02-21 起算,0050 含息同期年化 22.5%。
差一點的 4 支:前半段沒贏原策略
另外 4 支在 9 組參數裡有 7 到 8 組贏原策略,卡在「前後兩段都要贏原策略」:
- 高股息四因子:日夏普 1.24 → 1.39,回撤 -27.6% → -15.1%,但前半段 0.90 低於原策略的 0.98。
- 四因子複合:日夏普 1.44 → 1.59,前半段 1.40 低於原策略的 1.50。
- 金控高殖利率前 5 名:日夏普 1.00 → 1.20,前半段 0.61 同時輸原策略 0.69 與 0050 含息 0.63。
- 品質動能低波:前半段 0.706 輸原策略的 0.936,也略輸 0050 含息的 0.712。
這 4 支的日夏普改善都來自後半段(後半段比原策略高 0.31 到 0.46),前半段都比原策略差,所以照事先寫定的條件不算過關。
均線天數與緩衝:跌破季線就出場最差

左圖是大盤均線濾網 9 組參數下,31 支裡有幾支日夏普高於原策略。季線(60 日)不留緩衝只有 2 支;同樣是季線,留 2% 緩衝就有 22 支。兩者的進出次數差很多:2007 到 2026 年,季線不留緩衝出場 125 次,平均一年 6.6 次,指數在季線附近來回就會跟著賣出、買回;留 2% 緩衝降到 41 次。半年線不留緩衝 78 次、留 2% 是 31 次,年線分別是 52 次與 20 次。每一趟都要付手續費與證交稅,也可能賣在短線低點、買在短線高點。如果要用「跌破季線」當訊號,至少要留一點緩衝,或改看半年線。
波動度控管:回撤變淺,但跟原策略幾乎是同一支
波動度控管讓 31 支的最大回撤全部變淺(中位數淺 4.7 個百分點),平均在場 86%。問題是它幾乎只在原策略本來就很穩的時候滿倉、波動變大時減碼一部分,週報酬跟原策略的相關全部在 0.95 以上(0.951 到 0.985),等於同一支策略少持有一些。日夏普只有 5 支上升,中位數 -0.055。
表現最好的是營收連續成長創新高:日夏普 1.55 → 1.66,最大回撤 -39.3% → -23.1%,9 組有 7 組贏原策略,但前半段 1.880 略低於原策略的 1.883,相關 0.97,沒有過關。右圖也顯示,回看 21 日的版本贏原策略的比較多(19 支),回看 63 日以上就剩 7 支以下;波動度控管在這批台股策略上看不出穩定的好處。Cederburg 等人(2020) 用美股 103 個股票策略測試也發現,波動度管理在樣本外多半沒有比原策略好,跟這裡的結果一致。
用 finlab 重現
以下是過關的極小型股版本。build_base_report() 是原策略,跟極小型股策略頁同一份;market_exposure() 算大盤濾網,build_report() 把兩者疊在一起。
顯示程式碼
import pandas as pd
from finlab import data
from finlab.backtest import sim
MA_DAYS = 120 # 半年線
BUFFER = 0.02 # 跌破均線再低 2% 才出場
def build_base_report():
"""原策略:每月底取市值最小的 30 檔,等權持有。"""
market_cap = data.get("etl:market_value")
position = market_cap.is_smallest(30)
return sim(position, resample="M", upload=False)
def market_exposure():
"""1 是照原策略持有,0 是空手;介於兩條線之間維持前一天的狀態。"""
index = data.get("benchmark_return:發行量加權股價報酬指數")["發行量加權股價報酬指數"].dropna()
average = index.rolling(MA_DAYS).mean()
state = pd.Series(float("nan"), index=index.index)
state[index >= average] = 1.0
state[index < average * (1 - BUFFER)] = 0.0
return state.ffill().fillna(1.0)
def build_report():
base = build_base_report()
# 原策略每次換股的權重,換股日遇到休市時用之前最後一個交易日
days = data.get("price:收盤價").index
days = days[days <= base.creturn.index[-1]]
weights = base.position[base.position.index < days[-1] + pd.offsets.BDay()]
weights.index = days[days.searchsorted(weights.index, side="right") - 1]
weights = weights[~weights.index.duplicated(keep="last")]
days = days[days >= weights.index[0]]
# 權重延用到下次換股,乘上大盤濾網的曝險
exposure = market_exposure().reindex(days, method="ffill").fillna(1.0)
switches = exposure.index[exposure.ne(exposure.shift())][1:]
position = weights.reindex(days, method="ffill").fillna(0.0).mul(exposure, axis=0)
return sim(position, resample=weights.index.union(switches), upload=False)
report = build_report()resample 傳的是「原策略換股日」加上「濾網切換日」,所以只有這兩種日子會下單。要套在自己的策略上,把 build_base_report() 換成自己的 sim() 就好。完整版會輸出淨值與統計,在下方下載。
回測方法與限制
- 交易成本:
sim()台股預設手續費 0.1425%、賣出證交稅 0.3%。濾網每次出場都是整個組合賣出、回場再全部買回,這兩次的成本都有扣。 - 滑價與容量:沒有另外假設滑價,也沒有估算容量。極小型股 30 檔沒有流動性門檻,實際成交會比回測差。
- 股票池、排除類別與權重:每支照原策略自己的設定,本文沒有另外改。
- 前視偏差:濾網用的是當天收盤的報酬指數與均線,下一個交易日收盤才成交;波動度控管只用每月底以前的報酬。原策略的財報、月營收對齊方式照各自策略頁。
- 進出次數:大盤均線濾網原參數 2007 到 2026 年出場 31 次;極小型股的期間(2013 年起)出場 19 次。
- 樣本內外:全部是 2007 到 2026 年的樣本內回測,用前後兩段與鄰近參數檢查穩定度,沒有另外留樣本外資料。31 支原策略本身也是在這段資料上驗證過才上線的。
- 只測兩種濾網:大盤指標還有很多種。外資期貨未平倉、PMI 等 13 個訊號在台股 13 個大盤訊號回測用在 0050 上測過,融資維持率在 0050 融資維持率擇時,這篇沒有重測。
這個結果能怎麼用
如果你在意的是回撤,大盤均線濾網確實有用:31 支裡 27 支回撤變淺,平均約 20% 的時間空手。如果你在意的是報酬,它幾乎一定讓年化變少。日夏普會不會變好,先看原策略在大盤弱的時候還賺不賺:把自己的策略回測拆成「指數在半年線下」與「在半年線上」兩段,下面那段夏普偏低(本文的門檻大約是 0.5),濾網才可能有幫助;營收創新高、價格動能這類在弱勢時照樣強的策略,加了反而變差。
用均線做個股選股是另一個問題:那篇測的是個股自己的均線,本文測的是大盤的均線。四種大盤指標(ADLs、VIX、融資維持率、多空頭排列家數)當濾網擇時 0050 的結果,在大盤濾網指標實測這篇補上了三項驗證,扣成本後四種都沒贏 0050。
常見問題
大盤跌破季線是什麼意思?
加權指數收盤低於自己的 60 日均線,代表最近一季的平均成本被跌破,常被當成短中期轉弱的訊號。本文 2007 到 2026 年的資料裡,指數跌破半年線再低 2% 以後,平均仍有年化 +1.2% 的報酬,波動卻從 16.4% 升到 26.2%;跌破均線之後通常是波動變大,不一定繼續跌。
季線、半年線、年線哪個比較好用?
對這 31 支策略,季線(60 日)不留緩衝最差,只有 2 支贏原策略,19 年出場 125 次;季線留 2% 緩衝有 22 支、半年線留 2% 有 17 支、半年線留 4% 有 21 支,年線在 7 到 12 支之間。差別主要來自進出次數,均線越短、緩衝越小,來回越頻繁。
大盤跌破季線要把股票賣掉嗎?
要看你的策略。原策略在大盤弱勢時日夏普低於 0.5 的 9 支,加濾網後全部變好;高於 0.9 的 8 支全部變差。賣掉一定會少賺一部分報酬(31 支年化中位數少 4.3 個百分點),換來的是回撤變淺。
大盤濾網和停損有什麼不同?
停損看每一檔股票自己的跌幅,觸發時只賣那一檔;大盤濾網只看指數,觸發時整個組合一起出場。站上的ATR 移動停損實測測的是個股停損,加在月營收動能上沒有幫助。本文 31 支裡有 6 支原策略本身就帶停損,大盤濾網跟停損同時存在、各自運作。
波動度控管是什麼?為什麼沒有用?
波動度控管是在策略最近波動變大時減碼、波動變小時加回,讓組合的波動維持穩定。它讓 31 支回撤全部變淺,但週報酬跟原策略的相關都在 0.95 以上,等於同一支策略持股少一點,日夏普只有 5 支上升。美股 QQQ 單獨做波動度目標的結果在QQQ 波動度目標策略。
為什麼營收動能策略加大盤濾網會變差?
營收創新高、營收動能這類策略挑的是基本面正在變好、股價也強的公司,大盤跌破均線時它們常常照樣上漲。營收連續成長創新高在大盤濾網空手的日子年化 47.7%、日夏普 1.91,比在場的日子還好,加濾網後年化從 46.2% 降到 33.2%。
過關的 3 支能拿來用嗎?
它們每天在策略頁更新,程式可以帶到 FinLab Studio 重跑。要知道的是三支加濾網後年化都比原策略少,其中兩支的年化也低於 0050 含息,換到的是較淺的回撤;極小型股的回測沒有考慮成交量限制,資金大的話實際報酬會明顯低於回測。
可以自己重跑嗎?
可以。下方的 research.py 會下載 31 支原策略的程式、疊上兩種濾網跑完全部參數;3 支過關策略各有獨立的 strategy.py。安裝 finlab 後執行即可,finlab 需要資料時會自動引導登入。
延伸閱讀
- 極小型股+大盤半年線濾網的策略頁:本文過關的策略之一,淨值每天更新。
- 小型股效應:極小型股 30 檔原策略的研究。
- 台股四萬點選股攻略 與 AI Agent 量化交易工具比較:核心衛星 60/40 與營業利益率三因子原策略的出處。
- 台股 13 個大盤訊號回測:大盤訊號直接擇時 0050 的結果。
- 0050 融資維持率擇時:用融資維持率當進出場訊號。
- 台股選股方法完整指南:選股策略的整體框架。
- 量化交易是什麼:從選股、擇時到風控的入門總覽。
- 美股 200 日均線大盤濾網:同一套方法用在兩支美股策略上的結果。
下載資源
| 檔案 | 內容 |
|---|---|
| research.py | 下載 31 支台股與 2 支美股原策略、疊上兩種濾網、跑完三項驗證與相關係數 |
| metrics.json | 31 支台股策略各 18 組濾網參數的日夏普、年化、回撤、前後兩段、相關係數與空手期間統計 |
| data.csv | 31 支原策略、兩種濾網原參數與 0050 含息的每週淨值 |
| small-cap-effect-market-filter/strategy.py | 極小型股+大盤半年線濾網(策略頁同一份) |
| 30k-stock-selection-market-filter/strategy.py | 核心衛星+大盤半年線濾網(策略頁同一份) |
| operating-margin-three-factor-market-filter/strategy.py | 營業利益率三因子+大盤半年線濾網(策略頁同一份) |
| report_strategy.html | 極小型股+大盤半年線濾網的互動式回測報告 |
風險提示
本文所有策略與回測結果僅供教學與研究用途,不構成投資建議,也不推薦任何個股。過去績效不代表未來表現,小型股的實際成交價格可能與回測差距很大。投資一定有風險,請依自身風險承受能力審慎評估。
最後更新:2026-11|回測區間:2007-10 ~ 2026-11|作者:FinLab 量化研究團隊(經量化研究員審閱)
FinLab AI
想建立自己的策略?
用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案
免費開始


