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

機器學習預測股價沒用?改用 AI 產生交易訊號,
台股 8 年樣本外實測

機器學習預測股價的價位幾乎注定失真。正解是讓模型對全市場做橫截面排序、產生選股訊號。本文用 LightGBM + 12 因子,標籤為次月超額報酬,2019 至 2026 樣本外實測:訊號分組單調有效(第 10 組月超額 2.64%、Rank IC 0.027),但年化 26.0%、最大回撤 -45.8%,仍輸給含息 0050 的 29.9%。附可下載 strategy.py。

機器學習產生台股交易訊號 樣本外累積淨值對比含息0050

核心結論先講:用機器學習直接預測股價的「價位」幾乎注定失真;但把同一套模型拿來對全市場股票做「橫截面排序」、產生選股訊號,在台股 2019 至 2026 的樣本外是有效的。 模型分數最高的一組(第 10 組)次月相對中位數的超額報酬達 2.64%,由低到高大致單調遞增,樣本外 Rank IC 0.027、且 CPCV 15 折全為正。但把訊號做成每月買進前 30 名的策略後,樣本外年化報酬 26.0%、日夏普 0.98、最大回撤 -45.8%,仍輸給同期含息 0050 的年化 29.9%、日夏普 1.38、最大回撤 -34.0%。訊號真的有預測力,做成實際策略卻沒打敗大盤,這兩件事可以同時成立,本文用真實回測把它拆給你看。

關鍵數字表(2019 至 2026 樣本外)

指標 機器學習排序選股 含息 0050
年化報酬(CAGR) 26.0% 29.9%
日夏普比率 0.98 1.38
月夏普比率 0.87 1.25
最大回撤(MDD) -45.8% -34.0%
累積報酬 463.6% 607.4%
樣本外 Rank IC 0.027 不適用
平均月周轉率 164% 約 0%

回測區間 2019-01 至 2026-06,模型只用 2018 年底以前的資料訓練,2019 年起為完全未見過的樣本外資料。交易成本由 finlab sim() 內扣(手續費 0.1425%、證交稅 0.3%)。基準為含息 0050(etl:adj_close 還原價買進持有),對齊同一視窗。

為什麼「預測股價」這條路走不通

把股價當成一條時間序列、要模型輸出「明天收盤價是多少」,看起來很自然,實務上卻有兩個致命問題。

第一,股價不是穩定(stationary)的序列。它的平均值與波動會隨時間漂移,今天訓練好的數值關係,到了下一個多空循環就失效。模型為了在訓練集把誤差壓低,往往退化成「用昨天的價格猜今天」,結果就是大家熟知的預測延遲:預測曲線永遠比真實價格慢半拍,看起來很貼近,拿去交易卻一文不值,因為等訊號出現,行情早就走完了。

第二,就算誤差很小,也不代表能賺錢。預測值與真實值的均方誤差(MSE)衡量的是「猜得準不準」,但交易要的是「方向對不對、相對強弱排得對不對」。一個 MSE 很低的模型,可能在每個轉折點都站錯邊。Gu, Kelly & Xiu (2020) 在橫跨數十年的美股大型實證裡就指出,機器學習對資產報酬的價值,主要來自橫截面的相對排序,而非對單一資產價位的點預測。

正確用法:用模型產生「排序訊號」

換個問法,問題就變得可解:不要問「這檔股票會漲到多少」,改問「這檔股票下個月會不會贏過市場上一半的股票」。 這是一個橫截面排序問題,輸出是一個相對分數,不是絕對價位。

落到 finlab 的實作上,這對應到 finlab.ml.label.excess_over_median:它把每一檔股票「次月相對全市場中位數的超額報酬」當成學習標籤。模型學的是「誰會贏過中位數」這個排序關係,而不是「股價會到幾元」。每個月底,模型對全市場每一檔流動性足夠的股票打一個分數,我們做多分數最高的前 30 名,下個月底再重排一次。

