Stata:投资组合有效边界

文摘   教育   2024-11-11 22:00   中国  

👇 连享会 · 推文导航 | www.lianxh.cn

🍓 课程推荐:2024 机器学习与因果推断专题
主讲老师:司继春 (上海对外经贸大学) ;张宏亮(浙江大学)
课程时间:2024 年 11 月 9-10 日 ;16-17日
课程咨询:王老师 18903405450(微信)

 课程特色 · 2024机器学习与因果推断

  • 懂原理、会应用。本次课程邀请了两位老师合作讲授,目的在于最大限度地实现理论与应用的有机结合。为期四天的课程,分成两个部分:第一部分讲解常用的机器学习算法和适用条件,以及文本分析和大语言模型;第二部分通过精讲 4-6 篇发表于 Top 期刊的论文,帮助大家理解各类机器学习算法的应用场景,以及它们与传统因果推断方法的巧妙结合。
  • 以 Top 期刊论文为范例。目前多数人的困惑是不清楚如何将传统因果推断方法与机器学习结合起来。事实上,即便是 MIT 和 Harvard 的大牛们也都在「摸着石头过河」。为此,通过论文精讲和复现来学习这部分内容或许是目前最有效的方式了。张宏亮老师此前在浙江大学按照这一模式教授了「因果推断和机器学习」课程,效果甚佳:学生们能够逐渐建立起研究设计的理念,并在构造识别策略时适当地嵌入机器学习方法。

作者:史津宇 (中山大学)
E-Mail: shijy2000@outlook.com

指导老师: 连玉君(中山大学)
E-mail: arlionn@163.com


目录

  • 1. 话题引入

    • 1.1 何为最优投资组合?

    • 1.2 何谓有效前沿?

  • 2. 股票数据获取与预处理

    • 2.1 获取股票数据

    • 2.2 观察股票价格走势

    • 2.3 计算收益率与协方差

  • 3. 构造投资组合

    • 3.1 两项资产的情况

    • 3.2 添加第三项资产

  • 4. 计算并绘制有效边界

    • 4.1 蒙特卡洛模拟初窥边界

    • 4.2 最优化与有效边界计算

  • 5. 快捷命令

  • 6. 结束语

  • 7. 参考资料

    • 数据处理和计算相关

    • Stata 有效前沿的相关命令

  • 8. 相关推文



温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」,或直接长按/扫描如下二维码,直达原文:


1. 话题引入

有效前沿 (Efficient Frontier)是马科维茨投资组合理论的进一步延伸,它基于每类风险资产回报率、波动性、相关系数等历史数据,刻画不同资产配比下的多个投资组合散点图,进而回答资产配置的一个关键性问题——如何构建最优投资组合

1.1 何为最优投资组合?

根据 马科维茨投资组合理论:由多只证券构成的投资组合中一定存在一系列最优投资组合,它们既是相同风险水平下收益最大的组合,也是相同收益水平下风险最小的组合。

以下图为例,假设虚拟投资 A、B、C 是有价证券按照不同配置比例所构成的三个投资组合,它们按照 均值—方差 的不同特征,在平面坐标系上处于不同的位置。

那么,从投资的角度,同样的收益水平下,A 点风险更小;同样的风险水平下,C 点收益更高。但如果没更多的信息,我们将无法直接比较 A 和 C 。

均值-方差示意图

而假若补充一个投资组合 D,那无论是预期收益还是波动率角度看, D 毫无疑问将是最优组合。

1.2 何谓有效前沿?

由于在无数投资组合中,只要给出既定风险水平,我们总是可以找到收益最高的一个组合。 所以,当投资者可承受的风险水平变化时,与该风险水平相对应的最优投资组合也一直存在,并且随着风险水平变化不断的移动。

这条由不同风险水平下最优投资组合点构成的曲线,称之为有效曲线,又叫有效前沿(Efficient frontier)。

推荐阅读

  • Markowitz, H. M. . "Portfolio selection." The Journal of Finance 7.1(1952):77. - PDF -
  • Sharpe, W. F. . "Asset allocation: Management style and performance measurement." The Journal of Portfolio Management 18.2(1992):7-19.  - PDF -
  • 投资组合理论学习之马科维茨投资模型(一)

接下来,让我们了解如何利用 Stata 完成构造。

2. 股票数据获取与预处理

2.1 获取股票数据

