A股投资组合历史数据回测比较分析

数据准备

选择如下几只股票,从tushare.org获取其2007-10-31到2017-10-31十年的交易数据,保存为csv文件以备后用:

  • 招商证券 600999
  • 广发证券 000776
  • 万科a 000002
  • 保利地产 600048
  • 招商银行 600036
  • 工商银行 601398
  • 恒瑞医药 600276
  • 同仁堂 600685
  • 大族激光 002008
  • 三安光电 600703
  • 中国石油 601857
  • 中国石化 600028
  • ST中富 000659
  • ST山水 600234
  • 沪深300指数
import tushare as ts
import pandas as pd

codes=[
    (u'招商证券','600999'),(u'广发证券','000776'),(u'万科a','000002'),
    (u'保利地产','600048'),(u'招商银行','600036'),(u'工商银行','601398'),
    (u'恒瑞医药','600276'),(u'同仁堂','600685'),(u'大族激光','002008'),
    (u'三安光电','600703'),(u'中国石油','601857'),(u'中国石化','600028'),
    (u'ST中富','000659'),(u'ST山水','600234'),(u'沪深300','hs300')
]

for c in codes:
    df=ts.get_hist_data(c[1],start='2007-10-31',end='2017-10-31')
    df.to_csv('assets/'+c[0]+'.csv')
    print 'now '+c[0]+' earliest='+str(df.index[-1])

实际执行结果:

now 招商证券 earliest=2014-11-03
now 广发证券 earliest=2014-11-03
now 万科a earliest=2014-11-03
now 保利地产 earliest=2014-11-03
now 招商银行 earliest=2014-11-03
now 工商银行 earliest=2014-11-03
now 恒瑞医药 earliest=2014-11-03
now 同仁堂 earliest=2014-11-03
now 大族激光 earliest=2014-11-04
now 三安光电 earliest=2014-11-03
now 中国石油 earliest=2014-11-03
now 中国石化 earliest=2014-11-03
now ST中富 earliest=2014-11-03
now ST山水 earliest=2015-01-26
now 沪深300 earliest=2014-11-03

从结果看,只能选择 2014-11-03 之后到 2017-9-26 之前的数据,因为获取到的最早和最近的数据是这样。

%matplotlib inline

import matplotlib as mpl
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

plt.rcParams['font.sans-serif']=['SimHei']
# myfont=FontProperties(fname=u'C:\\Windows\Fonts\\幼圆.TTF')
mpl.rcParams['axes.unicode_minus']=False

# legend_font=FontProperties(fname=u'C:\\Windows\Fonts\\幼圆.TTF',size=10)

dpi = 72.
xinch = 800 / dpi
yinch = 400 / dpi
mpl.rcParams['figure.figsize']=(xinch,yinch)

stocks=[
    (u'招商证券','600999'),(u'广发证券','000776'),(u'万科a','000002'),
    (u'保利地产','600048'),(u'招商银行','600036'),(u'工商银行','601398'),
    (u'恒瑞医药','600276'),(u'同仁堂','600685'),(u'大族激光','002008'),
    (u'三安光电','600703'),(u'中国石油','601857'),(u'中国石化','600028'),
    (u'ST中富','000659'),(u'ST山水','600234'),(u'沪深300','hs300')
]

codes={}
for s in stocks:
    codes[s[0]]=s[1]

symbols=codes.keys()

def col_converter(x):
    try:
        return float(x)
    except:
        return None

prices=None
for i,s in enumerate(symbols):
    p=pd.read_csv('assets/'+s.upper()+'.csv',usecols=['close','date'],index_col='date',converters={'close':col_converter})
    if i==0:
        prices=pd.DataFrame(index=p.index)
    prices[s]=p['close']

prices.sort_index(ascending=True,inplace=True)
prices.dropna(inplace=True)

两支地产股和两支券商股的比较

股价波动情况

prices[[u'招商证券',u'广发证券',u'万科a',u'保利地产']].plot()
plt.ylabel(u'每日收盘价')    
plt.xlabel(u'日期')
plt.legend()