這段就是核心程式碼,複製即可在 finlab 跑

下面這段把流程拆成「組特徵 → 設標籤 → 訓練 → 每月選前 30 名 → 回測」五步,你可以直接貼進 finlab 環境執行。完整版本(含 CPCV 穩健性檢查與繪圖)在文末提供下載。

顯示程式碼
import finlab
from finlab import data
import finlab.ml.feature as mlf
import finlab.ml.label as mll
from finlab.backtest import sim
from lightgbm import LGBMRegressor
 
finlab.login()  # finlab 會在需要資料時自動引導登入
 
# 步驟一:組多因子特徵矩陣(技術面 + 基本面 + 籌碼面),月頻
features = {
    "rsi": data.indicator("RSI"),
    "mom": data.indicator("MOM", timeperiod=120),
    "adx": data.indicator("ADX"),
    "price_pos": data.get("price:收盤價") / data.get("price:收盤價").rolling(240).mean(),
    "pb": data.get("price_earning_ratio:股價淨值比"),
    "rev_yoy": data.get("monthly_revenue:去年同月增減(%)"),
}
X = mlf.combine(features, resample="ME")
 
# 步驟二:標籤 = 次月相對中位數的超額報酬(排序訊號,而非價位預測)
y = mll.excess_over_median(X.index, resample="ME")
 
# 步驟三:只用 2018 年底以前的資料訓練模型
dt = X.index.get_level_values("datetime")
train = dt <= "2018-12-31"
model = LGBMRegressor(n_estimators=400, num_leaves=31, learning_rate=0.05)
model.fit(X[train].fillna(0), y[train])
 
# 步驟四:對全市場打分,每月做多分數最高的前 30 名
score = model.predict(X.fillna(0))
score = pd.Series(score, index=X.index).unstack("instrument")
position = score.rank(axis=1, ascending=False) <= 30
 
# 步驟五:回測,內扣手續費與證交稅
report = sim(position, resample="M", fee_ratio=0.001425, tax_ratio=0.003)
report.display()

整個流程沒有一個地方在預測價位。模型輸出的是一個排序分數,交易訊號來自「分數排在前面」這個相對位置。這正是早年用深度學習模型解析 K 線、標註轉折點的研究想表達、卻沒有用樣本外回測與對帳單證明的論點,本文把它補上。

樣本外驗證:訊號分組是否單調有效

一個排序訊號好不好,最直接的檢驗是把它分成十組,看「模型越看好的組,未來報酬是不是越高」。下圖是 2019 至 2026 樣本外的結果:橫軸是模型分數由低到高分成 10 組,縱軸是各組「次月相對中位數的超額報酬」月平均。

樣本外模型分數分組的次月超額報酬 第10組最高呈單調遞增

第 1 組(最不看好)月超額 1.68%,第 10 組(最看好)2.64%,由低到高大致單調遞增,第 6 組之後明顯墊高。整體樣本外 Rank IC 為 0.027。這張圖取代了舊版文章那種「事後挑一段漂亮走勢、畫上轉折點」的示意圖:這裡的每一個數字都來自模型在訓練時完全沒看過的期間,沒有事後諸葛的空間。

需要說明的是,這十組的超額報酬全都是正的(1.4% 到 2.6%)。原因是流動性宇宙裡的中型股,在這段期間整體就比全市場中位數強;訊號的價值在於組與組之間的「斜率」,也就是它能把相對更強的標的排到前面,而不在於某一組是正是負。

不是靠某一次切分的運氣:CPCV 15 折檢驗

只跑一次「訓練 2018 以前、測試 2019 以後」的切分,可能只是運氣好。為了排除這點,本文採用 López de Prado (2018) 提出的 CPCV(Combinatorial Purged Cross-Validation,組合式淨化交叉驗證):把樣本切成 6 段、每次抽 2 段當測試集,並在訓練與測試的邊界加上淨化(purge)缺口,避免標籤跨期偷看未來。6 段抽 2 段共有 15 種組合,等於 15 個獨立的樣本外切分。

