最近,在用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%。
但我們從圖中看,就很有意思:
(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年股市上漲中,基金定投收益又會快速上升)
最後我們基本上可以得出這樣的結論:
(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成功驗證巴菲特推崇的“指數定投”