- Introduced a new "tilt" parameter to the strength scoring system, allowing for the assessment of triangle slope directionality. - Renamed existing parameters: "拟合贴合度" to "形态规则度" and "边界利用率" to "价格活跃度" for improved clarity. - Updated normalization methods for all strength components to ensure they remain within the [0, 1] range, facilitating LLM tuning. - Enhanced documentation to reflect changes in parameter names and scoring logic, including detailed explanations of the new tilt parameter. - Modified multiple source files and scripts to accommodate the new scoring structure and ensure backward compatibility. Files modified: - `src/converging_triangle.py`, `src/converging_triangle_optimized.py`, `src/triangle_detector_api.py`: Updated parameter names and scoring logic. - `scripts/plot_converging_triangles.py`, `scripts/generate_stock_viewer.py`: Adjusted for new scoring parameters in output. - New documentation files created to explain the renaming and new scoring system in detail.
14 KiB
强度分中增加"角度"参数的深度分析
一、问题背景
根据讨论记录(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 |
价格对通道空间的利用程度 |
计算公式:
strength = (
0.50 × 突破幅度分 +
0.15 × 收敛度分 +
0.10 × 成交量分 +
0.10 × 形态规则度 +
0.15 × 价格活跃度
)
2.2 现有的斜率数据
实际上,代码中已经计算并存储了斜率信息:
# converging_triangle.py: line 86-87
upper_slope: float = 0.0 # 上沿斜率
lower_slope: float = 0.0 # 下沿斜率
但这些斜率未被纳入强度分计算,仅用于:
- 形态识别约束:确保三角形相向收敛(上沿向下,下沿向上)
- 可视化展示:绘制三角形边界线
三、"角度"参数的含义与作用
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 用户需求推测
根据"用户可调整强度分中的每个参数"的需求,增加"角度"参数的目的可能是:
- 筛选特定形态:只要对称三角形(中轴接近水平)或只要上升/下降三角形
- 控制倾斜度:排除过于陡峭或过于平缓的形态
- 评估突破质量:角度影响突破的有效性(如陡峭向上的支撑线更可能向上突破)
四、增加"角度"参数的具体实现方案
4.1 推荐方案:增加"中轴倾斜度分"
核心思路:将三角形的整体倾斜方向纳入强度分,反映市场趋势的偏向性。
4.1.1 计算方法
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:从"突破幅度分"中分配
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:均匀分配
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 修改位置
需要修改以下文件:
-
src/converging_triangle.py- 在
ConvergingTriangleResult中新增字段:tilt_score: float = 0.0 # 倾斜度分数 - 新增函数
calc_tilt_score() - 修改
calc_breakout_strength()函数,纳入倾斜度分
- 在
-
src/converging_triangle_optimized.py- 新增 Numba 优化版本的
calc_tilt_score_numba() - 修改
calc_breakout_strength_numba()
- 新增 Numba 优化版本的
-
src/triangle_detector_api.py- 在
StrengthComponents中新增:tilt_score: float # 倾斜度分数
- 在
-
docs/强度分组成梳理.md- 更新为6个组成部分,添加倾斜度的说明
4.2 备选方案:增加"收敛角度分"
核心思路:将三角形的收敛尖锐程度纳入强度分。
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:线性归一化
# 将 [-5.7°, +5.7°] 映射到 [0, 1]
normalized = (angle_deg + 5.7) / 11.4
# 默认值 0.5 对应 0° (水平)
方法2:sigmoid 归一化
# 使用 sigmoid 函数,0° 映射到 0.5
normalized = 1 / (1 + exp(-angle_deg / 3))
# 默认值 0.5 对应 0°
方法3:绝对值归一化(仅关心角度大小,不关心方向)
# 将 [0°, 5.7°] 映射到 [0, 1]
normalized = abs(angle_deg) / 5.7
# 默认值 0.5 对应 约 2.85°
5.2 为 LLM 设计的可调参数接口
在 triangle_detector_api.py 中新增参数:
@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 短期方案(最小改动)
仅暴露斜率信息,不改变强度分计算
- 在 API 返回结果中添加斜率字段的解释说明
- 在可视化和导出中突出显示角度信息
- 用户可以在后处理时根据角度手动筛选
优点:零风险,不影响现有逻辑
缺点:未真正集成到强度分,用户需要自己处理
6.2 中期方案(推荐)
增加"倾斜度分"作为第6个维度
- 新增
calc_tilt_score()函数 - 修改
calc_breakout_strength()将倾斜度纳入加权 - 调整权重配置(建议从突破幅度中分出5%)
- 更新文档和测试
优点:有实际技术分析意义,易于理解
缺点:需要调整权重,可能影响现有结果的一致性
6.3 长期方案(完全可配置)
允许用户自定义强度分的权重
- 将所有权重作为参数暴露给 LLM
- 新增多种角度相关的分数(倾斜度、收敛角度、上下沿独立角度)
- 用户可以根据自己的策略调整权重组合
优点:最大灵活性,适应不同交易策略
缺点:复杂度高,需要大量测试和文档支持
七、潜在的技术挑战与注意事项
7.1 数值稳定性
- 斜率接近0时,角度变化敏感,需要设置阈值
- 极端情况(垂直线)需要特殊处理
7.2 多重共线性
- 倾斜度与"收敛度"可能相关(如对称三角形收敛度通常更高)
- 需要验证新参数是否引入冗余信息
7.3 历史数据回测
- 增加新参数后,需要重新回测所有历史数据
- 评估对现有高强度信号的影响
7.4 用户理解成本
- "角度"参数的含义可能不如"突破幅度"直观
- 需要提供清晰的文档和示例
八、推荐的实施路径
阶段1:数据验证(2小时)
- 统计现有数据中斜率的分布情况
- 分析角度与突破强度的相关性
- 确认增加角度参数的必要性
阶段2:方案确认(1小时)
- 与用户确认具体需求(是倾斜度、收敛角度还是其他?)
- 确定权重分配方案
- 确定参数归一化方式
阶段3:代码实现(4小时)
- 修改
converging_triangle.py(1.5小时) - 修改
converging_triangle_optimized.py(1.5小时) - 修改
triangle_detector_api.py(1小时)
阶段4:测试与验证(3小时)
- 单元测试(1小时)
- 历史数据回测(1小时)
- 可视化验证(1小时)
阶段5:文档更新(1小时)
- 更新
docs/强度分组成梳理.md - 更新 API 文档
- 添加使用示例
总计:约 11 小时
九、决策建议
根据以上分析,我的建议是:
-
采用中期方案(增加倾斜度分)
- 有明确的技术分析意义
- 实现成本适中
- 对现有系统影响可控
-
参数设计
- 新增
tilt_score作为第6个维度 - 权重从突破幅度中分配 5%
- 归一化到 [0, 1],默认值 0.5
- 新增
-
下一步行动
- 与用户确认具体需求(是否就是"倾斜度")
- 进行小规模数据验证
- 如果验证通过,再进入实施阶段
文档创建时间:2026-01-29
作者:AI Assistant
状态:待用户确认