策略範例
因子擁擠度分析
本頁內容6
研究因子分析,增減修改因子,不再靠感覺。這一頁用一個由市值、營收、動能三個因子組成的策略,示範 FinLab 提供的因子分析流程,適合手上已有多條件策略、想知道哪個條件真正有效的人。
分析流程
原始數據
|
|--- 特徵工程 -----> 因子特徵 (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_ic(features, labels, rank=True)
策略邏輯
這個策略由非常基本的三個因子組成,三個條件同時成立才買進:
- 市值:每天在所有股票中,市值排名最小的 30%。
- 營收:近 3 個月平均營收 ÷ 近 12 個月平均營收,排名最高的 30%。
- 動能:近 20 日的漲幅(
price / price.shift(20)),排名最高的 30%。 - 換股:每月一次(
resample='ME')。
完整程式碼
先看這個策略的績效:
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()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)衡量某個因子在一段時間內帶來的超額報酬,常用來評估因子的有效性與投資價值。依不同的因子(如市值、營收成長、動能)建立特徵後,計算每個因子的因子報酬;累積因子報酬的走勢可以看出該因子的長期表現與穩定性,作為因子篩選與組合的重要依據。
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)是用來量化「共同性」的指標,定義如下:
其中, 為因子對於第一主成分的佔比,$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)
calc_shapley_values 枚舉所有因子組合,每個時間點取同時符合組合內所有因子的股票的等權平均超額報酬(沒有股票時記 0),平分給組合內的每個因子;每個因子的貢獻度,是它參與的所有組合分到的報酬總和。值越高,代表含有該因子的組合表現越好。
名稱雖叫 Shapley,但這不是賽局論的 Shapley 值:它沒有計算加入某個因子前後的報酬變化,各因子的值加總也不等於所有因子同時成立時的報酬。
from finlab.tools.factor_analysis import calc_shapley_values
from finlab.plot import plot_line
plot_line(calc_shapley_values(features, labels))算出因子 IC
因子 IC(Information Coefficient)是衡量因子預測能力的重要指標,常用於評估因子與未來報酬之間的相關性:
其中, 表示相關係數(通常為皮爾森相關), 為因子分數, 為未來一段期間的資產報酬。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))怎麼調整
- 換因子:改
feature.combine()裡的字典,增加、刪除或修改因子,再重跑上面的分析。 - 集中度的視窗
calc_centrality(..., 12):第二個參數是window,計算集中度時取的期數。 - IC 或 RankIC
calc_ic(..., rank=True):rank=True算 RankIC;不加rank=True就是 IC。
下一步
這一頁有幫到你嗎?