请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3364680 新帖:1

MPT模型研究

2020来了发表于:5 月 9 日 20:13回复(1)

在量化课堂基础上自己搞的研究验证。
金融资产配置的目标是将投资资金合理地分配在多种资产上,在将风险控制在一定范围内的同时把收益率最大化。其中最著名的理论是现代资产配置理论(Modern Portfolio Theory),简称 MPT,由 Markowitz 在1952年提出。MPT 的核心思想是以最小化标准差(或同理的,方差)并最大化预期收益为目标来进行资产配置,有时也称为均值-方差分析(Mean-Variance Analysis),是金融经济学的一个重要基础理论。

写在前面:¶

  • 在金融工程中,对收益期望与风险都是基于历史统计数据,即认为资产表现会大致趋同于其历史表现。
  • 一般将资产风险定义为资产收益的标准差。这是马科维茨对风险的定义,之后一直被机构投资者 视为风险的标准定义。当然还有其它定义方法,比如半方差、损失概率等,本文本统一定义风险为标准差。

一、收益与风险的关系:¶

单一资产的收益-风险(均值-标准差)之间会存在着什么样的关系,是否真如常言所说风险越大收益越大这样的同增同减关系? 我们选取某一时间段沪深全部股票,过滤掉停牌超过15天的个股(否则会影响标准差计算),获取这些股票每个交易日的收益,并计算得到每只股这段时间的单日收益率期望和标准差,在(标准差-收益率期望)坐标轴上标出各个股的分布,如下图:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from jqdata import *


start_date = datetime.date(2016, 6, 1)
end_data = datetime.date(2018, 6, 1)

FilterPauedDay = 15 # 停牌超过一定天数,过滤

choiceStock = list(get_all_securities(types=["stock"], date=start_date).index)

panel = get_price(choiceStock, start_date=start_date, end_date=end_data, frequency='daily', fields=["close", "pre_close", "paused"], skip_paused=False, fq='pre')
df_rate = panel["close"] / panel["pre_close"]-1

delColunms = panel["paused"].sum() > FilterPauedDay # 停牌超过一定天数,过滤掉
for s, v in delColunms.items():
    if v:
        df_rate = df_rate.drop(s, axis=1)

# 优化columns,使标题更直观
tl = []
for one in df_rate.columns:
    displayName = get_security_info(one).display_name
    tl.append("%s[%s]" % (displayName, one))
df_rate.columns = tl

series_mean_rate = df_rate.mean()
series_std = df_rate.std()

# print("日平均收益:\n", series_mean_rate.sort_values())
# print("日收益标准差:\n", series_std.sort_values())

# 绘制各股均值方差分布图
fig = plt.figure(figsize=(12, 12), dpi=80)
plt.plot(series_std, series_mean_rate, ".")
plt.grid(True)
plt.title("A股单日收益率的“标准差-收益率期望”分布图")
plt.xlabel("标准差")
plt.ylabel("收益率期望")


# 标记出选出的股票各自的均值-标准差分布
choiceStock2 = ["601668.XSHG", "002714.XSHE", "000333.XSHE", "000001.XSHE", "000725.XSHE"]
panel2 = get_price(choiceStock2, start_date=start_date, end_date=end_data, frequency='daily', fields=["close", "pre_close", "paused"], skip_paused=False, fq='pre')
df_rate2 = panel2["close"] / panel2["pre_close"]-1
series_mean_rate2 = df_rate2.mean()
series_std2 = df_rate2.std()
plt.plot(series_std2, series_mean_rate2, "*")
print(series_mean_rate2)
/opt/conda/lib/python3.6/site-packages/jqresearch/api.py:87: FutureWarning: 
Panel is deprecated and will be removed in a future version.
The recommended way to represent these types of 3-dimensional data are with a MultiIndex on a DataFrame, via the Panel.to_frame() method
Alternatively, you can use the xarray package http://xarray.pydata.org/en/stable/.
Pandas provides a `.to_xarray()` method to help automate this conversion.

  pre_factor_ref_date=_get_today())