print '----期初股价----'
print prices[[u'招商证券',u'广发证券',u'万科a',u'保利地产']].head(1)
print '----期末股价----'
print prices[[u'招商证券',u'广发证券',u'万科a',u'保利地产']].tail(1)
----期初股价----
            招商证券  广发证券    万科a   保利地产
date                                
2015-02-03  24.9  22.3  12.96  10.15
----期末股价----
             招商证券   广发证券    万科a   保利地产
date                                  
2017-09-26  20.59  18.87  26.76  10.65
output_3_1.png

收益率比较

假定同时在2014-11-03日买入这四只股票和沪深300指数,比较一下到2017-9-26的收益率

prices_norm=prices.copy()
for symbol in symbols:
    prices_norm[symbol]=prices[symbol]/prices[symbol][0]
prices_norm[[u'招商证券',u'广发证券',u'万科a',u'保利地产']].plot()
plt.ylabel(u'收益率')    
plt.xlabel(u'日期')
plt.legend()

print prices_norm[[u'招商证券',u'广发证券',u'万科a',u'保利地产']].tail(1)
                招商证券      广发证券       万科a      保利地产
date                                              
2017-09-26  0.826908  0.846188  2.064815  1.049261
output_5_1.png

从图表来看,到2017-10-31为止,投资万科a收益率最高(是期初的206.4%),投资招商证券最低(是期初的82.70%,还在站岗中)

股价波动情况比较

再看看两支券商股和两支地产股的收盘价波动情况,同时与沪深300的收盘价波动情况比较:

prices.pct_change()[[u'招商证券',u'广发证券',u'万科a',u'保利地产',u'沪深300']].plot()
plt.ylabel(u'每日波动率')    
plt.xlabel(u'日期')
plt.legend()

print prices.pct_change()[[u'招商证券',u'广发证券',u'万科a',u'保利地产',u'沪深300']].describe()
             招商证券        广发证券         万科a        保利地产       沪深300
count  332.000000  332.000000  332.000000  332.000000  332.000000
mean     0.000319    0.000345    0.002647    0.000730    0.000556
std      0.042842    0.042965    0.030688    0.033740    0.021790
min     -0.297507   -0.313300   -0.100045   -0.229651   -0.151217
25%     -0.009038   -0.007870   -0.011612   -0.011329   -0.004597
50%      0.000000   -0.000584   -0.000400    0.000460    0.000990
75%      0.008002    0.008111    0.010071    0.010879    0.005632
max      0.470405    0.551145    0.113119    0.169173    0.196912
output_7_1.png

从图像上看广发证券外波动最大,但是从区间收盘价标准差来看,其实招商证券和广发证券都在0.043附近,风险程度相近。保利地产标准差仅0.022,风险最小。

计算股价波动的相关性

co=prices.pct_change().corr()
for symbol in symbols:
    v=co[symbol].sort_values()
    print symbol,u' | 正相关度最高: ',v.index[-2],u' 相关系数=',v[-2],u'   | 负相关度最高: ',v.index[0],u' 相关系数=',v[0]
    print ''
恒瑞医药  | 正相关度最高:  招商证券  相关系数= 0.373459451207    | 负相关度最高:  ST山水  相关系数= -0.184459943941

中国石化  | 正相关度最高:  中国石油  相关系数= 0.924324466248    | 负相关度最高:  恒瑞医药  相关系数= 0.086023084494

大族激光  | 正相关度最高:  沪深300  相关系数= 0.661414109    | 负相关度最高:  恒瑞医药  相关系数= 0.0872177335242

中国石油  | 正相关度最高:  中国石化  相关系数= 0.924324466248    | 负相关度最高:  ST山水  相关系数= 0.117857884825

沪深300  | 正相关度最高:  广发证券  相关系数= 0.860752981977    | 负相关度最高:  恒瑞医药  相关系数= 0.289424888497

三安光电  | 正相关度最高:  ST山水  相关系数= 0.621160353597    | 负相关度最高:  恒瑞医药  相关系数= 0.0579186039258

万科a  | 正相关度最高:  保利地产  相关系数= 0.575758930125    | 负相关度最高:  恒瑞医药  相关系数= 0.196663064699

工商银行  | 正相关度最高:  中国石油  相关系数= 0.782436477866    | 负相关度最高:  ST山水  相关系数= 0.0843699347197

