原文鏈接:http://tecdat.cn/?p=20360
本文將說明金融數學中的R 語言優化投資組合,因子模型的實現和使用。
具有單一市場因素的宏觀經濟因素模型
我們將從一個包含單個已知因子(即市場指數)的簡單示例開始。該模型為
其中顯式因子ft為S&P 500指數。我們將做一個簡單的最小二乘(LS)回歸來估計截距α和加載β:
大多數代碼行用於准備數據,而不是執行因子建模。讓我們開始准備數據:
-
-
-
# 設置開始結束日期和股票名稱列表
-
begin_date <- "2016-01-01"
-
end_date <- "2017-12-31"
-
-
-
# 從YahooFinance下載數據
-
data_set <- xts()
-
for (stock_index in 1:length(stock_namelist))
-
data_set <- cbind(data_set, Ad(getSymbols(stock_namelist[stock_index],
-
from = begin_date, to = end_date,
-
head(data_set)
-
#> AAPL AMD ADI ABBV AEZS A APD AA CF
-
#> 2016-01-04 98.74225 2.77 49.99239 49.46063 4.40 39.35598 107.89010 23.00764 35.13227
-
#> 2016-01-05 96.26781 2.75 49.62508 49.25457 4.21 39.22057 105.96097 21.96506 34.03059
-
#> 2016-01-06 94.38389 2.51 47.51298 49.26315 3.64 39.39467 103.38042 20.40121 31.08988
-
#> 2016-01-07 90.40047 2.28 46.30082 49.11721 3.29 37.72138 99.91463 19.59558 29.61520
-
#> 2016-01-08 90.87848 2.14 45.89677 47.77789 3.29 37.32482 99.39687 19.12169 29.33761
-
#> 2016-01-11 92.35001 2.34 46.98954 46.25827 3.13 36.69613 99.78938 18.95583 28.14919
-
-
head(SP500_index)
-
#> index
-
#> 2016-01-04 2012.66
-
#> 2016-01-05 2016.71
-
#> 2016-01-06 1990.26
-
#> 2016-01-07 1943.09
-
#> 2016-01-08 1922.03
-
#> 2016-01-11 1923.67
-
plot(SP500_index)
-
-
-
# 計算股票和SP500指數的對數收益率作為顯式因子
-
X <- diff(log(data_set), na.pad = FALSE)
-
N <- ncol(X) # 股票數量
-
T <- nrow(X) # 天數
現在我們准備進行因子模型擬合。LS擬合很容易在R中實現,如下所示:
-
-
beta <- cov(X,f)/as.numeric(var(f))
-
alpha <- colMeans(X) - beta*colMeans(f)
-
sigma2 <- rep(NA, N)
-
-
print(alpha)
-
#> index
-
#> AAPL 0.0003999086
-
#> AMD 0.0013825599
-
#> ADI 0.0003609968
-
#> ABBV 0.0006684632
-
#> AEZS -0.0022091301
-
#> A 0.0002810616
-
#> APD 0.0001786375
-
#> AA 0.0006429140
-
#> CF -0.0006029705
-
print(beta)
-
#> index
-
#> AAPL 1.0957919
-
#> AMD 2.1738304
-
#> ADI 1.2683047
-
#> ABBV 0.9022748
-
#> AEZS 1.7115761
-
#> A 1.3277212
-
#> APD 1.0239453
-
#> AA 1.8593524
-
#> CF 1.5702493
或者,我們可以使用矩陣表示法進行擬合,我們定義
和擴展因子
。然后最小化
-
t(X) %*% F_ %*% solve(t(F_) %*% F_)
-
-
#> alpha beta
-
#> AAPL 0.0003999086 1.0957919
-
#> AMD 0.0013825599 2.1738304
-
#> ADI 0.0003609968 1.2683047
-
#> ABBV 0.0006684632 0.9022748
-
#> AEZS -0.0022091301 1.7115761
-
#> A 0.0002810616 1.3277212
-
#> APD 0.0001786375 1.0239453
-
#> AA 0.0006429140 1.8593524
-
#> CF -0.0006029705 1.5702493
-
E <- xts(t(t(X) - Gamma %*% t(F_)), index(X)) # 殘差
-
另外,我們可以簡單地使用R為我們完成工作:
-
-
cbind(alpha = factor_model$alpha, beta = factor_model$beta)
-
#> alpha index
-
#> AAPL 0.0003999086 1.0957919
-
#> AMD 0.0013825599 2.1738304
-
#> ADI 0.0003609968 1.2683047
-
#> ABBV 0.0006684632 0.9022748
-
#> AEZS -0.0022091301 1.7115761
-
#> A 0.0002810616 1.3277212
-
#> APD 0.0001786375 1.0239453
-
#> AA 0.0006429140 1.8593524
-
#> CF -0.0006029705 1.5702493
可視化協方差矩陣
有趣的是,可視化對數收益率[算術處理誤差]以及殘差Ψ的估計協方差矩陣。讓我們從對數收益率的協方差矩陣開始:
-
-
main = "單因子模型對數收益的協方差矩陣")
我們可以觀察到所有股票都是高度相關的,這是市場因素的影響。為了檢查股票相關關系,我們繪制相關圖:
-
plot(cov2cor(Psi),
-
main = "殘差協方差矩陣")
-
-
cbind(stock_namelist, sector_namelist) # 股票的行業
-
#> stock_namelist sector_namelist
-
#> [1,] "AAPL" "Information Technology"
-
#> [2,] "AMD" "Information Technology"
-
#> [3,] "ADI" "Information Technology"
-
#> [4,] "ABBV" "Health Care"
-
#> [5,] "AEZS" "Health Care"
-
#> [6,] "A" "Health Care"
-
#> [7,] "APD" "Materials"
-
#> [8,] "AA" "Materials"
-
#> [9,] "CF" "Materials"
有趣的是,我們可以觀察到對Ψ執行的自動聚類可以正確識別股票的行業。
評估投資資金
在此示例中,我們將基於因子模型評估幾種投資基金的績效。我們將標准普爾500指數作為明確的市場因素,並假設無風險收益為零 rf = 0。特別是,我們考慮六種交易所買賣基金(ETF):
我們首先加載數據:
-
-
-
# 設置開始結束日期和股票名稱列表
-
begin_date <- "2016-10-01"
-
end_date <- "2017-06-30"
-
-
# 從YahooFinance下載數據
-
data_set <- xts()
-
for (stock_index in 1:length(stock_namelist))
-
data_set <- cbind(data_set, Ad(getSymbols(stock_namelist[stock_index],
-
-
head(data_set)
-
#> SPY XIVH SPHB SPLV USMV JKD
-
#> 2016-10-03 203.6610 29.400 31.38322 38.55683 42.88382 119.8765
-
#> 2016-10-04 202.6228 30.160 31.29729 38.10687 42.46553 119.4081
-
#> 2016-10-05 203.5195 30.160 31.89880 38.02249 42.37048 119.9421
-
#> 2016-10-06 203.6610 30.160 31.83196 38.08813 42.39899 120.0826
-
#> 2016-10-07 202.9626 30.670 31.58372 37.98500 42.35146 119.8296
-
#> 2016-10-10 204.0197 31.394 31.87970 38.18187 42.56060 120.5978
-
-
head(SP500_index)
-
#> index
-
#> 2016-10-03 2161.20
-
#> 2016-10-04 2150.49
-
#> 2016-10-05 2159.73
-
#> 2016-10-06 2160.77
-
#> 2016-10-07 2153.74
-
#> 2016-10-10 2163.66
-
-
# 計算股票和SP500指數的對數收益率作為顯式因子
-
X <- diff(log(data_set), na.pad = FALSE)
-
N <- ncol(X) # 股票數量
-
T <- nrow(X) # 天數
-
-
現在我們可以計算所有ETF的alpha和beta:
-
-
#> alpha beta
-
#> SPY 7.142225e-05 1.0071424
-
#> XIVH 1.810392e-03 2.4971086
-
#> SPHB -2.422107e-04 1.5613533
-
#> SPLV 1.070918e-04 0.6777149
-
#> USMV 1.166177e-04 0.6511667
-
#> JKD 2.569578e-04 0.8883843
現在可以進行一些觀察:
- SPY是S&P 500的ETF,如預期的那樣,其alpha值幾乎為零,beta值幾乎為1: α= 7.142211×10-5和 β= 1.0071423。
- XIVH是具有高alpha值的ETF,計算出的alpha值是ETF中最高的(高1-2個數量級): α= 1.810392×10-3。
- SPHB是一種ETF,據推測具有很高的beta,而計算出的beta卻是最高的,但不是最高的:β= 1.5613531。有趣的是,計算出的alpha為負,因此,該ETF應謹慎。
- SPLV是降低波動性的ETF,實際上,計算得出的beta偏低:β= 0.6777072。
- USMV還是降低波動性的ETF,實際上,計算出的beta是最低的:β= 0.6511671。
- JKD顯示出很好的折衷。
我們可以使用一些可視化:
-
-
barplot(rev(alpha), horiz = TRUE, main = "alph
我們還可以使用例如Sharpe比率,以更系統的比較不同的ETF。回顧一種資產和一個因素的因子模型
我們獲得
夏普比率如下:
假設。因此,基於Sharpe比率對不同資產進行排名的一種方法是根據α/β比率對它們進行排名:
-
-
print(ranking)
-
#> alpha/beta SR alpha beta
-
#> XIVH 7.249952e-04 0.13919483 1.810392e-03 2.4971086
-
#> JKD 2.892417e-04 0.17682677 2.569578e-04 0.8883843
-
#> USMV 1.790904e-04 0.12280053 1.166177e-04 0.6511667
-
#> SPLV 1.580189e-04 0.10887903 1.070918e-04 0.6777149
-
#> SPY 7.091574e-05 0.14170591 7.142225e-05 1.0071424
-
#> SPHB -1.551287e-04 0.07401566 -2.422107e-04 1.5613533
可以看到:
- 就α/β而言,XIVH最佳(α最大),而SPHB最差(α負)。
- 就夏普比率(更確切地說,是信息比率,因為我們忽略了無風險利率)而言,JDK是最好的,其次是SPY。這證實了大多數投資基金的表現不超過市場的觀點。
- 顯然,無論以哪種衡量標准,SPHB都是最差的:負α,負β比率和Sharpe比率。
- JDK之所以能夠取得最佳性能,是因為它的alpha值很好(盡管不是最好的),而同時具有0.88的中等beta值。
- XIVH和SPHB有大量不同的beta,因此在市場上具有極端敞口。
- USMV在市場上的曝光率最小,有可接受的alpha值,並且其Sharpe比率接近第二和第三高的位置。
Fama-French三因子模型
該示例將說明使用標准普爾500指數中的九種股票的Fama-French三因子模型。讓我們從加載數據開始:
-
-
-
# 設置開始結束日期和股票名稱列表
-
begin_date <- "2013-01-01"
-
end_date <- "2017-08-31"
-
-
# 從YahooFinance下載數據
-
data_set <- xts()
-
for (stock_index in 1:length(stock_namelist))
-
data_set <- cbind(data_set, Ad(getSymbols(stock_namelist[stock_index],
-
-
# 下載Fama-French因子
-
-
-
head(fama_lib)
-
#> Mkt.RF SMB HML
-
#> 1926-07-01 0.10 -0.24 -0.28
-
#> 1926-07-02 0.45 -0.32 -0.08
-
#> 1926-07-06 0.17 0.27 -0.35
-
#> 1926-07-07 0.09 -0.59 0.03
-
#> 1926-07-08 0.21 -0.36 0.15
-
#> 1926-07-09 -0.71 0.44 0.56
-
tail(fama_lib)
-
#> Mkt.RF SMB HML
-
#> 2017-11-22 -0.05 0.10 -0.04
-
#> 2017-11-24 0.21 0.02 -0.44
-
#> 2017-11-27 -0.06 -0.36 0.03
-
#> 2017-11-28 1.06 0.38 0.84
-
#> 2017-11-29 0.02 0.04 1.45
-
#> 2017-11-30 0.82 -0.56 -0.50
-
-
# 計算股票的對數收益率和Fama-French因子
-
X <- diff(log(data_set), na.pad = FALSE)
-
N <- ncol(X) #股票數量
-
-
現在我們在矩陣F中具有三個因子,並希望擬合模型,其中現在的載荷是一個beta矩陣:
。我們可以做最小二乘擬合,最小化
。更方便地,我們定義
和擴展因子
。然后可以將LS公式寫為最小化
-
print(Gamma)
-
#> alpha b1 b2 b3
-
#> AAPL 1.437845e-04 0.9657612 -0.23339130 -0.49806858
-
#> AMD 6.181760e-04 1.4062105 0.80738336 -0.07240117
-
#> ADI -2.285017e-05 1.2124008 0.09025928 -0.20739271
-
#> ABBV 1.621380e-04 1.0582340 0.02833584 -0.72152627
-
#> AEZS -4.513235e-03 0.6989534 1.31318108 -0.25160182
-
#> A 1.146100e-05 1.2181429 0.10370898 -0.20487290
-
#> APD 6.281504e-05 1.0222936 -0.04394061 0.11060938
-
#> AA -4.587722e-05 1.3391852 0.62590136 0.99858692
-
#> CF -5.777426e-04 1.0387867 0.48430007 0.82014523
另外,我們可以使用R完成:
-
#> alpha Mkt.RF SMB HML
-
#> AAPL 1.437845e-04 0.9657612 -0.23339130 -0.49806858
-
#> AMD 6.181760e-04 1.4062105 0.80738336 -0.07240117
-
#> ADI -2.285017e-05 1.2124008 0.09025928 -0.20739271
-
#> ABBV 1.621380e-04 1.0582340 0.02833584 -0.72152627
-
#> AEZS -4.513235e-03 0.6989534 1.31318108 -0.25160182
-
#> A 1.146100e-05 1.2181429 0.10370898 -0.20487290
-
#> APD 6.281504e-05 1.0222936 -0.04394061 0.11060938
-
#> AA -4.587722e-05 1.3391852 0.62590136 0.99858692
-
#> CF -5.777426e-04 1.0387867 0.48430007 0.82014523
統計因子模型
現在讓我們考慮統計因子模型或隱式因子模型,其中因子和載荷均不可用。調用具有 K因子的模型 XT =α1T+ BFT + ET的主成分方法:
- PCA:
- 樣本均值:
- 矩陣:
- 樣本協方差矩陣:
- 特征分解:
- 樣本均值:
- 估計:
-
- 更新特征分解:
- 重復步驟2-3,直到收斂為止。
-
#> alpha
-
#> AAPL 0.0007074564 0.0002732114 -0.004631647 -0.0044814226
-
#> AMD 0.0013722468 0.0045782146 -0.035202146 0.0114549515
-
#> ADI 0.0006533116 0.0004151904 -0.007379066 -0.0053058139
-
#> ABBV 0.0007787929 0.0017513359 -0.003967816 -0.0056000810
-
#> AEZS -0.0041576357 0.0769496344 0.002935950 0.0006249473
-
#> A 0.0006902482 0.0012690079 -0.005680162 -0.0061507654
-
#> APD 0.0006236565 0.0005442926 -0.004229364 -0.0057976394
-
#> AA 0.0006277163 0.0027405024 -0.009796620 -0.0149177957
-
#> CF -0.0000573028 0.0023108605 -0.007409061 -0.0153425661
同樣,我們可以使用R完成工作:
-
#> alpha factor1 factor2 factor3
-
#> AAPL 0.0007074564 0.0002732114 -0.004631647 -0.0044814226
-
#> AMD 0.0013722468 0.0045782146 -0.035202146 0.0114549515
-
#> ADI 0.0006533116 0.0004151904 -0.007379066 -0.0053058139
-
#> ABBV 0.0007787929 0.0017513359 -0.003967816 -0.0056000810
-
#> AEZS -0.0041576357 0.0769496344 0.002935950 0.0006249473
-
#> A 0.0006902482 0.0012690079 -0.005680162 -0.0061507654
-
#> APD 0.0006236565 0.0005442926 -0.004229364 -0.0057976394
-
#> AA 0.0006277163 0.0027405024 -0.009796620 -0.0149177957
-
#> CF -0.0000573028 0.0023108605 -0.007409061 -0.0153425661
通過不同因子模型進行協方差矩陣估計的最終比較
我們最終將比較以下不同的因子模型:
- 樣本協方差矩陣
- 宏觀經濟一因素模型
- 基本的三因素Fama-French模型
- 統計因素模型
我們在訓練階段估計模型,然后將估計的協方差矩陣與測試階段的樣本協方差矩陣進行比較。估計誤差將根據PRIAL(平均損失提高百分比)進行評估:
加載訓練和測試集:
-
# 設置開始結束日期和股票名稱列表
-
begin_date <- "2013-01-01"
-
end_date <- "2015-12-31"
-
-
# 准備股票數據
-
data_set <- xts()
-
for (stock_index in 1:length(stock_namelist))
-
data_set <- cbind(data_set, Ad(getSymbols(stock_namelist[stock_index],
-
-
-
# Fama-French 因子
-
mydata <- mydata[-nrow(mydata),
-
-
-
# 准備指數
-
f_SP500 <- diff(log(SP500_index), na.pad = FALSE)
-
-
# 將數據拆分為訓練數據和測試數據
-
T_trn <- round(0.45*T)
-
X_trn <- X[1:T_trn, ]
-
X_tst <- X[(T_trn+1):T, ]
現在讓我們用訓練數據估算不同的因子模型:
-
-
# 樣本協方差矩陣
-
Sigma_SCM <- cov(X_trn)
-
-
# 單因素模型
-
Gamma <- t(solve(t(F_) %*% F_, t(F_) %*% X_trn))
-
-
E <- xts(t(t(X_trn) - Gamma %*% t(F_)), index(X_trn))
-
-
# Fama-French三因子模型
-
-
Sigma_FamaFrench <- B %*% cov(F_FamaFrench_trn) %*% t(B) + diag(diag(Psi))
-
-
# 統計單因子模型
-
-
while (norm(Sigma - Sigma_prev, "F")/norm(Sigma, "F") > 1e-3) {
-
B <- eigSigma$vectors[, 1:K, drop = FALSE] %*% diag(sqrt(eigSigma$values[1:K]), K, K)
-
-
-
-
# 統計三因子模型
-
K <- 3
-
-
while (norm(Sigma - Sigma_prev, "F")/norm(Sigma, "F") > 1e-3) {
-
B <- eigSigma$vectors[, 1:K] %*% diag(sqrt(eigSigma$values[1:K]), K, K)
-
Psi <- diag(diag(Sigma - B %*% t(B)))
-
-
Sigma_PCA3 <- Sigma
-
-
# 統計五因子模型
-
K <- 5
-
-
eigSigma <- eigen(Sigma)
-
while (norm(Sigma - Sigma_prev, "F")/norm(Sigma, "F") > 1e-3) {
-
B <- eigSigma$vectors[, 1:K] %*% diag(sqrt(eigSigma$values[1:K]), K, K)
-
Psi <- diag(diag(Sigma - B %*% t(B)))
最后,讓我們比較測試數據中的不同估計:
-
-
Sigma_true <- cov(X_tst)
-
-
barplot(error, main = "協方差矩陣估計誤差",
-
-
PRIAL <- 100*(ref - error^2)/ref
-
-
barplot(PRIAL, main = "協方差矩陣估計的先驗方法",
最終可以看到使用因子模型進行協方差矩陣估計會有所幫助。
最受歡迎的見解
1.用機器學習識別不斷變化的股市狀況—隱馬爾科夫模型(HMM)的應用