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

W底、M頭回測:四個設計未通過驗證

W底、M頭與雙重底怎麼用?本次固定兩個轉折的間隔、容差與頸線突破條件,分別測試台股個股及0050,再把持有時段反過來比較。四個設計各跑九組參數,檢查前後兩段與預設交易成本,沒有一個通過。附買訊次數、現金比重、參數熱圖、逐日資料與可重跑的FinLab程式。

這組規則未通過驗證

不用操作程式,直接看報酬、最大跌幅與比較結果。

看比較結果
未通過本次驗證

W底、M頭各設計的日夏普與同期基準

4個設計都未通過。下方兩欄摘要可同時比較報酬與最大跌幅,完整參數圖可點開原尺寸。

W底突破買進、M頭跌破賣出的四個台股設計,在本次固定條件下都沒有通過驗證。本文以反面教材為主。個股與0050的訊號數相差很大:同一個形狀規則放在分散持股的ETF上,可能多年只出現少數買點。將等待時間及交易成本一起算進來,結果和事後圈出幾個漂亮的W很不同。

W底、雙重底與M頭怎麼畫

W底與M頭描述兩次試探相近價格後反轉的型態。W底先跌、反彈、再跌,兩個低點構成雙底;中間反彈高點就是本次的水平頸線。收盤由下往上穿越它才買。M頭則是漲、回檔、再漲,跌破中間低點才賣出持股。

名稱 轉折序列 完成條件 本次操作
W底、雙重底 低、高、低 第二低點確認後突破中間高點 建立多頭持股
M頭、雙重頂 高、低、高 第二高點確認後跌破中間低點 賣出既有持股
尚未突破的雙底 低、高、低 價格仍低於頸線 保持原狀,不提前買
突破後再跌回 曾完成W底 本次仍等對應賣訊或60日 不事後剔除失敗案例

兩個底必須相隔至少22個交易日、最多120日,相對高度差不超過設定容差;中間反彈至少比第一個低點高3%。M頭採鏡像條件。第二個低點可以略高或略低,但低到變成另一段下跌,就可能不符合容差。名稱只提供形狀,不能替代可重複的數值定義。

Lo、Mamaysky與Wang(2000)提出用平滑價格與極值位置辨識型態。本文將雙底改成連續三個已確認轉折,加入頸線穿越與持有期限,屬於自訂的可交易實驗,沒有宣稱完整重現原論文的雙底搜尋演算法。

正向與避開訊號的結果

報酬與最大跌幅

斜線前是年化報酬,後是從高點最多跌多少。

設計 年化/最大跌幅
個股買進 2.2% / -49.3%
個股避開 20.9% / -57.6%
0050買進 3.2% / -8.4%
0050避開 18.6% / -34.0%
0050含息 22.8% / -34.0%

下方完整比較表可左右滑動,查看夏普、參數勝出數與平均持股權重。

完整比較

設計 年化報酬 日夏普 最大回撤 前/後半段日夏普 參數贏基準 平均在場權重
台股個股・W/M・正向 2.2% 0.21 -49.3% 0.57/-0.08 0/9 83.5%
台股個股・W/M・避開 20.9% 0.74 -57.6% 0.58/0.87 0/9 100.0%
0050・W/M・正向 3.2% 0.73 -8.4% 1.14/0.24 0/9 7.5%
0050・W/M・避開 18.6% 0.98 -34.0% 0.80/1.13 0/9 92.5%
0050含息持有 22.8% 1.13 -34.0% 1.14/1.16 — 100.0%

本文提供研究結果,沒有推薦這些買賣規則。想自行重跑,可先 設定 FinLab 環境,再 下載研究程式(.py);其他檔案見 研究下載區。

個股正向版有不少時間持股,表現卻沒有超過0050。0050正向版的在場權重很低,較小回撤主要伴隨長時間現金,不能單憑跌得少便認定擇時有效。所有結果都用完整日曆,現金日的報酬記為零,沒有把它們移除後重算夏普。

