无法基于日期数据完成指数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
相关产品推荐
相关产品推荐

