You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法基于日期数据完成指数curve_fit拟合,求助解决方案

解决SPY指数拟合curve_fit收敛失败问题

错误原因分析

你遇到的Optimal parameters not found: Number of calls to function has reached maxfev = 800错误,本质是非线性拟合(指数/幂函数)时,优化器无法在默认迭代次数内找到最优参数,核心问题出在日期数值过大和缺少初始参数猜测。


疑问解答

1. 日期处理方式是否正确?

当前将日期转成Unix时间戳的方式可行,但数值太大(比如最新SPY数据的时间戳是10位以上整数),会导致指数函数计算时出现数值爆炸/下溢,让优化器难以收敛。

更合理的处理是将日期转换为相对时间:比如从数据起始日期开始,按月度数据计算已过去的月份数,把x的数值范围缩小到几十到几百的量级,大幅降低拟合难度。

2. 是否需要设置p0初始参数?

必须设置。线性拟合对初始值不敏感,但非线性拟合(指数、幂函数)的优化过程严重依赖初始参数猜测。curve_fit默认初始值是全1,和SPY真实的指数增长参数差距极大,直接导致优化器无法找到收敛方向。


修正后的完整代码

import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
from scipy.optimize import curve_fit
from matplotlib.dates import DateFormatter

# 获取月度SPY数据
df = yf.download("SPY", interval='1mo')
df = df.reset_index()

# 定义指数拟合函数(适配SPY的增长趋势)
def exp_func(x, a, b, c):
    return a * np.exp(b * x) + c

# 处理日期:转换为相对起始日期的月份数(缩小x数值范围)
df['relative_month'] = (df['Date'].dt.year - df['Date'].dt.year.min()) * 12 + (df['Date'].dt.month - df['Date'].dt.month.min())
xdata = df['relative_month'].to_numpy()
ydata = df['Close'].to_numpy()

# 设置初始参数猜测p0:贴合SPY历史走势的合理值
p0 = (10, 0.01, 0)
popt, pcov = curve_fit(exp_func, xdata, ydata, p0=p0, maxfev=2000)  # 可选调高迭代次数

print("指数拟合参数:", popt)

# 生成拟合曲线
y_pred = exp_func(xdata, *popt)

# 绘图(保留原始日期作为x轴)
plt.figure(figsize=(10,6))
plt.plot(df['Date'], ydata, label='SPY实际收盘价')
plt.plot(df['Date'], y_pred, '-r', label=f'指数拟合曲线: y={popt[0]:.2f}e^({popt[1]:.4f}x)+{popt[2]:.2f}')

# 设置x轴日期格式(满足日期显示需求)
date_form = DateFormatter("%Y-%m")
plt.gca().xaxis.set_major_formatter(date_form)
plt.xticks(rotation=45)

plt.legend()
plt.tight_layout()
plt.show()

关键说明

  • 相对时间转换:把Date转成relative_month,x的范围从10位时间戳变成0到几百,避免指数计算的数值异常
  • 初始参数p0:a取SPY早期收盘价附近值,b取0.01左右(对应月度级别的指数增长),c取0作为基线,贴合实际走势
  • 可选调整maxfev:如果仍收敛失败,可以适当调高迭代次数,比如2000

内容的提问来源于stack exchange,提问作者Randy Pierson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:43:11