# 强度分中增加"角度"参数的深度分析 ## 一、问题背景 根据讨论记录(`discuss/20260129-讨论.md`),需要在"强度分"中新增"角度"参数,即斜率、三角形的旋转角度。 ## 二、当前"强度分"的组成结构 ### 2.1 现有五大维度 根据 `docs/强度分组成梳理.md`,当前强度分由以下**5个组成部分**加权求和(总权重100%): | 序号 | 组成部分 | 权重 | 英文字段名 | 说明 | |------|---------|------|-----------|------| | 1 | **突破幅度分** | 50% | `price_score` | 价格突破上/下沿的幅度(tanh归一化) | | 2 | **收敛度分** | 15% | `convergence_score` | 三角形收敛程度(1 - width_ratio) | | 3 | **成交量分** | 10% | `volume_score` | 突破时的放量程度 | | 4 | **形态规则度** | 10% | `geometry_score` | 枢轴点到拟合线的贴合程度 | | 5 | **价格活跃度** | 15% | `activity_score` | 价格对通道空间的利用程度 | **计算公式**: ```python strength = ( 0.50 × 突破幅度分 + 0.15 × 收敛度分 + 0.10 × 成交量分 + 0.10 × 形态规则度 + 0.15 × 价格活跃度 ) ``` ### 2.2 现有的斜率数据 实际上,代码中**已经计算并存储了斜率信息**: ```python # converging_triangle.py: line 86-87 upper_slope: float = 0.0 # 上沿斜率 lower_slope: float = 0.0 # 下沿斜率 ``` 但这些斜率**未被纳入强度分计算**,仅用于: 1. **形态识别约束**:确保三角形相向收敛(上沿向下,下沿向上) 2. **可视化展示**:绘制三角形边界线 ## 三、"角度"参数的含义与作用 ### 3.1 "角度"的数学定义 收敛三角形有**两条边界线**,因此涉及到**多个角度**: #### 方案A:上沿/下沿的倾斜角度(独立角度) - **上沿角度**:`θ_upper = arctan(upper_slope)` - **下沿角度**:`θ_lower = arctan(lower_slope)` 示例: - 上沿斜率 = -0.05 → 角度 ≈ -2.86°(向下倾斜) - 下沿斜率 = +0.03 → 角度 ≈ +1.72°(向上倾斜) #### 方案B:三角形的整体倾斜方向(合成角度) - **三角形中轴角度**:`θ_mid = arctan((upper_slope + lower_slope) / 2)` - 中轴向上倾斜 → 上升三角形 - 中轴向下倾斜 → 下降三角形 - 中轴接近水平 → 对称三角形 #### 方案C:三角形的收敛角度(张角) - **收敛角度**:`θ_apex = arctan(upper_slope - lower_slope)` - 反映三角形收敛的"尖锐程度" - 张角越小 → 形态越尖锐,预示突破可能更强 ### 3.2 "角度"参数的技术分析意义 | 角度类型 | 技术分析含义 | 对突破的影响 | |---------|-------------|------------| | **上沿倾斜度** | 压力线的陡峭程度 | 过于陡峭可能表示抛压过大 | | **下沿倾斜度** | 支撑线的强度 | 陡峭向上表示买盘强劲 | | **中轴倾斜方向** | 市场整体趋势偏向 | 向上偏=多头趋势,向下偏=空头趋势 | | **收敛张角** | 多空力量博弈的紧张度 | 张角越小=能量积蓄越充分 | ### 3.3 用户需求推测 根据"用户可调整强度分中的每个参数"的需求,增加"角度"参数的目的可能是: 1. **筛选特定形态**:只要对称三角形(中轴接近水平)或只要上升/下降三角形 2. **控制倾斜度**:排除过于陡峭或过于平缓的形态 3. **评估突破质量**:角度影响突破的有效性(如陡峭向上的支撑线更可能向上突破) ## 四、增加"角度"参数的具体实现方案 ### 4.1 推荐方案:增加"中轴倾斜度分" **核心思路**:将三角形的整体倾斜方向纳入强度分,反映市场趋势的偏向性。 #### 4.1.1 计算方法 ```python def calc_tilt_score( upper_slope: float, lower_slope: float, breakout_dir: str, ) -> float: """ 计算三角形倾斜度分 (0~1) 衡量三角形中轴的倾斜方向与突破方向的一致性。 趋势偏向与突破方向一致时,得分越高。 计算方法: 1. 计算中轴斜率:mid_slope = (upper_slope + lower_slope) / 2 2. 计算倾斜度:tilt = arctan(mid_slope) / (π/4),归一化到 [-1, +1] - 向上倾斜(上升三角形):tilt > 0 - 向下倾斜(下降三角形):tilt < 0 - 对称三角形:tilt ≈ 0 3. 根据突破方向计算得分: - 向上突破:score = (1 + tilt) / 2 # 倾斜向上时得分高 - 向下突破:score = (1 - tilt) / 2 # 倾斜向下时得分高 归一化映射(以向上突破为例): - 上升三角形(中轴向上15°)+ 向上突破 → 得分 0.85 - 对称三角形(中轴水平) + 向上突破 → 得分 0.50 - 下降三角形(中轴向下15°)+ 向上突破 → 得分 0.15(逆势突破) Args: upper_slope: 上沿斜率 lower_slope: 下沿斜率 breakout_dir: 突破方向 "up" | "down" | "none" Returns: tilt_score: 0~1,越大表示倾斜方向与突破方向越一致 """ import math # 1. 计算中轴斜率 mid_slope = (upper_slope + lower_slope) / 2.0 # 2. 计算倾斜角度(弧度),并归一化到 [-1, +1] # 使用 arctan(slope) / (π/4) 映射: # - 45° 向上 → +1 # - 0° 水平 → 0 # - 45° 向下 → -1 angle_rad = math.atan(mid_slope) tilt = angle_rad / (math.pi / 4) # 归一化到 [-1, +1] tilt = max(-1.0, min(1.0, tilt)) # 限制在 [-1, 1] # 3. 根据突破方向计算得分 if breakout_dir == "up": # 向上突破:倾斜向上时得分高 score = (1.0 + tilt) / 2.0 elif breakout_dir == "down": # 向下突破:倾斜向下时得分高 score = (1.0 - tilt) / 2.0 else: # 未突破:使用中性分数(0.5) score = 0.5 return max(0.0, min(1.0, score)) ``` #### 4.1.2 权重分配调整 新增"倾斜度分"后,需要调整权重(保持总和100%): **方案1:从"突破幅度分"中分配** ```python W_PRICE = 0.45 # 突破幅度权重(从50%降至45%) W_CONVERGENCE = 0.15 # 收敛度权重 W_VOLUME = 0.10 # 成交量权重 W_GEOMETRY = 0.10 # 形态规则度权重 W_ACTIVITY = 0.15 # 价格活跃度权重 W_TILT = 0.05 # 倾斜度权重(新增,占5%) ``` **方案2:均匀分配** ```python W_PRICE = 0.47 # 突破幅度权重(50% → 47%) W_CONVERGENCE = 0.13 # 收敛度权重(15% → 13%) W_VOLUME = 0.08 # 成交量权重(10% → 8%) W_GEOMETRY = 0.10 # 形态规则度权重 W_ACTIVITY = 0.15 # 价格活跃度权重 W_TILT = 0.07 # 倾斜度权重(新增,占7%) ``` #### 4.1.3 修改位置 需要修改以下文件: 1. **`src/converging_triangle.py`** - 在 `ConvergingTriangleResult` 中新增字段: ```python tilt_score: float = 0.0 # 倾斜度分数 ``` - 新增函数 `calc_tilt_score()` - 修改 `calc_breakout_strength()` 函数,纳入倾斜度分 2. **`src/converging_triangle_optimized.py`** - 新增 Numba 优化版本的 `calc_tilt_score_numba()` - 修改 `calc_breakout_strength_numba()` 3. **`src/triangle_detector_api.py`** - 在 `StrengthComponents` 中新增: ```python tilt_score: float # 倾斜度分数 ``` 4. **`docs/强度分组成梳理.md`** - 更新为6个组成部分,添加倾斜度的说明 ### 4.2 备选方案:增加"收敛角度分" **核心思路**:将三角形的收敛尖锐程度纳入强度分。 ```python def calc_apex_angle_score( upper_slope: float, lower_slope: float, ) -> float: """ 计算收敛角度分 (0~1) 衡量三角形的收敛尖锐程度(张角大小)。 张角越小(形态越尖锐),得分越高。 计算方法: 1. 张角 = arctan(upper_slope - lower_slope) 2. 归一化到 [0, 1]: - 张角 < 5° → 得分 1.0 (极度尖锐) - 张角 ≈ 15° → 得分 0.7 - 张角 ≈ 30° → 得分 0.4 - 张角 > 45° → 得分 0.1 (过于开阔) Args: upper_slope: 上沿斜率 lower_slope: 下沿斜率 Returns: angle_score: 0~1,越大表示形态越尖锐 """ import math # 计算张角(绝对值) slope_diff = abs(upper_slope - lower_slope) angle_rad = math.atan(slope_diff) angle_deg = math.degrees(angle_rad) # 指数衰减归一化(张角越大分数越低) # 使用 exp(-angle_deg / 20) 映射: # - 0° → 1.00 # - 10° → 0.61 # - 20° → 0.37 # - 30° → 0.22 # - 45° → 0.11 score = math.exp(-angle_deg / 20.0) return max(0.0, min(1.0, score)) ``` ## 五、对"LLM 调参"友好性的考虑 ### 5.1 要求所有参数在 0-1 区间 根据讨论记录第3点:"强度分内所有参数需保持在 0-1 区间,便于 LLM 调参;要求均匀/正态分布,默认值为 0.5。" #### 当前"角度"的原始值范围 - 斜率范围:约 -0.1 ~ +0.1(受代码约束) - 角度范围:约 -5.7° ~ +5.7°(arctan(±0.1)) #### 归一化到 [0, 1] 的方法 **方法1:线性归一化** ```python # 将 [-5.7°, +5.7°] 映射到 [0, 1] normalized = (angle_deg + 5.7) / 11.4 # 默认值 0.5 对应 0° (水平) ``` **方法2:sigmoid 归一化** ```python # 使用 sigmoid 函数,0° 映射到 0.5 normalized = 1 / (1 + exp(-angle_deg / 3)) # 默认值 0.5 对应 0° ``` **方法3:绝对值归一化(仅关心角度大小,不关心方向)** ```python # 将 [0°, 5.7°] 映射到 [0, 1] normalized = abs(angle_deg) / 5.7 # 默认值 0.5 对应 约 2.85° ``` ### 5.2 为 LLM 设计的可调参数接口 在 `triangle_detector_api.py` 中新增参数: ```python @dataclass class DetectionParams: """检测参数,都有合理默认值,大多数场景无需调整""" # ===== 用户可调参数 ===== window: int = 240 min_convergence: float = 0.45 breakout_threshold: float = 0.005 volume_multiplier: float = 1.5 # 【新增】角度相关参数 tilt_preference: float = 0.5 # 倾斜偏好 [0, 1] # 0=偏好下降三角形,0.5=中性,1=偏好上升三角形 apex_angle_preference: float = 0.5 # 收敛角度偏好 [0, 1] # 0=偏好开阔形态,0.5=中性,1=偏好尖锐形态 # 【新增】权重配置 weight_price: float = 0.45 # 突破幅度权重 weight_convergence: float = 0.15 # 收敛度权重 weight_volume: float = 0.10 # 成交量权重 weight_geometry: float = 0.10 # 形态规则度权重 weight_activity: float = 0.15 # 价格活跃度权重 weight_tilt: float = 0.05 # 倾斜度权重(新增) ``` ## 六、实现步骤总结 ### 6.1 短期方案(最小改动) **仅暴露斜率信息,不改变强度分计算** 1. 在 API 返回结果中添加斜率字段的解释说明 2. 在可视化和导出中突出显示角度信息 3. 用户可以在后处理时根据角度手动筛选 **优点**:零风险,不影响现有逻辑 **缺点**:未真正集成到强度分,用户需要自己处理 ### 6.2 中期方案(推荐) **增加"倾斜度分"作为第6个维度** 1. 新增 `calc_tilt_score()` 函数 2. 修改 `calc_breakout_strength()` 将倾斜度纳入加权 3. 调整权重配置(建议从突破幅度中分出5%) 4. 更新文档和测试 **优点**:有实际技术分析意义,易于理解 **缺点**:需要调整权重,可能影响现有结果的一致性 ### 6.3 长期方案(完全可配置) **允许用户自定义强度分的权重** 1. 将所有权重作为参数暴露给 LLM 2. 新增多种角度相关的分数(倾斜度、收敛角度、上下沿独立角度) 3. 用户可以根据自己的策略调整权重组合 **优点**:最大灵活性,适应不同交易策略 **缺点**:复杂度高,需要大量测试和文档支持 ## 七、潜在的技术挑战与注意事项 ### 7.1 数值稳定性 - 斜率接近0时,角度变化敏感,需要设置阈值 - 极端情况(垂直线)需要特殊处理 ### 7.2 多重共线性 - 倾斜度与"收敛度"可能相关(如对称三角形收敛度通常更高) - 需要验证新参数是否引入冗余信息 ### 7.3 历史数据回测 - 增加新参数后,需要重新回测所有历史数据 - 评估对现有高强度信号的影响 ### 7.4 用户理解成本 - "角度"参数的含义可能不如"突破幅度"直观 - 需要提供清晰的文档和示例 ## 八、推荐的实施路径 ### 阶段1:数据验证(2小时) 1. 统计现有数据中斜率的分布情况 2. 分析角度与突破强度的相关性 3. 确认增加角度参数的必要性 ### 阶段2:方案确认(1小时) 1. 与用户确认具体需求(是倾斜度、收敛角度还是其他?) 2. 确定权重分配方案 3. 确定参数归一化方式 ### 阶段3:代码实现(4小时) 1. 修改 `converging_triangle.py`(1.5小时) 2. 修改 `converging_triangle_optimized.py`(1.5小时) 3. 修改 `triangle_detector_api.py`(1小时) ### 阶段4:测试与验证(3小时) 1. 单元测试(1小时) 2. 历史数据回测(1小时) 3. 可视化验证(1小时) ### 阶段5:文档更新(1小时) 1. 更新 `docs/强度分组成梳理.md` 2. 更新 API 文档 3. 添加使用示例 **总计**:约 11 小时 ## 九、决策建议 根据以上分析,我的建议是: 1. **采用中期方案(增加倾斜度分)** - 有明确的技术分析意义 - 实现成本适中 - 对现有系统影响可控 2. **参数设计** - 新增 `tilt_score` 作为第6个维度 - 权重从突破幅度中分配 5% - 归一化到 [0, 1],默认值 0.5 3. **下一步行动** - 与用户确认具体需求(是否就是"倾斜度") - 进行小规模数据验证 - 如果验证通过,再进入实施阶段 --- **文档创建时间**:2026-01-29 **作者**:AI Assistant **状态**:待用户确认