招商证券  | 正相关度最高:  广发证券  相关系数= 0.921710029685    | 负相关度最高:  ST山水  相关系数= 0.130198313722

招商银行  | 正相关度最高:  工商银行  相关系数= 0.686388691468    | 负相关度最高:  恒瑞医药  相关系数= 0.0239442789959

ST山水  | 正相关度最高:  三安光电  相关系数= 0.621160353597    | 负相关度最高:  恒瑞医药  相关系数= -0.184459943941

广发证券  | 正相关度最高:  招商证券  相关系数= 0.921710029685    | 负相关度最高:  ST山水  相关系数= 0.250817065922

同仁堂  | 正相关度最高:  沪深300  相关系数= 0.675505803837    | 负相关度最高:  恒瑞医药  相关系数= 0.11457913001

ST中富  | 正相关度最高:  广发证券  相关系数= 0.563662524852    | 负相关度最高:  招商银行  相关系数= 0.0833174028769

保利地产  | 正相关度最高:  沪深300  相关系数= 0.746992561689    | 负相关度最高:  ST山水  相关系数= 0.176521765306

结论有点意思:

  • 同属一个版块,中石油、中石化关联度很高;券商关联度也很高
  • 正相关中,沪深300 和 广发证券 出现频率最高,莫非广发证券也能作为大势研判的一个指标了,连ST的都与它正相关最高?
  • 恒瑞医药出现在负相关中的频率最高,属于独立行情,适合在资产配置加入,降低风险

聚类分析

看看基于股价波动性聚类,会是什么结果?

from sklearn.cluster import affinity_propagation

_,labels=affinity_propagation(co)
df_c=pd.DataFrame({'label':labels,'name':symbols})
g=df_c.groupby('label')
for item in g:
    print item[0],','.join(item[1]['name'].values)
    print '============='
0 恒瑞医药
=============
1 中国石化,中国石油,工商银行,招商银行
=============
2 大族激光,沪深300,三安光电,万科a,招商证券,ST山水,广发证券,同仁堂,ST中富,保利地产
=============

果然和前面的数值分析有很大的相关性! 恒瑞医疗就是独行侠,第一个归类里就只有它。石油、石化、银行混在一起,嗯,也符合它们的身份吧。

验证一下每日股价波动是否符合正态分布

prices.pct_change().hist(column=[u'恒瑞医药',u'招商银行',u'保利地产',u'三安光电'],sharex=True,sharey=True,bins=30)
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000000000CEDA320>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000000000CEF4588>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x000000000D210B00>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000000000D31CAC8>]], dtype=object)
output_13_1.png

从图表来看,所选样本波动率集中度都很高,也符合正太分布。

从投资组合的角度分析

仅选两支股票的投资组合

既然前面谈到了,恒瑞医药走出独立行情,那么就设定一种投资组合,都是恒瑞医药加上另一只票。如果投资风格是追求收益风险比值是最高,那么计算一下不同的组合中,如何配比可以达到最佳值。

恒瑞医药+万科a

group_dots=np.linspace(0,1,100,endpoint=False)
hryy_wka=pd.DataFrame({
    u'回报':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'万科a']).pct_change().mean() for r in group_dots],index=group_dots),
    u'风险':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'万科a']).pct_change().std() for r in group_dots],index=group_dots)
})
ax=hryy_wka.plot(secondary_y=u'风险')
ax.set_xlabel(u'恒瑞医药占比')
ax.set_ylabel(u'单日股价波动均值')
ax.right_ax.set_ylabel(u'单日股价波动标准差')
plt.title(u'恒瑞医药+万科a 不同配比的收益风险变化图')
<matplotlib.text.Text at 0x20e0b668>
output_15_1.png

绘制这个组合的风险回报比变化曲线

reward_over_risk=hryy_wka[u'回报']/hryy_wka[u'风险']
reward_over_risk.plot()
plt.xlabel(u'恒瑞医药占比')
plt.ylabel(u'回报/风险')
print  u'恒瑞医药最佳占比:', reward_over_risk.argmax()
恒瑞医药最佳占比: 0.14
output_17_1.png

分析表明:这个组合中 15%恒瑞医药+85%万科a 时,回报和风险比最高。

