- Introduced a new API for converging triangle detection, including the main function `detect_matrix()` for batch processing of stock data. - Added detailed documentation for the API, covering usage examples, parameter configurations, and output structures. - Created new markdown files for reference and usage instructions, enhancing the overall documentation quality. New files: - `src/triangle_detector_api.py`: Core API implementation. - `docs/triangle_api_reference.md`: Comprehensive API reference documentation. - `discuss/20260129-三角形强度.md`: Documentation for triangle strength detection functions. - `docs/2026-01-29_三角形数据_server.md`: Detailed usage of the triangle detection functions.
476 lines
12 KiB
Markdown
476 lines
12 KiB
Markdown
# 收敛三角形检测 API 参考文档
|
||
|
||
## 概览
|
||
|
||
`triangle_detector_api.py` 提供收敛三角形形态检测的完整封装,核心设计:
|
||
|
||
- **主函数 `detect_matrix()`**:全市场矩阵批量检测(如万得全A所有A股)
|
||
- **一个 `strength` 搞定筛选**:正值=向上,负值=向下,绝对值=强度
|
||
- **4 个核心参数**:都有合理默认值,大多数场景无需调整
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
```python
|
||
from triangle_detector_api import detect_matrix
|
||
|
||
# 输入:OHLCV 矩阵 (n_stocks, n_days)
|
||
df = detect_matrix(
|
||
high_mtx=high_mtx, # shape: (n_stocks, n_days)
|
||
low_mtx=low_mtx,
|
||
close_mtx=close_mtx,
|
||
volume_mtx=volume_mtx,
|
||
dates=dates, # shape: (n_days,)
|
||
tkrs=tkrs, # shape: (n_stocks,) 股票代码
|
||
tkrs_name=tkrs_name, # shape: (n_stocks,) 股票名称
|
||
)
|
||
|
||
# 筛选
|
||
df[df['strength'] > 0.5] # 强向上突破
|
||
df[df['strength'] < -0.5] # 强向下突破
|
||
df.sort_values('strength', ascending=False) # 排序
|
||
```
|
||
|
||
---
|
||
|
||
## 核心函数
|
||
|
||
### `detect_matrix()` ⭐ 主函数
|
||
|
||
全市场矩阵批量检测:每只股票每天都进行检测。适用于万得全A等全市场扫描场景。
|
||
|
||
```python
|
||
def detect_matrix(
|
||
high_mtx: np.ndarray, # (n_stocks, n_days)
|
||
low_mtx: np.ndarray,
|
||
close_mtx: np.ndarray,
|
||
volume_mtx: np.ndarray,
|
||
dates: np.ndarray, # (n_days,)
|
||
tkrs: np.ndarray = None, # (n_stocks,) 股票代码
|
||
tkrs_name: np.ndarray = None, # (n_stocks,) 股票名称
|
||
params: DetectionParams = None,
|
||
start_day: int = None,
|
||
end_day: int = None,
|
||
only_valid: bool = True,
|
||
verbose: bool = False,
|
||
) -> pd.DataFrame
|
||
```
|
||
|
||
**参数说明:**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `high_mtx` | ndarray | ✅ | 最高价矩阵 (n_stocks, n_days) |
|
||
| `low_mtx` | ndarray | ✅ | 最低价矩阵 |
|
||
| `close_mtx` | ndarray | ✅ | 收盘价矩阵 |
|
||
| `volume_mtx` | ndarray | ✅ | 成交量矩阵 |
|
||
| `dates` | ndarray | ✅ | 日期数组 (n_days,) |
|
||
| `tkrs` | ndarray | ❌ | 股票代码数组 |
|
||
| `tkrs_name` | ndarray | ❌ | 股票名称数组 |
|
||
| `params` | DetectionParams | ❌ | 检测参数 |
|
||
| `start_day` | int | ❌ | 起始日索引 |
|
||
| `end_day` | int | ❌ | 结束日索引 |
|
||
| `only_valid` | bool | ❌ | 只返回有效形态,默认 True |
|
||
| `verbose` | bool | ❌ | 打印进度 |
|
||
|
||
**返回值:** DataFrame
|
||
|
||
| 列名 | 说明 |
|
||
|------|------|
|
||
| `stock_idx` | 股票索引 |
|
||
| `stock_code` | 股票代码 |
|
||
| `stock_name` | 股票名称 |
|
||
| `date_idx` | 日期索引 |
|
||
| `date` | 日期 |
|
||
| `strength` | **强度分(核心输出)** |
|
||
| `is_valid` | 是否有效形态 |
|
||
| `direction` | 突破方向 |
|
||
| `width_ratio` | 收敛比例 |
|
||
|
||
**示例:**
|
||
|
||
```python
|
||
from triangle_detector_api import detect_matrix
|
||
|
||
# 批量检测
|
||
df = detect_matrix(high, low, close, volume, dates, tkrs, tkrs_name, verbose=True)
|
||
|
||
# 筛选
|
||
strong_up = df[df['strength'] > 0.5]
|
||
strong_down = df[df['strength'] < -0.5]
|
||
|
||
# 某日最强股票
|
||
latest_date = df['date'].max()
|
||
df[df['date'] == latest_date].sort_values('strength', ascending=False).head(10)
|
||
```
|
||
|
||
---
|
||
|
||
### `detect_triangle()`
|
||
|
||
单股票检测(用于生成图表数据)。
|
||
|
||
```python
|
||
def detect_triangle(
|
||
ohlc_data: Dict,
|
||
params: DetectionParams = None,
|
||
include_pivots: bool = True,
|
||
display_window: int = None,
|
||
) -> DetectionResult
|
||
```
|
||
|
||
**ohlc_data 格式:**
|
||
|
||
```python
|
||
{'dates': [...], 'open': [...], 'high': [...], 'low': [...], 'close': [...], 'volume': [...]}
|
||
```
|
||
|
||
**返回值:** `DetectionResult` 对象,包含 `chart_data` 可生成 ECharts 配置
|
||
|
||
---
|
||
|
||
## 入参配置
|
||
|
||
### `DetectionParams`
|
||
|
||
检测参数类,所有参数都有合理默认值。
|
||
|
||
```python
|
||
from triangle_detector_api import DetectionParams
|
||
|
||
# 使用默认参数(推荐)
|
||
params = DetectionParams()
|
||
|
||
# 自定义参数
|
||
params = DetectionParams(
|
||
window=120,
|
||
min_convergence=0.6,
|
||
)
|
||
```
|
||
|
||
**可调参数:**
|
||
|
||
| 参数 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `window` | int | 240 | 检测窗口大小(交易日) |
|
||
| `min_convergence` | float | 0.45 | 收敛比例阈值(末端宽度/起始宽度) |
|
||
| `breakout_threshold` | float | 0.005 | 突破阈值(0.5%) |
|
||
| `volume_multiplier` | float | 1.5 | 放量确认倍数 |
|
||
|
||
**参数调整建议:**
|
||
|
||
| 参数 | 较小值效果 | 较大值效果 |
|
||
|------|-----------|-----------|
|
||
| `window` | 检测短期形态,信号及时 | 检测中长期形态,信号可靠 |
|
||
| `min_convergence` | 要求更强收敛,形态标准 | 放宽收敛,更多候选 |
|
||
| `breakout_threshold` | 更敏感,可能假突破 | 减少假突破,可能漏信号 |
|
||
| `volume_multiplier` | 允许轻度放量 | 要求更强放量确认 |
|
||
|
||
---
|
||
|
||
## 输出结构
|
||
|
||
### `DetectionResult`
|
||
|
||
检测结果类。
|
||
|
||
```python
|
||
@dataclass
|
||
class DetectionResult:
|
||
# 核心输出
|
||
strength: float # 综合强度分 (-1 ~ +1)
|
||
is_valid: bool # 是否检测到有效形态
|
||
direction: BreakoutDirection # 突破方向
|
||
|
||
# 辅助输出
|
||
strength_up: float # 向上强度原始值 (0~1)
|
||
strength_down: float # 向下强度原始值 (0~1)
|
||
strength_components: StrengthComponents # 强度分分量
|
||
|
||
# 形态几何属性
|
||
width_ratio: float # 收敛比例
|
||
touches_upper: int # 触碰上沿次数
|
||
touches_lower: int # 触碰下沿次数
|
||
volume_confirmed: bool # 成交量确认
|
||
|
||
# 前端数据
|
||
chart_data: ChartData # 图表数据
|
||
```
|
||
|
||
### 核心字段:`strength`
|
||
|
||
**范围:-1 ~ +1**
|
||
|
||
| 范围 | 含义 | 建议操作 |
|
||
|------|------|----------|
|
||
| +0.7 ~ +1.0 | 强向上突破 ⬆️⬆️⬆️ | 重点关注 |
|
||
| +0.4 ~ +0.7 | 中等向上 ⬆️⬆️ | 关注 |
|
||
| +0.2 ~ +0.4 | 向上潜力 ⬆️ | 观察 |
|
||
| 0 | 无效形态 | 忽略 |
|
||
| -0.2 ~ -0.4 | 向下潜力 ⬇️ | 观察 |
|
||
| -0.4 ~ -0.7 | 中等向下 ⬇️⬇️ | 关注 |
|
||
| -0.7 ~ -1.0 | 强向下突破 ⬇️⬇️⬇️ | 重点关注 |
|
||
|
||
### `StrengthComponents`
|
||
|
||
强度分各分量,便于理解分数构成。
|
||
|
||
| 分量 | 权重 | 说明 |
|
||
|------|------|------|
|
||
| `price_score` | 50% | 价格突破幅度 |
|
||
| `convergence_score` | 15% | 收敛程度 |
|
||
| `volume_score` | 10% | 放量程度 |
|
||
| `fitting_score` | 10% | 拟合贴合度 |
|
||
| `utilization_score` | 15% | 边界利用率 |
|
||
|
||
---
|
||
|
||
## 筛选示例
|
||
|
||
### 基础筛选
|
||
|
||
```python
|
||
from triangle_detector_api import detect_matrix
|
||
|
||
# 批量检测
|
||
df = detect_matrix(high, low, close, volume, dates, tkrs, tkrs_name)
|
||
|
||
# 强向上突破
|
||
df[df['strength'] > 0.5]
|
||
|
||
# 强向下突破
|
||
df[df['strength'] < -0.5]
|
||
|
||
# 任意强信号
|
||
df[abs(df['strength']) > 0.3]
|
||
|
||
# 按强度排序
|
||
df.sort_values('strength', ascending=False)
|
||
```
|
||
|
||
### 按日期筛选
|
||
|
||
```python
|
||
# 某日的检测结果
|
||
target_date = 20260120
|
||
df_day = df[df['date'] == target_date]
|
||
|
||
# 某日最强的10只股票
|
||
df_day.sort_values('strength', ascending=False).head(10)
|
||
```
|
||
|
||
### 按股票筛选
|
||
|
||
```python
|
||
# 某只股票的历史检测结果
|
||
df_stock = df[df['stock_code'] == '000001.SZ']
|
||
|
||
# 查看该股票的强度分变化
|
||
df_stock[['date', 'strength', 'direction']].tail(20)
|
||
```
|
||
|
||
### 统计分析
|
||
|
||
```python
|
||
# 每日有效形态数量
|
||
df.groupby('date')['is_valid'].sum()
|
||
|
||
# 每日强向上突破数量
|
||
df[df['strength'] > 0.5].groupby('date').size()
|
||
|
||
# 强度分分布
|
||
df['strength'].describe()
|
||
```
|
||
|
||
---
|
||
|
||
## 前端集成
|
||
|
||
### Vue3 + ECharts
|
||
|
||
**1. 安装依赖**
|
||
|
||
```bash
|
||
npm install echarts vue-echarts
|
||
```
|
||
|
||
**2. 获取 ECharts 配置**
|
||
|
||
```python
|
||
result = detect_triangle(ohlc_data)
|
||
|
||
if result.chart_data:
|
||
echarts_option = result.chart_data.to_echarts_option("股票名称")
|
||
# echarts_option 可直接用于前端
|
||
```
|
||
|
||
**3. Vue3 组件使用**
|
||
|
||
```vue
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { use } from 'echarts/core'
|
||
import { CanvasRenderer } from 'echarts/renderers'
|
||
import { CandlestickChart, BarChart, LineChart, ScatterChart } from 'echarts/charts'
|
||
import { GridComponent, TooltipComponent, LegendComponent, MarkLineComponent } from 'echarts/components'
|
||
import VChart from 'vue-echarts'
|
||
|
||
use([
|
||
CanvasRenderer,
|
||
CandlestickChart,
|
||
BarChart,
|
||
LineChart,
|
||
ScatterChart,
|
||
GridComponent,
|
||
TooltipComponent,
|
||
LegendComponent,
|
||
MarkLineComponent
|
||
])
|
||
|
||
// 从 API 获取的配置
|
||
const chartOption = ref({})
|
||
|
||
async function loadChart(stockCode) {
|
||
const response = await fetch(`/api/triangle/${stockCode}`)
|
||
const data = await response.json()
|
||
chartOption.value = data.echarts_option
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<v-chart :option="chartOption" style="height: 500px" autoresize />
|
||
</template>
|
||
```
|
||
|
||
### ChartData 结构
|
||
|
||
```python
|
||
@dataclass
|
||
class ChartData:
|
||
candlestick: List[List[float]] # K线数据 [[open, close, low, high], ...]
|
||
dates: List[str] # 日期数组
|
||
volumes: List[float] # 成交量
|
||
upper_line: Optional[TrendLine] # 上沿趋势线
|
||
lower_line: Optional[TrendLine] # 下沿趋势线
|
||
pivots: List[PivotPoint] # 枢轴点列表
|
||
detection_window: Tuple[int, int] # 检测窗口范围
|
||
```
|
||
|
||
**注意:** ECharts K线格式为 `[open, close, low, high]`,与标准 OHLC 顺序不同。
|
||
|
||
---
|
||
|
||
## 完整示例
|
||
|
||
```python
|
||
from triangle_detector_api import detect_triangle, DetectionParams, quick_detect
|
||
|
||
# ============ 示例1:基础使用 ============
|
||
ohlc_data = {
|
||
'dates': dates_list,
|
||
'open': open_list,
|
||
'high': high_list,
|
||
'low': low_list,
|
||
'close': close_list,
|
||
'volume': volume_list,
|
||
}
|
||
|
||
result = detect_triangle(ohlc_data)
|
||
|
||
print(f"是否有效形态: {result.is_valid}")
|
||
print(f"强度分: {result.strength}")
|
||
print(f"突破方向: {result.direction.value}")
|
||
|
||
if result.is_valid:
|
||
print(f"收敛比例: {result.width_ratio:.2f}")
|
||
print(f"触碰次数: 上沿 {result.touches_upper}, 下沿 {result.touches_lower}")
|
||
|
||
# ============ 示例2:自定义参数 ============
|
||
params = DetectionParams(
|
||
window=120, # 短窗口,检测短期形态
|
||
min_convergence=0.6, # 放宽收敛要求
|
||
breakout_threshold=0.01, # 更严格的突破阈值
|
||
)
|
||
result = detect_triangle(ohlc_data, params)
|
||
|
||
# ============ 示例3:快速筛选 ============
|
||
strength = quick_detect(
|
||
dates=dates_list,
|
||
open_=open_list,
|
||
high=high_list,
|
||
low=low_list,
|
||
close=close_list,
|
||
volume=volume_list,
|
||
)
|
||
|
||
if strength > 0.5:
|
||
print("发现强向上突破信号!")
|
||
elif strength < -0.5:
|
||
print("发现强向下突破信号!")
|
||
|
||
# ============ 示例4:获取前端数据 ============
|
||
if result.chart_data:
|
||
# 获取 ECharts 配置
|
||
echarts_option = result.chart_data.to_echarts_option("000001.SZ 平安银行")
|
||
|
||
# 转为 JSON(用于 API 响应)
|
||
import json
|
||
json_data = json.dumps(echarts_option, ensure_ascii=False)
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q: 为什么强度分为 0?
|
||
|
||
**可能原因:**
|
||
1. 数据长度不足(需要至少 `window` 天的数据)
|
||
2. 未形成有效的收敛三角形形态
|
||
3. 斜率不满足收敛要求(上沿应向下,下沿应向上)
|
||
|
||
### Q: 如何调整检测敏感度?
|
||
|
||
```python
|
||
# 更严格(高质量形态)
|
||
params = DetectionParams(
|
||
min_convergence=0.4, # 要求更强收敛
|
||
breakout_threshold=0.01, # 要求更明显突破
|
||
volume_multiplier=1.8, # 要求更强放量
|
||
)
|
||
|
||
# 更宽松(更多候选)
|
||
params = DetectionParams(
|
||
min_convergence=0.7, # 放宽收敛要求
|
||
breakout_threshold=0.002, # 允许轻微突破
|
||
volume_multiplier=1.2, # 允许轻度放量
|
||
)
|
||
```
|
||
|
||
### Q: 图表数据格式与其他库不兼容?
|
||
|
||
ECharts K线格式为 `[open, close, low, high]`。
|
||
|
||
如需标准 OHLC 格式 `[open, high, low, close]`,可自行转换:
|
||
|
||
```python
|
||
# ECharts -> 标准 OHLC
|
||
def to_standard_ohlc(echarts_data):
|
||
return [[row[0], row[3], row[2], row[1]] for row in echarts_data]
|
||
```
|
||
|
||
---
|
||
|
||
## 版本信息
|
||
|
||
- **模块**: `triangle_detector_api.py`
|
||
- **核心依赖**: `converging_triangle.py`(自动使用 Numba 优化版本)
|
||
- **Python**: 3.8+
|
||
- **NumPy**: 1.20+
|
||
- **Numba**: 0.55+(可选,安装后自动启用加速)
|
||
|
||
> **性能优化说明**:`converging_triangle.py` 会自动检测并加载 `converging_triangle_optimized.py`(Numba 加速版)。启动时会打印:
|
||
> - `[性能优化] 已启用Numba加速` - 优化版本生效
|
||
> - `[性能优化] 未启用Numba加速` - 回退到原版(numba 未安装)
|