- 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.
435 lines
14 KiB
Markdown
435 lines
14 KiB
Markdown
# 强度分中增加"角度"参数的深度分析
|
||
|
||
## 一、问题背景
|
||
|
||
根据讨论记录(`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
|
||
**状态**:待用户确认
|