Stata 最优化与马科维茨有效前沿

Stata 最优化与马科维茨有效前沿

本文使用 4 只股票:银泰资源、大悦城、中国天楹和通化金马的历史数据演示了如何使用 Stata 进行股票分析、构建投资组合(夏普比率最大 or 方差最小)及寻找马科维茨有效前沿。

视频讲解

获取数据

我们使用 cntrade2 命令获取股票交易的历史数据(时间范围 2019-01-01 ~ 2019-12-31),这个命令修改自 cntrade。cntrade2 命令放在我的 finance 命令包里面,可以前往 GitHub 查看该命令包的安装方法:https://github.com/czxa/finance

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

然后再把这四个文件 merge 到一起:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

rawdata 数据集是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
list in 1/10

*> +------------------------------------------------------+
*> | date 银泰资源 大悦城 中国天楹 通化金马 |
*> |------------------------------------------------------|
*> 1. | 2019-01-02 10.07 4.86 5.54 7.01 |
*> 2. | 2019-01-03 10.44 4.86 5.61 6.77 |
*> 3. | 2019-01-04 10.51 4.99 5.56 6.86 |
*> 4. | 2019-01-07 10.36 5.02 5.53 6.92 |
*> 5. | 2019-01-08 9.94 5 5.54 6.97 |
*> |------------------------------------------------------|
*> 6. | 2019-01-09 9.97 5.04 5.42 6.99 |
*> 7. | 2019-01-10 10.26 4.99 5.39 6.87 |
*> 8. | 2019-01-11 10.2 5.01 5.47 6.88 |
*> 9. | 2019-01-14 10.14 5 5.57 6.8 |
*> 10. | 2019-01-15 10.29 5.06 5.54 6.77 |
*> +------------------------------------------------------+

观察四只股票的股价走势

把期初的股价标准化为100,观测四只股票的股价走势关系:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

接下来计算每只股票的对数收益率,这里需要注意由于股票交易日之间可能存在间隔,所以不能直接用日期作为时间变量:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

returndata 是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
list in 1/10

*> +-------------------------------------------------------+
*> | date 银泰资源 大悦城 中国天楹 通化金马 |
*> |-------------------------------------------------------|
*> 1. | 2019-01-02 . . . . |
*> 2. | 2019-01-03 0.0361 0.0000 0.0126 -0.0348 |
*> 3. | 2019-01-04 0.0067 0.0264 -0.0090 0.0132 |
*> 4. | 2019-01-07 -0.0144 0.0060 -0.0054 0.0087 |
*> 5. | 2019-01-08 -0.0414 -0.0040 0.0018 0.0072 |
*> |-------------------------------------------------------|
*> 6. | 2019-01-09 0.0030 0.0080 -0.0219 0.0029 |
*> 7. | 2019-01-10 0.0287 -0.0100 -0.0056 -0.0173 |
*> 8. | 2019-01-11 -0.0059 0.0040 0.0147 0.0015 |
*> 9. | 2019-01-14 -0.0059 -0.0020 0.0181 -0.0117 |
*> 10. | 2019-01-15 0.0147 0.0119 -0.0054 -0.0044 |
*> +-------------------------------------------------------+

观测一下股票对数收益率的分布:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这就是“尖峰厚尾”了(峰比正态分布高,尾比正态分布厚)。

投资组合的构建

最大化夏普比率

夏普比率代表交易者每多承担一份风险,相应的就可以拿到几份超额报酬。若其为正,代表回报率高过波动风险;若其为负值,代表操作风险大过回报率。这样,每个投资组合都可以计算夏普比率,即投资回报与多冒风险的比例,这个比率越高对应的投资组合越好。

$$Sharpe-ratio = \frac{R_{p} - R_{f}}{\sigma_{p}}$$

这里 $R_{p}$ 代表投资组合的收益率,$R_{f}$ 代表无风险利率,在下面的计算中被假定为 $4%$,$\sigma_{p}$ 代表投资组合收益的标准差,即回报率的波动。

假定在我们的投资组合中有 $n$ 中证券,证券 $i$ 的权重是 $w_{i}$,收益率为 $r_{i}$,那么这个投资组合的标准差为:$\sqrt{w’Vw}$,这里 $w$ 是权重向量, $V$ 是收益率向量的方差-协方差矩阵。下面我们要做的就是写一个 Stata 程序去最大化夏普比率。现在我们有四只股票,也就是说,我们要做的就是决定这四只股票在我们的投资组合中的权重,由于总权重是 1,所以实际上我们只需要决定其中三只股票的权重。