恒瑞医药+招商证券

group_dots=np.linspace(0,1,100,endpoint=False)
hryy_wka=pd.DataFrame({
    u'回报':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'招商证券']).pct_change().mean() for r in group_dots],index=group_dots),
    u'风险':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'招商证券']).pct_change().std() for r in group_dots],index=group_dots)
})
ax=hryy_wka.plot(secondary_y=u'风险')
ax.set_xlabel(u'恒瑞医药占比')
ax.set_ylabel(u'单日股价波动均值')
ax.right_ax.set_ylabel(u'单日股价波动标准差')
plt.title(u'恒瑞医药+招商证券 不同配比的收益风险变化图')
<matplotlib.text.Text at 0x213725f8>
output_19_1.png
reward_over_risk=hryy_wka[u'回报']/hryy_wka[u'风险']
reward_over_risk.plot()
plt.xlabel(u'恒瑞医药占比')
plt.ylabel(u'回报/风险')
print  u'恒瑞医药最佳占比:', reward_over_risk.argmax()
恒瑞医药最佳占比: 0.99
output_20_1.png

这个组合中,恒瑞医药几乎占据全部比例时,回报/风险值最佳。

恒瑞医药+三安光电

group_dots=np.linspace(0,1,100,endpoint=False)
hryy_wka=pd.DataFrame({
    u'回报':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'三安光电']).pct_change().mean() for r in group_dots],index=group_dots),
    u'风险':pd.Series([(r*prices_norm[u'恒瑞医药']+(1-r)*prices_norm[u'三安光电']).pct_change().std() for r in group_dots],index=group_dots)
})
ax=hryy_wka.plot(secondary_y=u'风险')
ax.set_xlabel(u'恒瑞医药占比')
ax.set_ylabel(u'单日股价波动均值')
ax.right_ax.set_ylabel(u'单日股价波动标准差')
plt.title(u'恒瑞医药+招商证券 不同配比的收益风险变化图')
<matplotlib.text.Text at 0x2166e0b8>
output_22_1.png
reward_over_risk=hryy_wka[u'回报']/hryy_wka[u'风险']
reward_over_risk.plot()
plt.xlabel(u'恒瑞医药占比')
plt.ylabel(u'回报/风险')
print  u'恒瑞医药最佳占比:', reward_over_risk.argmax()
恒瑞医药最佳占比: 0.89
output_23_1.png

这个组合中 89%恒瑞医药+11%三安光电 时,回报和风险比最高。

多支票组合的效果对比

如果同时选择恒瑞医药+沪深300+万科a,但是根据配比不同有以下三种方案:

  • 重仓恒瑞医药,恒瑞医药、沪深300和万科a三者配比为 50%:30%:20%
  • 重仓沪深300,恒瑞医药、沪深300和万科a三者配比为 20%:50%:30%
  • 重仓万科a,恒瑞医药、沪深300和万科a三者配比为 20%:30%:50%
portfolios=pd.DataFrame({
    u'重仓恒瑞医疗':0.5*prices_norm[u'恒瑞医药']+0.3*prices_norm[u'沪深300']+0.2*prices_norm[u'万科a'],
    u'重仓沪深300':0.2*prices_norm[u'恒瑞医药']+0.50*prices_norm[u'沪深300']+0.3*prices_norm[u'万科a'],
    u'重仓万科a':0.2*prices_norm[u'恒瑞医药']+0.30*prices_norm[u'沪深300']+0.5*prices_norm[u'万科a']
})
portfolios.plot()
print portfolios.pct_change().describe()
            重仓万科a      重仓恒瑞医疗     重仓沪深300
count  332.000000  332.000000  332.000000
mean     0.001767    0.001322    0.001347
std      0.023129    0.020336    0.020824
min     -0.123201   -0.148621   -0.133951
25%     -0.009271   -0.007207   -0.007543
50%      0.000218    0.001041    0.001170
75%      0.008352    0.008673    0.008061
max      0.136271    0.134773    0.152384
output_25_1.png

结论:

  • 重仓万科a收益率最高,但是风险值也更大,股价波动率标准差为0.023
  • 重仓恒瑞医药或沪深300,收益率相近,股价波动率标准差也相近,都在 0.020附近
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容