首先import需要用到的库
from numpy import *
from numpy.linalg import multi_dot
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import *
加载画图的库并忽略告警
import cufflinks as cf
cf.set_config_file(
offline = True,
dimensions = ((800, 600)),
theme = 'ggplot')
import plotly.express as px
px.defaults.width = 800
px.defaults.height = 600
import warnings
warnings.filterwarnings('ignore')
# 解决中文和负号问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
导入外部数据(https://download.csdn.net/download/weixin_55618145/87666946)
file_name = '2017_2021_daily.csv'
data = pd.DataFrame(pd.read_csv(file_name, index_col=0, parse_dates=True)).dropna()
data.head()
展示历史价格走势
(data/data.iloc[0]).plot(figsize = (10,6))
plt.xlabel('日期')
plt.ylabel('价格走势(起始为1)')
plt.title('6只股票历史价格走势')
plt.show()
显示如下:
计算历史回报及波动
returns = log(data/data.shift(1)).dropna()
# 年化收益率及波动
pd.DataFrame({
'年化收益率(%)': round(returns.mean()*250*100, 2),
'年化波动率(%)': round(returns.std()*sqrt(250)*100, 2),
'夏普比率': round(returns.mean()/returns.std()*sqrt(250), 2)
}).iplot(kind='bar', title='年化收益率(%)、年化波动率(%)及夏普比率', shared_xaxes=True, subplots=True)
结果如下
有效边界及市场组合——蒙特卡洛模拟
运行10000次随机构建的组合比例(不做空任何一只股票)
# 组合的股票构成
symbols = ['顺发恒业', '贵州茅台', '重庆啤酒', '中南传媒', '海天味业', '五粮液']
numofasset = len(symbols)
# 定义一个组合的函数
def portfolio_simulation(returns):
rets = []; vols=[]; wts=[]
# 模拟10000次6只股票不同权重的组合
for i in tqdm(range(10000)):
# 产生随机权重
weights = random.random(numofasset)[:, newaxis]
weights = weights/weights.sum()
# 记录组合的收益、波动、权重
rets.append(weights.T @ array(returns.mean()*250)[:,newaxis])
vols.append(sqrt(multi_dot([weights.T, returns.cov()*250, weights])))
wts.append(weights.flatten())
# 记录组合各数据
portdf = 100 * pd.DataFrame({
'port_rets': array(rets).flatten(),
'port_vols': array(vols).flatten(),
'weights': list(array(wts))
})
portdf['Sharp_ratio']=portdf['port_rets']/portdf['port_vols'] #假设rf为0
return round(portdf, 2)
# 用6只股票组成投资组合并模拟
temp = portfolio_simulation(returns)
temp.head(10)
获取全部模拟中夏普比率最大值
temp.iloc[temp.Sharp_ratio.idxmax()]
最后把结果可视化
# 绘制模拟组合(每个组合一个点)
fig = px.scatter(
temp, x='port_vols', y='port_rets', color='Sharp_ratio',
labels={'port_vols': '预期波动(%)','port_rets': '预期收益(%)', 'Sharp_ratio':
'夏普比率'},
title='投资组合蒙特卡洛模拟'
).update_traces(mode='markers', marker=dict(symbol='circle'))
# 标记最大夏普比率的组合(市场组合)
fig.add_scatter(mode='markers',
x=[temp.iloc[temp.Sharp_ratio.idxmax()]['port_vols']],
y=[temp.iloc[temp.Sharp_ratio.idxmax()]['port_rets']],
marker=dict(color='Blue', size=14, symbol='square'),
name = '市场组合'
).update(layout_showlegend=False)
fig.update_xaxes(showspikes=True)
fig.update_yaxes(showspikes=True)
fig.show()
模拟结果如下(右上角蓝色方块对应夏普比率最大的组合)
版权归原作者 cal_the_world 所有, 如有侵权,请联系我们删除。