实锤,无脑定投指数基金真的可以赚钱么?

Posted babycomeon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实锤,无脑定投指数基金真的可以赚钱么?相关的知识,希望对你有一定的参考价值。

技术图片

投资有风险,入市需谨慎,本文不构成任何投资理财建议,仅做交流学习使用。

不知道大家有没有在网上见过各种理财课程,说什么小白入门最简单的就是定投指数基金,还说人家巴菲特也这么投,这种课程介绍是越写越夸张,后面最夸张说还能打成一个小目标。

过分了啊,如果打成小目标这么简单,那不是中国打成小目标的怎么地也有个百分之十左右了吧,但是我身边好像没见过达成小目标的人啊,难道是因为我太 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 + ‘
‘)

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 上,方便大家取用。

示例代码-Github

示例代码-Gitee

以上是关于实锤,无脑定投指数基金真的可以赚钱么?的主要内容,如果未能解决你的问题,请参考以下文章

投资指数基金一定能赚到钱吗?

投资指数基金一定能赚到钱吗?

投资指数基金一定能赚到钱吗?

5月6日最新指数基金估值表(坚持定投财务自由)

2019年4月17日指数基金估值表(今日定投)

指数基金估值在哪查?怎么看?定投前要知道