如何分析因子¶
研究因子分析,增減修改因子,不再靠感覺 以下是 FinLab Package 提供的因子分析流程:
原始數據
│
├─── 特徵工程 ────→ 因子特徵 (Features)
│
└─── 標籤工程 ────→ 超額報酬 (Labels)
│
├─── calc_factor_return() ────→ 因子報酬
│ │
| └── calc_centrality() ─→ 因子集中度
│
├─── calc_shapley_values() ───→ 因子貢獻度
│
└─── calc_ic() ───────────────→ 因子相關性(IC)
- 先產生特徵與標籤(features, labels),特徵是因子,標籤是股票的超額報酬
- 計算因子報酬:
calc_factor_return(features, labels)
- 計算因子擁擠度:
calc_centrality(factor_return, window)
- 計算因子貢獻度:
calc_shapley_values(features, labels)
- 計算因子相關性(IC):
calc_ic(features, labels)
- 計算因子相關性(RankIC):
calc_rank_ic(features, labels)
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()
Your version is 1.3.0, please install a newer version. Use "pip install finlab==1.4.0" to update the latest version.
請從 https://ai.finlab.tw/api_token 複製驗證碼: 輸入成功! 之後可以使用以下方法自動登入 import finlab finlab.login("YOUR API TOKEN")
<Axes: xlabel='date'>
分析因子,先產生特徵與標籤¶
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()
marketcap | revenue | momentum | ||
---|---|---|---|---|
datetime | instrument | |||
2013-04-30 | 1101 | False | True | True |
1102 | False | True | True | |
1103 | False | True | False | |
1104 | False | True | False | |
1108 | False | True | False |
labels.dropna().head()
datetime instrument 2007-04-30 1101 0.042548 1102 0.081764 1103 -0.016863 1104 -0.047492 1108 -0.002247 dtype: float64
因子報酬(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
plot_line(calc_centrality(calc_factor_return(features, labels), 12), title='Centrality')
Rolling Centrality: 148it [00:00, 733.93it/s]
上圖中,當市值因子目前擁擠度較低,可以換一個因子,讓策略更穩定。
另外,也可以密切觀察市值因子,等擁擠度上升時,馬上利用此因子選股。
Shapley Values¶
Shapley Values 是一種用於量化各個因子對投資組合報酬的貢獻度,是一種公平分配的數學方法。
我們枚舉所有可能的因子組合,計算每個因子組合的報酬,並計算每個因子對報酬的貢獻度。
我們甚至可以計算出,每個因子、每個時間點,對報酬的貢獻度。
值得一提的是,Shapley Values 的計算時間複雜度為 $O(2^n)$,其中 $n$ 為因子個數,因此計算時間較長,在因子個數較多時,建議使用其他方法。
from finlab.tools.factor_analysis import calc_shapley_values
plot_line(calc_shapley_values(features, labels))
WARNING finlab.tools.factor_analysis:factor_analysis.py:calc_shapley_values()- Feature and label date indices do not match exactly Calculating Shapley values: 100%|██████████| 7/7 [00:01<00:00, 6.42it/s]
因子 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 越高的因子通常更值得納入投資組合。
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))