如何利用Ramer–Douglas–Peucker算法(RDP)的Python实现优化股价走势图去噪?
修复Ramer–Douglas–Peucker算法处理股价走势图的代码问题
我帮你分析下代码里的几个核心问题,然后给出修改后的完整方案:
原代码的主要问题
- 数据格式错误:
rdp库要求输入是二维点数组(每个元素是[x, y]形式的坐标点),但你传入的是单独的收盘价数组np.array([nfy]),这不符合算法的输入要求,算法无法计算点之间的距离。 - 时间轴未数值化:你用的datetime索引不能直接参与RDP的距离计算,算法需要数值类型的x坐标,得把时间转成可计算的数值(比如序列索引)。
- 绘图逻辑缺失:处理后的数据没有对应正确的x轴,导致图表空白或者显示异常。
修改后的完整代码
import yfinance as yf import matplotlib.pyplot as plt import numpy as np from rdp import rdp # 下载股票数据 stock = 'AMZN' start = '2020-11-01' df = yf.download(stock, start=start) # 准备二维点数据:x用序列索引,y用收盘价 # 用索引位置作为x值,避免datetime的计算问题 points = np.column_stack((np.arange(len(df)), df['Close'].values)) # 应用RDP算法,epsilon是控制简化程度的阈值(值越大简化越明显) simplified_points = rdp(points, epsilon=2.0) # 提取简化后的x和y数据 simplified_x = simplified_points[:, 0] simplified_y = simplified_points[:, 1] # 绘制原数据和简化后的数据对比图 plt.figure(figsize=(12, 6)) plt.plot(df.index, df['Close'], label='原始收盘价', alpha=0.5) plt.plot(df.index[simplified_x.astype(int)], simplified_y, label='RDP简化后', linewidth=2, color='orange') plt.title(f'{stock} 股价走势图(RDP去噪)') plt.xlabel('日期') plt.ylabel('收盘价') plt.legend() plt.grid(True) plt.show()
关键修改点说明
- 二维点数组构建:用
np.column_stack把x(序列索引)和y(收盘价)合并成[[x0,y0], [x1,y1], ...]的格式,这是rdp库要求的标准输入。 - 时间轴处理:用
np.arange(len(df))生成数值化的x坐标,后续绘图时再通过索引映射回原始的datetime日期,既满足算法计算要求,又保证图表的可读性。 - epsilon阈值调整:原代码的
0.2阈值太小,对股价来说几乎看不到简化效果,建议根据股价波动调整(比如示例中的2.0),值越大,简化后的折线越平滑,保留的关键点越少。 - 对比绘图:同时绘制原始数据和简化后的数据,方便你直观看到去噪效果。
内容的提问来源于stack exchange,提问作者BenjaminDiLorenzo




