technical-patterns-lab/docs/triangle_api_reference.md
褚宏光 7bdcb474ba Add triangle detection API and documentation
- 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.
2026-01-29 13:13:52 +08:00

476 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 收敛三角形检测 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 未安装)