跳轉到

因子擁擠度分析

研究因子分析,增減修改因子,不再靠感覺。以下是 FinLab Package 提供的因子分析流程:

原始數據
    |
    |--- 特徵工程 -----> 因子特徵 (Features)
    |
    +--- 標籤工程 -----> 超額報酬 (Labels)
                |
                |--- calc_factor_return() -----> 因子報酬
                |      |
                |      +-- calc_centrality() --> 因子集中度
                |
                |--- calc_shapley_values() ----> 因子貢獻度
                |
                +--- calc_ic() ----------------> 因子相關性(IC)
  1. 先產生特徵與標籤 (features, labels),特徵是因子,標籤是股票的超額報酬
  2. 計算因子報酬: calc_factor_return(features, labels)
  3. 計算因子擁擠度: calc_centrality(factor_return, window)
  4. 計算因子貢獻度: calc_shapley_values(features, labels)
  5. 計算因子相關性 (IC): calc_ic(features, labels)
  6. 計算因子相關性 (RankIC): calc_rank_ic(features, labels)

範例策略

此策略是由非常基本的三個因子組成:

  1. 市值
  2. 營收
  3. 動能

我們先來看此策略的績效:

from finlab import data
from finlab.backtest import sim

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

cond1 = marketcap.rank(pct=True, axis=1) < 0.3
cond2 = (revenue.average(3) / revenue.average(12)).rank(pct=True, axis=1) > 0.7
cond3 = (price / price.shift(20)).rank(pct=True, axis=1) > 0.7

pos = cond1 & cond2 & cond3

report = sim(pos, resample='ME', upload=False)
report.creturn.plot()

分析因子,先產生特徵與標籤

使用 feature.combine() 將多個因子條件整合成特徵矩陣,並用 label.excess_over_mean() 計算未來一個月的超額報酬作為標籤。

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

features = feature.combine({
    'marketcap': cond1,
    'revenue': cond2,
    'momentum': cond3
}, resample='ME')

# 計算未來 1M 的標籤
labels = label.excess_over_mean(index=features.index, resample='ME')

features.dropna().head()
labels.dropna().head()

因子報酬 (Factor Return)

因子報酬(Factor Return)是衡量某因子在一段時間內所帶來超額報酬的指標,常用於評估因子的有效性與投資價值。

在本分析流程中,會先根據不同的因子(如市值、營收成長、動能等)建立特徵,並計算每個因子的因子報酬。透過累積因子報酬的走勢,可以觀察該因子的長期表現與穩定性,進一步作為因子篩選與組合的重要依據。

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

plot_line(
    calc_factor_return(features, labels).cumsum(),
    unit='.0%',
    title='Factor Cumulative Return'
)

圖中,可以觀察月營收因子效果顯著比較好,但市值因子效果較差。

因子集中度 (Factor Centrality)

因子集中度(Factor Centrality),是用來量化「共同性」的指標。

因子集中度(Centrality)定義如下:

\[ \text{Centrality}_i = \frac{\lambda_i}{ \sum_{j=1}^{k}\lambda_j} \]

其中,\(\lambda_j\) 為因子對於第一主成分的佔比,\(k\) 為因子總數。

此指標反映了因子報酬的共同性:

  • 數值越大表示:
    • 利用此因子選股,在近期績效比較好。
    • 集中度越高,進而增加未來回檔的風險,需密切觀察。
  • 數值越小表示:
    • 利用此因子選股,在近期績效較差。
    • 集中度越低,未來回檔的風險較低。
    • 可以在因子擁擠度較低的時候,密切觀察,等擁擠度上升時,馬上利用此因子選股。
from finlab.tools.factor_analysis import calc_centrality
from finlab.plot import plot_line

plot_line(
    calc_centrality(calc_factor_return(features, labels), 12),
    title='Centrality'
)

上圖中,當市值因子目前擁擠度較低,可以換一個因子,讓策略更穩定。

另外,也可以密切觀察市值因子,等擁擠度上升時,馬上利用此因子選股。

Shapley Values

Shapley Values 是一種用於量化各個因子對投資組合報酬的貢獻度,是一種公平分配的數學方法。

我們枚舉所有可能的因子組合,計算每個因子組合的報酬,並計算每個因子對報酬的貢獻度。我們甚至可以計算出,每個因子、每個時間點,對報酬的貢獻度。

值得一提的是,Shapley Values 的計算時間複雜度為 \(O(2^n)\),其中 \(n\) 為因子個數,因此計算時間較長,在因子個數較多時,建議使用其他方法。

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

plot_line(calc_shapley_values(features, labels))

因子 IC (Information Coefficient)

因子 IC(Information Coefficient)是衡量因子預測能力的重要指標,常用於評估因子與未來報酬之間的相關性。

IC 的計算公式如下:

\[ IC = \text{corr}(\text{Factor Score}, \text{Future Return}) \]

其中,\(\text{corr}\) 表示相關係數(通常為皮爾森相關),\(\text{Factor Score}\) 為因子分數,\(\text{Future Return}\) 為未來一段期間的資產報酬。

IC 數值範圍通常在 -1 到 1 之間:

  • IC 越接近 1,表示因子對未來報酬有很強的正向預測能力。
  • IC 越接近 -1,表示因子對未來報酬有很強的反向預測能力。
  • IC 接近 0,表示因子對未來報酬幾乎沒有預測能力。

在量化選股中,IC 是判斷因子有效性的重要依據,IC 越高的因子通常更值得納入投資組合。

注意:計算 IC 時,特徵需要使用連續數值而非布林條件,因此這裡重新定義特徵:

from finlab.tools.factor_analysis import calc_ic

features = feature.combine({
    'marketcap': -marketcap,                          # 小市值
    'revenue': revenue.average(3) / revenue.average(12),
    'momentum': price / price.shift(20)
}, resample='ME')

plot_line(calc_ic(features, labels, rank=True))