- Added support for a detailed chart mode in plot_converging_triangles.py, allowing users to visualize all pivot points and fitting lines. - Improved pivot fitting logic to utilize multiple representative points, enhancing detection accuracy and reducing false positives. - Introduced a new real-time detection mode with flexible zone parameters for better responsiveness in stock analysis. - Updated README.md and USAGE.md to reflect new features and usage instructions. - Added multiple documentation files detailing recent improvements, including pivot point fitting and visualization enhancements. - Cleaned up and archived outdated scripts to streamline the project structure.
383 lines
8.4 KiB
Markdown
383 lines
8.4 KiB
Markdown
# 突破方向计算逻辑详解
|
||
|
||
**日期**: 2026-01-26
|
||
**类型**: 算法说明
|
||
|
||
---
|
||
|
||
## 📋 概述
|
||
|
||
图表中的"突破方向"(`breakout_dir`)显示了价格相对于三角形上下沿线的突破状态,取值为:
|
||
- **`up`**: 向上突破(突破上沿线)
|
||
- **`down`**: 向下突破(跌破下沿线)
|
||
- **`none`**: 未突破(在三角形内部)
|
||
|
||
---
|
||
|
||
## 🎯 计算逻辑
|
||
|
||
### 核心代码
|
||
|
||
```597:607:src/converging_triangle.py
|
||
# 突破判定
|
||
breakout_dir: Literal["up", "down", "none"] = "none"
|
||
breakout_idx: Optional[int] = None
|
||
|
||
if close[end] > upper_end * (1 + params.break_tol):
|
||
breakout_dir = "up"
|
||
breakout_idx = end
|
||
elif close[end] < lower_end * (1 - params.break_tol):
|
||
breakout_dir = "down"
|
||
breakout_idx = end
|
||
```
|
||
|
||
### 判定标准
|
||
|
||
#### 1. 向上突破 (`up`)
|
||
|
||
**条件**:
|
||
```
|
||
当前收盘价 > 上沿线终点价格 × (1 + break_tol)
|
||
```
|
||
|
||
**详细说明**:
|
||
- `close[end]`: 检测窗口最后一天的收盘价(当前价格)
|
||
- `upper_end`: 上沿线在窗口终点的拟合值
|
||
- `break_tol`: 突破容忍度(默认 `0.001` = 0.1%)
|
||
|
||
**示例**:
|
||
```python
|
||
# 假设
|
||
upper_end = 100.0 # 上沿线终点在 100 元
|
||
break_tol = 0.001 # 0.1% 容忍度
|
||
close[end] = 100.2 # 当前收盘价 100.2 元
|
||
|
||
# 判断
|
||
threshold = 100.0 * (1 + 0.001) = 100.1
|
||
100.2 > 100.1 # True
|
||
→ breakout_dir = "up"
|
||
```
|
||
|
||
#### 2. 向下突破 (`down`)
|
||
|
||
**条件**:
|
||
```
|
||
当前收盘价 < 下沿线终点价格 × (1 - break_tol)
|
||
```
|
||
|
||
**详细说明**:
|
||
- `lower_end`: 下沿线在窗口终点的拟合值
|
||
- 需要跌破下沿线至少 `break_tol` 的幅度
|
||
|
||
**示例**:
|
||
```python
|
||
# 假设
|
||
lower_end = 50.0 # 下沿线终点在 50 元
|
||
break_tol = 0.001 # 0.1% 容忍度
|
||
close[end] = 49.8 # 当前收盘价 49.8 元
|
||
|
||
# 判断
|
||
threshold = 50.0 * (1 - 0.001) = 49.95
|
||
49.8 < 49.95 # True
|
||
→ breakout_dir = "down"
|
||
```
|
||
|
||
#### 3. 未突破 (`none`)
|
||
|
||
**条件**:
|
||
```
|
||
当前收盘价在 [lower_end * (1 - break_tol), upper_end * (1 + break_tol)] 区间内
|
||
```
|
||
|
||
**说明**:
|
||
- 价格仍在三角形内部
|
||
- 或者突破幅度不足 `break_tol`
|
||
|
||
---
|
||
|
||
## ⚙️ 参数说明
|
||
|
||
### `break_tol` (突破容忍度)
|
||
|
||
**位置**: `triangle_config.py`
|
||
|
||
```python
|
||
break_tol: float = 0.001 # 默认 0.1%
|
||
```
|
||
|
||
**作用**:
|
||
- 过滤微小的价格波动
|
||
- 避免将正常波动误判为突破
|
||
- 确保突破的有效性
|
||
|
||
**取值建议**:
|
||
|
||
| break_tol | 突破要求 | 适用场景 |
|
||
|-----------|---------|---------|
|
||
| 0.0005 | 0.05% | 非常敏感,捕获微小突破 |
|
||
| 0.001 | 0.1% | **默认**,平衡敏感度和准确性 |
|
||
| 0.002 | 0.2% | 宽松,只关注明显突破 |
|
||
| 0.005 | 0.5% | 非常宽松,过滤大部分噪声 |
|
||
|
||
**影响**:
|
||
- **太小**(如 0.0001):过于敏感,噪声突破增多
|
||
- **太大**(如 0.01):不够敏感,错过早期突破信号
|
||
- **推荐**:0.001(0.1%)适合大多数场景
|
||
|
||
---
|
||
|
||
## 📊 视觉示意
|
||
|
||
### 突破判定区域
|
||
|
||
```
|
||
价格
|
||
^
|
||
| 向上突破区域
|
||
| ─────────────────────── upper_end × (1 + 0.001)
|
||
| ╱╲ ← 上沿线 (upper_end)
|
||
| ╱ ╲
|
||
|╱ ╲ 未突破区域 (三角形内部)
|
||
| ╲
|
||
| ╲╱ ← 下沿线 (lower_end)
|
||
| ─────────────────────── lower_end × (1 - 0.001)
|
||
| 向下突破区域
|
||
└────────────────────────> 时间
|
||
↑
|
||
end (当前)
|
||
```
|
||
|
||
### 实际案例分析
|
||
|
||
**案例 1: SZ002343 慈文传媒**
|
||
|
||
```
|
||
上沿线终点: 约 8.9 元
|
||
下沿线终点: 约 7.7 元
|
||
当前收盘价: 约 7.6 元
|
||
|
||
判断:
|
||
7.6 < 7.7 × (1 - 0.001) = 7.69 # True
|
||
→ breakout_dir = "down"
|
||
```
|
||
|
||
**案例 2: 未突破**
|
||
|
||
```
|
||
上沿线终点: 100.0 元
|
||
下沿线终点: 80.0 元
|
||
当前收盘价: 90.0 元
|
||
|
||
判断:
|
||
90.0 不大于 100.1 # 未向上突破
|
||
90.0 不小于 79.92 # 未向下突破
|
||
→ breakout_dir = "none"
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 相关计算
|
||
|
||
### 1. 上下沿线终点值
|
||
|
||
**上沿线终点** (`upper_end`):
|
||
```python
|
||
upper_end = a_u * end + b_u
|
||
```
|
||
- `a_u`: 上沿线斜率
|
||
- `b_u`: 上沿线截距
|
||
- `end`: 窗口终点索引
|
||
|
||
**下沿线终点** (`lower_end`):
|
||
```python
|
||
lower_end = a_l * end + b_l
|
||
```
|
||
- `a_l`: 下沿线斜率
|
||
- `b_l`: 下沿线截距
|
||
|
||
### 2. 突破强度计算
|
||
|
||
突破方向只是定性判断(up/down/none),突破强度是定量评分(0~1):
|
||
|
||
```python
|
||
strength_up, strength_down = calc_breakout_strength(
|
||
close=close[end],
|
||
upper_line=upper_end,
|
||
lower_line=lower_end,
|
||
volume_ratio=volume_ratio,
|
||
width_ratio=width_ratio,
|
||
)
|
||
```
|
||
|
||
**详见**: [突破强度计算方法.md](./突破强度计算方法.md)
|
||
|
||
---
|
||
|
||
## 🎨 图表显示
|
||
|
||
### 标题栏信息
|
||
|
||
```
|
||
SZ002343 慈文传媒 - 收敛三角形 (检测窗口: 20250123 ~ 20260120)
|
||
显示范围: 20231227 ~ 20260120 (500个交易日) 突破方向: down 宽度比: 0.30 极轴点: 高6/低4 触碰: 上5/下2 放量确认: 否
|
||
```
|
||
|
||
**突破方向**显示:
|
||
- `up` → 红色
|
||
- `down` → 绿色
|
||
- `none` → 灰色
|
||
|
||
---
|
||
|
||
## 📐 计算流程
|
||
|
||
### 完整流程
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[开始检测] --> B[拟合上下沿线]
|
||
B --> C[计算终点线值]
|
||
C --> D[获取当前收盘价]
|
||
D --> E{close > upper × 1.001?}
|
||
E -->|是| F[向上突破 up]
|
||
E -->|否| G{close < lower × 0.999?}
|
||
G -->|是| H[向下突破 down]
|
||
G -->|否| I[未突破 none]
|
||
F --> J[计算突破强度]
|
||
H --> J
|
||
I --> J
|
||
J --> K[返回结果]
|
||
```
|
||
|
||
### 代码执行顺序
|
||
|
||
1. **拟合趋势线** (第 520-540 行)
|
||
```python
|
||
a_u, b_u, selected_ph = fit_pivot_line(ph_in, high[ph_in], mode="upper")
|
||
a_l, b_l, selected_pl = fit_pivot_line(pl_in, low[pl_in], mode="lower")
|
||
```
|
||
|
||
2. **计算终点值** (第 543-548 行)
|
||
```python
|
||
upper_end = float(a_u * end + b_u)
|
||
lower_end = float(a_l * end + b_l)
|
||
```
|
||
|
||
3. **判定突破方向** (第 597-606 行)
|
||
```python
|
||
if close[end] > upper_end * (1 + params.break_tol):
|
||
breakout_dir = "up"
|
||
elif close[end] < lower_end * (1 - params.break_tol):
|
||
breakout_dir = "down"
|
||
```
|
||
|
||
4. **计算突破强度** (第 624-631 行)
|
||
```python
|
||
strength_up, strength_down = calc_breakout_strength(...)
|
||
```
|
||
|
||
---
|
||
|
||
## 💡 常见问题
|
||
|
||
### Q1: 为什么有 break_tol 容忍度?
|
||
|
||
**A**:
|
||
- 价格波动是连续的,完全精确的边界不现实
|
||
- 0.1% 的容忍度可以过滤微小噪声
|
||
- 确保只标记"真实的、有意义的"突破
|
||
|
||
### Q2: 能否同时向上和向下突破?
|
||
|
||
**A**: 不能。逻辑是互斥的:
|
||
```python
|
||
if close > upper: # 先判断向上
|
||
dir = "up"
|
||
elif close < lower: # 再判断向下
|
||
dir = "down"
|
||
else: # 否则未突破
|
||
dir = "none"
|
||
```
|
||
|
||
### Q3: 突破方向与突破强度的关系?
|
||
|
||
**A**:
|
||
- **突破方向**: 定性判断(是否突破、方向)
|
||
- **突破强度**: 定量评分(突破的质量、程度)
|
||
|
||
示例:
|
||
```
|
||
breakout_dir = "down" # 向下突破
|
||
breakout_strength_down = 0.65 # 强度 65%(中等强度)
|
||
```
|
||
|
||
### Q4: 为什么图表显示 "down" 但收盘价看起来在下沿线上?
|
||
|
||
**A**: 可能原因:
|
||
1. **视觉误差**: 图表是近似显示
|
||
2. **容忍度**: 实际判断用了 0.1% 的容忍度
|
||
3. **拟合线**: 下沿线是拟合值,不一定正好穿过所有点
|
||
|
||
验证方法:
|
||
```python
|
||
# 查看详细数值
|
||
print(f"收盘价: {close[end]:.2f}")
|
||
print(f"下沿线: {lower_end:.2f}")
|
||
print(f"阈值: {lower_end * 0.999:.2f}")
|
||
```
|
||
|
||
### Q5: 如何修改突破敏感度?
|
||
|
||
**A**: 修改 `triangle_config.py`:
|
||
|
||
```python
|
||
# 更敏感(捕获更多突破)
|
||
break_tol = 0.0005 # 0.05%
|
||
|
||
# 默认
|
||
break_tol = 0.001 # 0.1%
|
||
|
||
# 更宽松(只捕获明显突破)
|
||
break_tol = 0.005 # 0.5%
|
||
```
|
||
|
||
---
|
||
|
||
## 🔗 相关文档
|
||
|
||
- [突破强度计算方法.md](./突破强度计算方法.md) - 突破强度的详细说明
|
||
- [枢轴点分段选择算法详解.md](./枢轴点分段选择算法详解.md) - 趋势线拟合
|
||
- [系统架构.md](./系统架构.md) - 整体架构
|
||
|
||
---
|
||
|
||
## 📝 总结
|
||
|
||
### 核心要点
|
||
|
||
1. **简单比较**: 当前价格 vs 上下沿线终点值
|
||
2. **容忍度**: ±0.1% 过滤噪声
|
||
3. **互斥判断**: 先判断向上,再判断向下
|
||
4. **实时计算**: 基于窗口终点的实时价格
|
||
|
||
### 计算公式
|
||
|
||
```
|
||
向上突破: close > upper_end × 1.001
|
||
向下突破: close < lower_end × 0.999
|
||
未突破: 其他情况
|
||
```
|
||
|
||
### 可调参数
|
||
|
||
```python
|
||
# triangle_config.py
|
||
break_tol = 0.001 # 突破容忍度,推荐 0.0005 ~ 0.005
|
||
```
|
||
|
||
---
|
||
|
||
**版本**: v1.0
|
||
**更新**: 2026-01-26
|
||
|