1. 首页 > 基金定投

基金定投为何不赚钱(基金定投是否稳赚不赔)

最近逛知乎时,我发现大家对于“基金定投能不能赚钱?”这个话题特别感兴趣。

基金定投一定赚钱吗?1.7 万赞同 · 676 评论回答

你看,投资一直是热门话题,尤其是当股市红红火火的时候。基金定投作为一种相对风险更低的投资方式,再加上支付宝、微信这些平台的推广,很多人开始考虑是否要加入定投大军。

关于基金定投的方法、优缺点,这里面的水很深,我就不在这里多说了。可以去看看那些高赞回答,讲得头头是道。

不过啊,磊哥哥作为一个理工科出身的人,看到那些回答总觉得哪里不踏实。没有数据支撑的结论,总感觉像是空中楼阁。我心里有几个疑问:

  1. 这些回答里的结论,数据支持得住吗?
  2. 定投的方式和周期,对收益的影响到底有多大?
  3. 如果基金定投真有那么赚钱,为啥还有那么多人去炒股、搞期货呢?

看了那么多回答,我的疑惑一点也没解开。所以啊,磊哥哥决定自己来动手研究一番。

出于对科学的尊重,我研究的方法必须是数据驱动的——没数据,就没说服力。我相信,人可能会撒谎,但数据,是骗不了人的。

既然决定了,那就开始吧。(一定要看到最后,会有收获的!加油!)

第一部 获取数据

以数据为支撑,那么第一步就是获取数据。我们首先要获取各基金的历史净值,并且保存下来,方便后续处理。

我先是找到了一款强大的Python库——akshare,它能帮我们获取到所有A股基金的代码和名称。

简单几段代码,就能获取A股基金的相关数据,具体的使用,请访问akshare查询。

import akshare as ak
# 获取所有A股基金的代码和名称
fund_list = ak.fund_name_em()
fund_list.to_csv('china_funds.csv', index=False, encoding='utf-8-sig')
fund_code="001258" #先拿这个基金代码举例子
# 获取历史数据


磊哥哥
7 次咨询
5.0
14230 次赞同
去咨询


hist_data = ak.fund_open_fund_info_em(symbol=fund_code, indicator="单位净值走势")

上面的代码先获取了所有A股基金的代码和名称,并保存到了csv文件,这个文件内容的截图如下:

然后通过fund_open_fund_info_em函数获取了一个基金的历史行情数据,我们这里现拿001258这个基金举例。

根据基金代码获取基金名

这里没什么好说的,这是一个工具函数,目的是根据基金代码获取基金名字。这个函数以后要用:

def find_fund_name(fund_code):
    # 在基金列表中查找对应的基金代码
    fund_info = fund_list[fund_list['基金代码'] == fund_code]
    # 如果找到了对应的基金,返回基金名称
    if not fund_info.empty:
        return fund_info.iloc[0]['基金简称']
    else:
        return "基金代码不存在

制定定投策略 编写回测函数

接下来,就是回测的环节了。我定义了一个backtest函数,用来模拟定投的整个过程,从开始投资的那天起,直到定投的最后一天。这个过程中,每个月我都会投入相同的金额,然后看看最后的收益如何。

这个backtest函数回测一个简单的定投策略,即初始投资XXXX元,然后每个月月初一号定投xxxx元。同时这个函数还接受定投初始日期和结束日期。

这是一个再简单不过的策略,也是普通老板姓最容易操作的策略。我们简单起见,把这个策略具体化:初始投资10000元,然后每个月月初一号定投1000元。

整个模拟过程中,我记录下了投资的总金额、每个月的投资价值、最终的净值、收益率和最大回撤。这些都是评估一个投资是否成功的关键指标。

代码如下:

def backtest(fund_code, start_date, end_date, initial_investment, monthly_investment):
    # 获取历史数据
    hist_data = ak.fund_open_fund_info_em(symbol=fund_code, indicator="单位净值走势")
    
    if '净值日期' not in hist_data.columns:
        print(f"Columns in the dataframe: {hist_data.columns}")
        print("The column '净值日期' was not found in the data returned by akshare.")
        return None
    
    hist_data['净值日期'] = pd.to_datetime(hist_data['净值日期'])
    hist_data = hist_data.set_index('净值日期')
    hist_data = hist_data[(hist_data.index >= start_date) & (hist_data.index <= end_date)]
    
    # 初始化投资状态
    total_investment = initial_investment
    fund_units = initial_investment / hist_data.iloc[0]['单位净值']
    portfolio_value = [fund_units * hist_data.iloc[0]['单位净值']]
    investment_dates = pd.date_range(start_date, end_date, freq='M')

    # 定投逻辑
    for date in investment_dates:
        closest_date = hist_data.index.asof(date)
        if pd.notnull(closest_date):
            nav = hist_data.at[closest_date, '单位净值']
            fund_units += monthly_investment / nav
            total_investment += monthly_investment
            portfolio_value.append(fund_units * nav)
        else:
            portfolio_value.append(portfolio_value[-1])  # 如果没有净值数据,保持不变

    # 创建回测结果DataFrame
    result_df = pd.DataFrame(data={
        'Date': investment_dates.union([start_date]),
        'Portfolio Value': portfolio_value,
        'Total Investment': [initial_investment + monthly_investment * i for i in range(len(portfolio_value))],
    })

    # 计算统计数据
    result_df['Net Value'] = result_df['Portfolio Value'] - result_df['Total Investment']
    result_df['Return'] = result_df['Net Value'] / result_df['Total Investment']
    result_df['Drawdown'] = 1 - (result_df['Portfolio Value'] / result_df['Portfolio Value'].cummax())

    return result_df

