如何在两个Pandas Series数据点间绘制无限延伸直线并提取直线对应值至DataFrame
解决方案:绘制无限延伸直线并提取对应值
我来帮你搞定这个问题!要实现无限延伸的直线,核心是先推导两点的直线方程,再基于方程覆盖整个图表的x轴范围来绘制;提取对应y值则直接用直线方程计算即可。下面是修改后的完整代码,我会一步步拆解关键部分:
1. 先推导直线方程
从你选出的极值点中,我们需要先获取两点的坐标,转换为可计算的数值后算出直线的斜率和截距(也就是y = kx + b里的k和b):
import yfinance as yf import numpy as np from scipy.signal import argrelextrema import matplotlib.pyplot as plt import pandas as pd # 你的原始数据获取代码 data = yf.download("AAPL", start="2021-01-01", interval = "1d").drop(columns=['Adj Close']) data = data[30:].rename(columns={"Open": "open", "High": "high", "Low": "low", "Close": "close", "Volume": "volume"}) local_max = argrelextrema(data['high'].values, np.greater)[0] local_min = argrelextrema(data['low'].values, np.less)[0] highs = data.iloc[local_max,:] lows = data.iloc[local_min,:] highesttwo = highs["high"].nlargest(2) lowesttwo = lows["low"].nsmallest(2) # --- 新增:计算直线方程核心逻辑 --- # 处理阻力线(最高点连线):日期转ordinal(可计算的数值类型) x1_high, y1_high = highesttwo.index[0].toordinal(), highesttwo.iloc[0] x2_high, y2_high = highesttwo.index[1].toordinal(), highesttwo.iloc[1] # 计算斜率和截距 slope_high = (y2_high - y1_high) / (x2_high - x1_high) intercept_high = y1_high - slope_high * x1_high # 同理处理支撑线(最低点连线) x1_low, y1_low = lowesttwo.index[0].toordinal(), lowesttwo.iloc[0] x2_low, y2_low = lowesttwo.index[1].toordinal(), lowesttwo.iloc[1] slope_low = (y2_low - y1_low) / (x2_low - x1_low) intercept_low = y1_low - slope_low * x1_low
2. 绘制无限延伸的直线
我们不需要只在两点之间绘制,而是取整个数据的x轴范围(从第一个日期到最后一个日期)作为直线的覆盖区间,这样直线就会贯穿整个图表,视觉上就是无限延伸的:
fig = plt.figure(figsize=[10,7]) # 绘制原始价格和极值点 data['high'].plot(marker='o', markevery=local_max, label='High Prices') data['low'].plot(marker='o', markevery=local_min, label='Low Prices') # --- 绘制无限延伸的直线 --- # 获取整个数据的x范围(转ordinal) x_start = data.index[0].toordinal() x_end = data.index[-1].toordinal() # 生成阻力线的x/y序列 x_line_high = np.linspace(x_start, x_end, 100) # 生成100个点保证平滑 y_line_high = slope_high * x_line_high + intercept_high # 转回datetime类型,和原始数据x轴对齐 x_line_high_dt = pd.to_datetime([pd.Timestamp.fromordinal(int(x)) for x in x_line_high]) plt.plot(x_line_high_dt, y_line_high, '--r', label='Resistance Line (Infinite)') # 同理绘制支撑线 x_line_low = np.linspace(x_start, x_end, 100) y_line_low = slope_low * x_line_low + intercept_low x_line_low_dt = pd.to_datetime([pd.Timestamp.fromordinal(int(x)) for x in x_line_low]) plt.plot(x_line_low_dt, y_line_low, '--g', label='Support Line (Infinite)') plt.legend() plt.title('AAPL Prices with Infinite Support/Resistance Lines') plt.show()
3. 提取给定x值的直线y值到新DataFrame
用直线方程直接计算任意日期对应的y值,整理成DataFrame即可:
# 定义函数:根据日期计算直线对应的y值 def get_line_y(date, slope, intercept): x_ordinal = date.toordinal() return slope * x_ordinal + intercept # 计算data中所有日期对应的阻力线、支撑线y值 line_values = pd.DataFrame({ 'Date': data.index, 'Resistance_Y': data.index.map(lambda d: get_line_y(d, slope_high, intercept_high)), 'Support_Y': data.index.map(lambda d: get_line_y(d, slope_low, intercept_low)) }).set_index('Date') # 查看结果 print("直线对应值的DataFrame预览:") print(line_values.head())
关键细节说明:
- 为什么要转ordinal?因为datetime类型无法直接参与数值计算,转成ordinal(从公元1年1月1日开始的天数)后就能正常计算斜率和截距了。
- 用
np.linspace生成足够多的点,能保证直线绘制出来足够平滑。 - 用
map方法可以快速批量计算所有日期对应的直线y值,效率很高。
内容的提问来源于stack exchange,提问作者sword134
相关产品推荐
相关产品推荐