W底、M頭中央設定的同日起始淨值與含息基準

淨值圖同時放個股與0050的正向、避開版本,再加0050含息持有。每條線在2017年1月3日從1開始。避開版是從股票池中排除正向持有狀態,再依相同流動性規則選股;它沒有拿M頭去放空,也沒有測跌幅加倍或反向ETF。

雙底最容易偷看未來的位置

候選低點要比前後各三天的平滑價格都低,所以當天看不到「後三天」的比較結果。本文等到第三天結束,才把該低點加入辨識序列。確認完成後,還要求一次新的頸線突破;如果股價早在等待期間就跳過頸線,不回填成較便宜的進場價。這也是前視偏差會藏在畫圖工具裡的地方。

平滑採24日單邊Gaussian權重,頻寬2、3、4日;兩底或兩頂容差用2%、3%、4%,全組合共九組。中央設定是3日與3%。最後一個轉折後最多等20日,超過便放棄該次突破。持股遇M頭跌破就出場,或滿60個交易日退出,沒有因為尚未回到成本就延長持有。

相同類型的極值連續出現時,只保留當下較極端的一點,歷史持倉不改。程式另做截斷測試:把資料結束日提前,再補上後面行情,前面的所有訊號都必須相同。這能檢查實作是否回寫,不能保證原始資料永遠不被資料商修訂。

九格參數和兩段時間都要成立

固定鄰近參數的日夏普差熱圖,正值代表贏同期含息基準

熱圖顏色是策略日夏普減0050日夏普,零是分界。每個設計至少要七格為正,中央設定也要在前後半段各自領先。台股切點為2021年11月25日與11月26日,持倉連續保留,不在切點重新挑一組比較好看的股票。

前半段與後半段日夏普和同期含息基準比較

本次前後半段是同一段歷史的穩健性檢查,沒有獨立樣本外,也沒有發表後測試。Bailey等人(2015)討論回測過擬合風險;反覆嘗試交易規則,再只留下最好的一個,可能讓歷史勝出失去解釋力。這次沒有因為某一格接近基準,就改動雙底間隔或容差再試到過關。

股票池與實際換股

個股股票池每日取60日平均原價成交額前300名,股價至少10元、成交額至少2千萬元、有252日價格。代碼限首碼1至9的四位數個股,ETF另測0050。金融、KY沒有另排除,全額交割未另辨識;未用今天名單回頭挑股票,資料來源缺少的下市標的仍可能造成存活偏差。

當股票先前252日有至少50%單日異動,從隔日起排除;這個限制只根據當時已發生的資料,不預知未來的拆併股或異常。訊號出現後取流動性最高的最多10檔,每檔上限10%,沒有名額的訊號仍計入符合資格買訊。當日收盤決策、次一交易日收盤成交,每日排序會產生額外換股。

表格日夏普不扣無風險利率;互動報告預設扣2%,讀數因此不同。台股使用FinLab sim()預設每邊0.1425%手續費與賣出0.3%證交稅,未再加滑價;0050含息基準直接由還原價連乘,不扣交易成本。股票少於10檔時剩餘現金不分配給其他持股。這個設定避免只找到一個W底時,就假設全部資金集中在那一檔,但也讓選股數和現金比重成為績效的一部分。風險管理指南有更多關於集中持股與回撤的解釋。

設計 符合資格買訊 實際選入次數 平均個股權重固定組夏普 年周轉 單月最高周轉
台股個股・W/M・正向 375 654 1.18 6.80 1.40
台股個股・W/M・避開 375 346 1.41 3.53 0.90
0050・W/M・正向 3 3 1.13 0.32 0.50
0050・W/M・避開 3 4 1.13 0.32 0.50

買訊是原始正向進場事件,避開版因此使用相同計數;實際選入次數反映了排名及重新選入,不能視為同一個指標。年周轉用每日目標權重變動絕對值的一半再乘252,單月最高則逐月加總;這是資金換手強度,與交易勝率無關。