601668.XSHG    0.001116
002714.XSHE    0.001744
000333.XSHE    0.002139
000001.XSHE    0.000486
000725.XSHE    0.001365
dtype: float64

由上图可见,收益与风险并不呈现一种我们期待的线性关系,至少在定义风险为标准差的前提下,对于个股,中期,收益与风险没有表现出特别明显的关系,似乎是散乱分布的。但也能发现一些规律:

  • 收益大的,一般标准差都大,现实中这也好理解,一般涨起来,都是几波单日偏移均值较大的上涨,大量资金关注,这样就加波动率。
  • 损失大的,一般标准备差也大,估计是一般都是几波无量跌停,不仅拉大了波动率,也拉小了收益。

二、资产组合的收益与风险的关系:¶

上面我们看了单只风险资产的收益与风险的分布,发现单只标的的收益与风险很难捉摸,下面我们看下风险资产组合的收益与风险关系: 我们选择5只收益均值为正的股票,画出这5只股票的各种组合情况的“收益-风险”分布图,由于计算量的关系,以每只股0.1权重的step来计算,如下图,其中星星是单一标的的收益-风险分布位置:

def CalculateWeightedMean(valueList, weightList):
    return np.average(valueList, weights=weightList)

stockCnt = len(choiceStock2)
allWeightList = []
def GetWeight(iLeft, weightList):
    if len(weightList) >= stockCnt-1:
        weightList.append(iLeft)
        allWeightList.append(weightList)
        return
    for i in range(iLeft+1):
        newWeightList = weightList[:]
        newWeightList.append(i)
        GetWeight(iLeft-i, newWeightList)

GetWeight(10, [])

diffWeightRate = []
diffWeightRisk = []
for weightList in allWeightList:
    seriesWeightMean = df_rate2.apply(CalculateWeightedMean, axis=1, args=[weightList,])
    oneRate = seriesWeightMean.mean()
    oneRisk = seriesWeightMean.std()
    diffWeightRate.append(oneRate)
    diffWeightRisk.append(oneRisk)

plt.plot(diffWeightRisk, diffWeightRate, ".")
plt.grid()
plt.title("资产组合的“标准差-收益率期望”分布图")
plt.xlabel("标准差")
plt.ylabel("收益率期望")

plt.plot(series_std2, series_mean_rate2, "*")
[<matplotlib.lines.Line2D at 0x7f6a08384160>]

由上图发现:

  • 通过对多个资产不同权重配置的配置,可以得到风险比单一资产更小的组合。
  • 所有的组合的收益不会高过只配置收益最高的单一资产的收益(如果允许加杠杆的话,图形是无限向右发散的)。
  • 我们可以看到所有在相同收益下风险最小的组合,即在图的最左沿的组合,是像子弹一样的一条曲线,叫有效前沿,这就是著名的马科维茨子弹
  • 同样,在相同风险情况下收益最优是有效前沿曲线的上半部分,故一般只把曲线上半部分当作有效前沿。

图中可以看到,资产组合的最小风险在图的最左端,大约为0.011左右,即如果配置组合的资产都是风险资产的话,无论怎么配置,基本不能把风险降为零(除非选的各个单一资产每天收益与均值的偏差每天都完全对冲了,这在现实中基本不可能,除非有意为之)。但如果我们引入无风险资产,情况会是怎么样呢?

三、引入无风险资产的组合的风险与收益的关系:¶

我们在组合中加入日利率为(0.05/250)的无风险资产,得到各种权重配置情况下的组合的(收益-风险)分布,蓝色是配置了无风险资产的分布,绿色是只有风险资产的分布:

