天天看點

基金定投需要注意波段操作!(文章有點長,含Python代碼)

最近,在用Python對股市進行量化分析,發現網上流傳很廣的一些結論并不一定正确。

定投政策就是不要管股市是漲是跌,每個月都定期的拿出一筆錢來買基金。股市總是上演七陪二平一賺的股市,散戶因為沒有能力判斷,索性不判斷,而基金定投就被認為是一種投資的途徑。

其中,邢不行老師的 《【量化小講堂系列14-Python量化入門】資料告訴你:驚人的指數定投政策》在網上傳播很廣。(2)(3)

而這種理論一個最大的依據是 “巴菲特這一輩子曾經無數次的說過:對于個人投資者,最好的投資方式就是指數基金定投。”

但也有人專門為此較真,拿了巴菲特的原文,認為巴菲特根本沒有推薦過這種方法。(1)

那麼定投究竟美不美?為什麼這麼多的理财和銀行都在推薦?我們用Python進行簡單的分析一下。(文章後面提供源代碼,應該容易讀懂)

首先驗證邢老師的第一個例子,從2007年10月股市最高點開始定投,一直到2009年7月股市3000點,文中用滬深300指數作為定投标的,但指數不能直接買賣,而滬深300基金(510300)是2012年才開始,是以我們把50ETF(510050)作為依據計算定投收益,結果如下,的确如邢不行老師的結論,50ETF價格下降了35.93%,理财定投隻有3.91%,50ETF定投收益率達到24.28%。

基金定投需要注意波段操作!(文章有點長,含Python代碼)
基金定投需要注意波段操作!(文章有點長,含Python代碼)

但我們從圖中看,就很有意思:

(1)基金定投與基金價格的趨勢基本上是一緻的,

(2)基金定投的收益明顯高于基金本身的收益,特别在2009年開始後的收益。

(3)基金定投收益一直低于理财定投,隻有在2009年6月中旬開始才超過理财定投。

(4)在2007年10月到2008年12月間,股市下跌,50ETF無論是定投還是基金本身,收益都是很差的;而在2008年12月到2009年7月,股市上漲,50ETF無論定投還是基金本身收益都很好,也是因為這段時間的收益,導緻了最終定投收益超過理财收益。

我們再拿滬深300ETF(510300)驗證,假設從成立開始的2012年5月28日開始,就定投基金,一直持有到2018年底,投資收益情況如下:

(1)定投收益率(10.85%)不如理财定投收益(14.75%)不如直接的基金收益(26.79%)

(2) 基金定投收益趨勢與基金價格變化趨勢基本一緻。

(3) 基金定投收益與基金價格變化犬牙交錯,并不一定高于基金價格變化。

(4) 這種情況購買反而在2015年股市高峰期後基金定投收益大部分時間高于理财定投收益。

(5) 但在2018年不斷下降中,基金定投收益又開始快速下降,直到2018年末甚至低于理财定投收益。(大家可以自己驗證,在2019年股市上漲中,基金定投收益又會快速上升)

基金定投需要注意波段操作!(文章有點長,含Python代碼)
基金定投需要注意波段操作!(文章有點長,含Python代碼)

最後我們基本上可以得出這樣的結論:

(1)基金定投并沒有我們想象那麼好,至少在A股市場,基金定投并不是一門好生意。

(2)基金定投依然波段十分明顯,與股市變化趨勢基本一緻。抓住幾個大的峰值是十分重要的。

(3)總的而言,基金定投在股市上漲中追不上股市的上漲速度,在股市下跌中下跌也會相對比股市跌幅小,有一定的緩和作用,但作用并不是那麼明顯。

(4)定投政策不僅可以用于基金,也可以用于其他的股票(隻要把源碼中參數改變即可驗證),但無論投資品種是什麼,定投政策也必須根據趨勢進行高抛低吸。

最後給出源代碼如下(直接用tushare提供資料源,如果又需要股市的資料檔案,可以私信交流):

#你一定要相信,你自己就是一道風景,沒有必要在别人的風景裡仰視!
#不是每一次努力都有收獲,但是每一次收獲都必須努力
#人的一切痛苦,本質上都是對自己的無能的憤怒。——王小波

import pandas as pd
import tushare as ts
import numpy as np
import datetime
import matplotlib.pyplot as plt  

def function(a, b):
	if a == b:
		return 0
	else:
		return 1