开始策略回测

然后,重头戏来了,我们开始回测这个测略和数据分析。

我把所有基金的回测结果都统计出来,还找出了最小回撤、最高收益率、最高平均收益率以及最大净值的那几个基金。这样一来,我们就可以清楚地看到,哪些基金在过去的时间里表现得最好。

当然,我也把这些数据整理成了一份漂亮的HTML报告。这样,就算是对Python一窍不通的朋友,也能一目了然地看到结果。我把代码中输出图像的代码给注释了,如果你要循环回测多个基金,生成图像有点慢,如果是一个基金,那你可以把他们打开。

代码如下:

# 回测所有选定基金,并收集统计数据
num_funds = len(selected_fund_codes)
num_columns = 4
num_rows = num_funds // num_columns + (num_funds % num_columns > 0)

# Create the subplot grid
# fig, axs = plt.subplots(num_rows, num_columns, figsize=(28, 7 * num_rows),squeeze=False)
# fig.suptitle('Portfolio Value of Randomly Selected Funds Over Time')
# axs = axs.flatten()[:num_funds]
for i, fund_code in enumerate(selected_fund_codes):
    # Calculate row and column index for the current subplot
    # row_idx = i // num_columns
    # col_idx = i % num_columns
    # Perform backtesting
    print("开始回测基金:", fund_code,"这是第",i+1,"个基金")
    try:
        result_df = backtest(fund_code, starttime, endtime, 10000, 1000)
    except Exception as e:
        print("Error: ",e.args)
        
    if result_df is None:
        continue
   
     # Plot the data
    # axs[i].plot(result_df['Date'], result_df['Portfolio Value'], label="Portfolio Value of Fund: "+fund_code)
    # axs[i].plot(result_df['Date'], result_df['Return'], label="Return Ratio of Fund: " +fund_code)
    # axs[i].legend()
    # axs[i].set_title(f"Fund Code: {fund_code} - {find_fund_name(fund_code)}")
    # 添加总投资金额
    total_investment_amount = result_df['Total Investment'].iloc[-1]
    
    stats.append({
         '基金名称': find_fund_name(fund_code),
        '基金代码': fund_code,
        '最大回撤': result_df['Drawdown'].max(),
        '最大收益率': result_df['Return'].max(),
        '平均收益率': result_df['Return'].mean(),
        '平均回撤': result_df['Drawdown'].mean(),
        '最终净值': result_df['Portfolio Value'].iloc[-1],
        '净值与总投资差额': result_df['Portfolio Value'].iloc[-1] - total_investment_amount,
        '总投资金额': total_investment_amount
    })

# 调整图表布局并保存
# plt.tight_layout()
# plt.savefig('backtest_curves.png')
# plt.show()

# 转换统计数据为DataFrame
stats_df = pd.DataFrame(stats)

# 为表格添加“总投资金额”列
stats_df['总投资金额'] = stats_df['最终净值'] - stats_df['净值与总投资差额']

# 选择最优基金
best_fund_idx = stats_df['最大回撤'].idxmin()
best_max_return_idx = stats_df['最大收益率'].idxmax()
best_avg_return_idx = stats_df['平均收益率'].idxmax()
best_netValue = stats_df['最终净值'].idxmax()

best_fund = stats_df.loc[[best_fund_idx, best_max_return_idx, best_avg_return_idx,best_netValue]]

# 输出HTML表格
html_table = stats_df.to_html(index=False)
best_funds_html_table = best_fund.to_html(index=False)

# 保存HTML文件
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
html_file_name = f'backtest_stats_{timestamp}.html'
with open(html_file_name, 'w', encoding='utf-8') as f:
    f.write(f"<h1>回测时间段:{starttime} -> {endtime}</h1>")
    f.write(html_table)
    f.write('<br><br>')
    f.write('Best Funds: 三个基金分别为:最小回撤基金,最大峰值收益率,最大平均收益率,还有剩余最大净值的基金,最后一个基金应该是该定投方案最好的基金<br>')
    f.write(best_funds_html_table)