CPCV十五折樣本外Rank IC全為正 平均0.030

15 折的 Rank IC 全部為正,落在 0.015 到 0.048 之間,平均 0.030。沒有任何一折出現負值。這代表「模型分數能正向排序次月報酬」這件事,並非單一切分的偶然。

訊號有效,為什麼策略還是輸 0050

這是本文最重要、也最容易被略過的一段。訊號的橫截面排序力(Rank IC 為正)與「把訊號做成策略後能否打敗大盤」是兩個不同層次的問題。 把上面那個排序訊號做成「每月買前 30 名」的實際策略,樣本外的成績是這樣:

機器學習選股樣本外回撤更深 最大回撤-45.8% vs 0050的-34.0%

樣本外年化報酬 26.0%,輸給含息 0050 的 29.9%;最大回撤 -45.8%,比 0050 的 -34.0% 還深超過 10 個百分點。也就是說,承擔了更高的風險,換到的卻是更低的報酬,日夏普 0.98 對 1.38,風險調整後完全落後。原因有三個,都很實在。

第一,平均每月周轉率 164%,意思是每個月幾乎整批換股。即使每筆已內扣手續費與證交稅,高頻換股仍會持續啃食報酬,這是排序型訊號天生的弱點。

第二,2019 至 2026 這段期間,台股大型權值股(台積電為首)特別強,而含息 0050 高度集中在這些權值股。一個分散到 30 檔中型股的策略,先天就難贏過押注在少數超級強勢股的指數。

第三,訊號的 Rank IC 雖然穩定為正,但 0.027 的量級偏小。它足以讓「分組單調」這件事成立,卻不足以在扣掉成本與承擔額外波動後,轉化成超越大盤的淨績效。

下面是這個策略的完整互動式回測報告,你可以自行檢視每月持股、年度報酬與回撤明細:

過度配適的代價:樣本內亮眼、樣本外現形

如果只看樣本內,這個模型會讓人誤以為找到聖杯。下圖把樣本內與樣本外的同口徑指標並排(縱軸為對稱對數軸,因為兩者量級差距極大)。

過度配適 樣本內CAGR338%夏普6.8 樣本外驟降至26%夏普0.98

樣本內 Rank IC 0.529、年化 338%、日夏普 6.79,數字漂亮到不真實,因為模型在訓練時已經透過標籤「看過」那段期間的答案。一進到樣本外,Rank IC 掉到 0.027、年化 26.0%、日夏普 0.98。這個落差就是過度配適的代價,也是為什麼任何宣稱機器學習選股年化三位數的成績,只要沒有嚴格的樣本外切分,都應該直接打上問號。關於如何量化一個策略過擬合的機率,可參考用回測過擬合機率判斷策略真實力

模型究竟在看什麼?下圖是 LightGBM 的特徵重要度。

LightGBM特徵重要度 股價位置與量能比與估值並重

排在前面的是「股價相對 240 日均線的位置」「量能比」「本益比」「月營收月增率」,技術面的價量位置與基本面的估值並重,而非單純追逐某一個技術指標。這也呼應一個常見誤解:把一堆技術指標丟給模型,它不會自動變強;真正有貢獻的,往往是把價量、估值、營收動能、籌碼放在一起的橫截面比較。想知道單一技術指標各自當選股因子的真回測表現,可參考13 個常用技術指標總覽,裡面把 RSI、MACD、均線、ATR 等指標一一拆成因子與風控做了台股長期實測;本文等於把這些指標放進同一個模型,讓它自己學習彼此的相對權重。

機器學習選股的三個過度配適陷阱,以及這份研究怎麼防

網路上多數「AI 預測股價」「機器學習選股年化破百」的內容,問題不在演算法,而在三個反覆出現、卻很少被攤開的過度配適陷阱。這份研究的設計,主要就是針對這三點做防護,把它寫清楚比給一個漂亮數字更有意義。

