基金定投需要注意波段操作!(文章有点长,含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%。
在这里插入图片描述
在这里插入图片描述
但我们从图中看,就很有意思:
(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成功验证巴菲特推崇的“指数定投”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章