# 枢轴点检测与可视化修复 **日期**: 2026-01-26 **版本**: v1.0 ## 问题概述 收敛三角形检测系统存在多个问题,导致: 1. 非收敛形态(如上升三角形)被误判 2. 绘图与检测结果不一致 3. 窗口末端枢轴点无法识别 --- ## 问题1: 斜率约束过于宽松 ### 现象 "上升三角形"(上沿水平+下沿向上)被误判为"收敛三角形"。 ### 原因 ```python upper_slope_max=0.10, # 允许上沿向上 lower_slope_min=-0.10, # 允许下沿向下 ``` ### 解决方案 **文件**: `scripts/triangle_config.py` ```python upper_slope_max=0, # 上沿必须向下或水平(≤0) lower_slope_min=0, # 下沿必须向上或水平(≥0) ``` --- ## 问题2: 绘图与检测枢轴点不一致 ### 现象 图表显示的枢轴点和趋势线与实际检测结果不同。 ### 原因 - 检测代码使用 `pivots_fractal_hybrid`(实时模式) - 绘图代码使用 `pivots_fractal`(标准模式) ### 解决方案 **文件**: `scripts/plot_converging_triangles.py` ```python from triangle_config import REALTIME_MODE, FLEXIBLE_ZONE if REALTIME_MODE: confirmed_ph, confirmed_pl, candidate_ph, candidate_pl = pivots_fractal_hybrid( high_win, low_win, k=params.pivot_k, flexible_zone=FLEXIBLE_ZONE ) # 合并确认枢轴点和候选枢轴点 ph_idx = np.concatenate([confirmed_ph, candidate_ph]) if len(candidate_ph) > 0 else confirmed_ph pl_idx = np.concatenate([confirmed_pl, candidate_pl]) if len(candidate_pl) > 0 else confirmed_pl ph_idx = np.sort(ph_idx) pl_idx = np.sort(pl_idx) ``` --- ## 问题3: 窗口末端枢轴点识别失败 ### 现象 图表最右边明显的低点/高点没有被识别为枢轴点。 ### 原因 `FLEXIBLE_ZONE=5` 太小,末端枢轴点超出灵活区域范围。 ### 解决方案 **文件**: `scripts/triangle_config.py` ```python FLEXIBLE_ZONE = 15 # 与 pivot_k 一致,确保末端枢轴点能被识别 ``` --- ## 问题4: NaN值导致比较失败 ### 现象 包含 NaN 值的数据窗口中,枢轴点检测完全失效。 ### 原因 ```python np.min([30.0, np.nan, 29.0]) # 返回 nan 30.0 == nan # 永远为 False ``` ### 解决方案 **文件**: `src/converging_triangle.py` ```python # 使用 nanmin/nanmax 忽略 NaN 值 if not np.isnan(high[i]) and high[i] == np.nanmax(high[i - k : i + k + 1]): confirmed_ph.append(i) if not np.isnan(low[i]) and low[i] == np.nanmin(low[i - k : i + k + 1]): confirmed_pl.append(i) ``` --- ## 问题5: 候选枢轴点未合并 ### 现象 `pivots_fractal_hybrid` 返回的候选枢轴点在绘图时被丢弃。 ### 原因 ```python ph_idx, pl_idx, _, _ = pivots_fractal_hybrid(...) # 候选点被忽略 ``` ### 解决方案 见问题2的解决方案,合并 confirmed 和 candidate。 --- ## 问题6: 对称窗口逻辑优化 ### 现象 窗口末端的局部低点/高点,因右侧数据不足无法识别。 ### 解决方案 **文件**: `src/converging_triangle.py` ```python # 候选枢轴点使用对称的短窗口 for i in range(max(k, n - flexible_zone), n): right_avail = n - 1 - i left_look = min(k, max(right_avail + 1, 3)) # 至少看3天 left_start = max(0, i - left_look) right_end = min(n, i + right_avail + 1) if high[i] == np.nanmax(high[left_start : right_end]): candidate_ph.append(i) ``` --- ## 修改文件清单 | 文件 | 修改内容 | |------|----------| | `scripts/triangle_config.py` | 斜率约束(`upper_slope_max=0`, `lower_slope_min=0`)、`FLEXIBLE_ZONE=15` | | `scripts/plot_converging_triangles.py` | 实时模式枢轴点检测、候选点合并、排序 | | `src/converging_triangle.py` | NaN处理(`nanmin/nanmax`)、对称窗口逻辑 | --- ## 效果验证 修复前后对比: | 指标 | 修复前 | 修复后 | |------|--------|--------| | SZ300892 低点枢轴点 | 4个 | 7个 | | 末端低点识别 | ❌ | ✅ | | 图表/检测一致性 | ❌ | ✅ | | 非收敛形态过滤 | ❌ | ✅ |