为获取股票交易数据,我们首先安装外部命令 cntrade 便于下载个股和市场指数实时数据:

ssc install cntrade, replace 
ssc install openall, replace

本文选取贵州茅台 (600519)、药明康德 (603259)、科大讯飞 (002230) 三只股票为例,利用 cntrade 命令下载并转化数据储存格式:

  local list "600519 603259 002230"
cntrade `list'
openall `list'
gen year = year(date)
keep if year == 2020 //保留2020年数据
save "mstocks_long.dta", replace //保存合并后的数据

use "mstocks_long.dta", clear // Long format
keep stkcd date clsprc //保留需要纵横变换的变量
xtset date stkcd
reshape wide clsprc, i(date) j(stkcd)
save "mstocks_wide.dta", replace // Wide format

2.2 观察股票价格走势

由于每只股票单价差距较大,为方便观察股价走势,我们分别将其指标准化(2020 年第一个交易日的股票价格定为 100):

 use mstocks_wide, clear
foreach i of varlist clsprc*{
if "`i'" != "date"{
replace `i' = (`i' / `=`i'[1]') * 100
format `i' %6.2f
}
} //标准化股价

tw
line clsprc* date, ///
xla(21915(45)22281, ang(20)) ///
leg(order(1 "贵州茅台" 2 "药明康德" ///
3 "科大讯飞" ) position(1) ring(0)) ///
title("股价走势图(2020年)") ///
xtitle("日期") ///
ytitle("标准化股价")
graph export "$out\price_trend.png", replace

导出图片呈现如下:

price_trend

贵州茅台和药明康德的股价涨幅相对于科大讯飞更高;相对的,前两者也承担了更高的风险——这正是 CAPM 中重要的 风险和收益的权衡原则

2.3 计算收益率与协方差

接下来,我们计算每只股票的年均收益率、方差以及股票间的协方差。此处我们采取对数收益率的计算方法,即根据公式:

了解更多关于收益率的 Stata 计算命令,欢迎参见 Stata 数据处理:ascol-mtoq-日收益转周-月-季-年度数据

use mstocks_wide, clear
gen dateid = _n
tsset dateid
foreach i of varlist clsprc*{
gen l`i' = l.`i'
replace `i' = log(`i'/l`i')
drop l`i'
}
drop dateid
rename (clsprc2230 clsprc600519 clsprc603259)///
(科大讯飞 贵州茅台 药明康德)
save return, replace

同样可以通过 CAPM 模型,计算股票的贝塔系数进而获得预期收益率。详情参见连享会推文 实时估计个股贝塔(beta)系数

得到对数收益率数据格式如下:

list in 1/5

| date 科大讯飞 贵州茅台 药明康德 |
|---------------------------------------------------|
1. | 2020-01-02 . . . |
2. | 2020-01-03 -.01090398 -.04659081 -.02609613 |
3. | 2020-01-06 .05773528 -.00052862 -.03025364 |
4. | 2020-01-07 .00081666 .01522685 .01501375 |
5. | 2020-01-08 -.01923136 -.00585523 -.00627605 |

根据获得的对数收益率,计算出年均收益率、协方差并分别储存在对应矩阵中:

use return, clear
drop in 1
local j = 1
foreach i of varlist 科大讯飞 贵州茅台 药明康德{
qui sum `i'
local r`j' = r(mean)
local j = `j' + 1
}
mat rets = (`r1', `r2', `r3')// 年均收益率矩阵

corr 科大讯飞 贵州茅台 药明康德, cov
mat cov = r(C) // 协方差矩阵

存储得到的矩阵结果如下:

mat list rets

rets[1,3]
c1 c2 c3
r1 .00063598 .00235508 .00159318

mat list cov

symmetric cov[3,3]
科大讯飞 贵州茅台 药明康德
科大讯飞 .00068277
贵州茅台 .00018373 .00032969
药明康德 .00032823 .00023092 .00115149


3. 构造投资组合

3.1 两项资产的情况

完成之前的一系列准备工作后,我们首先用两个资产(贵州茅台和科大讯飞)进行尝试构造可能出现的投资组合。

假设,科大讯飞所占比重为 ,贵州茅台所占比重为 ,其中,.

投资组合的预期收益:

预期的波动率:


观察不同比重组合下的收益率和方差:

