Shapely无法识别明确存在的股票均线交点问题求助
问题原因与解决方案
核心原因分析
NaN值导致线段断裂
你的SMA数据前半部分存在大量NaN,用这些数据构造LineString时,Shapely会将NaN对应的位置视为线段的断裂点,最终生成多段不连续的折线。而line1.intersection(line2)仅会检测两条折线中连续线段部分的交点,断裂的无效段会被直接忽略。数值量级差异引发精度丢失
日期转换后的数值是1e18级别的超大数,而收盘价仅为几百,二者量级差距超过15个数量级。Shapely的几何计算依赖浮点精度,这种极端的量级差会导致计算时精度溢出,无法准确检测到交点。离散线段的交点不在采样点区间内
可视化看到的“相交”是两条均线趋势上的交叉,但Shapely的LineString是连接离散采样点的折线,只有当两条折线的相邻采样点构成的线段真正相交时,才会返回交点。如果交叉点位于两个采样点之间的区间而非线段上,直接调用整体intersection是无法识别的。坐标顺序逻辑混淆
你构造LineString时用的是[Close, Date](收盘价为X轴,日期为Y轴),这与常规可视化的[Date, Close]逻辑相反,虽然不直接导致无交点,但会让几何计算的逻辑更难排查。
分步解决方案
1. 清理无效数据(移除NaN行)
先过滤掉含NaN的行,只保留有效均线数据:
new50 = new50.dropna(subset=['Close']).reset_index(drop=True) new200 = new200.dropna(subset=['Close']).reset_index(drop=True)
2. 调整坐标顺序并优化数值量级
将日期转换为相对数值(缩小量级),并使用常规的[日期, 收盘价]坐标顺序构造线段:
# 计算相对日期,降低数值量级 min_date = min(new50.Date.min(), new200.Date.min()) new50['Date_rel'] = new50.Date - min_date new200['Date_rel'] = new200.Date - min_date # 构造正确坐标顺序的LineString line1 = LineString(np.column_stack([new50.Date_rel, new50.Close])) line2 = LineString(np.column_stack([new200.Date_rel, new200.Close]))
3. 逐段检测线段交点
如果直接调用line1.intersection(line2)仍无结果,说明交叉点位于采样点区间之间,需要遍历两条折线的每一段线段,逐一检测交点:
from shapely.geometry import LineString def find_segment_intersections(line_a, line_b): intersections = [] # 遍历line_a的每一段线段 for i in range(len(line_a.coords) - 1): seg_a = LineString([line_a.coords[i], line_a.coords[i+1]]) # 遍历line_b的每一段线段 for j in range(len(line_b.coords) - 1): seg_b = LineString([line_b.coords[j], line_b.coords[j+1]]) inter = seg_a.intersection(seg_b) if not inter.is_empty: intersections.append(inter) return intersections # 获取所有交点 all_intersections = find_segment_intersections(line1, line2) for idx, inter in enumerate(all_intersections): print(f"交点 {idx+1}: {inter}") # 转换回原始日期(可选) original_date = min_date + inter.x print(f"对应日期: {pd.to_datetime(original_date)}")
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