print(f"Backtest statistics and best funds saved to {html_file_name}")

数据分析

我先回测了001258这个基金的情况。回测的时间段为:"2021-01-01"-> "2023-12-31",结果如下:

统计数据如下:

我们代码很好的给了我们结果,可以看到,这样的定投策略对于这个基金而言,在时间段"2021-01-01"-> "2023-12-31"里,显然是不赚钱的。我们在两年的定投中,损失了3117元,这还不如去银行存款!

找出能赚钱的基金

上面的代码给了我们一个基金的回测数据,显然这个基金不能赚钱,但是,回到开头的问题。A股中有没有通过定投可以赚钱的基金?

既然有了代码,我们就开始循环回测随机50个基金。循环回测代码如下:

# 随机选出10个基金代码
selected_fund_codes = random.sample(fund_list['基金代码'].tolist(), 50)

for i, fund_code in enumerate(selected_fund_codes):
    # Calculate row and column index for the current subplot
    row_idx = i // num_columns
    col_idx = i % num_columns
    #Perform backtesting
    print("开始回测基金:", fund_code,"这是第",i+1,"个基金")
    
    try:
        result_df = backtest(fund_code, "2021-01-01", "2023-12-31", 10000, 1000)
    except Exception as e:
        print("Error: ",e.args)
    if result_df is None:
        continue

运行上面的代码后,结果如下:

Best Funds: 三个基金分别为:最小回撤基金,最大峰值收益率,最大平均收益率,还有剩余最大净值的基金,最后一个基金应该是该定投方案最好的基金

可以看到如果以最终收益最为衡量标准,001829这个基金,是这50个基金中定投效果最好的,投资两年,赚了2544,2年综合收益率为5.5%,年化简单计算,大概为2.6%。其他结论我就不总结了,聪明的你可以看看上面的数据表格总结。

这个收益率,嗯~~~~还真不如银行存款。

我搞了了两年定投,最后还不如银行存款来的高,我还要挑选半天基金。而且从上面的数据可以看到,大部分基金都是亏的,这样定投,挑选基金的风险很高啊,这折腾半天干啥?

到这里,似乎我们开头的问题有了答案,基金定投亏多赚少,而且要仔细挑选基金,大部分基金都是亏的,挑选基金有很多坑。而且就算赚钱,似乎好不如银行存款的利率。

但我还是不死心,我想看看A股里所有的基金的回测结果,看看是不是能找到几个收益率高赚钱的基金。

那么说干就干。

A股中所有基金的回测

我用上面的代码,回测了所有A股中的基金,一共有20083个。这么多基金,我的电脑都跑冒烟了,麻烦点个赞鼓励下,这些回测结果,我放到我自己的网站上,大家可以查看。

基金定投是否稳赚不赔?-从数据揭秘定投的真相-Always Learn For Life​alwayslearn.life/216

我这里直接给出结论:

Best Funds: 三个基金分别为:最小回撤基金,最大峰值收益率,最大平均收益率,还有剩余最大净值的基金,最后一个基金应该是该定投方案最好的基金

什么?收益最好的基金。。。既然赚了130多万?回报率足足有1100%。这太恐怖了。

我赶紧去查了下这个基金:

看起来也很一般,是一个稳健理财的基金,普通人还买不到。

我把所有回测的数据放到Excel里,按照收益排名,以下是截图,请自由享用。

同样Excel数据在我网站上可以下载。

你如果看到这里,恭喜你,我们似乎找到了财富密码,这几个表现最好的基金,也就是我现在定投的基金,我们通过数据分析,找到了定投的方向,投资是一场马拉松,而数据就是我们的北星,指引我们前行的方向。实话实话,目前这几个基金表现还不错,但是我要表明的是,以上只是对历史数据的回测得出的结论,不代表未来基金的走势,只是这几个基金前两年表现好,不代表以后会表现良好,总之,投资需谨慎~~!

通过这次回测,我们能够清晰地看到,虽然不是所有基金都能带来预期的收益,但确实有一部分基金表现得非常突出。这验证了我的一点想法——基金定投可以赚钱,但关键在于选择哪些基金,以及如何定投。

最后,我将所有的数据和分析结果整理成了一份报告,并保存为HTML格式,你们不需要懂编程,也能轻松查看。

如果你对这次实验的详细过程感兴趣,或者想要学习如何使用Python和AI进行投资分析,我在我的网站上准备了一系列的高清视频课程。只需点击这里,就可以开始你的智能投资学习之旅了

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站不拥有所有权,不承担相关法律责任。如发现有侵权/违规的内容, 联系QQ15101117,本站将立刻清除。

联系我们

在线咨询:点击这里给我发消息

微信号:666666