专栏首页量化投资与机器学习指数夏普 VS 相关矩阵:多场景数据模型

指数夏普 VS 相关矩阵:多场景数据模型

作者:Marti 编译:1+1=6

在本文中,我们将建立一个机基于标普500指数夏普与相关矩阵的数据集,展示不同的场景。这是一个包含3类100×100相关矩阵的数据集:

  • 与压力市场相关的相关矩阵
  • 与反弹市场相关的相关矩阵
  • 与正常市场相关的相关矩阵

压力市场定义

在研究期内(252个交易日),100只等权重股票组成的股票池夏普指数低于-0.5。

反弹市场定义

在研究期内(252个交易日),100只等权重股票组成的股票池夏普指数高于2。

正常市场定义

在研究期内(252个交易日),100只等权重股票组成的股票池夏普指数在-0.5到2之间。

一旦我们得到了这个数据集,我们就可以拟合生成模型,如条件CorrGAN,以生成看起来类真实且不可见的相关矩阵。利用这些生成模型,我们可以比较不同基于风险的投资组合构建方法性能,如层次风险平价、层次风险贡献、风险平价、反向波动率、最小方差、等权重等在模拟且非真实数据上的表现。

相关阅读

CorrGAN:比较基于网络和最小方差的投资组合

数据是标普500的复权价(adj)

import sys
from random import randint
import pandas as pd
import numpy as np
import fastcluster
from scipy.cluster import hierarchy
from scipy.stats import rankdata
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

df = pd.read_csv('data/SP500_HistoTimeSeries.csv')

df['Date'] = pd.to_datetime(df['Date'], infer_datetime_format=True)

df.index = df['Date']
del df['Date']
df = df.sort_index()

returns = df.pct_change(periods=1)

dim = 100
tri_a, tri_b = np.triu_indices(dim, k=1)

随机抽取500只股票一年的日收益率(连续252个交易日)作为样本。删除缺失值。从可用的股票中随机选择100只股票。估计100×100经验相关矩阵。根据这100只等权重股票的夏普,将这个矩阵分为3类:压力型、反弹型、正常型。

corr_vs_sharpe = []
stressed_mats = []
stressed_count = 0
rally_mats = []
rally_count = 0
normal_mats = []
normal_count = 0
for loop in range(20000):
    try:
        t_idx = randint(0, len(returns) - 252)

        period_returns = returns.iloc[t_idx:(t_idx + 252)]

        rmv = 0
        for col in period_returns.columns:
            if len(period_returns[col].dropna()) < 252:
                rmv += 1
                del period_returns[col]
        rmv, period_returns.shape

        idx = list(np.random.choice(len(period_returns.columns), dim,
                                    replace=False))

        period_returns[period_returns.columns[idx]].dropna().shape

        corr = period_returns[
            period_returns.columns[idx]].dropna().corr().values
        corr.mean()

        mean_return = (period_returns[period_returns.columns[idx]]
                       .dropna()
                       .mean(axis=1)
                       .mean() * 252)
        vol = (period_returns[period_returns.columns[idx]]
               .dropna()
               .mean(axis=1)
               .std() * np.sqrt(252))
        sharpe = mean_return / vol

        dist = 1 - corr
        Z = fastcluster.linkage(dist[tri_a, tri_b], method='ward')
        permutation = hierarchy.leaves_list(
            hierarchy.optimal_leaf_ordering(Z, dist[tri_a, tri_b]))
        prows = corr[permutation, :]
        ordered_corr = prows[:, permutation]

        corr_vs_sharpe.append([corr.mean(), sharpe])
        
        if sharpe < -0.5:
            stressed_mats.append(ordered_corr)
            np.save('stressed_mats/mat_{}.npy'.format(stressed_count),
                    ordered_corr)
            stressed_count += 1
        elif sharpe > 2:
            rally_mats.append(ordered_corr)
            np.save('rally_mats/mat_{}.npy'.format(rally_count),
                    ordered_corr)
            rally_count += 1
        else:
            normal_mats.append(ordered_corr)
            np.save('normal_mats/mat_{}.npy'.format(normal_count),
                    ordered_corr)
            normal_count += 1

        if loop < 10:
            plt.figure(figsize=(20, 8))
            plt.subplot(1, 2, 1)
            plt.plot((1 + period_returns[
                period_returns.columns[idx]]
                      .dropna().mean(axis=1)).cumprod())
            plt.title("sharpe: " + str(np.round(sharpe, 2)))

            plt.subplot(1, 2, 2)
            plt.pcolormesh(ordered_corr)
            plt.colorbar()
            plt.title("mean corr: " + str(np.round(corr.mean(), 2)))
            plt.show()
    except:
        pass

