# 收敛三角形形态可视化验证工具 - 技术文档 > 文档更新日期:2026-03-04 ## 1. 项目概述 收敛三角形(Converging Triangle)形态检测可视化验证工具。通过 HTTP API 调用远程公式执行,绘制 K 线图 + 三角形趋势线,帮助快速目测验证形态检测结果。 **支持**: - A 股和美股(如英伟达、苹果等) - 日K / 周K / 月K 三种频率 - 中文名称自动搜索转换为股票代码 ## 2. 数据流程 ``` validate.py │ ├─① GET {SEARCH_API_URL}/smartstock/assets/search?q=<关键词> │ └─ 获取正确的 ticker(中控技术 → SH688777,英伟达 → NVDA.O) │ ├─② POST {GPT_SERVER_URL}/innerServer/runOneFormula │ body: { formula_str: "结果=收敛三角形详情(ticker,freq,True,mode)" } │ └─ response.output = MongoDB _id │ ├─③ GET {DATA_SERVER_URL}/api/timeSeries/requestIndexDetail?id=<_id> │ header: Authorization: Bearer │ └─ data.data_info.detail │ ├─ strength / direction / is_valid │ ├─ breakout_price_up / breakout_price_down │ └─ chart_data │ ├─ upper_line / lower_line (趋势线端点) │ ├─ upper_pivots / lower_pivots (枢轴点) │ └─ window_start_date / window_end_date │ ├─④ GET {KLINE_API_URL}/dataSupport/getKLineDataByTicker?ticker=&begin_date= │ └─ 获取 K 线 OHLC 数据(默认 3 年历史) │ └─⑤ chart.draw_triangle_chart(detail) ├─ K 线数据按频率聚合(日K/周K/月K) ├─ mplfinance 绘制 K 线 + 趋势线 ├─ Y 轴自动调整以包含趋势线 └─ output/{ticker}_{freq}K_{date}.png ``` ## 3. K 线聚合逻辑 ### 3.1 与前端一致 K 线数据聚合逻辑与前端 `TechPattern.vue` 中的 `filterAndProcessKLineData` 函数完全一致。 ### 3.2 聚合规则 | 频率 | 聚合方式 | |------|----------| | 日K | 原始数据,不聚合 | | 周K | 同一周的日K聚合成一根(开=首日开,高=最高,低=最低,收=末日收)| | 月K | 同一月的日K聚合成一根(开=首日开,高=最高,低=最低,收=末日收)| ### 3.3 代码示例 ```python # validate.py 中的 aggregate_klines 函数 def aggregate_klines(klines: dict, freq: str) -> dict: """ 将日K数据聚合成周K或月K """ if freq == '日': return klines # 按周/月分组 for d in daily_data: if freq == '周': # 计算该日期所在周的周一 monday = date_obj - timedelta(days=day_of_week) key = monday.strftime('%Y%m%d') else: # 月 key = date_str[:6] # YYYYMM # 聚合每组数据 result_open.append(group[0]['open']) # 开盘取第一天 result_high.append(max(d['high'] for d in group)) # 最高取最高 result_low.append(min(d['low'] for d in group)) # 最低取最低 result_close.append(group[-1]['close']) # 收盘取最后一天 ``` ## 4. 趋势线绘制逻辑 ### 4.1 与前端一致 趋势线绘制逻辑与前端 `TechPattern.vue` 中的 `getExtendedLinePoints` 函数完全一致。 ### 4.2 关键点 1. **趋势线延伸**:从 `window_start_date` 延伸到 `window_end_date` 2. **斜率计算**:使用公式数据中的 `index` 字段计算 3. **坐标映射**:将日期映射到 K 线数据的索引位置 4. **Y 轴调整**:自动调整 Y 轴范围以包含趋势线(增加 5% 边距) ### 4.3 代码示例 ```python # chart.py 中的趋势线绘制逻辑 def make_extended_aline(line_pts, pivot_point, color): # 使用原始 index 计算斜率 slope = (p2['price'] - p1['price']) / (p2['index'] - p1['index']) # 前端: startIdx = 0 (window_start_date 对应 index 0) start_idx = 0 # 查找 window_end_date 对应的 index end_idx = p2['index'] # 计算延伸后的价格 start_price = pivot_price + slope * (start_idx - pivot_index) end_price = pivot_price + slope * (end_idx - pivot_index) return ((kline_start_idx, start_price), (kline_end_idx, end_price)) ``` ## 5. 周K/月K 形态检测说明 ### 5.1 检测逻辑 收敛三角形详情函数会根据传入的频率参数(日/周/月)在**对应周期的数据**上寻找形态。 ### 5.2 默认参数(来自 config.py) | 参数 | 中文名称 | 日K (D) | 周K (W) | 月K (M) | |------|----------|---------|---------|---------| | window | 检测窗口 | 240 | 104 | 60 | | pivot_k | 枢轴点左右窗口 | 15 | 5 | 3 | | breakout_threshold | 突破阈值 | 0.005 | 0.010 | 0.020 | | vol_window | 成交量均线周期 | 20 | 8 | 4 | | volume_multiplier | 放量倍数 | 1.5 | 1.5 | 1.3 | | min_convergence | 最小收敛比例 | 0.45 | 0.45 | 0.50 | | false_break_m | 假突破回看天数 | 5 | 2 | 1 | | flexible_zone | 实时模式灵活区域 | 15 | 5 | 2 | | display_bars | 图表显示 K 线数 | 300 | 130 | 72 | #### 参数详解(通俗版) **1. window(检测窗口)** - **含义**:往回看多少根 K 线来寻找三角形形态 - **日K 240 根** ≈ 1 年的交易日 - **周K 104 根** ≈ 2 年的周数 - **月K 60 根** ≈ 5 年的月数 - **通俗理解**:就像你用多长的"尺子"去量历史数据,尺子越长,能看到的形态越大 **2. pivot_k(枢轴点左右窗口)** - **含义**:判断一个点是不是"高点"或"低点"时,往左往右看多少个点 - **日K 15**:左右各看 15 天 - **周K 5**:左右各看 5 周 - **月K 3**:左右各看 3 个月 - **通俗理解**:就像选班长,要看看这个人是不是比左右同学都高(或都矮),看的人越多越准确 **3. breakout_threshold(突破阈值)** - **含义**:价格突破趋势线多少才算"真突破" - **日K 0.005** = 0.5% - **周K 0.010** = 1% - **月K 0.020** = 2% - **通俗理解**:就像跳高,杆子是趋势线,你要跳过去还要超出一定高度才算成功,周K/月K波动大所以阈值更高 **4. vol_window(成交量均线周期)** - **含义**:计算成交量均线时用多少天的数据 - **日K 20**:20 日成交量均线 - **周K 8**:8 周成交量均线 - **月K 4**:4 月成交量均线 - **通俗理解**:用过去一段时间的平均成交量作为"正常水平"的参考 **5. volume_multiplier(放量倍数)** - **含义**:成交量要是均线的多少倍才算"放量" - **日K/周K 1.5**:成交量要比平均高 50% - **月K 1.3**:成交量要比平均高 30% - **通俗理解**:突破时成交量要"热闹"一点,比平时多人才算有效 **6. min_convergence(最小收敛比例)** - **含义**:三角形的开口要缩小到什么程度才算"收敛" - **日K/周K 0.45**:结束时宽度要小于开始时的 45% - **月K 0.50**:结束时宽度要小于开始时的 50% - **通俗理解**:三角形要足够"尖",太扁平的就不算了 **7. false_break_m(假突破回看天数)** - **含义**:判断是不是假突破时,往后看多少天 - **日K 5**:往后看 5 天 - **周K 2**:往后看 2 周 - **月K 1**:往后看 1 个月 - **通俗理解**:突破后如果很快又跌回来,就是"假突破",要看几天才能确定 **8. flexible_zone(实时模式灵活区域)** - **含义**:在最新数据附近,允许一定的灵活度 - **日K 15**:最近 15 天可以灵活处理 - **周K 5**:最近 5 周可以灵活处理 - **月K 2**:最近 2 个月可以灵活处理 - **通俗理解**:最新数据可能还在变化,给一点容错空间 **9. display_bars(图表显示 K 线数)** - **含义**:生成的图表显示多少根 K 线 - **日K 300**:显示约 300 天 - **周K 130**:显示约 130 周 - **月K 72**:显示约 72 个月(6 年) - **通俗理解**:图表的"视野"有多大,让形态看起来更完整 ### 5.3 形态有效性判定条件 1. **收敛比 (width_ratio)**:`width_end / width_start <= shrink_ratio`(默认 0.8) 2. **触碰点数量**:`touches_upper >= 2` 和 `touches_lower >= 2` 3. **违规点限制**:违规点不能超过枢轴点的 1/3 ### 5.4 不同股票的检测结果示例 | 股票 | 日K | 周K | |------|-----|-----| | 中控技术 | ✅ 有效 | ❌ 无效(收敛不足或触碰点不够)| | 比亚迪 | - | ✅ 有效 | | 贵州茅台 | - | ❌ 无效 | **结论**:不是所有股票在周K/月K上都有有效的收敛三角形形态,这是正常现象。 ## 6. 常见问题 ### Q1: 为什么周K/月K没有收敛三角形? **A**: 这是因为该股票在周K/月K数据上没有形成有效的收敛三角形形态,可能原因: - 收敛比例不足(`width_ratio > 0.8`) - 触碰点不足(需要上下各至少 2 个触碰点) ### Q2: 为什么 K 线图显示 3 年数据,但形态窗口只有几个月? **A**: 这是正常的设计: - K 线数据:显示 `--window` 参数指定的时间范围(默认 3Y) - 形态窗口:由公式检测到的有效形态范围,通常只是 K 线数据的一部分 ### Q3: 美股如何获取 K 线数据? **A**: 使用中文名称(如"英伟达"),程序会自动通过搜索接口获取正确的 ticker(如 `NVDA.O`),然后获取 K 线数据。 ### Q4: 趋势线价格超出 K 线范围怎么办? **A**: 代码会自动调整 Y 轴范围以包含趋势线,并增加 5% 边距(与前端一致)。 ## 7. 文件结构 ``` triangle-validator/ ├── validate.py # 主入口:单股验证 ├── batch_validate.py # 批量验证多只股票 ├── chart.py # K 线 + 三角形绘图模块 ├── config.py # API 端点 & 认证配置 ├── requirements.txt # Python 依赖 ├── docs/ # 文档目录 │ └── triangle-validator-guide_20260304.md ├── output/ # 生成的图片(自动创建) ├── README.md # 使用说明 └── CLAUDE.md # Claude Code 指引 ``` ## 8. 相关源码位置 - 收敛三角形详情函数:`D:\project\dunhe_dataServer\src\library\expression\funcs\pattern.py` - 形态检测核心逻辑:`D:\project\dunhe_dataServer\src\library\pattern\converging_triangle.py` - 参数配置:`D:\project\dunhe_dataServer\src\library\pattern\config.py` - 前端 K 线图表:`D:\project\frontend_mobile\src\views\workflow\components\assetRatingV2\components\TechPattern.vue`