clear
set obs 11
egen double w1=fill(0(0.1)1)
format w1 %tg
gen w2=1-w1
format w2 %tg

gen r_P = w1*rets[1,1] + w2*rets[1,2]
gen varP= w1^2*cov[1,1] + w2^2*cov[2,2] ///
+ 2*w1*w2*cov[2,1]
gen sdP=sqrt(varP)

twoway (scatter r_P sdP, msize(medlarge) ///
mlabel(w1) mlabcolor(edkblue)), ///
ytitle(收益率) ///
ylabel(#5) ///
xtitle(波动性) ///
title(Frontier using ///
2 stocks(科大讯飞 & 贵州茅台))

graph export "$out\Frontier_using_2_stocks.png" ///
, as(png) replace

横坐标是波动性,纵坐标是收益率,得到的图形如下:

3.2 添加第三项资产

在投资组合中添加第三项风险投资股票——药明康德,所占比重为 ,此时 .

对于新的投资组合,我们的预期收益为:

预期的波动性为:


同上,观察不同比重组合下的收益率和方差:

clear
set obs 101
egen double w1=fill(0(0.01)1)
format w1 %tg
egen double w2=fill(0(0.01)1)
gen w3=1-w1-w2
format w2 %tg
format w3 %tg

gen r_P = w1*rets[1,1] + w2*rets[1,2] + w3*rets[1,3]

gen varP= w1^2*cov[1,1] + w2^2*cov[2,2] ///
+ w3^2*cov[3,3] ///
+ 2*w1*w3*cov[1,3] ///
+ 2*w2*w3*cov[2,3] ///
+ 2*w1*w2*cov[2,1]

gen sdP=sqrt(varP)

twoway (scatter r_P sdP, msize(tiny) ///
mlabcolor(edkblue)), ///
ytitle(收益率) ylabel(#5) xtitle(波动性) ///
title("Frontier with 3 stocks") ///
subtitle("(科大讯飞 & 贵州茅台 & 药明康德)")

graph export "$out\Frontier_using_3_stocks.png"///
, as(png) replace

得到的投资组合收益率-波动性关系为:

Efficient Frontier using 3 stocks

将此类情形拓展到  种资产,则预期收益为:

预期的波动性为:


然而,这样的投资组合总是 有效 的吗?

答案是否定的。由于此时获得的收益率只是来自于不同权重的组合,而非限制波动性最小情况下的最优值,所以接下来需要我们计算有效前沿。

4. 计算并绘制有效边界

4.1 蒙特卡洛模拟初窥边界

当样本数据量足够大的时候,通常会非常接近正确答案——有效边界了。所以我们试图设置样本点为 10000 个,对于不同比重的资产组合计算均值与方差。

首先,基于以上三种股票的收益率、波动性和协方差,我们编写一个的蒙特卡洛模拟的 Stata 程序并封装此程序:

cap prog drop front
prog def front, rclass
version 15.0
use return, clear
local w1 = runiform()
local w2 = runiform()
local w3 = runiform()
mat weight = (`w1' \ `w2' \ `w3' )
mat list weight
mat weight = weight / (`w1'+`w2'+`w3')
mat list weight
ret scalar w1 = weight[1, 1]
ret scalar w2 = weight[2, 1]
ret scalar w3 = weight[3, 1]
local j = 1
foreach i of varlist _all{
if "`i'" != "date"{
qui sum `i'
local r`j' = r(mean)
local j = `j' + 1
}
}
mat rets = (`r1', `r2', `r3')
mat a = rets * weight
mat list a
ret scalar ret = a[1, 1]
corr 科大讯飞 贵州茅台 药明康德, cov
ret list
mat cov = r(C)
mat b = weight' * cov * weight
mat list b
ret scalar var = b[1, 1]
ret scalar std = sqrt(b[1, 1])
end

了解更多关于蒙特卡洛模拟分析的 Stata 介绍,欢迎参见连享会专题文章  Stata:蒙特卡洛模拟分析 (Monte Carlo Simulation)

设置执行 100000 次蒙特卡洛模拟:

simulate ret = r(ret)   ///
var = r(var) ///
std = r(std) ///
w1 = r(w1) ///
w2 = r(w2) ///
w3 = r(w3) ///
, reps(100000): front
save dataset, replace
graph export "$out\Portfolio.png", as(png) replace

得到图片,我们可以在后面对其边界进行验证:

Portfolio

4.2 最优化与有效边界计算

我们需要找到最小化方差点,该点以上的曲线部分是有效的,以下的部分则是无效的。即最小化方差  ,对于这类最优化问题——我们可以借助 Mata 中的函数 optimize 来实现。由于权重和为 1,因此只需计算得到两种资产占比,即可得第三种资产权重。

输入 mata: 进入 Mata 环境,考虑到 optimize 默认计算最大值,加入负号即可计算最小值。

mata:
mata clear
void min_std(real scalar todo,///
real vector w12, std, g, H)
{
real scalar w3
w3 = 1 - sum(w12)
real vector r_mean
r_mean= st_matrix("rets")
// 将储存于 Stata 的矩阵导入 Mata环境
real vector w
w = (w12, w3)
real scalar r_P
r_P = w * r_mean'
real matrix var_P
var_P = st_matrix("cov")
var_P = w * var_P * w'
std = -sqrt(var_P[1, 1])
// 加入负号以达到求最小值的目的
}

S = optimize_init()
optimize_init_evaluator(S, &min_std())
optimize_init_params(S, J(1, 2, 0))
wh = optimize(S)

w = (wh, 1-sum(wh))
r_Pm = (wh, 1-sum(wh)) * st_matrix("rets")'
var_P = (w * st_matrix("cov") * w')
std = sqrt(var_P[1, 1])

w
r_Pm
std

end

最小方差点的均值-方差为 (0.0019607171 , 0.0171638423),科大讯飞、贵州茅台、药明康德在投资组合中的比重依次为:

     1             2             3
+-------------------------------------------+
1 | .2085128365 .744359616 .0471275475 |
+-------------------------------------------+

紧接着,需要计算投资组合并保证每个组合的收益率对应的最小方差。该步骤只需要在上一步的基础上嵌套关于预期收益率取值的循环:

mata:
mata clear
void min_std(real scalar todo,///
real vector w123, std, g, H)
{
real vector rmean
rmean = st_matrix("rets")
real scalar rp
real vector w
w = w123
rp = w * rmean'
real matrix variancep
variancep = st_matrix("cov")
variancep = w * variancep * w'
std = -sqrt(variancep[1, 1])
}

std_vector = J(1, 40, 0)

// 最小化方差对应的收益率为 0.00196,
// 此时收益率较低,为仅购入贵州茅台时的 0.00235

j=1
for (i = 0.00196; i < 0.00235; i = i + 0.00001)
{
S = optimize_init()
optimize_init_evaluator(S, &min_std())
optimize_init_technique(S, "nr")
optimize_init_constraints(S, ///
((st_matrix("rets")\ J(1, 3, 1)), (i \ 1)))
optimize_init_params(S, J(1, 3, 0))
wh = optimize(S)
variancep = (wh * st_matrix("cov") * wh')
std = sqrt(variancep[1, 1])
std_vector[1, j] = std
j = j + 1
}
st_matrix("std_vector", std_vector)

end

画图,做出有效前沿:

clear
set obs 40
gen ret = (_n + 195) / 100000
gen std = .
forval i = 1/40{
replace std = std_vector[1, `i'] in `i'
}
gen front = 1
drop if std == 0
save front, replace


tw ///
sc ret std if front == 1, ///
msize(tiny) msymbol(D) ///
mc("blue") leg(off) || ///
scatteri .0019607171 ///
.0171638423 "最小方差点", ///
mc("red") msymbol(o) mlabc("pink")
Efficient Frontier using 3 stocks

补充显示上一步通过蒙特卡洛模拟做出的数据集:

use dataset1, clear
append using front

twoway ///
scatter ret std, msize(*0.01) ///
xtitle(波动率) ytitle(收益率) ///
title("Efficient Frontier using 3 stocks")///
msymbol(o) ///
xlabel(#6, format(%6.3f)) ylabel(, ///
format(%6.4f))|| scatteri ///
.0019607171 .01716384 "最小方差点", ///
mc("pink") msymbol(o) mlabc("pink") || ///
scatter ret std if front == 1, ///
msize(tiny) msymbol(D) ///
mc("blue") leg(off)

graph export ///
"$out\Investment_portfolio_using_3_stocks.png"///
, as(png) replace
Investment_portfolio_using_3_stocks

5. 快捷命令

虽说花费如此多的篇幅去折腾这一条曲线,但在搜集信息的过程中,笔者发现了用 Stata 最快做出有效前沿的命令—— mvport.

这个由 Carlos Alberto Dorantes 提供的多个投资组合模型的估计程序,可以一步计算最小方差组合、最大夏普比率组合,同时这些组合也可以施加约束,包括是否允许卖空,是否有最小或最大权重的限制等等。

以本文中选取的三只股票为例,一条命令就可以计算得出最小方差组合的的权重:

use return.dta, clear
gmvport 科大讯飞 贵州茅台 药明康德, noshort

Number of observations used to calculate///
expected returns and var-cov matrix : 243
The weight vector of the Global Minimum ///
Variance Portfolio (NOT Allow Short Sales) is:

Weights
科大讯飞 .20851284
贵州茅台 .74435962
药明康德 .04712755

The return of the Global Minimum Variance ///
Portfolio is: .00196288

The standard deviation (risk) of the Global ///
Minimum Variance Portfolio is: .01716384

同样,借助命令 efrontier 画出有效前沿也丝毫不在话下:

use return.dta, clear
efrontier 科大讯飞 贵州茅台 药明康德
Efficient Frontier

有关更多使用指南,读者可以通过以下指令自行探索:

findit mvport

6. 结束语

有效前沿可以帮助专业投资者,很好地评价自己过去的投资组合离最优投资组合的偏差,还可以在总结过往数据表现的基础上发现一些规律,较好地指导未来投资实践,如对当前投资组合做出调整和优化等。

当然,虽然有效前沿对资产组合配置有较强的指导意义,我们也必须意识到,由于上述分析完全基于已知的过去资产价格数据,未来的价格数据具有不确定性,因此有效前沿不能精准预测未来。

7. 参考资料

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」

数据处理和计算相关

Stata 有效前沿的相关命令

  • findit mvport // 一组计算投资效率和投资组合的命令
  • help grsftest // Econometrica 57(5)
    • Gibbons, M.R., S. Ross, and J. Shanken, 1989. "A test of the efficiency of a given portfolio" Econometrica, 57(5), 1121-1152. - PDF -
  • search fetchcomponents // Stata Journal 13-3
    • Mehmet F. Dicle, 2013, Financial Portfolio Selection using the Multifactor Capital Asset Pricing Model and Imported Options Data, Stata Journal, 13(3): 603–617. - PDF -

8. 相关推文

Note:产生如下推文列表的 Stata 命令为:
  lianxh 投资组合 收益 事件研究
安装最新版 lianxh 命令:
  ssc install lianxh, replace

  • 专题:Stata教程
    • 事件研究法笔记:Stata连享会
    • 公司财务-投资组合Stata实现-Berk-Corporate-Finance-Chapter-11-Examples
  • 专题:数据处理
    • Stata数据处理:ascol-mtoq-日收益转周-月-季-年度数据
  • 专题:回归分析
    • Stata:短期事件研究法(Event_Study)教程
    • 残差是个宝:盈余管理、过度投资、超额收益怎么算?

🍓 课程推荐:2024 机器学习与因果推断专题
主讲老师:司继春 (上海对外经贸大学) ;张宏亮(浙江大学)
课程时间:2024 年 11 月 9-10 日 ;16-17日
课程咨询:王老师 18903405450(微信)

尊敬的老师 / 亲爱的同学们:

连享会致力于不断优化和丰富课程内容,以确保每位学员都能获得最有价值的学习体验。为了更精准地满足您的学习需求,我们诚挚地邀请您参与到我们的课程规划中来。请您在下面的问卷中,分享您 感兴趣的学习主题或您希望深入了解的知识领域 。您的每一条建议都是我们宝贵的资源,将直接影响到我们课程的改进和创新。我们期待您的反馈,因为您的参与和支持是我们不断前进的动力。感谢您抽出宝贵时间,与我们共同塑造更加精彩的学习旅程!https://www.wjx.cn/vm/YgPfdsJ.aspx# 再次感谢大家宝贵的意见!

New! Stata 搜索神器:lianxh 和 songbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
  . ssc install lianxh
  . ssc install songbl
👉  使用:
  . lianxh DID 倍分法
  . songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。


连享会
连玉君老师团队分享,主页:lianxh.cn。白话计量,代码实操;学术路上,与君同行。
 最新文章