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

如何在两个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:32:47