#按 利率 計算 期間定投收益,AIP:automatic investment plan
def AIP(inRate,startdate,enddate):

    df = pd.DataFrame(index=None,columns=['date','rate','profit'])

    d1 = datetime.datetime.strptime(startdate, '%Y-%m-%d')
    d2 = datetime.datetime.strptime(enddate, '%Y-%m-%d')
    delta = d2 - d1
    n = delta.days   # 投資的總日期

    df['date'] = pd.date_range(start=startdate,end=enddate,periods=n+1) #按日期數量産生日期
    df['rate'] = inRate/365              # 簡單按365日把年華收益轉化為日收益
    df['profit']=(df['rate']+1).cumprod()  # 計算累計收益
    df['month']=df['date'].apply(lambda x: datetime.datetime.strftime(x,"%m"))
    df['month1']=df['month'].shift(1)
    df['isinv']=df.apply(lambda x: function(x.month,x.month1),axis=1)  #計算是否為第一日
    df['理财投資額']=df['isinv']*1000     #如果第一日就會進行投資買入理财産品
    df['理财總投資']=df['理财投資額'].cumsum()   # 累計投資總和
    df['理财份額']=df['理财投資額']/df['profit']  
    df['理财總份額']=df['理财份額'].cumsum()
    df['理财價值']=df['理财總份額']*df['profit']
    df['理财收益']=df['理财價值']-df['理财總投資']
    df['理财收益率']=df['理财收益']/df['理财總投資']

    df.set_index('date',inplace=True)  # 把日期作為排序依據
    
    return df

# 按某個代碼進行定投計算(可以是基金也可以是股票)
def Stock(sCode,startdate,enddate):

    # 采集資料
    df=ts.get_k_data(code=sCode,start=startdate,end=enddate)
    df['s_month']='1'  #初始化月份填一個數
    df['s_month1']='0'   # 初始化
    df['s_month']=df['date'].str[0:4]+df['date'].str[5:7]  # 月份比較,尋找月初第一日如果是下一日月份沒變 
    df['s_month1']=df['s_month'].shift(1)
    df['date'] = pd.to_datetime(df['date'])
    df['s_isinv']=df.apply(lambda x: function(x.s_month,x.s_month1),axis=1)  # 根據月份變化是否标志出是否月初
    df['股票份額'] = round(df['s_isinv']*1000/df['close']/100,0)*100  #買賣股票一般按100股進行
    # df['股票份額'] = round(df['s_isinv']*1000/df['close'],0)  # 不按100股買賣進行計算
    df['股票總份額']=df['股票份額'].cumsum()
    df['股票價值']=df['股票總份額']*df['close']
    df['股票投資額']=df['股票份額']*df['close']
    df['股票總投資']=df['股票投資額'].cumsum()
    df['股票收益']=df['股票價值']-df['股票總投資']
    df['股票收益率'] = df['股票收益']/df['股票總投資']

    return df

start_date = '2012-05-12'
end_date = '2018-12-30'
scode = '510300'
plt.figure()
plt.rcParams['font.sans-serif']=['SimHei'] #用來正常顯示中文标簽
plt.rcParams['axes.unicode_minus']=False #用來正常顯示負号

plt.title(scode +"股票收益率計算")

df1 = Stock(scode,start_date,end_date)

df2 = AIP(0.04,start_date,end_date)

# 把投資和理财合并,并且把沒用的列盡量去除
daily_data=pd.merge(df1,df2,'inner',on='date')
daily_data.drop(['month','month1','s_month','s_month1','isinv','s_isinv'],axis=1,inplace=True)
daily_data.drop(['股票份額','股票投資額','rate','profit','理财投資額','理财份額'],axis=1,inplace=True)

iclose = daily_data['close'].iloc[0]  #取得首日的股價

daily_data['股價變化率'] = daily_data['close']/iclose-1  #單純按最後一天和首日股價進行比較
daily_data.set_index("date",inplace=True)
print('起投日期:',start_date)
print('結束時間:',end_date)
print('收市價收益率','{:.2%}'.format(daily_data.iloc[-1]['股價變化率']))

print('股票總投資',daily_data.iloc[-1]['股票總投資'])
print('股票價值',daily_data.iloc[-1]['股票價值'])
print('股票收益',daily_data.iloc[-1]['股票收益'])
print('股票收益率','{:.2%}'.format(daily_data.iloc[-1]['股票收益率']))

print('理财總投資',daily_data.iloc[-1]['理财總投資'])
print('理财價值',daily_data.iloc[-1]['理财價值'])
print('理财收益',daily_data.iloc[-1]['理财收益'])
print('理财收益率','{:.2%}'.format(daily_data.iloc[-1]['理财收益率']))

daily_data.to_excel("daily.xls")

daily_data['股價變化率'].plot()
daily_data['理财收益率'].plot()
daily_data['股票收益率'].plot()

plt.legend()

plt.show()


           

參考文獻:

1、巴菲特又被冤枉了,他從沒推薦過指數定投!

2、資料告訴你:驚人的指數定投政策

人大經濟論壇,詳細出處參考: https://bbs.pinggu.org/forum.php?mod=viewthread&tid=4585892&page=1

3、用Python成功驗證巴菲特推崇的“指數定投”

繼續閱讀