左边是夏普值的分布(每个样本1年 x100只股票的夏普值)。我们基本上可以观察到两种模式:一种模式在0点,另一种模式在1.5点左右,样本量是原来的两倍。对于平均相关值(每个样本1年 x100只股票的平均相关值),我们可以观察到几种模式:

  • 0.25(低)
  • 0.34(均值)
  • 0.5(高)
corr_vs_sharpe = np.array(corr_vs_sharpe)

plt.figure(figsize=(20, 6))
plt.subplot(1, 2, 1)
plt.hist(corr_vs_sharpe[:, 1], bins=100)
plt.title('Distribution of Sharpe')

plt.subplot(1, 2, 2)
plt.hist(corr_vs_sharpe[:, 0], bins=100)
plt.title('Distribution of Mean Correlation')
plt.show()

我们在下面的图表中说明了夏普和平均相关性之间的反相关关系:高平均相关性倾向于低夏普相关性;低平均相关性倾向于高夏普相关性。

plt.figure(figsize=(20, 6))
plt.subplot(1, 2, 1)
plt.scatter(corr_vs_sharpe[:, 0], corr_vs_sharpe[:, 1])
plt.xlabel('mean corr')
plt.ylabel('sharpe')

plt.subplot(1, 2, 2)
plt.scatter(rankdata(corr_vs_sharpe[:, 0]),
            rankdata(corr_vs_sharpe[:, 1]))
plt.xlabel('rank mean corr')
plt.ylabel('rank sharpe')
plt.show()

从这个抽样程序中,我们从20000个矩阵中得到以下结果:

len(stressed_mats), len(rally_mats), len(normal_mats)

(1004, 3091, 15897)

也就是说,5% 的压力矩阵,15% 的反弹矩阵,80% 的正常矩阵。

下面我们展示了一些重新排序的相关矩阵,它们与压力市场状态相关。

for i, mat in enumerate(stressed_mats):
    plt.pcolormesh(mat)
    plt.colorbar()
    plt.title(round(mat.mean(), 2))
    plt.show()
    
    if i > 5:
        break

下面我们展示了一些重新排序的相关矩阵,它们与反弹市场状态相关。

for i, mat in enumerate(rally_mats):
    plt.pcolormesh(mat)
    plt.colorbar()
    plt.title(round(mat.mean(), 2))
    plt.show()
    
    if i > 5:
        break

最后,我们显示了与3个市场状态相关的所有矩阵的所有相关系数分布(橙色压力,绿色反弹,蓝色正常):

stressed_corr_coeffs = []
for mat in stressed_mats:
    stressed_corr_coeffs.extend(list(mat[tri_a, tri_b]))

rally_corr_coeffs = []
for mat in rally_mats:
    rally_corr_coeffs.extend(list(mat[tri_a, tri_b]))
    
normal_corr_coeffs = []
for mat in normal_mats:
    normal_corr_coeffs.extend(list(mat[tri_a, tri_b]))

 
nbins = 500
plt.figure(figsize=(15, 6))
plt.hist(normal_corr_coeffs, bins=nbins, alpha=1,
         label='normal: $-0.5 \leq$ sharpe $\leq 2$',
         density=True, log=False)