第一個陷阱是時間洩漏(look-ahead leakage)。最常見的形式,是用一段期間的全部資料訓練、又在同一段期間回測,模型早就透過標籤「看過」答案。本文的樣本內成績正是這個樣子:Rank IC 0.529、年化 338%、日夏普 6.79,數字漂亮到不真實。防護方式是嚴格的時間切分加上 CPCV 的淨化缺口:模型只用 2018 年底以前的資料訓練,2019 年起完全是它沒看過的期間;CPCV 在訓練與測試的邊界再加 31 天淨化缺口,避免次月報酬這種跨期標籤偷看到測試集的未來。一旦把洩漏堵掉,Rank IC 立刻從 0.529 掉到 0.027,這個落差就是洩漏被擠出去後的真實樣貌。

第二個陷阱是只跑一次切分就宣稱有效。單一次「訓練前段、測試後段」的好成績,可能只是剛好那一刀切在對的位置。本文用 CPCV 把樣本切成 6 段、每次抽 2 段當測試集,6 段抽 2 段共 15 種組合,等於 15 條獨立的樣本外路徑。15 折的 Rank IC 全部為正、落在 0.015 到 0.048,沒有任何一折翻負,這才讓「訊號存在」這個結論不依賴某一次幸運的切分。

第三個陷阱是忽略成本與周轉,用無摩擦的紙上績效誇大結論。一個每月幾乎整批換股、平均月周轉率 164% 的策略,若不扣手續費與證交稅,淨值曲線會比實際好看一大截。本文的回測由 finlab sim() 內扣手續費 0.1425% 與證交稅 0.3%,因此呈現出來的樣本外年化 26.0%、日夏普 0.98,是扣掉成本後的數字。也正是把成本算進去之後,這個訊號雖然 Rank IC 穩定為正,卻沒能在扣成本與承擔更深回撤後贏過含息 0050。更多回測與實單之間的落差,可參考回測限制與回測陷阱:過度擬合、流動性與實務落差

把這三點對照來看就會發現:舊版那種「事後挑一段漂亮走勢、畫上轉折點、宣稱抓到頂底」的示意圖,恰好同時踩中第一與第二個陷阱(用看過的資料、只展示一段),又完全沒回答第三點(沒有對帳單、沒有成本)。本文用真實樣本外回測把這三件事補上,結論即使不漂亮,也是可以被你自己重跑驗證的。我們也把機器學習選股的模擬對帳單每天公開,讓績效在時間裡接受檢驗,而不是只截一張漂亮的圖。

回測方法與口徑限制

把這些數字怎麼算出來的講清楚,比給一個漂亮數字更重要。

  • 交易成本: finlab sim() 預設並由本文明確指定內扣手續費 0.1425%、證交稅(賣出)0.3%。
  • 滑價: 未額外假設滑價;實際衝擊取決於資金規模與個股成交量,本文未估算策略容量。
  • 股票池: 全上市櫃,並以 60 日平均成交額大於 5,000 萬作為流動性過濾,排除代號 00 開頭的 ETF。未特別排除金融股與 KY 股。
  • 前視偏差: 特徵均為月底可得資料;月營收用 finlab 對齊後的公布期數,價量與估值用月底收盤計算;標籤用次月報酬,並在 CPCV 訓練與測試邊界加 31 天淨化缺口。
  • 權重: 等權,單檔上限設 10%。
  • 周轉率: 平均每月約 164%,屬高周轉,成本敏感。
  • 樣本內外: 模型只用 2018 年底前資料訓練,2019 年起為樣本外;另以 CPCV 15 折交叉驗證穩健性。

把可重現的程式碼與資料一起附上,是為了讓你能自己驗證、甚至推翻本文的結論。讀到這裡想自己動手,用一句話讓 AI 幫你把 finlab 環境設好,再用真實台股資料跑一次這個排序訊號的回測:

