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

Python Matplotlib获取日期格式X轴下两条折线的交点坐标

实现方案

核心思路

因为x轴是日期格式,不能直接参与数值计算,所以按以下步骤实现:

  • 将日期字符串转换为数值型的序数(toordinal方法,每个日期对应唯一整数,代表从公元元年1月1日到该日期的天数)
  • 计算MACD和信号线的差值,找到差值符号发生突变的位置,即两条线的交叉区间
  • 对每个交叉区间做线性插值,计算精确的交点对应数值日期,再转换回字符串格式的日期

完整可运行代码

import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
from matplotlib import rcParams

# 你提供的示例数据
macd = [1.6522, 1.609, 1.567, 1.6067, 1.7226, 2.0908, 2.0447, 1.9124, 1.8883, 1.7857, 1.9119, 2.0594, 2.178, 2.3221, 2.457, 2.5518, 2.6062, 2.7862, 2.9194, 3.2483, 3.5899, 3.9609, 3.9387, 3.9394, 3.9562, 4.0844, 4.2297, 4.5641, 4.895, 4.7674, 4.4558, 4.1092, 4.0209, 3.628, 3.4255]
signals = [1.7937, 1.829, 1.884, 1.9633, 2.0524, 2.1349, 2.1459, 2.1712, 2.2359, 2.3228, 2.4571, 2.5934, 2.7269, 2.8641, 2.9996, 3.1352, 3.2811, 3.4498, 3.6157, 3.7898, 3.9251, 4.0089, 4.0209, 4.0415, 4.0671, 4.0948, 4.0974, 4.0643, 3.9393, 3.7004, 3.4337, 3.1782, 2.9454, 2.6765, 2.4387]
dates = ['2021-08-25', '2021-08-24', '2021-08-23', '2021-08-20', '2021-08-19', '2021-08-18', '2021-08-17', '2021-08-16', '2021-08-13', '2021-08-12', '2021-08-11', '2021-08-10', '2021-08-09', '2021-08-06', '2021-08-05', '2021-08-04', '2021-08-03', '2021-08-02', '2021-07-30', '2021-07-29', '2021-07-28', '2021-07-27', '2021-07-26', '2021-07-23', '2021-07-22', '2021-07-21', '2021-07-20', '2021-07-19', '2021-07-16', '2021-07-15', '2021-07-14', '2021-07-13', '2021-07-12', '2021-07-09', '2021-07-08']

# ---------------------- 交点计算逻辑 ----------------------
# 日期转数值序数
date_objs = [datetime.strptime(d, '%Y-%m-%d') for d in dates]
date_nums = np.array([d.toordinal() for d in date_objs])
macd_np = np.array(macd)
signals_np = np.array(signals)

# 找交叉区间:差值符号变化的位置
diff = macd_np - signals_np
sign_change = np.diff(np.sign(diff))
cross_indices = np.where(sign_change != 0)[0]

cross_result = []
for idx in cross_indices:
    x0, x1 = date_nums[idx], date_nums[idx+1]
    y0, y1 = diff[idx], diff[idx+1]
    # 线性插值求交点x值
    cross_x_num = x0 - y0 * (x1 - x0) / (y1 - y0)
    # 转成日期字符串,四舍五入到天
    cross_date = datetime.fromordinal(int(round(cross_x_num))).strftime('%Y-%m-%d')
    # 计算交点y值
    cross_y = macd_np[idx] + (macd_np[idx+1] - macd_np[idx]) * (cross_x_num - x0)/(x1 -x0)
    cross_result.append({'日期': cross_date, '交点数值': round(cross_y,4)})

# ---------------------- 输出和绘图 ----------------------
print("检测到的交点:", cross_result)
# 绘图验证
rcParams['figure.figsize'] = (25, 12)
plt.plot(dates, macd, label='MACD')
plt.plot(dates, signals, label='Signal')
# 标记交点
for point in cross_result:
    plt.scatter(point['日期'], point['交点数值'], c='red', s=200, zorder=10, label=f'交叉点:{point["日期"]}')
plt.gca().invert_xaxis()
plt.legend(fontsize=15)
plt.xticks(rotation=45)
plt.show()

示例数据运行结果

给定的示例数据中仅检测到1个交点,输出为:

检测到的交点: [{'日期': '2021-07-21', '交点数值': 4.0942}]

红色标记点会出现在图表对应位置,和两条线的交叉位置完全吻合。

内容的提问来源于stack exchange,提问作者Adam Demo_Fighter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:30:02