把「靈感」煉成「因子」:從感覺到證據的逆襲

  • Post author:
  • Reading time:8 mins read
image 2
封面圖片

你一定懂那種瞬間——螢幕上跳出一檔飆股,心裡直覺「它會漲」。但直覺不會每次都對。於是我們決定反過來做:把靈感拆成可驗證的「因子」,把「為什麼漲」說清楚,然後用資料驗證。

難嗎?不簡單。因為我們有工具可以把難的事做得乾淨俐落。

和一般做法,哪裡不一樣?

一般做法:先選幾個看起來厲害的指標,湊一套回測;結果好就覺得是神功,結果差就再換一套。

我們的做法:先把策略拆解,再逐一檢驗每個因子的線索:它帶來的超額報酬是多少?在什麼狀態下有效?會不會太擁擠(大家都在用)?彼此相關性高不高?

沒有 Finlab 我們得自己處理:資料下載、清洗、對齊、換股對齊、月/季頻率對接… 一個環節錯了,結果就不可信。

有了 finlab,我們可以直接用一致頻率的資料集與安全的 resample 邏輯,把時間對齊、避免偷看未來;剩下的,就是認真跟資料搏鬥。

我們的範例策略:

三個最基本、卻常被忽略「為什麼」的因子:市值、營收動能、價格動能。

  • 為什麼要小市值?因為小市值在資訊修正與資金挹注時,彈性常常更大。
  • 為什麼看營收加速?因為是最扎實的推力。
  • 為什麼要動能?因為市場的從眾與慣性,往往延長趨勢。
from finlab import data, backtest

marketcap = data.get('etl:market_value')
revenue   = data.get('monthly_revenue:當月營收')
close     = data.get('price:收盤價')

cond_smallcap = marketcap.rank(pct=True, axis=1) < 0.3
cond_revgro   = (revenue.average(3) / revenue.average(12)).rank(pct=True, axis=1) > 0.7
cond_momentum = (close / close.shift(20)).rank(pct=True, axis=1) > 0.7

pos = cond_smallcap & cond_revgro & cond_momentum
report = backtest.sim(pos, resample='ME', upload=False)
report.display()

為什麼要用 rank?比較的是「相對位置」,而不是絕對數值。

CleanShot 2025 08 22 at 10.46.02@2x
回測結果

把策略拆成可驗證的語言:特徵 & 標籤

先定義我們「到底要預測什麼」:未來一段時間的超額報酬(相對市場平均)。這是策略的真目標,而不是單看漲跌。

from finlab import data
import finlab.ml.feature as feature
import finlab.ml.label as label

features = feature.combine({
    'marketcap' : cond_smallcap,
    'revenue'   : cond_revgro,
    'momentum'  : cond_momentum
}, resample='ME')

labels = label.excess_over_mean(index=features.index, resample='ME')

為什麼用超額報酬? 因為我們將焦點從「追隨市場」轉向「超越對手」。我們比較的不是大盤的絕對速度,而是相對於競爭者的反應速度。

因子報酬(Factor Return):它到底有沒有賺到「解釋力」?

把每個因子的「獨立效果」抽出來,看長期累積報酬線條。線條不只代表報酬,更是「這個因子值得被相信」的證詞。

from finlab.tools.factor_analysis import calc_factor_return
from finlab.plot import plot_line

factor_return = calc_factor_return(features, labels).cumsum()
plot_line(factor_return, unit='.0%', title='因子累積報酬')
CleanShot 2025 08 22 at 11.03.52
因子累積報酬

為什麼先看累積線? 因為短期雜訊會騙人,長期線條的斜率與轉折,才能看出它是偶然還是規律。

因子集中度(Centrality):因子擁擠嗎?

當一個因子被同時大量採用,接著因子趨向擁擠、碰到回檔風險上升。我們用主成分分析的權重,量化「共同性」。

  • 數值大:近期用它選股都賺,表示擁擠;下一步要警戒回檔
  • 數值小:近期表現差,反而可能接近「冷門反擊」的起點。
from finlab.tools.factor_analysis import calc_centrality
centrality = calc_centrality(calc_factor_return(features, labels), 12)

plot_line(centrality, title='因子集中度')
CleanShot 2025 08 22 at 11.12.41@2x
因子集中度

