1.什麼是指數基金
2.什麼是基金定投
3.本次數據來源
4.作出假設
5.改變定投策略,獲得更好的收益(以2018和2019的平均收益率分析)
1.什麼是指數基金
股票指數是指按照一定的規則所選擇的股票的平均值。比如:
上證50指數:就是把上海證券交易所規模最大、流動性最好的50家公司的股票統計起來的股票平均值。
滬深300指數:就是把上交所和深交所前300只規模最大、流動最好的300家公司的股票統計起來的股票平均值。
中證500指數:把滬深300指數的前300家大公司排除,剩下的大公司中再選前500只規模最大、流動最好的500家公司的股票統計起來的股票平均值。
因此:指數基金即按照某選股規則選出來的一堆股票的集合即指數基金
2.什麼是基金定投
基金定投,就是按照固定的頻率和固定的金額,不停分批次小額買入金融市場上的基金。定投可以選擇任何種類的基金。我們以指數基金爲例(大部分傳說中無腦定投的案例都是以指數基金的定投方式),分析本案例
3.本次數據來源
通過API接口從網易財經上進行調取
接口規範
http://quotes.money.163.com/service/chddata.html?code=003833&start=19901219&end=20200228&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;VOTURNOVER;VATURNOVER
說明:
code參數後面的7位整數代表了股票代碼;比如0000001指的是上證指數。注意這串數字要分0和000001兩部分看。0代表sh,1代表sz。所以0000001其實是sh000001的意思。同理,0 000300也就是sh000300 滬深300的代碼。
start和end參數後面的8位整數代表年(xxxx)月(xx)日(xx)
fields選項中,TCLOSE,HIGH,LOW,TOPEN分別表示當日的收盤,最高,最低,開盤價;LCLOSE表示昨日收盤>價。CHG,PCHG,VOTURNOVER,VAT分別表示漲跌額,漲跌幅,成交量,成交金額。
本次研究滬深300指數基金
4.作出假設
# 加載模塊
from datetime import datetime,timedelta
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
# 指定默認字體
plt.rcParams['font.family']=['SimHei']
# 解決負號'-'顯示爲方塊的問題
plt.rcParams['axes.unicode_minus']=False
# 獲取數據
def get_data(indexID,dateStart="20000101",dateEnd="20200320",local=True):
# 定義網絡數據接口
api="http://quotes.money.163.com/service/chddata.html?code="
if local:
data=pd.read_csv(indexID[1:]+'.csv',index_col=0,encoding='gb2312') # index_col將第一列作爲index使用,'gb2312'文件裏有中文
else:
api+=indexID+"&start="+dateStart+"&end="+dateEnd
api+="&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;VOTURNOVER;VATURNOVER"
data=pd.read_csv(api,index_col=0,encoding='gb2312')
data=data.loc[(data.index>datetime.strptime(dateStart,"%Y%m%d").strftime("%Y-%d-%m"))
&(data.index<datetime.strptime(dateEnd,"%Y%m%d").strftime("%Y-%d-%m"))]
data=data.sort_values(by=['日期']) #排序
return data
def invest(indexID,dateStart,dateEnd,amount,freq,fixRate=None,fixPercent=0.15,strategy=1):
'''
簡單定投的實現
strategy-定投策略:
1-固定金額(amount)
2-固定比例(fixPercent)
3-給定最小投入額情況下的固定比例(max(fixPercent,amount))
4-逢低加大買入
fixRate-定期存款的年利率:用於計算收益對比
'''
# 獲取數據
data=get_data(indexID,dateStart,dateEnd,False)
# 初始化定投金額/份額列表/定投日期
listAmount=[]
listShare=[]
listDate=[]
# 定投比例
percent=fixPercent
# 定投次數
num=0
# 固定收益
fixProfit=0
# 開始定投
st=datetime.strptime(dateStart,"%Y%m%d")
sd=datetime.strptime(dateEnd,"%Y%m%d")
while True:
if st.strftime("%Y-%m-%d") not in data.index:
st+=timedelta(days=1)
else:
#投入金額
price=data.loc[st.strftime("%Y-%m-%d")]['收盤價']
listDate.append(st)
if strategy==1:
listAmount.append(amount)
elif strategy==2:
listAmount.append(price*percent)
else:
listAmount.append(max(price*percent,amount))
share=listAmount[-1]/price
listShare.append(share)
#定投週期
st+=timedelta(days=freq)
# 固定收益更新
fixProfit+=(1+fixRate)**((sd-listDate[-1]).days/365)*listAmount[-1]
num+=1
if st>sd:
break
# 計算定投收益
totalInvest=sum(listAmount)
totalProfit=sum(listShare)*price-totalInvest
# 計算固定利率收益
fixProfit=fixProfit-totalInvest
return totalInvest,totalProfit,fixProfit
每週定投一次,每次定投500,計算2019年對滬深300指數基金進行定投的收益率
# 數據參數
indexID='0000300' #滬深300
dateStart='20190101' #開始日期
dateEnd='20191231' #結束日期
# 固定年利率 作爲收益對比
fixRate=0.03
# 定投參數
amount=500 # 每期定投金額(單位:元)
freq=7 # 定投週期(單位:天)
# 數據獲取
data=get_data(indexID,dateStart,dateEnd,False)
data.head()
# 數據可視化
'''
str轉換爲datetime 通過datetime.strptime()
datetime對象 轉換爲str 通過datetime.strftime()
'''
xs=[datetime.strptime(d,'%Y-%m-%d').date() for d in data.index]
plt.figure(figsize=(16,8))
plt.subplot(121)
plt.plot(xs,data["收盤價"])
plt.xlim([xs[0],xs[-1]])
plt.xticks(rotation=60)
plt.xlabel("日期")
plt.ylabel("指數值")
plt.title(data["名稱"][0])
plt.grid()
plt.subplot(122)
plt.plot(xs,pd.to_numeric(data['漲跌幅'],errors='coerce'))
plt.xlim(xs[0],xs[-1])
plt.xticks(rotation=60)
plt.xlabel("日期")
plt.ylabel("指數變化值")
plt.title(data['名稱'][0]+"日漲跌值")
plt.grid()
totalInvest,totalProfit,fixProfit=invest(indexID,dateStart,dateEnd,amount,freq,fixRate=fixRate,fixPercent=0.15,strategy=1)
print("定投總投入爲%10.2f元,獲得收益%10.2f元,固定年利率收益爲%10.2f元"%(totalInvest,totalProfit,fixProfit))
print("定投收益率{:6.2f}%".format(totalProfit/totalInvest*100))
'''
輸出結果:
定投總投入爲 26000.00元,獲得收益 2531.34元,固定年利率收益爲 382.18元
定投收益率 9.74%
'''
每週定投一次,每次定投500,分別計算從2002年開始到2019年,每年定投滬深300指數基金的收益率
# 數據參數
indexID="0000300"
firstYear=2002
nYears=18
#固定年利率-收益對比
fixRate=0.03
# 定投參數
amount=500 # 每期定投金額
freq=7 # 定投週期(單位:天)
# 定投收益
profits=[]
# 遍歷年份
for year in range(nYears):
thisYear=str(firstYear+year)
dateStart=thisYear+"0101"
dateEnd=thisYear+"1231"
totalInvest,totalProfit,fixProfit=invest(indexID,dateStart,dateEnd,amount,freq,fixRate=fixRate,fixPercent=0.15,strategy=1)
profits.append(totalProfit/totalInvest*100)
print("{}年的定投收益率{:6.2f}%".format(thisYear,totalProfit/totalInvest*100))
'''
輸出結果:
2002年的定投收益率-13.37%
2003年的定投收益率 0.10%
2004年的定投收益率-13.56%
2005年的定投收益率 0.13%
2006年的定投收益率 53.12%
2007年的定投收益率 41.79%
2008年的定投收益率-33.18%
2009年的定投收益率 20.27%
2010年的定投收益率 2.45%
2011年的定投收益率-19.91%
2012年的定投收益率 4.39%
2013年的定投收益率 -4.43%
2014年的定投收益率 50.56%
2015年的定投收益率 -2.79%
2016年的定投收益率 3.06%
2017年的定投收益率 10.84%
2018年的定投收益率-15.05%
2019年的定投收益率 9.74%
'''
# 可視化定投結果
xs=[datetime.strptime(str(d),'%Y').date() for d in range(2002,2020)]
plt.figure(figsize=(16,8))
plt.plot(xs,profits,'bo-.')
plt.xlim(xs[0],xs[-1])
plt.xlabel("年份")
plt.ylabel("收益百分比")
plt.title("滬深300的年定投收益率(每週固定金額的定投)")
plt.grid()
for i in range(len(profits)):
if profits[i]>0:
plt.text(xs[i],profits[i]+2,str(round(profits[i],2))+"%",color='r',fontsize=13)
else:
plt.text(xs[i],profits[i]-4,str(round(profits[i],2))+"%",color='g',fontsize=13)
5.改變定投策略,獲得更好的收益(以2018和2019的平均收益率分析)
# 數據參數
indexID="0000300"
firstYear=2002
nYears=18
#固定年利率-收益對比
fixRate=0.03
# 定投參數
amount=500 # 每期定投金額
freq=7 # 定投週期(單位:天)
# 定投收益
quarterly_profits=[]
改變定投週期(每三個月定投)
for year in range(nYears):
thisYear=str(firstYear+year)
# 遍歷一年中的四個季度
for quarter in range(4):
monthStart=quarter*3+1
monthEnd=monthStart+2
dateStart=thisYear+str(monthStart).zfill(2)+"01"
dateEnd=thisYear+str(monthEnd).zfill(2)+"30"
totalInvest,totalProfit,fixProfit=invest(indexID,dateStart,dateEnd,amount,freq,fixRate=fixRate,fixPercent=0.15,strategy=1)
quarterly_profits.append(totalProfit/totalInvest*100)
# 可視化定投結果
xs=[datetime.strptime(str(d)+str(m).zfill(2),'%Y%m').date() for d in range(2002,2020) for m in range(1,12,3)]
plt.figure(figsize=(16,8))
plt.plot(xs,quarterly_profits,'bo-.')
plt.xlim(xs[0],xs[-1])
plt.xlabel("年份")
plt.ylabel("收益百分比")
plt.title("滬深300的年定投收益率(每週固定金額的定投)")
plt.grid()
for i in range(len(quarterly_profits)):
if quarterly_profits[i]>0:
plt.text(xs[i],quarterly_profits[i]+1,str(round(quarterly_profits[i],2))+"%",color='r',fontsize=13)
else:
plt.text(xs[i],quarterly_profits[i]-2,str(round(quarterly_profits[i],2))+"%",color='g',fontsize=13)
2018、2019平均收益率如下:
改變定投金額(設置投入資金固定比例)
及時止損(即資金最大時收盤)
爲了更加細緻地得到最大定投收益,我們將定投週期改爲日,只定投18、19年,其他不變,找出最大收益的日期爲截至定投日期,並計算截至日期之前的平均收益率
這種方法,是基於知道了每日的收盤價,然後計算每天的收益率,當是一年的最大值時就停止定投,類似於”上帝視角“。
def invest(df,invest_cycle,invest_amount):
'''
返回每次投資的收益率
invest_cycle:定投週期
invest_amount:定投金額
'''
data=df['收盤價']
time=list(df.index.values)
time.append("2020")
rate_dic={} #記錄 每一次的定投的收益率
total_invest=0
total_invest_dic={}
share=0
for i in range(len(data)): # len(data)=len(time)+1
if time[i][:4]==time[i+1][:4]:
if i%invest_cycle==0: # 符合定投日期
share=share+invest_amount/data[i] #買入
total_invest=total_invest+invest_amount # 記錄定投時的總投資
total_invest_dic[time[i][:4]]=total_invest # 記錄每次定投的投資
rate_dic[time[i]]=(share*data[i]/total_invest-1)*100 #每次定投時的收益率
else: # 一年的最後一天
if i%invest_cycle==0: # 符合定投日期
share=share+invest_amount/data[i] #買入
total_invest=total_invest+invest_amount # 記錄定投時的總投資
total_invest_dic[time[i][:4]]=total_invest # 記錄每次定投的投資
rate_dic[time[i]]=(share*data[i]/total_invest-1)*100 #每次定投時的收益率
share=0 #計算下一年清零
total_invest=0
return rate_dic
def date_close(result):
'''
返回最大投資的日期
策略:反向搜索
計算每日的定投收益率-->確定最大收益的投資截至的日期
'''
dic_18={} # 記錄2018年的定投日期及收益率
dic_19={}
key=result.keys() # 記錄定投的日期
value=result.values() # 記錄定投的收益率
for i in range(len(list(key))):
if list(key)[i][:4]=='2018':
dic_18[i]=list(value)[i]
else:
dic_19[i]=list(value)[i]
max1=max(dic_18.values())
id=list(dic_18.keys())[list(dic_18.values()).index(max(dic_18.values()))] # 最大值的id
date_close1=list(key)[id]
max2=max(dic_19.values())
id=list(dic_19.keys())[list(dic_19.values()).index(max(dic_19.values()))] # 最大值的id
date_close2=list(key)[id]
return [max1,max2,date_close1,date_close2]
#當 週期爲1
data_1819=get_data(indexID,'20180101','20191231',False)
result=invest(data_1819,1,500)
plt.figure(figsize=(16,6))
plt.title("週期爲1 投資金額爲500 的每日收益趨勢")
plt.xticks([0,50,100,150,200,250,300,350,400,450])
plt.plot(result.keys(),result.values())
# 截至定投的日期
d=date_close(result)
# 計算此時的平均收益
print("平均收益",(d[0]+d[1])/2)