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
相关产品推荐
相关产品推荐