為什麼要看擁擠度? 因為市場是動態的,當所有人一起衝進同一個因子,邊際報酬就會變脆弱。

因子貢獻度 (Shapley Values):把功勞分清楚

我們不只看「有賺」,還要知道「誰在出力」。Shapley 用公平分配的方式,拆解各因子的邊際貢獻。

from finlab.tools.factor_analysis import calc_shapley_values
shapley = calc_shapley_values(features, labels)
plot_line(centrality, title='因子貢獻度')
CleanShot 2025 08 22 at 11.16.23@2x
因子貢獻度

為什麼要拆貢獻? 因為多因子策略容易「誰都沾一點」,但在壓力時刻,你要知道要砍誰、留誰。

IC(Information Coefficient):預測力的體檢表

我們把分數和未來報酬做相關(可用 rank),長期 IC 穩定偏正、且不是只靠少數極端時期拉高,才叫做真正的「可預測」。

from finlab.tools.factor_analysis import calc_ic

features_ic = {
    'marketcap': -marketcap,  # 小市值用負號
    'revenue'  : revenue.average(3) / revenue.average(12),
    'momentum' : close / close.shift(20),
}
features_ic = feature.combine(features_ic, resample='ME')

ic_df = calc_ic(features_ic, labels, rank=True)
plot_line(ic_df, title='因子相關性')
CleanShot 2025 08 22 at 11.35.02@2x
因子相關性

為什麼要看 IC? 因為報酬可能來自風格或偶然,但「相關性」在長期裡更難偽裝。

趨勢偵測:隨時間變化數值

我們用回歸去看「集中度、貢獻、IC」的趨勢:上升?下降?還是平?

from finlab.tools.factor_analysis import calc_regression_stats
centrality_trend = calc_regression_stats(centrality)

  • p 值小 + 斜率正:真正在升溫;
  • p 值小 + 斜率負:退潮真正發生;
  • 解釋力低(R²小):暫時別下定論,當它不存在。
p_valuer_squaredslopetrend含義
up強烈且穩定的上升趨勢
down強烈且穩定的下降趨勢
任意flat趨勢存在但效果小/雜訊大
任意flat樣本少,雜訊高,無法判斷
任意flat基本無趨勢且模型無解釋力

實例分析

  • Marketcap (市值因子)

slope: -0.000111 (負值)
p_value: 3.10e-17 (極度顯著)
r_squared: 0.40 (中等偏強解釋力)
trend: down

解讀: 市值因子的集中度呈現非常強烈且統計上極度顯著的下降趨勢。

  • Revenue (營收因子)

slope: 0.000018 (正值)
p_value: 0.0048 (顯著)
r_squared: 0.056 (解釋力較弱)
trend: flat (因 r_squared < 0.1)

解讀: 營收因子有統計上顯著的上升趨勢,但由於解釋力不足 (r_squared < 0.1),被歸類為 flat。

  • Momentum (動能因子)

slope: 0.000093 (顯著正值)
p_value: 1.14e-17 (極度顯著)
r_squared: 0.41 (中等偏強解釋力)
trend: up

解讀: 動能因子的集中度呈現非常強烈且統計上極度顯著的上升趨勢。這是一個明確的信號,表明動能因子非常「熱門」,大量資金正在追逐這個策略。

為什麼做趨勢? 因為資金有輪動。與其死守某一信仰,不如跟著證據調整權重。

總結

解決分析前的難點

  • 多頻資料對齊:日價、月營收、季財報……沒有統一索引會災難。
  • 風險:偷看未來、不同頻率窗口誤用,都會讓結果「看起來很美」。
  • 擁擠:策略跑出來以後,大家都用,它就不香了。這就是為什麼Centrality趨勢偵測是必要的。
  • 因子工具把「報酬、擁擠、貢獻、IC」變成可重複的研究流程。

行動建議:你可以直接用這篇當「研究框架」模板

  1. 用 feature.combine/label.excess_over_mean 定義問題;
  2. 跑 因子報酬 / 集中度 / Shapley / IC / 趨勢 五件套;
  3. 用趨勢結果去調整權重,而不是迷信單因子。

歡迎參考 Colab 範例檔