# 引入无风险资产的组合
risk_free_rate = 0.05/250 # 无风险资产收益取5%
newColumns = list(df_rate2.columns)
newColumns.append("risk_free")
df_rate_with_risk_free = df_rate2.reindex(columns=newColumns, fill_value=risk_free_rate)
series_mean_rate_with_risk_free = df_rate_with_risk_free.mean()
series_std_with_risk_free = df_rate_with_risk_free.std()
print("各单一资产收益期望:", series_mean_rate_with_risk_free)
print("各单一资产收益标准差:", series_std_with_risk_free)

stockCnt = len(series_mean_rate_with_risk_free)  # 组合的资产数量
allWeightList = []
def GetWeight(iLeft, weightList):
    if len(weightList) >= stockCnt-1:
        weightList.append(iLeft)
        allWeightList.append(weightList)
        return
    for i in range(iLeft+1):
        newWeightList = weightList[:]
        newWeightList.append(i)
        GetWeight(iLeft-i, newWeightList)

GetWeight(10, [])


diffWeightRateWithRiskFree = []
diffWeightRiskWithRiskFree = []
for weightList in allWeightList:
    seriesWeightMean = df_rate_with_risk_free.apply(CalculateWeightedMean, axis=1, args=[weightList,])
    oneRate = seriesWeightMean.mean()
    oneRisk = seriesWeightMean.std()
    diffWeightRateWithRiskFree.append(oneRate)
    diffWeightRiskWithRiskFree.append(oneRisk)

plt.plot(diffWeightRiskWithRiskFree, diffWeightRateWithRiskFree, ".")
plt.grid()
plt.title("引入无风险资产后资产组合的“标准差-收益率期望”分布图")
plt.xlabel("标准差")
plt.ylabel("收益率期望")

plt.plot(series_std_with_risk_free, series_mean_rate_with_risk_free, "*")
plt.plot(diffWeightRisk, diffWeightRate, "g.")
各单一资产收益期望: 601668.XSHG    0.001116
002714.XSHE    0.001744
000333.XSHE    0.002139
000001.XSHE    0.000486
000725.XSHE    0.001365
risk_free      0.002000
dtype: float64
各单一资产收益标准差: 601668.XSHG    1.883966e-02
002714.XSHE    2.339986e-02
000333.XSHE    2.019977e-02
000001.XSHE    1.571868e-02
000725.XSHE    2.241199e-02
risk_free      1.302378e-18
dtype: float64
[<matplotlib.lines.Line2D at 0x7f69e8150c88>]

  由上图可以看出,引入无风险资产后,得到的均值-标准差分布变成了三角形,并且包含了全部配置风险资产时的所有分布。它的左端在横轴0点,代表全部配置无风险资产的情况。有效前沿变成了一条直线,似乎是过(0,无风险收益率)点的,全为风险资产配置的有效前沿的切线,为了验证是不是巧合通过调整无风险收益率得到下面这些图:_auto_9_auto_10_auto_11

  由上面的图看出,加上无风险资产后的最有效前沿确实是切于全部配置风险资产时的有效前沿的直线。这条直线有什么特殊的呢?

四、有效前沿的组合中哪个性价比最高?¶

  我们知道有效前沿是在相同收益下风险最低的或说是相同风险下收益最高的,其中根据风险和收益的要求不同可以从中选出很多组合,但是选择哪个组合性价比最高呢?即哪个组合增加相同风险同时增加最多的收益?即满足 $\frac{r_p}{\sigma_p}$最大,其中$r_p$是组合的收益,$\sigma_p$是组合的风险。即满足原点到组合的点连线斜率最大。从上面的图我们可以看到,全部配置无风险资产是最优的。
  而上面图的有效前沿直线是增加单位风险同时增加最多无风险收益的情况,即$\frac{r_p-r_f}{\sigma_p}$最大的情况,这公式便是大名鼎鼎的夏普比率,故可知,带上无风险资产的风险组合的有效前沿是夏普比率最高的组合。所以我们为什么常用夏普比率来衡量一个策略的好坏。而这条直线就是资本市场线

 

全部回复

0/140

量化课程

    移动端课程