投资组合可行集即风险资产可能形成的所有投资组合的总体,位于可有效边界上或其内部。
本文以包含四支股票的投资组合为例,分别为贵州茅台,中天科技,万科A,上证指数,绘制该投资组合的可行集。
高校学生或老师也可以联系社区管理员进行认证,认证完成即可获得一定积分,然后就可以使用一些里面的数据。认证只需不到24h,很方便!
下面进入代码部分。前期准备:
import os, sys
import pandas as pd
import matplotlib as mpl
import tushare as ts
import matplotlib.pyplot as plt
from matplotlib.pylab import date2num
import datetime
import mplfinance as mpf
import numpy as np
from matplotlib.font_manager import FontProperties
import csv
from pandas.core.frame import DataFrame
import numpy as np
from functools import reduce
from scipy.optimize import minimize
from tkinter import *
import glob
import time
import shutil
plt.rcParams["font.sans-serif"]=["SimHei"] #中文
plt.rcParams["axes.unicode_minus"] = False
pro = ts.pro_api("这里输入你的token")
#投资组合中的股票数量和股票代码
l=4
mycode=["000001","000002","600519","600522"]
清洗数据:
#查找完整股票代码
full=[]
for scode in mycode:
dat1 = pro.query("stock_basic", fields="ts_code,symbol,name")
code = list(dat1.loc[dat1["symbol"] == scode].ts_code)
code=",".join(code)
tscode=full.append(code)
full1=",".join(full)
#提取股票日交易信息
def get_trade_price(stock_code):
df = pro.daily(ts_code=stock_code, start_date="20190128", end_date="20190222")
df.to_csv(".daily.csv")
return df
get_trade_price(full1)
#csv编辑
#删除多余列
d=pd.read_csv(".daily.csv",index_col=0)
d=d.drop(["open","high","low","pre_close","change","close","vol","amount"],axis=1)
d.to_csv(".Drop.csv",index=False,encoding="utf-8")
# 分类保存
# 按股票分类
if os.path.exists("分类数据"):
shutil.rmtree("分类数据")
if not os.path.exists("分类数据"):
os.makedirs("分类数据")
with open(".Drop.csv") as fin:
csvin = csv.DictReader(fin)
outputs = {}
for row in csvin:
td = row["ts_code"]
if td not in outputs:
fout = open(".分类数据{}.csv".format(td), "w",newline="")
dw = csv.DictWriter(fout, fieldnames=csvin.fieldnames)
outputs[td] = fout, dw
dw1 = csv.writer(fout)
dw1.writerow(["ts_code","date",td])
outputs[td][1].writerow(row)
for fout, _ in outputs.values():
fout.close()
#保存日期序列
s1=full[1]
date=pd.read_csv(".分类数据{}.csv".format(s1))
date=date.drop(["ts_code",s1],axis=1)
date.to_csv(".date.csv",index=False,encoding="utf-8")
#删除股票代码列
for i in range(0,len(full)):
stock=full[i]
print(stock)
d=pd.read_csv(".分类数据{}.csv".format(stock))
d=d.drop(["ts_code"],axis=1)
d.to_csv(".分类数据{}.csv".format(stock),index=False,encoding="utf-8")
#股票合并为最终csv
outputfile=".date.csv"
csv_list = glob.glob(".分类数据*.csv")
print(u"共发现%s个CSV文件"%len(csv_list))
filepath = csv_list[0]
for i in range(0,len(csv_list)):
filepath = csv_list[i]
df1 = pd.read_csv(filepath, encoding="utf-8")
df2 = pd.read_csv(outputfile, encoding="utf-8")
outfile = pd.merge(df1, df2, on="date",how="right")
outfile.to_csv(".date.csv", index=False,encoding="utf-8")
再绘制投资组合可行集:
#获取收益率的dataframe
#构建有效边界
tmp_list=[]
with open(".date.csv", "r") as f:
reader=csv.reader(f)
for row in reader: #每个row是一个列表
tmp_list.append(row[1:])
print("
")
df=pd.DataFrame(tmp_list[1:], columns=tmp_list[0])
df=df.apply(pd.to_numeric, errors="coerce").fillna(0) #转换为数值
df=df/100
print(df)
#四支股票的风险溢价和协方差矩阵
mean=df.mean()
cov=df.cov()
print(mean)
#找到最大和最小均值
def cut(num,c):
c=10**(-c)
return (num//c)*c
max_mean=cut(float(np.format_float_positional(max(mean),precision=2,fractional=False,trim="-")),3)
min_mean=cut(float(np.format_float_positional(min(mean),precision=2,fractional=False,trim="-"))+0.001,3)
print(max_mean,min_mean)
#定义用来计算组合风险溢价、标准差的函数
weight=np.random.rand(l)
weight/=sum(weight)
def risk_prem(w):
return np.dot(w,mean)
def std_dev(w):
return np.sqrt(reduce(np.dot,[w,cov,w.T]))
#根据收益-方差对找出所有可行组合
rtn=[]
sds=[]
for i in range(80000):
weight=np.random.rand(l)
weight=weight/sum(weight)
rtn.append(risk_prem(weight))
sds.append(std_dev(weight))
plt.scatter(sds,rtn,cmap="YlGnBu", marker="o", edgecolor="none",s=10, alpha=0.3)
plt.colorbar()
plt.title("投资组合可行集")
plt.xlabel("组合标准差")
plt.ylabel("组合期望收益")
plt.show()
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点