实验环境
操作系统:Win 10 64bit
软件:Matlab 2019b (academic use)
模型
在Mean-Variance框架下使用因子模型,多因子模型可以降低计算的矩阵的维度,并且可以解释大部分市场上的随机性信息,这些因子可以是统计意义上,或者是宏观因子或者是基本面因子.
数据预处理
%% 数据预处理
load('asset_return_100_simulated.mat');
[nObs, p]=size(stockReturns);
% 划分训练集和测试集
sp=ceil(nObs*0.6);
train=1:sp;
test=sp+1: nObs;
trainN=numel(train); % 统计训练集中元素的数量
可视化收益曲线
%% 绘制收益率曲线
hold on;
plot(ret2tick(stockReturns{train, 1:5}, 'method', 'simple')*100); % 前5只资产训练期间的价格
xlabel('Timestep');
ylabel('Value');
title('Equity Curve');
% 设置图例
legend(stockReturns.Properties.VariableNames(1:5), 'Location', 'bestoutside', 'Interpreter', 'none');
hold off;
可视化图像如下
因子模型中计算资产最优化配置
可以直接从资产收益序列中提取统计因子,考虑使用主成分分析(PCA)方法提取统计因子. 在因子模型中,
p
p
p项资产可以用
k
k
k个因子收益线性组合得到,且
k
≪
p
k\ll p
k≪p.
r
a
=
μ
a
+
F
r
f
+
ε
a
r_a=\mu_a+Fr_f+\varepsilon_a
ra=μa+Frf+εa
在mean-variance
模型中,组合风险为
V
(
R
p
)
=
V
(
r
a
T
w
a
)
=
V
(
(
μ
a
+
F
r
f
+
ε
a
)
T
w
a
)
=
w
a
T
(
F
Σ
f
F
T
+
D
)
w
a
=
w
f
T
Σ
f
w
f
+
w
a
T
D
w
a
\begin{aligned} \mathbb{V}(R_p)&=\mathbb{V}(r_a^Tw_a)=\mathbb{V}((\mu_a+Fr_f+\varepsilon_a)^Tw_a)\\ &=w_a^T(F\Sigma_f F^T+D)w_a\\ &=w_f^T\Sigma_f w_f+w_a^T Dw_a \end{aligned}
V(Rp)=V(raTwa)=V((μa+Frf+εa)Twa)=waT(FΣfFT+D)wa=wfTΣfwf+waTDwa
方程的符号表如下
符号 | 含义 |
---|---|
R p R_p Rp | 组合收益(标量) |
r a r_a ra | 资产收益列向量, p × 1 p\times 1 p×1 |
μ a \mu_a μa | 资产收益的均值, p × 1 p\times 1 p×1列向量 |
F F F | 因子载荷矩阵, p × k p\times k p×k |
r f r_f rf | 因子收益, k × 1 k\times 1 k×1列向量 |
ε a \varepsilon_a εa | 各资产收益中不可被因子解释的部分(idiosyncratic return related to each asset), p × 1 p\times 1 p×1列向量 |
w a w_a wa | 资产权重, p × 1 p\times 1 p×1列向量 |
w f w_f wf | 因子权重, w f = w a T F w_f=w_a^TF wf=waTF, k × 1 k\times 1 k×1列向量 |
Σ f \Sigma_f Σf | 因子协方差矩阵, k × k k\times k k×k矩阵 |
D D D | 不可解释部分方差(variance of idioisyncratic returns), p × p p\times p p×p对角矩阵 |
所以可以得到优化问题如下,设置风险上限为
t
t
t.
max
μ
a
T
w
a
s
.
t
.
{
F
T
w
a
=
w
f
w
f
T
Σ
f
w
f
+
w
a
T
D
w
a
≤
t
0
≤
w
≤
1
e
T
w
a
=
1
(1)
\begin{aligned} &\max \mu_a^Tw_a\\ &s.t. \begin{cases} F^Tw_a=w_f\\ w_f^T\Sigma_fw_f+w_a^TDw_a\leq t\\ 0\leq w\leq 1\\ e^Tw_a=1 \end{cases} \end{aligned}\tag{1}
maxμaTwas.t.⎩⎪⎪⎪⎨⎪⎪⎪⎧FTwa=wfwfTΣfwf+waTDwa≤t0≤w≤1eTwa=1(1)
主成分信息提取
在
p
p
p项资产形成的
p
p
p维空间中,PCA算法可以找出其中最重要的
k
k
k个可以捕获
p
p
p项资产变化的信息的方向,并且
k
<
p
k<p
k<p. 通过PCA算法可以将
p
p
p项资产的收益分解到
k
k
k个因子上,这样可以明显地降低问题的维度.
k
k
k个主方向就是因子载荷(factor loadings
),回归得到的分数(scores
)为因子收益,在本例中令
k
=
10
k=10
k=10,也可以通过设置解释阈值来找到合适的
k
k
k值,一般设置主成分解释95%的方差.
%% pca
k=10; % 设置主方向为10个
[factor_loading, factor_ret, latent, tsq, explained, mu]=pca(stockReturns{train, :}, 'NumComponents', k);
disp(size(factor_loading));
disp(size(factor_ret));
输出得到
p
×
k
p\times k
p×k的因子载荷矩阵factor_loading
,每一列是一个主成分(pricinpal component),每个时间戳的资产收益向量被分解到这
k
k
k维空间中,输出
trainN
×
k
\text{trainN}\times k
trainN×k的factor_ret
矩阵.
估计因子方差-协方差矩阵
covarFactor=cov(factor_ret);
根据公式 r a = μ a + F r f + ε a r_a=\mu_a+Fr_f+\varepsilon_a ra=μa+Frf+εa重构训练集样本点收益序列
recon_ret=factor_ret*factor_loading'+mu; % 收益序列重构
unexplained_ret=stockReturns{train, :}-recon_ret; % 因子模型不可解释部分
产生因子模型不可解释部分收益 ε a \varepsilon_a εa因为pca算法舍弃了 p − k p-k p−k个成分,这一部分信息可以用矩阵 D D D表示
unexplained_covar=diag(cov(unexplained_ret));
D=diag(unexplained_covar);
最优模型建模计算
根据方程组 ( 1 ) (1) (1)建立最优化模型
%% optimization model
t_std=0.007; % 组合标准差
t_risk=t_std*t_std; % 组合方差
mean_ret = mean(stockReturns{train, :}); % 训练期均值
% 定义最优化问题
% 目标函数为求最大化
optimProb=optimproblem('Description', 'Portfolio with factor covariance matrix', 'ObjectiveSense', 'max');
% 变量:资产权重(p * 1)向量和因子权重(k*1)向量
wgtAsset=optimvar('asset_weight', p, 1, 'Type', 'continuous', 'LowerBound', 0, 'UpperBound', 1);
wgtFactor=optimvar('factor_weight', k, 1, 'Type', 'continuous');
% 优化目标为组合收益
optimProb.Objective=sum(mean_ret' .*wgtAsset);
% 约束
% w_f和w_a之间的关系
optimProb.Constraints.asset_factor_weight=factor_loading'*wgtAsset-wgtFactor==0;
% 风险约束
optimProb.Constraints.risk=wgtFactor'*covarFactor*wgtFactor+wgtAsset'*D*wgtAsset<=t_risk;
% budget
optimProb.Constraints.budget=sum(wgtAsset)==1;
% 初始值
x0.asset_weight=ones(p, 1)/p;
x0.factor_weight=zeros(k, 1);
% 优化算法设置
opt=optimoptions("fmincon", "Algorithm", "sqp", "Display", "off", 'ConstraintTolerance', 1.0e-8, 'OptimalityTolerance', 1.0e-8, ...
'StepTolerance', 1.0e-8);
% 求解
x=solve(optimProb, x0, "Options", opt);
assetWgt1=x.asset_weight;
对投资比重大于5%的资产进行列表显示
%% check portfolio
tol = 0.05;
asset_names=stockReturns.Properties.VariableNames(assetWgt1>=tol)';
weights = assetWgt1(assetWgt1>=tol);
T1=table(asset_names, weights)
使用portfolio类进行计算
如果已经得到因子载荷矩阵(
F
F
F)和因子方差-协方差矩阵
Σ
f
\Sigma_f
Σf,可以直接使用这些信息调用Portfolio Class
在mean-variance
框架下进行计算.
%% optimize by Portfolio class with Factor information
covarAsset=factor_loading*covarFactor*factor_loading'+D;
port=Portfolio('AssetMean', mean_ret, 'AssetCovar', covarAsset, 'lowerbound', 0, 'upperbound', 1, 'budget', 1);
assetWgt2=estimateFrontierByRisk(port, t_risk);
asset_names_2=stockReturns.Properties.VariableNames(assetWgt2>=tol)';
weights_2=assetWgt2(assetWgt2>=tol);
T2=table(asset_names_2, weights_2)
得到组合权重分布如下表所示
测试集表现
将得到的组合权重在测试期数据进行回测
%% test period data
t_ret_1=stockReturns{test, :}*assetWgt1;
t_ret_2=stockReturns{test, :}*assetWgt2;
hold on;
t1=plot(ret2tick(t_ret_1, 'method', 'simple')*100);
t2=plot(ret2tick(t_ret_2, 'method', 'simple')*100);
xlabel('TimeStep');
ylabel('Value');
legend([t1, t2], "factor model 1", "factor model 2");
title('Portfolio Equity Curve');
hold off;
回测结果如图所示
后记
本实验的因子载荷矩阵由PCA算法直接得到,如果需要显式计算需要线性回归的方法.
代码下载
参考资料
Portfolio Optimization Using Factor Models
sklearn中的pca算法库函数
matlab中的pca算法包
First Choose Problem-Based or Solver-Based Approach
Portfolio set for optimizaiton using portfolio object