首先计算每只股票对数收益率的均值,然后存储在矩阵 returns 中(其实是个一维的行向量):

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

然后计算协方差矩阵,并将协方差矩阵存储在矩阵 variance 中:

1
2
3
4
5
6
7
8
9
10
corr 银泰资源 大悦城 中国天楹 通化金马, cov

*> |银泰资源大悦城中国天楹通化金马
*> ---------+------------------------------------
*> 银泰资源 | .000846
*> 大悦城 | .000066 .000472
*> 中国天楹 | .000159 .000181 .000626
*> 通化金马 | .000165 .000363 .000301 .001137

mat variance = r(C)

接下来就是使用 Stata 进行最优化的,为了便于大家理解,我先举一个 Stata 帮助文档里面的例子。假如我想寻找 $x$ 最大化 $y = e^{-x^2 + x - 3}$,代码如下:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

可以看到最优化之后得到的 x 取值是 0.5。我们可以把这个函数的图像画出来看看:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

可以看到,确实是 0.5 处的 y 取最大值。

我再解释一下这段最优化代码,因为它不同于我们常见的 Stata 代码,它是 Mata 的代码:

mata: 表示进入 Mata 语言的环境,然后是一个 myeval 函数,这个函数名前面有个 void,表示这个函数是无返回值的。函数有五个参数 —— todo, x, y, g, H,我们这里只需要用到 x 和 y,剩下三个参数的含义可以自行阅读帮助文档(help optimize)。

也就是说,待调优的参数是放在函数的第二个参数上;函数的返回值是放在第三个参数上。

S = optimize_init() 表示初始化,optimize_init_evaluator(S, &myeval()) 设定要最优化的函数;optimize_init_params(S, 0) 是设定初始值,这里是设定初始的 x = 0,然后默认使用的最优化方法是 Newton–Raphson 方法。最后执行 x = optimize(S) 进行最优化,x 就是我们需要的结果。

我们再回到我们的投资组合构建上。

首先我们允许卖空,就是说权重参数可以为负数:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这里我的 w123 就是类似于简单示例中的 x,是个三维的行向量。

这就是允许卖空时夏普比率最大的组合。

再考虑不允许卖空的情形,为了保证权重为正且总和为1,我借用了 e^x 函数的特点:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

不过需要注意的是,这里的最优化结果并没有达到收敛。能不能收敛跟数据是有关系的,无法收敛就说明在不允许卖空的时候无法达到夏普比率的最优化。注意到权重,实际上这个结果是让我们只买前两只股票。只要买一点点后两只股票,夏普比率就会变小。

夏普比率函数

我还写了个可以计算夏普比率的函数:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

结果:

1
2
mata: sharpe_ratio(0.3700694896, 1-0.3700694896, 0)
*> 1.304208617

和上面最优化运行得到的结果是一致的,也就是说,在不允许卖空的时候,夏普比率最大的组合是买入 0.37 份的银泰资源和 0.63 份的大悦城,剩下两只股票不买入。

下面我们再用蒙特卡洛模拟观测不允许卖空时,所有可能的组合的收益和标准差的关系:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

绘图展示:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

显然,卖空即提高了收益又增加了风险。

最小化方差

最小化方差也就是最小化标准差,显然就是上图中最右边的那个点了。下面用程序寻找这个点对于的组合构建方法。

首先还是运行做空:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

注意上面的代码里面,我在 std = -sqrt(variancep[1, 1]) 里面加了个负号,这样最大化 std 的时候就最小化标准差了。

这个点在这里:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

构造有效前沿

有效前沿是一条线,其上的点表示既定收益率下方差最小的投资组合。显然就是最小方差点到最大夏普比率点的边界线。从图中可以看出从最小方差到允许卖空的最大夏普比率点的收益率范围为:[0.33, 0.73],以 0.01 为间隔,计算每个收益率水平上的最小方差。

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这里我使用的是含约束的最优化,通过设定 optimize_init_constraints() 的约束矩阵实现的。

同样我们把刚刚得到的 41 个点(得删除 0.73 对应的点,这个点的 std = 0,因为允许卖空时的最大收益才 0.725)绘图展示:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

感觉用 Stata 做金融分析也是蛮有意思的。

知识星球附件链接:https://t.zsxq.com/mYjeMBY

#

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×