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.
This commit is contained in:
褚宏光 2026-01-29 13:13:52 +08:00
parent 3538b214ba
commit 7bdcb474ba
4 changed files with 1587 additions and 0 deletions

View File

View File

@ -0,0 +1,111 @@
## 1. `三角形强度()` - 全市场批量筛选
**作用**:对全市场所有股票、所有日期进行批量检测,返回强度矩阵,用于筛选和排序。
**入参**
| 参数 | 类型 | 默认值 | 说明 |
|-----|------|--------|------|
| `window` | int | 240 | 检测窗口(交易日) |
| `min_convergence` | float | 0.45 | 最小收敛比例(末端/起始宽度) |
| `breakout_threshold` | float | 0.005 | 突破阈值0.5% |
| `volume_multiplier` | float | 1.5 | 放量确认倍数 |
| `start_day` | int | -1 | 起始日索引(-1=自动) |
| `end_day` | int | -1 | 结束日索引(-1=自动) |
**返回值**
```python
np.ndarray # shape: (n_stocks, n_days)
```
- 正值 `+0 ~ +1`:向上突破/潜力,值越大越强
- 负值 `-1 ~ -0`:向下突破/潜力,绝对值越大越强
- `NaN`:无有效形态
**使用场景**
```python
强度 = 三角形强度()
# 筛选最新一天强向上的股票
强向上 = 强度[:, -1] > 0.5
# 按强度排序
排名 = np.argsort(强度[:, -1])[::-1]
```
---
## 2. `三角形详情(ticker)` - 单股票详情
**作用**:对单只股票进行检测,返回完整详情(强度分量、几何属性、图表数据),用于展示和分析。
**入参**
| 参数 | 类型 | 默认值 | 说明 |
|-----|------|--------|------|
| `ticker` | str | 必填 | 股票代码,如 `"SH600519"` |
| `window` | int | 240 | 检测窗口 |
| `min_convergence` | float | 0.45 | 最小收敛比例 |
| `breakout_threshold` | float | 0.005 | 突破阈值 |
| `volume_multiplier` | float | 1.5 | 放量倍数 |
| `display_days` | int | 300 | 图表显示天数 |
**返回值**`TriangleDetail` 对象
| 字段 | 类型 | 说明 |
|-----|------|------|
| `strength` | float | 综合强度 (-1 ~ +1) |
| `is_valid` | bool | 是否有效形态 |
| `direction` | str | `"up"` / `"down"` / `"none"` |
| `strength_up` | float | 向上强度原始值 (0~1) |
| `strength_down` | float | 向下强度原始值 (0~1) |
| `convergence_score` | float | 收敛分 (0~1) |
| `volume_score` | float | 成交量分 (0~1) |
| `fitting_score` | float | 拟合分 (0~1) |
| `width_ratio` | float | 收敛比例 |
| `upper_slope` | float | 上沿斜率 |
| `lower_slope` | float | 下沿斜率 |
| `touches_upper` | int | 触碰上沿次数 |
| `touches_lower` | int | 触碰下沿次数 |
| `volume_confirmed` | bool | 成交量是否确认 |
| `chart_data` | dict | 图表数据ECharts 格式) |
**`chart_data` 结构**
```python
{
'dates': [20260101, 20260102, ...], # 日期
'candlestick': [[o,c,l,h], ...], # K线数据
'upper_line': [[x1,y1], [x2,y2]], # 上沿线
'lower_line': [[x1,y1], [x2,y2]], # 下沿线
'detection_window': [start, end], # 检测窗口
'ticker': "SH600519",
'strength': 0.65,
'direction': "up",
}
```
**使用场景**
```python
详情 = 三角形详情("SH600519")
# 查看结果
print(f"强度: {详情.strength}")
print(f"方向: {详情.direction}")
print(f"收敛度: {详情.width_ratio}")
# 前端绑定
图表配置 = 详情.chart_data
```
---
## 典型工作流
```python
# 1. 批量筛选
强度 = 三角形强度()
目标股票索引 = np.where(强度[:, -1] > 0.5)[0]
# 2. 获取详情
tkrs = g.load_pkl()['tkrs']
for idx in 目标股票索引[:10]:
详情 = 三角形详情(tkrs[idx])
print(f"{tkrs[idx]}: {详情.strength:.2f}, {详情.direction}")
```

View File

@ -0,0 +1,475 @@
# 收敛三角形检测 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 未安装)

1001
src/triangle_detector_api.py Normal file

File diff suppressed because it is too large Load Diff