免費試用

用 AI 開始 FinLab

把這句話交給你的AI,它會帶你完成設定並做出第一個策略。

告訴你的AI:

幫我設定 FinLab,用機器學習對台股做橫截面排序產生選股訊號並回測,請讀:https://finlab.finance/setup?relatedUrl=/blog/machine-learning-predict-stock-price

適合誰、不適合誰

這套方法適合:想理解「機器學習在量化選股裡的正確定位」、願意接受訊號有效但不保證打敗大盤、並且想用真實樣本外回測檢驗每一個宣稱的人。它不適合:想找一鍵賺錢黑盒、或只看樣本內漂亮數字就下重注的人。本文的結果其實是個好消息:它示範了一套可重現、把成本與限制都攤開的研究流程,能讓你在投入真金白銀前,就分辨出「訊號有沒有用」與「策略能不能賺」這兩個不同的問題。

常見問題

機器學習真的完全無法預測股價嗎? 預測「精確價位」在實務上幾乎注定失真,因為股價非穩定序列、且低誤差不等於可獲利。但預測「橫截面相對排序」是可行的:本文樣本外 Rank IC 為正、分組單調,就是證據。

為什麼標籤要用次月超額報酬,而非原始報酬率? 因為相對中位數的超額報酬把「整體大盤漲跌」這個共同因子扣掉了,模型專注學習「誰相對更強」,這正是選股要的。若改以絕對報酬當標籤,模型會被多空頭的市場 beta 主導。

這個策略現在能照單買進嗎? 不建議。它在樣本外輸給含息 0050、且回撤更深。本文的價值在於方法示範與訊號驗證,並非提供一份可照抄的下單清單。

Rank IC 只有 0.027 會不會太低? 單因子或單模型月頻 Rank IC 約 0.03 到 0.05 就算可用。0.027 偏低但穩定為正,足以證明訊號存在,卻不足以在扣成本後贏過大盤。延伸閱讀:Rank IC 是什麼,和 Pearson IC 差在哪

怎麼把這個訊號改善成能打敗大盤? 方向包括降低周轉(拉長持有期、加入換股緩衝)、疊加品質與低波因子降低回撤、或把訊號當成擇股輔助而非全部。可參考多因子選股策略:營收+動能+ROE+低波

CPCV 跟普通交叉驗證差在哪? 普通交叉驗證會讓相鄰時間的樣本互相洩漏未來資訊。CPCV 在訓練與測試邊界加淨化缺口,並用多種組合取得多條樣本外路徑,對時間序列更嚴謹。

延伸閱讀

參考文獻

  • Gu, Kelly & Xiu (2020), Empirical Asset Pricing via Machine Learning:大型實證指出機器學習對報酬的價值主要來自橫截面排序,而非單一資產的價位點預測,直接支持本文「用排序訊號取代價位預測」的設計。
  • Jegadeesh & Titman (1993), Returns to Buying Winners and Selling Losers:動能效應的經典證據,支持以相對強弱(橫截面排序)作為選股訊號的合理性,也解釋為何本文的價量位置特徵重要度偏高。
  • López de Prado (2018), Advances in Financial Machine Learning:提出 CPCV 與淨化交叉驗證,用於避免時間序列回測的資訊洩漏與過度配適,是本文 15 折穩健性檢驗的方法依據。

下載與重現


投資警語:本文為機器學習量化選股的方法教學與回測說明,所有數據與範例僅供研究參考,不構成投資建議。過去績效不代表未來表現,本文策略在樣本外輸給含息 0050,投資前請自行評估風險。

最後更新:2026-06|回測區間:2019-01 至 2026-06 樣本外(訓練資料 2010 至 2018)|作者:FinLab 量化研究團隊(經量化研究員審閱)

FinLab AI

想建立自己的策略?

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

免費開始

更多AI 與程式研究

查看全部