plt.axvline(x=np.mean(normal_corr_coeffs), color='b',
            linestyle='dashed', linewidth=2)
plt.hist(stressed_corr_coeffs, bins=nbins, alpha=0.8,
         label='stressed: sharpe < -0.5',
         density=True, log=False)
plt.axvline(x=np.mean(stressed_corr_coeffs), color='r',
            linestyle='dashed', linewidth=2)
plt.hist(rally_corr_coeffs, bins=nbins, alpha=0.6,
         label='rally: 2 < sharpe',
         density=True, log=False)
plt.axvline(x=np.mean(rally_corr_coeffs), color='g',
            linestyle='dashed', linewidth=2)
plt.legend()
plt.show()

我们观察到,与压力市场相关的相关矩阵具有更高的相关系数(0.55)。反弹矩阵的分布是最对称的(0.25左右)。

在本文中,我们阐述了相关性和夏普之间的关系(注意,这种关系可以通过投资者在极端市场中的羊群效应来证明,也可以机械地通过将投资组合的波动性与资产相关性联系起来)。本文的主要目的是说明抽样过程,以便建立一个适合市场状态的GANs培训数据库。

本文分享自微信公众号 - 量化投资与机器学习(Lhtz_Jqxx),作者:QIML编辑部

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 寻找最优持仓期的开盘缺口盈利交易策略基于Matlab

    翻译整理 Watermelon 前言 很多投资者经常讨论股价的预测,基本面的消息等等。当我们在说这些的时候,其实,这些(我把它们归结为算法)算法的核心就是触发识...

    量化投资与机器学习微信公众号
  • 使用CorrGAN:比较基于网络和最小方差的投资组合(附代码)

    许多经济物理学家已经注意到,利用股票(或其他资产)收益估计的经验相关矩阵构建的网络leaves的投资组合,与对同一股票估计的经验协方差进行最小方差优化所得到的投...

    量化投资与机器学习微信公众号
  • 超火动态价格面积图:手把手教你!

    近日,公众号推出了一篇名为《超火动态排序图:代码不到40行,手把手教你!》的文章,反向十分强烈。各大公众号进行的了转载,知乎也是有400+的点赞。

    量化投资与机器学习微信公众号
  • 币聪早报:比特币哈希率在单日内突破1000万TH/s,比特大陆S11开启测试?

    尽管最近比特币价格走势疲软,但比特币挖掘的网络哈希率在过去两天突然大幅上涨。这种增加使其达到令人难以置信的每秒6200万terahashes。仅仅两天前,该网络...

    币聪财经
  • Mysql查询一段时间记录

    $sql="SELECT video_id,count(id)as n FROM rec_down WHERE UNIX_TIMESTAMP(NOW())-UN...

    Dream城堡
  • matplotlib 入门(一)

    matplotlib中的pyplot子模块,包含了一系列命令风格的函数,能使matplotlib像MATLAB的绘图命令那样的方式工作。

    用户6021899
  • Python数据处理从零开始----第四章(可视化)(3)目录正文

    plt.scatter相对于plt.plot的主要优势在于,前者在创建散点图时具有更高的灵活性,可以单独控制每个散点与数据匹配,也可以让每个散点具有不同的属性(...

    用户1359560
  • 15 种最常用的 matplotlib 可视化图表(附 Python 源码)

    开始练习之前,首先你需要安装 matplotlib。实验楼为大家提供了已经安装好了各个模块的实验环境,推荐直接来实验楼练习。

    程序员小强
  • 【数据分析与可视化】matplotlib简单绘图之subplot

    [<matplotlib.lines.Line2D at 0x116769150>]

    瑞新
  • 我的机器学习matplotlib篇导入画出第一个图形颜色,标记,线型刻度、标题、标签和图例!创建子图

    前言: matplotlib是python最常用的绘图库,能帮你画出美丽的各种图 导入 包含了中文显示,屏外显示 import matplotlib.p...

    DC童生

扫码关注云+社区

领取腾讯云代金券