1069 lines
44 KiB
Markdown
1069 lines
44 KiB
Markdown
# chanlun — 缠论技术分析 Rust 核心库
|
||
|
||
[](LICENSE)
|
||
[](https://www.rust-lang.org)
|
||
[](https://doc.rust-lang.org/edition-guide/rust-2024/)
|
||
|
||
基于[缠中说禅](https://zh.wikipedia.org/wiki/%E7%BC%A0%E4%B8%AD%E8%AF%B4%E7%A6%85)理论的量化技术分析核心库,将 Python 参考实现 (`chan.py`, ~4200行) 完整移植为 Rust,同时保持了 API 的完全兼容。
|
||
|
||
**约 13,700 行 Rust 代码**,39 个源文件,覆盖缠论的完整算法体系:K线包含处理、分型识别、笔划分、线段划分(含特征序列与缺口处理)、中枢识别(含延伸/扩展/多级中枢)、背驰检测(MACD/斜率/测度三种方式)、买卖点识别(18种类型)、多周期联立分析。
|
||
|
||
核心 crate 位于 `chanlun/` 目录。Python 绑定通过独立的 [`chanlun-py`](../chanlun-py/) crate 实现,使用 PyO3 将 Rust 核心封装为 Python 模块,API 与 `chan.py` 完全一致。所有类型名、方法名、字段名均使用中文标识符,与 Python 版本保持 1:1 对应。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [核心概念](#核心概念)
|
||
- [项目结构](#项目结构)
|
||
- [快速开始](#快速开始)
|
||
- [数据管线](#数据管线)
|
||
- [核心类型详解](#核心类型详解)
|
||
- [配置体系](#配置体系)
|
||
- [算法模块](#算法模块)
|
||
- [技术指标](#技术指标)
|
||
- [线程安全与并发](#线程安全与并发)
|
||
- [Python 绑定](#python-绑定)
|
||
- [数据序列化](#数据序列化)
|
||
- [测试](#测试)
|
||
- [许可](#许可)
|
||
|
||
---
|
||
|
||
## 核心概念
|
||
|
||
缠论是一种源自中国的技术分析理论,将价格走势分解为层级结构,从最底层K线逐渐向上构造:
|
||
|
||
```
|
||
原始K线 → 包含处理 → 缠论K线 → 顶底分型 → 笔 → 线段 → 中枢 → 买卖点
|
||
```
|
||
|
||
核心理念:
|
||
- **走势终完美**:任何级别的任何走势类型终要完成
|
||
- **自同构性**:不同级别的走势呈现相同的形态结构,可通过递归分析进行多级别联立
|
||
- **完全分类**:将走势分为上涨、下跌、盘整三种,每个节点都可通过买卖点找到操作依据
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
chanlun/
|
||
├── Cargo.toml # 依赖: serde, byteorder, chrono, cached, tracing
|
||
└── src/
|
||
├── lib.rs # 模块注册 (#![allow(non_snake_case)])
|
||
├── main.rs # 入口(CLI 工具)
|
||
├── config.rs # 缠论配置 (62 字段, serde, 622 行)
|
||
│
|
||
├── types/ # 基础类型 (5 文件, 514 行)
|
||
│ ├── mod.rs # 重导出: 买卖点类型, 相对方向, 分型结构, 缺口, SyncF64
|
||
│ ├── direction.rs # 相对方向 (9 变体): 向上/向下/向上缺口/向下缺口/衔接向上/衔接向下/顺/逆/同
|
||
│ ├── bsp_type.rs # 买卖点类型 (18 变体): 一二三买/卖 + T1/T1P/T2/T2S/T3A/T3B
|
||
│ ├── fractal.rs # 分型结构 (5 变体) + 有高低 trait
|
||
│ ├── gap.rs # 缺口: 高/低价格区间 + 居中截取
|
||
│ └── sync_f64.rs # SyncF64: 基于 AtomicU64 的线程安全 f64 容器
|
||
│
|
||
├── kline/ # K线层 (2 文件, 1113 行)
|
||
│ ├── mod.rs #
|
||
│ ├── bar.rs # 原始K线 (388 行): OHLCV + RwLock<指标容器>, Clone/Display, 大端字节序序列化
|
||
│ └── chan_kline.rs # 缠论K线 (725 行): 经包含处理后的K线, 分型标记, AtomicI64/SyncF64 内部可变性
|
||
│
|
||
├── indicators/ # 技术指标 (6 文件, 1589 行)
|
||
│ ├── mod.rs # K线取值: 开/高/低/收/高低均值/高低收均值/开高低收均值
|
||
│ ├── macd.rs # 平滑异同移动平均线 (215 行): EMA 快慢线 + DIF/DEA/MACD柱
|
||
│ ├── rsi.rs # 相对强弱指数 (240 行): Wilder SMA 平滑 + 超买超卖线
|
||
│ ├── kdj.rs # 随机指标 (289 行): RSV → K → D → J + 超买超卖阈值
|
||
│ ├── boll.rs # 布林带 (169 行): 中轨/上轨/下轨 + 带宽
|
||
│ ├── calculator.rs # 指标计算器 (476 行): 增量计算 + 回填新指标 + 均线
|
||
│ └── container.rs # 指标容器 (202 行): 注册表模式, 动态指标存取
|
||
│
|
||
├── algorithm/ # 核心算法 (4 文件, 4987 行)
|
||
│ ├── mod.rs #
|
||
│ ├── bi.rs # 笔划分算法 (1009 行): 递归分析, 笔弱化, 次级成笔, 实际高/低点
|
||
│ ├── segment.rs # 线段划分算法 (2078 行): 特征序列, 缺口处理, 四种修正机制, 扩展线段
|
||
│ ├── hub.rs # 中枢识别算法 (1041 行): 重叠检测, 延伸/扩展, 第三买卖点, 多级中枢
|
||
│ └── divergence.rs # 背驰检测 (227 行): MACD背驰/斜率背驰/测度背驰 + 四种组合模式
|
||
│
|
||
├── structure/ # 结构体 (4 文件, 2089 行)
|
||
│ ├── mod.rs #
|
||
│ ├── dash_line.rs # 虚线 (1712 行): 笔/线段的通用抽象, 买卖意义, MACD行为统计, 分段, 背驰检测
|
||
│ ├── fractal_obj.rs # 分型 (344 行): 左中右构型, 分型模式开关, 强度判定, MACD分型匹配
|
||
│ ├── segment_feat.rs # 线段特征 (668 行): 特征序列元素, 文/武取极值, 静态分析, 分型序列
|
||
│ └── feat_fractal.rs # 特征分型 (62 行): 三线段特征元素构成的分型
|
||
│
|
||
├── business/ # 业务层 (4 文件, 1648 行)
|
||
│ ├── mod.rs #
|
||
│ ├── observer.rs # 观察者 (1138 行): 单周期分析器, 流式管线, 3级线段/扩展/混合扩展
|
||
│ ├── bsp.rs # 基础买卖点 + 买卖点工厂 (595 行): 18种类型, 偏移/失效/终结
|
||
│ ├── synthesizer.rs # K线合成器 (161 行): 小周期→大周期合成, 时间戳对齐
|
||
│ └── multi_frame.rs # 立体分析器 (192 行): 多周期联立, 合成器+观察者协调
|
||
│
|
||
└── utils/ # 工具 (2 文件, 145 行)
|
||
├── mod.rs #
|
||
├── datetime.rs # 时间戳转换: 字符串↔Unix时间戳
|
||
└── format.rs # 格式化: f64→最小字符串 (format_f64_g)
|
||
```
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### Cargo 依赖
|
||
|
||
```toml
|
||
[dependencies]
|
||
chanlun = { path = "path/to/chanlun" }
|
||
```
|
||
|
||
### 基本用法 — 单周期分析
|
||
|
||
```rust
|
||
use chanlun::config::缠论配置;
|
||
use chanlun::kline::bar::K线;
|
||
use chanlun::business::observer::观察者;
|
||
|
||
// 1. 创建配置(所有字段带默认值)
|
||
let 配置 = 缠论配置::default();
|
||
|
||
// 2. 创建观察者(返回 Arc<RwLock<观察者>>)
|
||
let 观察员 = 观察者::new("BTCUSD".into(), 3600, 配置);
|
||
|
||
// 3. 逐根投喂K线(流式增量分析,每根K线触发全管线运算)
|
||
for k线 in k线数据流 {
|
||
观察员.write().unwrap().增加原始K线(k线);
|
||
}
|
||
|
||
// 4. 读取分析结果
|
||
let obs = 观察员.read().unwrap();
|
||
println!("笔数量: {}", obs.笔序列.len());
|
||
println!("线段数量: {}", obs.线段序列().len());
|
||
println!("中枢数量: {}", obs.中枢序列().len());
|
||
|
||
// 遍历笔
|
||
for 笔 in &obs.笔序列 {
|
||
println!("笔方向: {}, 高: {}, 低: {}", 笔.方向(), 笔.高(), 笔.低());
|
||
}
|
||
```
|
||
|
||
### 便捷投喂 — 直接从 OHLCV
|
||
|
||
```rust
|
||
let 观察员 = 观察者::new("ETHUSD".into(), 300, Default::default());
|
||
let mut obs = 观察员.write().unwrap();
|
||
obs.投喂原始数据(1736640000, 3500.0, 3550.0, 3480.0, 3520.0, 1200.0);
|
||
// ... 继续投喂 ...
|
||
```
|
||
|
||
### 加载 .nb 数据文件
|
||
|
||
```rust
|
||
let 观察员 = 观察者::new("btcusd".into(), 300, Default::default());
|
||
观察员.write().unwrap().读取数据文件("btcusd-300-1000000-1100000.nb", Default::default())?;
|
||
```
|
||
|
||
### 多周期分析
|
||
|
||
```rust
|
||
use chanlun::business::multi_frame::立体分析器;
|
||
|
||
// 周期组: [最小输入周期, 更多显示周期...]
|
||
// 只投喂最小周期K线,大周期自动合成
|
||
let mut 分析器 = 立体分析器::new(
|
||
"BTCUSD".into(),
|
||
vec![60, 300, 1800, 7200], // 1分钟 → 5分钟 → 30分钟 → 2小时
|
||
None, // 默认配置
|
||
None, // 无周期特定配置
|
||
);
|
||
|
||
// 投喂最小周期K线
|
||
for k线 in 小周期K线流 {
|
||
分析器.投喂K线(k线);
|
||
}
|
||
|
||
// 获取各周期观察者
|
||
if let Some(日线观察员) = 分析器.获取观察者(86400) {
|
||
let obs = 日线观察员.read().unwrap();
|
||
println!("日线笔数: {}", obs.笔序列.len());
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 数据管线
|
||
|
||
缠论分析按严格的层级顺序进行,每收到一根新K线,**增量更新**所有层级(而非批量重算)。这是该库适合实时交易系统的关键设计。
|
||
|
||
### 管线流程
|
||
|
||
```
|
||
原始K线 (K线)
|
||
│
|
||
├── 指标计算: MACD / RSI / KDJ / BOLL (增量更新, 含回填新指标)
|
||
│ ├── K线取值: 开/高/低/收/高低均值/高低收均值/开高低收均值
|
||
│ ├── 多参数组: MACD_参数列表 / RSI_周期列表 / KDJ_参数列表 / BOLL_参数列表
|
||
│ └── 均线组: SMA/EMA (均线_类型列表 × 均线_周期列表)
|
||
│
|
||
├── 包含处理 → 缠论K线 (缠论K线)
|
||
│ ├── 顺序包含合并 (顺方向取极值)
|
||
│ ├── 逆序包含合并 (更新时间/标的K线)
|
||
│ ├── 方向判定 (相对方向: 向上/向下/向上缺口/向下缺口/衔接/包含)
|
||
│ └── 合并替换模式: 缠K合并替换=false(原地修改) / true(产出新缠K)
|
||
│
|
||
├── 分型识别 → 分型 (分型)
|
||
│ ├── 由左中右三根缠论K线构成
|
||
│ ├── 类型: 顶分型 / 底分型 / 三连向上 / 三连向下 / 向右扩散
|
||
│ ├── 强度: 强 / 中 / 弱 (基于左中右收盘价关系)
|
||
│ ├── 分型模式: 全局开关控制缓存/实时读取
|
||
│ └── MACD柱子分型匹配 (左中右MACD柱形态判定)
|
||
│
|
||
├── 笔划分 → 笔 (虚线, 标识="笔", 级别=1)
|
||
│ ├── 递归分析算法: 顶底分型交替验证
|
||
│ ├── 成笔条件: 笔内元素数量≥5 (弱化模式≥3)
|
||
│ ├── 笔弱化策略: 放宽条件时尝试次高/次低成笔
|
||
│ ├── 实际高/低点选择: first/last (笔内相同终点取舍)
|
||
│ ├── 笔内起始分型包含整笔验证
|
||
│ └── 笔内原始K线包含整笔验证
|
||
│
|
||
├── 线段划分 → 线段 (虚线, 标识="线段", 级别=2)
|
||
│ ├── 特征序列提取: 从笔序列中提取同向特征序列元素 (线段特征.静态分析)
|
||
│ ├── 缺口处理:
|
||
│ │ ├── 有缺口 (老阴/老阳): 严格包含处理, 等待特征分型完成
|
||
│ │ └── 无缺口 (小阳/少阴): 允许逆序包含
|
||
│ ├── 四种修正机制 (依次尝试):
|
||
│ │ ├── _缺口突破: 老阳/老阴时价格突破前线段极值
|
||
│ │ ├── _非缺口下穿刺: 贯穿伤后出现方向相同的3笔
|
||
│ │ ├── _缺口后紧急修正: 前一线段有缺口时自动修正
|
||
│ │ └── _修正: 配置启用的短路修正 (≥9笔)
|
||
│ ├── 线段破坏判定: 新线段形成后前一线段被破坏
|
||
│ ├── 3级递归: 线段 → 线段<线段> → 线段<线段<线段>>
|
||
│ └── 扩展线段分析: 扩展线段 → 扩展线段<扩展线段> → ...
|
||
│
|
||
├── 中枢识别 → 中枢 (中枢)
|
||
│ ├── 基础检查: 三条连续虚线重叠且方向关系正确
|
||
│ ├── 中枢延伸: 后继虚线未离开中枢则加入基础序列
|
||
│ ├── 第三买卖点: 虚线离开中枢后不回中枢, 记录第三买卖线
|
||
│ ├── 中枢完成: 第三买卖线确立后开始新中枢
|
||
│ ├── 中枢扩展: ≥9段时调用扩展分析生成扩展中枢
|
||
│ └── 多级中枢:
|
||
│ ├── 笔中枢 (级别=1, 基于笔序列)
|
||
│ ├── 线段中枢 (级别=2, 基于线段序列)
|
||
│ ├── 扩展线段中枢 (基于扩展线段序列)
|
||
│ ├── 混合扩展中枢 (基于扩展线段<线段>序列)
|
||
│ └── 线段<线段>中枢 / 扩展线段<扩展线段>中枢 等
|
||
│
|
||
└── 买卖点识别 → 基础买卖点 (18种类型)
|
||
├── 6 类经典买卖点: 一买/一卖/二买/二卖/三买/三卖
|
||
├── 12 类扩展买卖点: T1/T1P/T2/T2S/T3A/T3B 各含买卖
|
||
├── 指标匹配: MACD柱子匹配 / KDJ金叉死叉 / RSI超买超卖
|
||
├── 背驰确认: MACD背驰 / 斜率背驰 / 测度背驰
|
||
├── 中枢来源策略: 实 / 虚 / 合
|
||
├── 买卖意义缓存: LRU 128条目, 指针身份key
|
||
└── 偏移/失效偏移/终结K线管理
|
||
```
|
||
|
||
### 流式增量处理
|
||
|
||
`观察者.__处理数据` 每收到一根新K线:
|
||
1. 计算指标并挂载到新K线
|
||
2. 执行缠K包含处理,产出缠K
|
||
3. 识别分型,添加到分型序列
|
||
4. 递归分析笔(可能生成新笔或修改最后一笔)
|
||
5. 递归分析中枢(笔中枢)
|
||
6. 递归分析线段(3级递归:线段→线段<线段>→线段<线段<线段>>)
|
||
7. 递归分析扩展线段(3级递归)
|
||
8. 递归分析混合扩展线段(3级递归,源序列为线段序列组[i])
|
||
|
||
每步都只处理最后几个元素,时间复杂度 O(1) 均摊。
|
||
|
||
---
|
||
|
||
## 核心类型详解
|
||
|
||
### 枚举类型
|
||
|
||
#### 相对方向 (`types::direction`)
|
||
用于描述两个价格区间(两根K线或两个分型)之间的位置关系,共 9 个变体:
|
||
|
||
| 变体 | 说明 | 示例场景 |
|
||
|------|------|---------|
|
||
| `向上` | 后K线高低点均高于前K线,且不构成缺口 | 正常上涨 |
|
||
| `向下` | 后K线高低点均低于前K线,且不构成缺口 | 正常下跌 |
|
||
| `向上缺口` | 后K线低点 > 前K线高点 | 大幅高开 |
|
||
| `向下缺口` | 后K线高点 < 前K线低点 | 大幅低开 |
|
||
| `衔接向上` | 后K线低点 == 前K线高点 | 精准衔接上涨 |
|
||
| `衔接向下` | 后K线高点 == 前K线低点 | 精准衔接下跌 |
|
||
| `顺` | 前K线包含后K线(前高≥后高 且 前低≤后低) | 顺序包含 |
|
||
| `逆` | 后K线包含前K线(前高≤后高 且 前低≥后低) | 逆序包含 |
|
||
| `同` | 两K线高低点完全相同 | 重复数据 |
|
||
|
||
提供方法:`翻转()`, `是否向上()`, `是否向下()`, `是否包含()`, `是否缺口()`, `是否衔接()`, `分析(前高,前低,后高,后低)`
|
||
|
||
#### 分型结构 (`types::fractal`)
|
||
三根K线构成的结构形态,共 5 个变体:
|
||
|
||
| 变体 | 左中右关系 |
|
||
|------|-----------|
|
||
| `上` | 向上类 + 向上类 |
|
||
| `下` | 向下类 + 向下类 |
|
||
| `顶` | 向上类 + 向下类(<u>Λ</u> 形) |
|
||
| `底` | 向下类 + 向上类(V 形) |
|
||
| `散` | 逆序包含 + 逆序包含 |
|
||
|
||
提供方法:`分析(左,中,右, 可以逆序包含, 忽视顺序包含)` — 通用分型识别
|
||
|
||
#### 买卖点类型 (`types::bsp_type`)
|
||
18 种买卖点分类:
|
||
|
||
| 类别 | 买点 | 卖点 | 说明 |
|
||
|------|------|------|------|
|
||
| 一类 | `一买` | `一卖` | 中枢背驰后的第一类买卖点 |
|
||
| 二类 | `二买` | `二卖` | 回调到中枢内的第二类买卖点 |
|
||
| 三类 | `三买` | `三卖` | 离开中枢后不回中枢的第三类买卖点 |
|
||
| 扩展T1 | `T1买` | `T1卖` | 事后确认型 |
|
||
| 扩展T1P | `T1P买` | `T1P卖` | 事后确认型+ |
|
||
| 扩展T2 | `T2买` | `T2卖` | 中枢回调型 |
|
||
| 扩展T2S | `T2S买` | `T2S卖` | 中枢回调次级 |
|
||
| 扩展T3A | `T3A买` | `T3A卖` | 第三类扩展A |
|
||
| 扩展T3B | `T3B买` | `T3B卖` | 第三类扩展B |
|
||
|
||
提供方法:`是买点()`, `是卖点()`
|
||
|
||
### 数据结构详解
|
||
|
||
#### K线 (`kline::bar`) — 原始OHLCV + 指标
|
||
```
|
||
K线 {
|
||
标识, 序号, 周期, 时间戳,
|
||
高, 低, 开盘价, 收盘价, 成交量,
|
||
指标: RwLock<指标容器> // MACD/RSI/KDJ/BOLL/均线
|
||
}
|
||
```
|
||
- 实现 `Clone` (深拷贝, 包括指标容器)
|
||
- 支持大端字节序序列化 (`to_bytes()` → 48字节, `from_bytes()`)
|
||
- 提供 `创建普K()` 工厂方法, `相等()` 结构化校验
|
||
- `获取MACD()` 计算两K线间的 MACD 柱面积 (阳/阴/合/总)
|
||
- `截取rc()` 按 Arc 指针截取序列片段
|
||
|
||
#### 缠论K线 (`kline::chan_kline`) — 包含处理后的K线
|
||
```
|
||
缠论K线 {
|
||
序号: AtomicI64,
|
||
时间戳: AtomicI64,
|
||
高: SyncF64, // 经包含处理可能被拉高
|
||
低: SyncF64, // 经包含处理可能被压低
|
||
方向: RwLock<相对方向>,
|
||
分型: RwLock<Option<分型结构>>,
|
||
分型特征值: SyncF64, // 历史高低点极值
|
||
周期, 标识,
|
||
原始起始序号, // 包含处理前
|
||
原始结束序号: AtomicI64, // 包含处理后更新
|
||
标的K线: RwLock<Arc<K线>>,
|
||
买卖点信息: RwLock<HashSet<String>>,
|
||
}
|
||
```
|
||
- 核心算法:`_兼并()` — 顺序/逆序包含合并, 重复提交检测, 原地修改
|
||
- `分析()` — 完整的普K→缠K+分型管线
|
||
- 指标匹配:`与MACD柱子匹配()` / `与RSI匹配()` / `与KDJ匹配()`
|
||
- 时间戳对齐:跨周期对齐至基线
|
||
- `相等()` — 20+ 字段逐项递归校验
|
||
|
||
#### 分型 (`structure::fractal_obj`) — 顶/底分型
|
||
```
|
||
分型 {
|
||
左: Option<Arc<缠论K线>>,
|
||
中: Arc<缠论K线>, // 核心K线
|
||
右: Option<Arc<缠论K线>>,
|
||
结构: 分型结构, // 构造时缓存
|
||
时间戳: i64, // 构造时缓存
|
||
分型特征值: f64, // 构造时缓存
|
||
}
|
||
```
|
||
- **分型模式** (`分型模式: AtomicBool`): 全局开关
|
||
- `true` (默认) — `时间戳()/结构()/分型特征值()` 返回构造时缓存值
|
||
- `false` — 从 `中` 缠K 实时读取(逆序包含后使用)
|
||
- 提供方法:`强度()` (强/中/弱), `关系组()` (左中右三组关系), `与MACD柱子分型匹配()`
|
||
- `相等()` — 递归校验左/中/右缠K + 自有缓存字段
|
||
- 实现 `有高低` trait: 高/低 → 中.高/中.低
|
||
|
||
#### 虚线 (`structure::dash_line`) — 笔和线段的通用数据结构
|
||
```
|
||
虚线 {
|
||
标识: RwLock<String>, // "笔"/"线段"/"扩展线段"/"线段<线段>" 等
|
||
序号: AtomicI64,
|
||
级别: AtomicI64, // 笔=1, 线段=2, 线段<线段>=3, ...
|
||
文: Arc<分型>, // 起点分型(不可变)
|
||
武: RwLock<Arc<分型>>, // 终点分型(可变,用于动态更新)
|
||
有效性: AtomicBool,
|
||
基础序列: RwLock<Vec<Arc<虚线>>>, // 构成虚线的子级虚线序列
|
||
特征序列: RwLock<Vec<Option<Arc<线段特征>>>>, // 线段特征序列
|
||
实_中枢序列: RwLock<Vec<Arc<中枢>>>,
|
||
虚_中枢序列: RwLock<Vec<Arc<中枢>>>,
|
||
合_中枢序列: RwLock<Vec<Arc<中枢>>>,
|
||
确认K线: RwLock<Option<Arc<缠论K线>>>,
|
||
模式: RwLock<String>, // 买卖点匹配模式
|
||
_特征序列_显示: AtomicBool,
|
||
前一缺口: RwLock<Option<缺口>>,
|
||
前一结束位置: RwLock<Option<Arc<虚线>>>,
|
||
短路修正: AtomicBool,
|
||
}
|
||
```
|
||
- 静态工厂:`创建笔()` (级别=1), `创建线段()` (级别=笔级别+1, 基础序列=笔序列)
|
||
- 属性:`方向()`, `高()`, `低()`, `之前是()`, `之后是()`
|
||
- 数据访问:`获取普K序列()`, `获取缠K序列()`, `获取_武()` (递归到底层笔)
|
||
- 买卖点模式匹配:`全量/任意/配置/相对` 四种指标组合策略
|
||
- MACD相关:`计算MACD柱子均值()`, `武之MACD均值()`, `武之MACD极值()`
|
||
- 趋势分析:`计算K线序列MACD趋向背驰()` (MACD柱/DIF/DEA三项背驰)
|
||
- 分段:`计算MACD柱子分段()` (按正负号分段)
|
||
- 行为统计:`统计MACD行为()` → `MACD行为统计 {DIF上下穿0, DEA上下穿0, 金叉/死叉次数, 密集交叉区域}`
|
||
- 核心判断:`买卖意义()` — LRU 缓存 128 条目,指针身份作为 key
|
||
- 序列化:`获取数据文本()` — 笔输出简洁格式,线段输出完整格式
|
||
- `相等()` — 递归校验文/武/基础序列/特征序列/中枢序列/确认K线/模式/缺口/结束位置等全部字段
|
||
|
||
#### 线段特征 (`structure::segment_feat`) — 特征序列元素
|
||
```
|
||
线段特征 {
|
||
序号: AtomicI64,
|
||
标识: RwLock<String>,
|
||
线段方向: 相对方向,
|
||
基础序列: Vec<Arc<虚线>>, // 构成该元素的虚线序列
|
||
}
|
||
```
|
||
- 虚拟端点:`文()` — 取特征值最大/最小的起点分型
|
||
- 虚拟端点:`武()` — 取特征值最大/最小的终点分型
|
||
- tiebreaker: 同特征值时取后时间戳
|
||
- `高()/低()` — 文/武中分型特征值的较大/较小者
|
||
- `方向()` — 线段方向的翻转
|
||
- 静态分析:从虚线序列生成特征序列元素列表,含分型替换逻辑
|
||
- 分型序列:从连续特征序列元素中提取特征分型
|
||
|
||
#### 特征分型 (`structure::feat_fractal`)
|
||
```
|
||
特征分型 {
|
||
左: Arc<线段特征>,
|
||
中: Arc<线段特征>,
|
||
右: Arc<线段特征>,
|
||
结构: 分型结构, // 由左中右三元素分析得出
|
||
}
|
||
```
|
||
|
||
#### 中枢 (`algorithm::hub`)
|
||
```
|
||
中枢 {
|
||
序号: AtomicI64,
|
||
标识: RwLock<String>, // "笔中枢<0>"/"线段中枢<1>" 等
|
||
级别: AtomicI64,
|
||
基础序列: RwLock<Vec<Arc<虚线>>>, // 至少3根, 延伸后可达9+
|
||
第三买卖线: RwLock<Option<Arc<虚线>>>,
|
||
本级_第三买卖线: RwLock<Option<Arc<虚线>>>,
|
||
}
|
||
```
|
||
- 属性:`高()` (前三根虚线的最高重叠), `低()` (前三根虚线的最低重叠)
|
||
- `文()` → `武()` → `方向()`
|
||
- `延伸序列()` → 首尾之外的虚线
|
||
- `获取数据文本()` — 完整中枢结构化描述
|
||
- `相等()` — 逐项递归校验基础序列和第三买卖线
|
||
- 向序列中添加/更新中枢(含显示名称映射)
|
||
|
||
#### 基础买卖点 (`business::bsp`)
|
||
```
|
||
基础买卖点 {
|
||
备注: String,
|
||
类型: 买卖点类型,
|
||
买卖点分型: Arc<分型>,
|
||
买卖点K线: Arc<缠论K线>, // = 买卖点分型.中
|
||
当前K线: Arc<K线>,
|
||
失效K线: Option<Arc<K线>>,
|
||
终结K线: Option<Arc<K线>>,
|
||
破位值: f64,
|
||
结构: Option<分型结构>,
|
||
当前缠K序号: Option<i64>,
|
||
}
|
||
```
|
||
- `偏移()` — 当前缠K序号与买卖点K线序号的差
|
||
- `有效性()` — 失效K线是否存在
|
||
|
||
### 服务类型
|
||
|
||
| 类型 | 职责 | 位置 |
|
||
|------|------|------|
|
||
| `观察者` | 单周期分析器, 接收K线流, 维护所有层级序列, 3级递归线段分析 | `business::observer` |
|
||
| `K线合成器` | 小周期→大周期合成, 高取max/低取min/量求和, 时间戳对齐 | `business::synthesizer` |
|
||
| `立体分析器` | 多周期联立, 内含合成器 + 每周期一个观察者, 对齐缠K序列 | `business::multi_frame` |
|
||
|
||
### 静态算法类
|
||
|
||
| 类型 | 职责 | 位置 |
|
||
|------|------|------|
|
||
| `笔` | 笔划分: 分型→笔 (递归分析, 笔弱化, 次级成笔, 实际高/低点, 是否背驰过) | `algorithm::bi` |
|
||
| `线段` | 线段划分: 笔→线段 (特征序列+缺口处理+四种修正+扩展分析+内部背驰判断) | `algorithm::segment` |
|
||
| `中枢` | 中枢识别: 虚线→中枢 (重叠检测+延伸/扩展+第三买卖点+向序列添加) | `algorithm::hub` |
|
||
| `背驰分析` | 背驰检测: MACD/斜率/测度 + 全量/任意/配置/相对四种组合 | `algorithm::divergence` |
|
||
| `指标计算器` | 指标增量计算: MACD/RSI/KDJ/BOLL + 回填新指标 + 均线 | `indicators::calculator` |
|
||
|
||
---
|
||
|
||
## 配置体系
|
||
|
||
`缠论配置` 是一个 serde 驱动的结构体,**62 个字段**全部带默认值,支持 JSON 往返和部分反序列化容错。
|
||
|
||
### 完整配置表
|
||
|
||
#### 基础设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `标识` | `"bar"` | 品种标识 |
|
||
|
||
#### 缠K设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `缠K合并替换` | `false` | false=原地修改, true=产出新缠K |
|
||
|
||
#### 笔设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `笔内元素数量` | `5` | 成笔最低缠K数 |
|
||
| `笔内相同终点取舍` | `false` | false=取first, true=取last |
|
||
| `笔内起始分型包含整笔` | `false` | 起点分型区间必须包含整笔 |
|
||
| `笔内起始分型包含整笔_包括右` | `false` | 同上+包含右端点 |
|
||
| `笔内原始K线包含整笔` | `false` | 原始K线区间必须包含整笔 |
|
||
| `笔次级成笔` | `false` | 允许在非分型处成笔 |
|
||
| `笔弱化` | `false` | 放宽成笔条件 |
|
||
| `笔弱化_原始数量` | `3` | 弱化模式最小原始K线数 |
|
||
|
||
#### 线段设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `线段_非缺口下穿刺` | `false` | 非缺口下的穿刺处理 |
|
||
| `线段_特征序列忽视老阴老阳` | `false` | 缺口时不严格处理包含 |
|
||
| `线段_缺口后紧急修正` | `true` | 缺口后自动修正 |
|
||
| `线段_修正` | `false` | 短路修正(不推荐) |
|
||
| `线段内部中枢图显` | `true` | 线段内部中枢图表显示 |
|
||
| `扩展线段_当下分析` | `false` | 扩展线段实时分析模式 |
|
||
|
||
#### 分析开关
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `分析笔` | `true` | |
|
||
| `分析线段` | `true` | |
|
||
| `分析扩展线段` | `true` | |
|
||
| `分析笔中枢` | `true` | |
|
||
| `分析线段中枢` | `true` | |
|
||
|
||
#### 终止
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `手动终止` | `""` | 手动终止时间字符串 |
|
||
|
||
#### 指标设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `计算指标` | `true` | 是否计算技术指标 |
|
||
| `计算BOLL` | `false` | 是否计算布林带 |
|
||
| `指标计算方式` | `"收"` | 开/高/低/收/高低均值/高低收均值/开高低收均值 |
|
||
|
||
#### MACD 参数
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `平滑异同移动平均线_快线周期` | `13` | |
|
||
| `平滑异同移动平均线_慢线周期` | `31` | |
|
||
| `平滑异同移动平均线_信号周期` | `11` | |
|
||
| `MACD_参数列表` | `[]` | 多参数变体: `Vec<(key, 快, 慢, 信号)>` |
|
||
|
||
#### RSI 参数
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `相对强弱指数_周期` | `13` | RSI计算周期 |
|
||
| `相对强弱指数_移动平均线周期` | `13` | RSI SMA平滑周期 |
|
||
| `相对强弱指数_超买阈值` | `75.0` | |
|
||
| `相对强弱指数_超卖阈值` | `25.0` | |
|
||
| `RSI_周期列表` | `[]` | 多周期变体: `Vec<(key, 周期)>` |
|
||
|
||
#### KDJ 参数
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `随机指标_RSV周期` | `13` | |
|
||
| `随机指标_K值平滑周期` | `5` | |
|
||
| `随机指标_D值平滑周期` | `5` | |
|
||
| `随机指标_超买阈值` | `80.0` | |
|
||
| `随机指标_超卖阈值` | `20.0` | |
|
||
| `KDJ_参数列表` | `[]` | 多参数变体 |
|
||
|
||
#### BOLL 参数
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `布林带_周期` | `20` | |
|
||
| `布林带_标准差倍数` | `2.0` | |
|
||
| `BOLL_参数列表` | `[]` | 多参数变体 |
|
||
|
||
#### 均线参数
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `均线_类型列表` | `[]` | `["SMA", "EMA", ...]` |
|
||
| `均线_周期列表` | `[]` | `[5, 10, 20, ...]` |
|
||
|
||
#### 推送/图表显示
|
||
| 字段 | 默认值 |
|
||
|------|--------|
|
||
| `图表展示` | `true` |
|
||
| `推送K线` | `true` |
|
||
| `推送笔` | `true` |
|
||
| `推送线段` | `true` |
|
||
| `推送中枢` | `true` |
|
||
| `图表展示_笔` | `true` |
|
||
| `图表展示_线段` | `true` |
|
||
| `图表展示_扩展线段` | `true` |
|
||
| `图表展示_扩展线段_线段` | `true` |
|
||
| `图表展示_线段_线段` | `true` |
|
||
| `图表展示_中枢_笔` | `true` |
|
||
| `图表展示_中枢_线段` | `true` |
|
||
| `图表展示_中枢_扩展线段` | `true` |
|
||
| `图表展示_中枢_扩展线段_线段` | `true` |
|
||
| `图表展示_中枢_线段_线段` | `true` |
|
||
| `图表展示_中枢_线段内部` | `true` |
|
||
|
||
#### 买卖点设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `买卖点偏移` | `1` | 最大偏移量 |
|
||
| `买卖点激进识别` | `false` | |
|
||
| `买卖点与MACD柱强相关` | `false` | |
|
||
| `买卖点错过误差值` | `0.01` | |
|
||
| `买卖点_指标模式` | `"配置"` | 任意/配置/全量/相对 |
|
||
| `买卖点_指标匹配_MACD` | `true` | |
|
||
| `买卖点_指标匹配_KDJ` | `true` | |
|
||
| `买卖点_指标匹配_RSI` | `true` | |
|
||
| `买卖点_背离率` | `INFINITY` | 不使用 |
|
||
| `买卖点_T2_回调阈值` | `1.0` | |
|
||
| `买卖点_T2S_最大层级` | `3` | |
|
||
| `买卖点_峰值条件` | `false` | |
|
||
| `买卖点_计算方式` | `"峰"` | |
|
||
| `买卖点_计算线段BSP1` | `true` | |
|
||
| `买卖点_处理BSP2` | `true` | |
|
||
| `买卖点_计算线段BSP3` | `true` | |
|
||
| `买卖点_依赖T1` | `true` | |
|
||
| `买卖点_中枢来源` | `"合"` | 实/虚/合 |
|
||
| `买卖点_调试输出` | `false` | |
|
||
|
||
#### 背驰设置
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `线段内部背驰_MACD` | `true` | 使用 MACD 背驰 |
|
||
| `线段内部背驰_斜率` | `true` | 使用斜率背驰 |
|
||
| `线段内部背驰_测度` | `true` | 使用测度背驰 |
|
||
| `线段内部背驰_模式` | `"相对"` | 任意/配置/全量/相对 |
|
||
|
||
#### 文件
|
||
| 字段 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `加载文件路径` | `""` | 数据文件路径 |
|
||
|
||
### 配置方法
|
||
|
||
```rust
|
||
// JSON 往返
|
||
let json = config.to_json(); // 序列化
|
||
let config2 = 缠论配置::from_json(&json)?; // 反序列化
|
||
|
||
// 文件 I/O
|
||
config.保存配置("/path/to/config.json")?; // 保存
|
||
let loaded = 缠论配置::加载配置("/path/to/config.json")?; // 加载
|
||
|
||
// 部分反序列化(缺失字段→默认值)
|
||
let config: 缠论配置 = serde_json::from_str(r#"{"笔内元素数量": 7}"#)?;
|
||
|
||
// 静默模式
|
||
let silent = config.不推送(); // 所有推送/展示开关设为 false
|
||
|
||
// 差异对比
|
||
let diffs = config_a.对比(&config_b); // → ["笔内元素数量", ...]
|
||
|
||
// 多参数解析(列表非空则使用列表,否则使用默认单组)
|
||
let macd参数 = config._解析MACD参数列表(); // Vec<(key, 快, 慢, 信号)>
|
||
let rsi周期 = config._解析RSI周期列表(); // Vec<(key, 周期)>
|
||
let kdj参数 = config._解析KDJ参数列表(); // Vec<(key, RSV, K, D)>
|
||
let boll参数 = config._解析BOLL参数列表(); // Vec<(key, 周期, 倍数)>
|
||
|
||
// 复合key重组(兼容旧版 "1_open" 格式)
|
||
let configs = 缠论配置::按序号重组字典(&default_config, &raw_json);
|
||
```
|
||
|
||
---
|
||
|
||
## 算法模块
|
||
|
||
### 笔划分 (`algorithm::bi`, 1009 行)
|
||
|
||
`笔` 是一个纯静态方法命名空间,核心方法:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `分析()` | 主算法:接收分型,递归分析生成笔 |
|
||
| `_获取缠K数量()` | 计算可成笔的缠K数量(含弱化模式) |
|
||
| `_实际高点() / _实际低点()` | 潜在成笔区域的最高/最低缠K |
|
||
| `_获取成笔核心分型()` | 笔弱化模式下获取次高/次低成笔的候选分型 |
|
||
| `根据缠K找笔()` | 在笔序列中查找包含指定缠K的笔 |
|
||
| `是否背驰过()` | 检查笔范围内是否发生过MACD背驰 |
|
||
|
||
关键设计:
|
||
- 笔弱化:当严格条件不满足时,允许 `笔弱化_原始数量` (≥3) 根原始K线成笔
|
||
- 次级成笔:允许次高/次低成笔的候选分型
|
||
- 相同终点取舍:false=取first, true=取last (Python `list.index` 行为)
|
||
- 笔内验证:起始分型包含整笔 / 原始K线包含整笔
|
||
|
||
### 线段划分 (`algorithm::segment`, 2078 行)
|
||
|
||
`线段` 是**最复杂的算法模块**,核心方法:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `分析()` | 主算法:从笔序列计算线段 |
|
||
| `扩展分析()` | 扩展线段分析(不同的缺口处理策略) |
|
||
| `分割序列()` | 将特征序列分割为前/后/三/贯穿伤四个部分 |
|
||
| `特征序列状态()` | 返回 (特征_a, 特征_b, 特征_c) 布尔标志 |
|
||
| `四象()` | 判断特征序列的类型:老阳/老阴/小阳/少阴 |
|
||
| `获取缺口()` | 获取特征序列第一二元素间的缺口 |
|
||
| `判断线段内部是否背驰()` | 线段内部进入段vs离开段背驰判断 |
|
||
| `是否背驰过()` | 线段范围内是否发生过背驰 |
|
||
| `获取所有停顿位置()` | 获取线段内部所有可能的停顿位置 |
|
||
| `获取内部中枢序列()` | 获取线段内部的中枢序列 |
|
||
|
||
四种修正机制(按优先级):
|
||
1. `_缺口突破` — 老阳/老阴状态 + 价格突破前线段极值 → 线段完成
|
||
2. `_非缺口下穿刺` — 贯穿伤存在 + 方向相同的3笔 → 线段完成
|
||
3. `_缺口后紧急修正` — 前一线段有缺口 + 价格反向突破 → 修正前一结束位置
|
||
4. `_修正` — 短线路径 (≥9笔) → 快速完成
|
||
|
||
### 中枢识别 (`algorithm::hub`, 1041 行)
|
||
|
||
`中枢` 既是数据结构也是算法命名空间:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `分析()` | 主算法:虚线→中枢,同时识别第三买卖点 |
|
||
| `线段扩展分析()` | 中枢扩展:≥9段时生成扩展中枢 |
|
||
| `高()` | 前三根虚线重叠区域的最高值 |
|
||
| `低()` | 前三根虚线重叠区域的最低值 |
|
||
| `文()` | 第一根虚线的起点分型 |
|
||
| `武()` | 第三根虚线的终点分型 |
|
||
| `方向()` | 当中枢高 > 中枢低时为向上,否则向下 |
|
||
| `延伸序列()` | 首尾之外的虚线 |
|
||
| `获取离开虚线()` | 找到离开中枢的虚线(第三买卖点) |
|
||
| `获取剩余虚线()` | 第三买卖点之后的虚线 |
|
||
| `获取第N买卖线()` | 获取第N个买卖点相关的虚线 |
|
||
|
||
中枢识别核心逻辑:
|
||
1. 基础检查:三条连续虚线必须重叠(`max(低) < min(高)`)且方向关系正确
|
||
2. 中枢延伸:在后继虚线中找离开中枢的虚线,未离开则加入基础序列
|
||
3. 第三买卖点:虚线离开中枢且不回中枢,记录 `第三买卖线`
|
||
4. 中枢完成:`第三买卖线` 确立后,在上方虚线开始新中枢
|
||
5. 中枢扩展:≥9段时调用 `线段扩展分析` 生成扩展中枢
|
||
|
||
### 背驰检测 (`algorithm::divergence`, 227 行)
|
||
|
||
`背驰分析` 提供三种检测方式:
|
||
|
||
| 方式 | 原理 | 方法 |
|
||
|------|------|------|
|
||
| MACD背驰 | 进入段vs离开段的MACD柱面积对比 (`阳 + |阴|` 绝对值和) | `MACD背驰()` |
|
||
| 斜率背驰 | 价格变化速率 (dy/dx) 减弱 | `斜率背驰()` |
|
||
| 测度背驰 | 价格-时间向量长度 (√(dx²+dy²)) 缩减 | `测度背驰()` |
|
||
|
||
四种组合模式:
|
||
|
||
| 模式 | 条件 |
|
||
|------|------|
|
||
| `全量` | MACD 且 斜率 且 测度 全满足 |
|
||
| `任意` | MACD 或 斜率 或 测度 任意满足 |
|
||
| `配置` | 根据 `线段内部背驰_MACD/斜率/测度` 配置组合 |
|
||
| `相对` | 至少两种方式满足(多数投票) |
|
||
|
||
---
|
||
|
||
## 技术指标
|
||
|
||
所有指标位于 `indicators/` 模块,均支持**首次计算**和**增量计算**两种模式。
|
||
|
||
### 统一指标容器 (`indicators::container`)
|
||
|
||
基于注册表模式,通过 `指标值` 枚举统一管理五种指标类型:
|
||
|
||
```rust
|
||
pub enum 指标值 {
|
||
MACD(平滑异同移动平均线),
|
||
RSI(相对强弱指数),
|
||
KDJ(随机指标),
|
||
BOLL(布林带),
|
||
均线(HashMap<String, f64>),
|
||
单值(HashMap<String, f64>),
|
||
}
|
||
```
|
||
|
||
- 预注册默认槽位:`macd`, `rsi`, `kdj`, `boll`, `均线`, `单值`
|
||
- 支持多参数变体:`MACD_13_31_11`, `RSI_14`, `KDJ_9_3_3` 等
|
||
- 便捷方法:`macd()`, `rsi()`, `kdj()`, `boll()`, `均线()`
|
||
- 动态注册:`注册(name, default_value)`, `设置(name, value)`
|
||
|
||
### 指标计算器 (`indicators::calculator`, 476 行)
|
||
|
||
`指标计算器::计算并挂载(全序列, 配置)` 是一次完整的指标计算周期:
|
||
|
||
1. **MACD组** — 遍历 `_解析MACD参数列表()`,对每个 (key, 快, 慢, 信号) 计算
|
||
2. **RSI组** — 遍历 `_解析RSI周期列表()`
|
||
3. **KDJ组** — 遍历 `_解析KDJ参数列表()`
|
||
4. **BOLL组** — 遍历 `_解析BOLL参数列表()`
|
||
5. **均线** — 遍历 `均线_类型列表 × 均线_周期列表`,MA/EMA 计算
|
||
6. **回填新指标** — 如果当前K线有前序K线遗漏的指标,回溯填充
|
||
|
||
K线取值 (`K线取值()`) 支持 7 种计算方式:
|
||
`开` / `高` / `低` / `收` / `高低均值` / `高低收均值` / `开高低收均值`
|
||
|
||
### MACD (`indicators::macd`, 215 行)
|
||
|
||
```
|
||
平滑异同移动平均线 {
|
||
时间戳, 收盘价, 快线周期, 慢线周期, 信号周期,
|
||
DIF: Option<f64>, // 快线EMA - 慢线EMA
|
||
DEA: Option<f64>, // DIF的信号线EMA
|
||
MACD柱: f64, // 2 * (DIF - DEA)
|
||
快线EMA: Option<f64>, // 计算中间值(增量用)
|
||
慢线EMA: Option<f64>,
|
||
DEA_EMA: Option<f64>,
|
||
}
|
||
```
|
||
|
||
- `首次计算(收盘价, 时间戳, 快线周期, 慢线周期, 信号周期)` — 初始EMA=SMA近似
|
||
- `增量计算(prev, 收盘价, 时间戳)` — EMA递推公式
|
||
- `计算K线MACD(普K序列, 快, 慢, 信号)` — 遍历序列批量计算
|
||
|
||
### RSI (`indicators::rsi`, 240 行)
|
||
|
||
```
|
||
相对强弱指数 {
|
||
时间戳, 收盘价, 周期,
|
||
超买阈值, 超卖阈值,
|
||
RSI: Option<f64>,
|
||
RSI_SMA: Option<f64>, // RSI的SMA信号线
|
||
平均上涨: Option<f64>, // Wilder平滑中间值(增量用)
|
||
平均下跌: Option<f64>,
|
||
}
|
||
```
|
||
|
||
- Wilder SMA 平滑算法
|
||
- `首次计算()` — 初始均值=SMA
|
||
- `增量计算()` — Wilder递推
|
||
|
||
### KDJ (`indicators::kdj`, 289 行)
|
||
|
||
```
|
||
随机指标 {
|
||
时间戳, 最高价, 最低价, 收盘价,
|
||
RSV周期, K值平滑周期, D值平滑周期,
|
||
超买阈值, 超卖阈值,
|
||
K: Option<f64>, // RSV的移动平均
|
||
D: Option<f64>, // K的移动平均
|
||
J: Option<f64>, // 3*K - 2*D
|
||
}
|
||
```
|
||
|
||
- `首次计算(全体)` — 从序列计算初始KDJ值
|
||
- `增量计算(全体, 当前, 周期, K平滑, D平滑)` — 增量更新
|
||
|
||
### BOLL (`indicators::boll`, 169 行)
|
||
|
||
```
|
||
布林带 {
|
||
时间戳, 收盘价, 周期,
|
||
标准差倍数,
|
||
中轨: Option<f64>, // SMA
|
||
上轨: Option<f64>, // 中轨 + 倍数 * 标准差
|
||
下轨: Option<f64>, // 中轨 - 倍数 * 标准差
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 线程安全与并发
|
||
|
||
### 内部可变性策略
|
||
|
||
缠K/虚线/中枢等结构体需要在多 `Arc` 共享时支持原地修改(如笔动态替换武、中枢延伸添加虚线)。Rust 中 `Arc` 的 `&self` 是不可变的,因此大量字段使用以下策略实现内部可变性:
|
||
|
||
| 机制 | 类型 | 适用场景 |
|
||
|------|------|---------|
|
||
| `SyncF64` | `AtomicU64` 位转换 | 价格字段 (高/低/分型特征值),需跨线程原子读写 |
|
||
| `AtomicI64` | 原子整数 | 序号/时间戳/原始结束序号 |
|
||
| `AtomicBool` | 原子布尔 | 有效性/短路修正/特征序列显示 |
|
||
| `RwLock<T>` | 读写锁 | 复杂字段 (Arc<分型>/Vec/标识/模式/中枢序列) |
|
||
|
||
### 全局缓存
|
||
|
||
- **买卖意义缓存**: `LazyLock<Mutex<LruCache<(usize, usize), (bool, String)>>>` — 128条目,key为 (虚线指针, 观察者指针) 地址对
|
||
- **与 Python 对齐**:Python 使用 `@lru_cache(maxsize=128)` 装饰器,Rust 使用全局 `LazyLock<Mutex<>>` 替代 PyO3 的 `thread_local!`(解决跨线程不可见问题)
|
||
|
||
### Send + Sync 保证
|
||
|
||
所有核心数据结构(`缠论K线`, `虚线`, `中枢`, `观察者`)均实现 `Send + Sync`,可以安全地跨线程传递和共享:
|
||
|
||
```rust
|
||
// 编译期断言
|
||
fn _需要_Send_Sync<T: Send + Sync>() {}
|
||
_需要_Send_Sync::<缠论K线>();
|
||
_需要_Send_Sync::<虚线>();
|
||
_需要_Send_Sync::<中枢>();
|
||
```
|
||
|
||
`观察者` 使用 `Arc<RwLock<观察者>>` 模式,多线程可以并发读取同一个观察者的分析结果。
|
||
|
||
### RwLock 死锁预防
|
||
|
||
Rust 的 `RwLock` 是**非递归锁**。在已有读锁的线程中尝试获取写锁会死锁。核心规则:
|
||
- 将读锁作用域化:在所有调用带写锁的方法之前释放 `prev_guard`
|
||
- 典型模式:`{ let prev_guard = ... ; /* 使用 prev_guard */ } // 作用域结束释放 → 安全调用回填`
|
||
|
||
---
|
||
|
||
## Python 绑定
|
||
|
||
Python 调用通过独立的 [`chanlun-py`](../chanlun-py/) crate 提供,使用 PyO3 包装。所有类型、方法、字段名与 `chan.py` **完全一致**,API 兼容。
|
||
|
||
```bash
|
||
cd chanlun-py
|
||
maturin develop --release
|
||
```
|
||
|
||
```python
|
||
import chanlun
|
||
|
||
# 创建/修改配置
|
||
config = chanlun.缠论配置()
|
||
config.笔内元素数量 = 7
|
||
config.MACD_参数列表 = [("my_macd", 12, 26, 9)]
|
||
|
||
# 创建观察者
|
||
obs = chanlun.观察者("BTCUSD", 3600, config)
|
||
|
||
# 通过 Python 属性直接修改配置(自动同步到核心层)
|
||
obs.配置.笔弱化 = True
|
||
|
||
# 投喂K线
|
||
k = chanlun.K线.创建普K("bar", 1736640000, 50000, 51000, 49000, 50500, 100, 0, 3600)
|
||
obs.增加原始K线(k)
|
||
|
||
# 获取分析结果
|
||
print(f"笔数量: {len(obs.笔序列)}")
|
||
print(f"线段数量: {len(obs.线段序列)}")
|
||
print(f"中枢数量: {len(obs.中枢序列)}")
|
||
|
||
# 全局开关
|
||
chanlun.分型模式 = False # 从缠K实时读取分型值(逆序包含后使用)
|
||
```
|
||
|
||
### 绑定层特性
|
||
|
||
- **配置缓存**: `obs.配置` 返回同一个 Python 对象(而非每次新建),确保 Python 端修改后 Rust 端可见
|
||
- **分型模式**: 模块级 `chanlun.分型模式` getter/setter,控制分型值的读取策略
|
||
- **数据文件兼容**: `chanlun.读取数据文件("file.nb", config, 观察员=obs)` 与 Python 版签名一致
|
||
- **跨线程身份**: 全局 `LazyLock` 保证跨线程 `is` 判断一致
|
||
|
||
---
|
||
|
||
## 数据序列化
|
||
|
||
### K线二进制格式
|
||
|
||
与 Python `struct.pack(">6d")` 完全兼容的大端字节序格式,每根K线 48 字节:
|
||
|
||
| 偏移 | 大小 | 字段 |
|
||
|------|------|------|
|
||
| 0 | 8 字节 | 时间戳 (Unix秒 as f64) |
|
||
| 8 | 8 字节 | 开盘价 |
|
||
| 16 | 8 字节 | 最高价 |
|
||
| 24 | 8 字节 | 最低价 |
|
||
| 32 | 8 字节 | 收盘价 |
|
||
| 40 | 8 字节 | 成交量 |
|
||
|
||
```rust
|
||
// 序列化
|
||
let bytes: [u8; 48] = k线.to_bytes();
|
||
|
||
// 反序列化
|
||
let k线 = K线::读取大端字节数组(&bytes, 周期, 标识);
|
||
|
||
// 解析原始数据(不构造K线)
|
||
let (时间戳, 开, 高, 低, 收, 量) = K线::解析原始数据(&bytes)?;
|
||
|
||
// 批量保存
|
||
K线::保存到DAT文件("output.dat", &[&k1, &k2])?;
|
||
```
|
||
|
||
### 配置 JSON
|
||
|
||
```json
|
||
{
|
||
"标识": "BTCUSD",
|
||
"笔内元素数量": 5,
|
||
"平滑异同移动平均线_快线周期": 13,
|
||
"平滑异同移动平均线_慢线周期": 31,
|
||
"买卖点_指标模式": "配置",
|
||
"线段内部背驰_模式": "相对"
|
||
}
|
||
```
|
||
|
||
- 使用 `#[serde(default)]` 实现前向/后向兼容,缺失字段自动使用默认值
|
||
- 字符串枚举字段(`指标计算方式`, `买卖点_指标模式`, `线段内部背驰_模式`)带有自定义反序列化器,非法值自动回退默认值并发出 `warn!` 日志
|
||
|
||
### 结构化相等校验
|
||
|
||
所有核心结构体都实现了 `相等(&self, other, 浮点容差) → (bool, String)` 方法,递归校验包括:
|
||
- 浮点字段使用容差比较(而非直接 `==`)
|
||
- `Arc` 指针共享的结构体深度校验值语义
|
||
- 嵌套容器(Vec, Option, HashMap)逐一比对
|
||
- 返回详细的差异描述,便于调试
|
||
|
||
---
|
||
|
||
## 测试
|
||
|
||
### 核心层测试 (`chanlun/`)
|
||
|
||
```bash
|
||
cargo test # 运行所有测试
|
||
cargo test -- test_重复计算 # 运行匹配模式的测试
|
||
```
|
||
|
||
测试覆盖:
|
||
- **配置**: 默认值、JSON 往返、部分反序列化、非法值回退、不推送模式
|
||
- **K线**: 方向判定、大端字节序列化往返
|
||
- **缠K**: 创建/镜像/包含合并/分型识别、三K线生成分型
|
||
- **分型**: 左中右构造、字段读写、关联指针
|
||
- **虚线**: Cell/RefCell 读写、Clone 后 Rc 指针一致、多 Arc 共享可见性、获取武递归、武修改不影响文
|
||
- **线段特征**: 文取max/min, 武取max/min, tiebreaker, 添加/删除
|
||
- **中枢**: 字段读写、Clone 后指针一致、多 Arc 共享
|
||
- **买卖点**: 偏移/失效偏移/有效性、18种类型生成
|
||
- **观察者**: 指针一致性 (普K/分型/笔/线段/中枢)、重复计算确定性、重置后数据一致、RefCell 借用安全、跨线程 Send/Sync
|
||
|
||
### Python 绑定层测试 (`chanlun-py/tests/test_all.py`)
|
||
|
||
```bash
|
||
cd chanlun-py && maturin develop
|
||
python3 -m pytest tests/test_all.py -v
|
||
# 107+ tests, 涵盖:
|
||
# - 指标挂载与回填
|
||
# - 跨线程身份一致性 (is 判断)
|
||
# - 买卖意义/趋向背驰/行为统计/停顿位置/线段内部背驰等 双端(Rust绑定 vs chan.py)数据对比
|
||
```
|
||
|
||
---
|
||
|
||
## 许可
|
||
|
||
MIT License. 详见 [LICENSE](LICENSE).
|
||
|
||
---
|
||
|
||
## 相关项目
|
||
|
||
- [`chan.py`](../chan.py) — Python 参考实现(~4200 行)
|
||
- [`chanlun-py`](../chanlun-py/) — PyO3 绑定,将本 crate 导出为 Python `chanlun` 模块
|
||
- [`main.py`](../main.py) — Python 图表可视化程序
|