投资有风险,入市需谨慎,本文不构成任何投资理财建议,仅做交流学习使用。
不知道大家有没有在网上见过各种理财课程,说什么小白入门最简单的就是定投指数基金,还说人家巴菲特也这么投,这种课程介绍是越写越夸张,后面最夸张说还能打成一个小目标。
过分了啊,如果打成小目标这么简单,那不是中国打成小目标的怎么地也有个百分之十左右了吧,但是我身边好像没见过达成小目标的人啊,难道是因为我太 qiong 的缘故?
还有那种用巴菲特举例子的课程介绍,拜托下次介绍的时候把故事讲完好不好,人家老巴是在美股定投基金,美股是一个熊短牛长的市场,已经连续十几年的牛市了,当然哈,最近因为疫情的影响我们和老巴一起见证了五六次的熔断。
想想都觉得自己牛逼,老巴这么大一把岁数,也不过比我们多见证了一次美股的熔断,那么,是不是说我约等于老巴?
所以,本着对任何事情都抱有怀疑的态度,我今天就要实锤一下,看看无脑定投我们国内的指数基金到底能不能赚钱。
首先如果我们在低点开始定投,在高点卖出,这个是肯定能赚钱的,这个大家都没什么疑问吧?如果这个再有问题就真的出门左转吧。
但是如果我们在高点开始定投,在低点卖出,这个真的也能赚钱么?
接下来,我会通过科学的工具以及方法,看看能不能锤爆那些卖理财课的。
开锤
第一步,我们要选定一个指数基金,这里我就已自己买过的沪深 300 指数基金,开始锤起来。
国内有很多网站都可以查到基金的历史净值,我这里选择天天基金网,选择的是「易方达沪深300ETF联接A(110020)」。名字和代码都有了,这个就不多说。
首先,我们打开这款基金的查询页面,链接: http://fundf10.eastmoney.com/jjjz_110020.html 。
可以看到哈,这个基金成立日期是 2009 年,足够我们做 10 年的数据回归分析了。
下一步就是要把这只基金的 10 年的数据抓取下来,前面看过我的爬虫系列的同学可以先停一下,自己动手试一下,没看过的可以接着往下看。
祭出神器 F12 ,选择 network 标签栏,顺便在页面上选择我们要的时间段,然后点击查询。
然后我们在 network 标签栏中,可以看到这么一条请求:
http://api.fund.eastmoney.com/f10/lsjz?callback=jQuery18303890660068294629_1586089381722&fundCode=110020&pageIndex=1&pageSize=20&startDate=2010-01-01&endDate=2020-04-05&_=1586089722912
可以看到有两个分页有关的参数,一个是 pageSize (每页数据量)另一个是 pageIndex (第几页),这里我们偷个懒,尝试一次把所有的数据都拉回来,把 pageSize 设置为 4000 , 10 年, 4000 个工作日,应该足够了。
接下来开始写第一小段代码:
import requests
startDate = ‘2010-01-01‘
endDate = ‘2020-04-05‘
foundCode = ‘110020‘
pageSize = 4000
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36‘,
‘Referer‘: f‘http://fundf10.eastmoney.com/jjjz_110020.html‘
}
url = f‘http://api.fund.eastmoney.com/f10/lsjz?&fundCode=110020&pageIndex=1&pageSize={pageSize}&startDate={startDate}&endDate={endDate}&_=1586089722912‘
response = requests.get(url, headers=header)
def write_file(content):
filename = ‘110020.txt‘
with open(filename, ‘a‘) as f:
f.write(content + ‘\n‘)
write_file(response.text)
这段代码很简单,就是把数据抓回来,并且创建了一个 txt 文件,然后把数据写进去,给你们看下结果:
数据量有点大,贴不下,就简单截个图,大致看了下数据, 10 年间,共计有 2502 条数据(这个意思就是 10 年间,只有 2502 个工作日咯)。
计算收益
接下来要做的事情就很明显了,我们要解析数据,开始按照定投的方式来计算收益了,对过程不敢兴趣的同学可以直接跳过这一小节,直接看后面的数据分析。
我这里按照两种定投方式做收益计算,一个是按周定投,每周投资 500 大洋;另一个是按月定投,每月投资 2000 大洋,看下最后的收益能差多少。
首先我们开始解析上面我们生成的那个 txt 文件,把我们需要的日期和金额取出来,使用 key 和 value 的形式组成一个 dict ,如下:
def get_data():
‘‘‘
获取数据
:return: dict
‘‘‘
with open(‘110020.txt‘) as f:
line = f.readline()
result = json.loads(line)
date_price = {}
for found in result[‘Data‘][‘LSJZList‘][::-1]:
date_price[found[‘FSRQ‘]] = found[‘DWJZ‘]
return date_price
date_price = get_data()
print(date_price)
结果我还是截图吧,数据毕竟也是有 2502 个key value 对的。
然后我们就开始制定我们的投资方式,第一个是按周定投,我们假定每周一定投,那么可以做一个函数 calculate_by_week(start_date, end_date)
来计算我们每周定投的收益情况,如下:
def calculate_by_week(start_date, end_date):
‘‘‘
每周一定投,每次定投 500
:param start_date: 开始时间
:param end_date: 结束时间
:return:
‘‘‘
total_stock = 0
total_amount = 0
nums = 0
day = start_date + datetime.timedelta(days=-1)
while day < end_date:
day = day + datetime.timedelta(days=1)
if day.weekday() != 1:
continue
while date_price.get(day.strftime(‘%Y-%m-%d‘), None) is None and day < end_date:
day += datetime.timedelta(days=1)
if day == end_date:
break
nums += 1
total_stock += round(500 / float(date_price[day.strftime(‘%Y-%m-%d‘)]), 2)
total_amount += 500
# 计算盈利
while date_price.get(end_date.strftime(‘%Y-%m-%d‘), None) is None:
end_date += datetime.timedelta(days=-1)
total_profit = round(total_stock, 2) * float(date_price[end_date.strftime(‘%Y-%m-%d‘)]) - total_amount
return nums, round(total_stock, 2), total_amount, round(total_profit)
上面这个函数会返回 4 个结果,分别是:定投次数,最终持有份额,买入总金额,实际收益。
接下来我们在写一个按月定投的,规则简单粗暴,每月 1 号定投,如果 1 号不是交易日,那么顺延至第一个交易日,如下:
def get_first_day_of_next_month(date):
first_day = datetime.datetime(date.year, date.month, 1)
days_num = calendar.monthrange(first_day.year, first_day.month)[1] # 获取一个月有多少天
return first_day + datetime.timedelta(days=days_num)
def calculate_by_month(start_date, end_date):
‘‘‘
按月定投,每月 1 号买入,如果 1 号不是交易日,则顺延至下一交易日
:param start_date:
:param end_date:
:return:
‘‘‘
total_stock = 0
total_amount = 0
nums = 0
first_day = datetime.datetime(start_date.year, start_date.month, 1)
day = first_day + datetime.timedelta(days=-1) # 将日期设置为 start_date 上个月最后一天
while day < end_date:
day = get_first_day_of_next_month(day)
while date_price.get(day.strftime(‘%Y-%m-%d‘), None) is None and day < end_date:
day = day + datetime.timedelta(days=1)
if day == end_date:
break
nums += 1
if day.strftime(‘%Y-%m-%d‘) in date_price:
total_stock += round(2000 / float(date_price[day.strftime(‘%Y-%m-%d‘)]), 2)
total_amount += 2000
# 计算盈利
while date_price.get(end_date.strftime(‘%Y-%m-%d‘), None) is None:
end_date += datetime.timedelta(days=-1)
total_profit = round(total_stock, 2) * float(date_price[end_date.strftime(‘%Y-%m-%d‘)]) - total_amount
return nums, round(total_stock, 2), total_amount, round(total_profit)
数据分析
我们先看下 110020 这只基金本身自己近 10 年的走势:
line = (
Line()
.add_xaxis(list(date_price.keys()))
.add_yaxis(
‘‘,
y_axis=list(date_price.values())
)
.set_global_opts(
title_opts=opts.TitleOpts(title=‘110020 基金走势图‘),
)
)
line.render()
结果如下:
从图中我们可以看到,在 2015 年前后达到了一个峰值,接着在 2018 年前后又有一个小高峰,随后在 2019 年一直阴跌,之后开始震荡。
原因嘛大家也都知道, 15 年有一个大牛市, 18 年也涨了一波,在 110020 这支基金的折线图上体现的是淋漓尽致。
而且 2010 年年初就净值和现在的净值相差并不大,我查了下数据, 2010 年初的单位净值为 1.06 元,而现在的单位净值为 1.3018 元,涨幅也就个 22.81% ,也就是说当年如果买了 1 万元的这个基金,到 10 年后点击今天,也就赚了个 2281 元,一年赚了 200 多,好像看起来还不如余额宝赚的多。
接下来就是激动人心的时刻,我们来验证我们定投的收益,我预计肯定会比一次买入赚的多,我们试试看。
首先第一组,我们从 10 年前开始买入,两组数据代入,如下:
# 按周定投
print(calculate_by_week(datetime.datetime.strptime(startDate,‘%Y-%m-%d‘).date(), datetime.datetime.strptime(endDate,‘%Y-%m-%d‘).date()))
# 按月定投
print(calculate_by_month(datetime.datetime.strptime(startDate,‘%Y-%m-%d‘), datetime.datetime.strptime(endDate,‘%Y-%m-%d‘)))
结果如下:
(533, 273836.56, 266500, 89980)
(125, 254918.67, 250000, 81853)
我先来解释下上面这组数据,第一组是按周定投的结果,我们总共定投了 533 次,买入的总金额是 266500 元,实际收益是 89980 元。第二组是按月定投的结果,我们总共定投了 125 次,买入的总金额是 250000 元,实际收益是 81853 元。
我用计算器算了一下,基本上收益 / 买入金额 * 100% 结果都在 33% 左右。
10 年 33% ,好像收益比余额宝差不多了,不过这里还有一个概念,就是我们这笔钱是逐年投入的,而不是一次性投入,实际上收益应该是个 2 倍左右的关系。这个和分期还款的利息算法差不多,不多说。
那么,还剩一个问题,我们如果是在 2015 年,也就是大牛市的最高点开始定投,直到今天那么还能赚钱么?
来,我们接着代入数据:
# 2015年开始,按周定投
print(calculate_by_week(datetime.datetime.strptime(‘2015-01-01‘,‘%Y-%m-%d‘).date(), datetime.datetime.strptime(endDate,‘%Y-%m-%d‘).date()))
# 2015年开始,按月定投
print(calculate_by_month(datetime.datetime.strptime(‘2015-01-01‘,‘%Y-%m-%d‘), datetime.datetime.strptime(endDate,‘%Y-%m-%d‘)))
结果如下:
(273, 113522.13, 136500, 11283)
(65, 106851.87, 130000, 9100)
当我看到这组数据的时候,说实话我是有点懵的,竟然真的还是能盈利的虽然赚的比例已经很低了,但是确实是还在赚钱的。
解释一下,从 2015 年 1 月 1 日起开始周定投,共计定投了 273 次,买入的总金额是 136500 元,实际收益是 11283 元。按照月定投,共计定投了 65 次,买入总金额是 130000 ,实际收益是 9100 。
小结
小结一下吧,我们简单的回测了 110020 这支沪深 300 的指数基金,当然我是使用 python 来完成的,如果您觉得不方便,通过 Excel 同样可以完成,方法是次要的,目标完成了就好。
简单分析一下,我们回测了 10 年定投和 5 年定投的结果,结果是 5 年定投的收益比 10 年定投的收益少了 7w 左右,当然,从牛市开始定投至今能达成正收益我自己也有点吃惊,不过还是可以简单的证明,即使选择在股市最高点入市,把时间拉长,指数定投也不会亏钱。
今天的实锤打的脸有点疼,我想静静。
最后还是那句话,投资有风险,入市需谨慎,本文不构成任何投资理财建议,仅做交流学习使用。
代码上传至代码仓库,有需要的同学可以自取。
示例代码
老规矩,所有的示例代码都会上传至代码管理仓库 Github 和 Gitee 上,方便大家取用。
原文地址:https://www.cnblogs.com/babycomeon/p/12641883.html