低波動因子選股:5 種指標篩選穩定飆股
認識低波動因子
什麼是低波動因子?
低波動因子是一種量化指標,用來衡量股票或資產在給定期間內的價格波動程度。這些因子通常用於選擇那些價格波動相對較小的股票,並構建低風險的投資組合。常見的低波動因子包括標準差、平均真實波幅(ATR)、最大回撤等。
為什麼要使用低波動因子?
使用低波動因子的主要原因包括:
- 風險管理:低波動因子有助於識別和選擇價格波動較小的股票,從而減少投資組合的整體波動性,降低投資風險。
- 穩定回報:歷史數據顯示,低波動股票在市場下跌時通常表現較好,能提供更穩定的回報 。
- 投資者行為偏差:投資者往往追求高風險高回報的股票,而忽視了低風險的股票。利用低波動因子可以逆勢投資,獲得超額收益 。
如何搭配低波動因子?
在實際應用中,可以將低波動因子與其他因子結合使用,以進一步優化投資組合。例如:
- 多因子模型:將低波動因子與動量因子、價值因子等結合,構建多因子模型,選擇綜合得分最高的股票進行投資。
- 權重分配:根據低波動因子的得分,對投資組合中的股票進行權重分配,增加低波動股票的權重,減少高波動股票的權重。
- 動態調整:定期重新計算和調整投資組合中的低波動因子,保持投資組合的穩定性和優化效果。
學術研究支持
低波動因子在優化投資組合方面的效果已在多項學術研究中得到證實。例如:
- Ang, A., Hodrick, R. J., Xing, Y., & Zhang, X. (2006). “The Cross-Section of Volatility and Expected Returns.” The Journal of Finance, 61(1), 259-299. 研究指出,低波動股票在風險調整後的回報率高於高波動股票 。
- Baker, M., Bradley, B., & Wurgler, J. (2011). “Benchmarks as Limits to Arbitrage: Understanding the Low-Volatility Anomaly.” Financial Analysts Journal, 67(1), 40-54. 該研究分析了低波動異象,並指出低波動股票在多種市場環境下均表現優異 。
透過這些研究,可以更好地理解低波動因子的應用價值及其在投資組合優化中的重要性。
因子的選擇與計算
在低波動策略中,我們會使用多種因子來衡量股票的波動性,以下是一些常見的低波動因子及其數學公式與計算方法:
NATR (Normalized Average True Range)
定義: NATR 是 ATR (Average True Range) 的標準化版本,用來衡量股票價格波動幅度的平均值。
計算公式:

其中,ATR (Average True Range) 的計算方式如下:


TR 表示真實波幅,ATR 表示在 n 天內的平均真實波幅。
標準差 (Standard Deviation)
定義: 標準差用來衡量股票收益率在特定時間窗口內的波動程度。
計算公式:

其中,
是第 i 天的收益率,
是 n 天內的平均收益率。
最低/最高比 (Min/Max Ratio)
定義: 最低/最高比用來衡量股票價格在特定時間窗口內的最低值與最高值之間的比率。
計算公式:

其中,
是第 i 天的收盤價。
最大回撤 (Maximum Drawdown)
定義: 最大回撤用來衡量在特定時間窗口內,股票價格從峰值下跌到谷底的最大跌幅。
計算公式:

其中,
是第 i 天的收盤價。
1/夏普比率 (1/Sharpe Ratio)
定義: 夏普比率用來衡量風險調整後的收益,1/夏普比率是其倒數,用來反映單位風險下的收益波動程度。
計算公式:

其中,
是 n 天內的平均收益率,
是無風險利率,STD_n 是 n 天內的收益率標準差。
這些因子都可以用來衡量股票的波動性,並且可以根據它們的歷史表現來選擇合適的因子進行投資決策。
以下是使用 Python 來計算的程式碼範例:
顯示程式碼
import numpy as np
import pandas as pd
from finlab import data
# 獲取調整後的收盤價
adj = data.get('etl:adj_close')
# 計算低波動因子
indicators = {
'NATR14': data.indicator('NATR', timeperiod=14),
'NATR60': data.indicator('NATR', timeperiod=60),
'STD14': adj.pct_change().rolling(14).std(),
'STD60': adj.pct_change().rolling(60).std(),
'MINMAX14': adj.rolling(14).min() / adj.rolling(14).max() - 1,
'MINMAX60': adj.rolling(60).min() / adj.rolling(60).max() - 1,
'MDD14': (adj / adj.cummax()).rolling(14).min() - 1,
'MDD60': (adj / adj.cummax()).rolling(60).min() - 1,
'1/SHARPE14': adj.pct_change().rolling(14).std() / adj.pct_change().rolling(14).mean(),
'1/SHARPE60': adj.pct_change().rolling(60).std() / adj.pct_change().rolling(60).mean(),
}因子IC值的計算與判斷
Information Coefficient (IC) 是一個衡量因子預測能力的指標,主要用來評估某一因子與未來股票收益率之間的相關性。具體而言,IC 是因子值與未來某一段時間內股票收益率之間的橫截面相關係數。
IC 值提供了因子有效性的度量:
- 正 IC 值:表示因子值與未來收益率之間有正相關性,因子值越高,未來收益率越高。這意味著因子具有良好的預測能力。
- 負 IC 值:表示因子值與未來收益率之間有負相關性,因子值越高,未來收益率越低。這同樣意味著因子具有預測能力,但方向相反。
- IC 值接近 0:表示因子值與未來收益率之間沒有顯著的相關性,因子預測能力較差。
以下是計算IC值的Python代碼:
顯示程式碼
from tqdm import tqdm
from finlab.dataframe import FinlabDataFrame
def ic(factor, adj_close, days=[10, 20, 60, 120]):
if isinstance(factor, pd.DataFrame):
factor = {'factor': factor}
for fname, f in factor.items():
factor[fname] = FinlabDataFrame(f).index_str_to_date()
first_ele = next(iter(factor))
findex = factor[first_ele].index
fcol = factor[first_ele].columns
ind = factor.copy()
adj = adj_close.copy()
inter_index = findex.intersection(adj.index)
inter_col = fcol.intersection(adj.columns)
adj = adj.loc[inter_index]
adj = adj[inter_col]
for fname, f in factor.items():
ind[fname] = ind[fname].loc[inter_index]
ind[fname] = ind[fname][inter_col]
ics = {}
total = len(days) * len(factor)
with tqdm(total=total, desc="Processing") as pbar:
for d in days:
ret = adj.shift(-d-1) / adj.shift(-1) - 1
for fname, f in ind.items():
ic = f.apply(lambda s: s.corr(ret.loc[s.name]), axis=1)
ics[f"{fname}_{d}"] = ic
pbar.update(1)
return pd.concat(ics, axis=1)
ics = ic(indicators, adj)
print(ics.mean().sort_values(ascending=False))
如此一來就可以來計算每個指標的有效程度。由此可見,NATR60 對於預測 120 天後的價格,有比較顯著的優勢。