為分辨「訊號好」和「只是現金多」,另算0050乘平均總權重的固定曝險組,以及各股票整段平均權重的固定持有診斷組。後者用了事後平均,只供分解績效,不能直接部署;缺價格的部分視為現金。也把中央設定報酬最高的一年移除,完整數字存入下載檔。四個設計都已在必要檢查失敗,沒有選擇性改用回撤指標宣稱通過。

W底與其他轉折研究怎麼分

雙底只需要三個轉折,頭肩頂與頭肩底需要五個,兩肩之間還有更突出的頭。型態越嚴,訊號可能越稀疏,兩者不能共用訊號數。若使用的是更高高點與更高低點,則接近道氏理論;以均線走平或回測為進場條件,另見葛蘭碧法則。

學習技術分析時,圖形定義、確認時點、執行規則應分開記錄。把W底當作標記行情的語言,可以有助討論;要用它決定資金進出,還需要比較同視窗基準和成本。程式交易完整指南整理把文字規則變成回測的流程,選股研究指南則說明股票池與排名怎麼影響結果。

常見問題

W底第二個低點一定要更低嗎?

本次只要求兩底在容差內,不強制第二個低點更低。加入洗盤、量縮等條件會形成新設計,不能拿本次結果代替。

W底突破後要追價嗎?

回測在訊號日之後的下一交易日收盤成交,沒有保證以頸線價買到。跳空越大,畫圖時想像的進場價與可成交價格可能越遠。

M頭出現就要放空嗎?

本文M頭只用於賣出已持有的股票。放空還涉及借券與回補限制,沒有包含在這組成本與績效中。

為什麼0050訊號那麼少?

相同的間隔、反彈深度與確認規則,套在ETF上未必頻繁成立。這是規則的可用範圍,不能刪掉空手年份來改善指標。

W底和三重底可以合併計算嗎?

不能直接合併。本文只取連續三個轉折,多一個底會改變狀態與觸發時點,應另外固定定義後檢驗。

未通過是否表示技術分析沒用?

只能支持本文的四個設計沒有通過這段資料的驗證。其他交易規則、風險承擔與樣本期間,需要各自研究,不能擴大成所有技術分析的結論。

下載與重跑

可下載逐日淨值 data.csv、完整參數與版本 metrics.json、單一設計 strategy.py,以及整批研究 research.py。整批研究需要把共用 strategy.py放在同一個資料夾;執行 python research.py,會輸出全部參數、各中央設定的回測報告與逐日資料。單篇的程式預設重跑該篇主題;這些規則尚未通過驗證,沒有對應的上架策略。

顯示程式碼
from strategy import load_prices, make_position
from finlab.backtest import sim
 
prices = load_prices("tw")
position, entries = make_position(prices, family="wm")
report = sim(position, position_limit=0.1, upload=False,
             end_date="2026-11-10")
report.to_html("report.html")

範例需先下載同資料夾的程式。環境使用 FinLab 2.3.8、pandas 3.1.1,另需 NumPy、SciPy、Numba、Plotly、Kaleido 與 python-dotenv。資料截至2026年11月10日,重跑日為11月11日;資料日與執行日分開記錄,日後上游修訂可能讓同視窗數值不同。安裝步驟見FinLab設定指南,名詞可查量化交易詞彙。

FinLab量化研究團隊以資料與可重跑規則研究投資方法。本文尚未做發表後的前瞻驗證,也未估算資金容量。

投資有風險,過去績效不代表未來表現。本內容僅供教學參考,不構成投資建議,請依個人風險承受度審慎評估。

最後更新:2026-11|回測區間:2017-01-03至2026-11-10|作者:FinLab量化研究團隊

FinLab AI

想建立自己的策略?

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

免費開始

更多技術指標研究

查看全部