2026-05-26 19:06:28 +08:00
|
|
|
|
# chanlun — 缠论技术分析 Rust 核心库
|
|
|
|
|
|
|
|
|
|
|
|
[](LICENSE)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
[](https://www.rust-lang.org)
|
|
|
|
|
|
[](https://doc.rust-lang.org/edition-guide/rust-2024/)
|
2026-06-16 12:01:58 +08:00
|
|
|
|
[](.)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
[缠中说禅](https://zh.wikipedia.org/wiki/%E7%BC%A0%E4%B8%AD%E8%AF%B4%E7%A6%85) 理论的 Rust 高性能实现——**约 14,000 行 Rust(2024 edition)**,覆盖缠论完整算法体系:K线包含处理、分型识别、笔/线段划分(含特征序列与缺口修正)、中枢识别(延伸/扩展/多级)、背驰检测(MACD/斜率/测度)、买卖点生成(18 种类型)、技术指标计算(MACD/RSI/KDJ/BOLL/均线)、信号匹配框架、编译期信号注册表与 .so 动态插件系统。
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
Python 参考实现 `chan.py`(~4,200 行)已完整移植,API **1:1 兼容**——所有类型、方法、字段名均使用中文标识符。Python 绑定通过 [`chanlun-py`](../chanlun-py/) crate(PyO3)发布为 `chanlun` PyPI 包。
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
- [核心概念](#核心概念)
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- [架构总览](#架构总览)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
- [项目结构](#项目结构)
|
|
|
|
|
|
- [快速开始](#快速开始)
|
|
|
|
|
|
- [数据管线](#数据管线)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- [核心类型详解](#核心类型详解)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
- [配置体系](#配置体系)
|
|
|
|
|
|
- [算法模块](#算法模块)
|
|
|
|
|
|
- [技术指标](#技术指标)
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- [信号框架](#信号框架)
|
|
|
|
|
|
- [插件系统](#插件系统)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- [线程安全与并发](#线程安全与并发)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
- [Python 绑定](#python-绑定)
|
|
|
|
|
|
- [数据序列化](#数据序列化)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- [测试](#测试)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
- [许可](#许可)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 核心概念
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
缠论将价格走势分解为层级结构,从最底层K线向上逐级构造:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
原始K线 → 包含处理 → 缠论K线 → 顶底分型 → 笔 → 线段 → 中枢 → 买卖点
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
理论核心:
|
|
|
|
|
|
- **走势终完美**:任何级别的走势类型终要完成,不可长期存续
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- **自同构性**:不同级别的走势呈现相同的形态结构,可通过递归分析进行多级别联立
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- **完全分类**:三段式完全分类(上涨/下跌/盘整),每个节点都可通过买卖点找到操作依据
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ Python 层 │
|
|
|
|
|
|
│ ┌─────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
|
|
|
|
|
|
│ │ main.py │ │ strategies.py│ │ signal_orchestrator.py │ │
|
|
|
|
|
|
│ │ (Web UI)│ │ (回测引擎) │ │ (混合信号编排: Rust+Py) │ │
|
|
|
|
|
|
│ └─────────┘ └──────────────┘ └─────────────────────────┘ │
|
|
|
|
|
|
│ │ PyO3 FFI │
|
|
|
|
|
|
├────────────────────────┼─────────────────────────────────────┤
|
|
|
|
|
|
│ PyO3 绑定层 (chanlun-py) │
|
|
|
|
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
|
|
|
|
│ │ config_py │ kline_py │ structure_py │ algorithm_py │ │
|
|
|
|
|
|
│ │ business_py │ signal_py │ signal_engine_py │ cache │ │
|
|
|
|
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
|
|
|
|
│ │ Rust API │
|
|
|
|
|
|
├────────────────────────┼─────────────────────────────────────┤
|
|
|
|
|
|
│ Rust 核心 (chanlun) │
|
|
|
|
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
|
|
|
|
│ │ config │ types │ kline │ indicators │ algorithm │ │
|
|
|
|
|
|
│ │ structure │ business │ signal (primitives + engine │ │
|
|
|
|
|
|
│ │ + registry + ffi + functions) │ utils │ │
|
|
|
|
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
|
|
|
|
└──────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**关键设计决策**:
|
|
|
|
|
|
|
|
|
|
|
|
| 决策 | 选择 | 原因 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 内部可变性 | `AtomicI64` / `SyncF64` / `RwLock<T>` | 多 Arc 共享下原地修改(如动态替换笔的武) |
|
|
|
|
|
|
| 增量计算 | 只重新分析末尾元素 | O(1) 均摊,适合实时交易 |
|
|
|
|
|
|
| 浮点原子 | `SyncF64`(`AtomicU64` 位转换) | 跨线程原子读写价格字段 |
|
|
|
|
|
|
| 按需计算 | 缠K/分型/笔/线段/中枢全部惰性 | 避免不必要的计算开销 |
|
|
|
|
|
|
| 3 级线段递归 | 线段 → 线段<线段> → 线段<线段<线段>> | 多级自同构性分析 |
|
|
|
|
|
|
| 中文标识符 | `#![allow(non_snake_case)]` | 与 Python `chan.py` API 完全对应 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
chanlun/
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── Cargo.toml # 依赖: serde, byteorder, chrono, sha2, inventory
|
|
|
|
|
|
├── README.md # 本文档
|
2026-05-26 19:06:28 +08:00
|
|
|
|
└── src/
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── lib.rs # 模块注册 + 日志开关 + tracing 初始化
|
|
|
|
|
|
├── main.rs # CLI 工具 (read/synth 子命令)
|
|
|
|
|
|
├── config.rs # 缠论配置 (44 字段, serde, model_fields/对比/往返)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── types/ # 基础类型 (5 文件, ~514 行)
|
|
|
|
|
|
│ ├── mod.rs # 重导出
|
|
|
|
|
|
│ ├── direction.rs # 相对方向 (9 变体): 向上/向下/缺口/衔接/顺/逆/同
|
|
|
|
|
|
│ ├── bsp_type.rs # 买卖点类型 (18 变体)
|
|
|
|
|
|
│ ├── fractal.rs # 分型结构 (5 变体) + 有高低 trait
|
|
|
|
|
|
│ ├── gap.rs # 缺口: 价格区间 + 居中截取
|
|
|
|
|
|
│ └── sync_f64.rs # SyncF64: AtomicU64 线程安全 f64
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── kline/ # K线层 (2 文件, ~1,113 行)
|
|
|
|
|
|
│ ├── bar.rs # 原始K线: OHLCV + RwLock<指标容器>, 48字节大端序列化
|
|
|
|
|
|
│ └── chan_kline.rs # 缠论K线: 包含处理后, 分型标记, 内部可变性字段
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── indicators/ # 技术指标 (7 文件, ~1,589 行)
|
|
|
|
|
|
│ ├── macd.rs # MACD (EMA快慢线, DIF/DEA/MACD柱, 首次+增量)
|
|
|
|
|
|
│ ├── rsi.rs # RSI (Wilder SMA 平滑, 超买超卖)
|
|
|
|
|
|
│ ├── kdj.rs # KDJ (RSV→K→D→J, 超买超卖阈值)
|
|
|
|
|
|
│ ├── boll.rs # BOLL (中轨/上轨/下轨, 带宽)
|
|
|
|
|
|
│ ├── calculator.rs # 指标计算器: 增量计算 + 回填 + 均线
|
|
|
|
|
|
│ └── container.rs # 指标容器: 注册表模式, 动态指标存取
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── algorithm/ # 核心算法 (4 文件, ~4,987 行)
|
|
|
|
|
|
│ ├── bi.rs # 笔划分: 递归分析, 弱化/次级/实际高低点
|
|
|
|
|
|
│ ├── segment.rs # 线段划分: 特征序列, 缺口处理, 四种修正, 扩展线段
|
|
|
|
|
|
│ ├── hub.rs # 中枢识别: 重叠检测, 延伸/扩展, 第三买卖点
|
|
|
|
|
|
│ └── divergence.rs # 背驰检测: MACD/斜率/测度 + 四种组合模式
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── structure/ # 结构体 (4 文件, ~2,089 行)
|
|
|
|
|
|
│ ├── dash_line.rs # 虚线: 笔/线段的通用抽象, MACD行为统计, 买卖意义
|
|
|
|
|
|
│ ├── fractal_obj.rs # 分型: 左中右构型, 强度判定, MACD匹配
|
|
|
|
|
|
│ ├── segment_feat.rs # 线段特征: 文/武取极值, 静态分析, 分型序列
|
|
|
|
|
|
│ └── feat_fractal.rs # 特征分型: 三线段特征元素构成的分型
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── business/ # 业务层 (4 文件, ~1,648 行)
|
|
|
|
|
|
│ ├── observer.rs # 观察者: 单周期流式分析器, 3级递归管线
|
|
|
|
|
|
│ ├── bsp.rs # 买卖点工厂: 18种类型, 偏移/失效/终结
|
|
|
|
|
|
│ ├── synthesizer.rs # K线合成器: 小周期→大周期合成
|
|
|
|
|
|
│ └── multi_frame.rs # 立体分析器: 多周期联立, 合成器+观察者协调
|
2026-06-07 13:08:19 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├── signal/ # 信号框架 (14 文件, ~4,300 行)
|
|
|
|
|
|
│ ├── mod.rs # 重导出 + 匹配值/信号字典/缺键错误/sha256前4
|
|
|
|
|
|
│ ├── signal.rs # Signal: czsc 风格七段key匹配 (k1~k3/v1~v3/score)
|
|
|
|
|
|
│ ├── factor.rs # Factor: 多信号all/not匹配 → name含哈希后缀
|
|
|
|
|
|
│ ├── event.rs # Event: 因子匹配 → 分配操作(开多/平多/开空/平空)
|
|
|
|
|
|
│ ├── operate.rs # Operate: 5 种操作枚举 (开多/平多/开空/平空/持币)
|
|
|
|
|
|
│ ├── position.rs # Position: 完整仓位状态机 (~1,039行)
|
|
|
|
|
|
│ │ # update() 事件匹配 + LO/SO/LE/SE 状态转换
|
|
|
|
|
|
│ │ # + 止损/超时/间隔检查 + pairs() 盈亏计算
|
|
|
|
|
|
│ ├── params.rs # 参数提取: get_int/get_float/get_string/get_bool
|
|
|
|
|
|
│ ├── registry.rs # 双注册表: 编译时(LazyLock) + 动态(RwLock)
|
|
|
|
|
|
│ ├── engine.rs # 信号引擎: 批量执行信号函数 + 自动挂载指标
|
|
|
|
|
|
│ ├── ffi.rs # C-ABI 导出: 供 .so 插件动态注册
|
|
|
|
|
|
│ ├── functions/ # 信号函数实现
|
|
|
|
|
|
│ │ ├── mod.rs #
|
|
|
|
|
|
│ │ ├── youwukuncheng.rs # 中枢第三买卖点 (~280行, 3种信号变体)
|
|
|
|
|
|
│ │ └── demo.rs # 示例信号 (~440行, 涨停/MACD金叉/MA/停顿分型/笔结束)
|
|
|
|
|
|
│ └── registry_macro_test.rs # #[signal] 宏端到端测试
|
|
|
|
|
|
│
|
|
|
|
|
|
└── utils/ # 工具 (2 文件, ~145 行)
|
|
|
|
|
|
├── datetime.rs # 时间戳转换: 字符串↔Unix时间戳
|
|
|
|
|
|
└── format.rs # 格式化: f64→最小字符串 (format_f64_g)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 依赖项
|
|
|
|
|
|
|
|
|
|
|
|
| 依赖 | 用途 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `serde` + `serde_json` | 配置序列化、信号参数解析 |
|
|
|
|
|
|
| `byteorder` | .nb 文件的大端字节序读写 |
|
|
|
|
|
|
| `chrono` | 时间戳<->日期转换(Position 交易日判断) |
|
|
|
|
|
|
| `sha2` | 信号 Factor/Event 名称确定性的 sha256 前4 |
|
|
|
|
|
|
| `inventory` | `#[signal]` 宏编译期注册表收集 |
|
|
|
|
|
|
| `parking_lot` | RwLock/Mutex(性能优于 std 实现) |
|
|
|
|
|
|
| `cached` | LRU 缓存(买卖意义/ MACD 行为) |
|
|
|
|
|
|
| `tracing` | 结构化日志(warn/info/error!) |
|
|
|
|
|
|
|
2026-05-26 19:06:28 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 快速开始
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 作为 Rust 库使用
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```toml
|
|
|
|
|
|
[dependencies]
|
2026-06-16 12:01:58 +08:00
|
|
|
|
chanlun = "26.6"
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 单周期分析
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun::config::缠论配置;
|
|
|
|
|
|
use chanlun::kline::bar::K线;
|
|
|
|
|
|
use chanlun::business::observer::观察者;
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 创建观察者(返回 Arc<RwLock<观察者>>,支持多线程共享)
|
|
|
|
|
|
let 观察员 = 观察者::new("BTCUSD".into(), 3600, 缠论配置::default());
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 逐根投喂 K 线(流式增量分析)
|
|
|
|
|
|
for k线 in 数据流 {
|
|
|
|
|
|
观察员.write().增加原始K线(k线);
|
2026-05-26 19:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 读取分析结果
|
|
|
|
|
|
let obs = 观察员.read();
|
|
|
|
|
|
println!("笔: {}, 线段: {}, 中枢: {}",
|
|
|
|
|
|
obs.笔序列.len(), obs.线段序列().len(), obs.中枢序列().len());
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 便捷投喂(无需构造 K 线对象)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
let 观察员 = 观察者::new("ETHUSD".into(), 300, Default::default());
|
2026-06-16 12:01:58 +08:00
|
|
|
|
观察员.write().投喂原始数据(
|
|
|
|
|
|
1736640000, // Unix 时间戳
|
|
|
|
|
|
3500.0, // 开盘
|
|
|
|
|
|
3550.0, // 最高
|
|
|
|
|
|
3480.0, // 最低
|
|
|
|
|
|
3520.0, // 收盘
|
|
|
|
|
|
1200.0, // 成交量
|
|
|
|
|
|
);
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 从 .nb 文件批量加载
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
2026-06-16 12:01:58 +08:00
|
|
|
|
观察员.write().读取数据文件("btcusd-300-1000000-1100000.nb", Default::default())?;
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 多周期联立分析
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun::business::multi_frame::立体分析器;
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 周期组: [60s, 300s, 1800s, 7200s]
|
|
|
|
|
|
// 只投喂最小周期 K 线,大周期自动合成
|
2026-05-26 19:06:28 +08:00
|
|
|
|
let mut 分析器 = 立体分析器::new(
|
|
|
|
|
|
"BTCUSD".into(),
|
2026-06-16 12:01:58 +08:00
|
|
|
|
vec![60, 300, 1800, 7200],
|
|
|
|
|
|
None, // 默认配置
|
|
|
|
|
|
None, // 无周期特定配置
|
2026-05-26 19:06:28 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
for k线 in 小周期K线流 {
|
|
|
|
|
|
分析器.投喂K线(k线);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 获取各周期分析结果
|
|
|
|
|
|
if let Some(日线) = 分析器.获取观察者(86400) {
|
|
|
|
|
|
println!("日线笔数: {}", 日线.read().笔序列.len());
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 信号计算
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun::signal::engine::{SignalEngine, SignalConfig};
|
|
|
|
|
|
|
|
|
|
|
|
// 构建信号引擎
|
|
|
|
|
|
let 引擎 = SignalEngine::new(vec![
|
|
|
|
|
|
SignalConfig {
|
|
|
|
|
|
signal_name: "youwukuncheng_中枢第三买卖点_V230602".into(),
|
|
|
|
|
|
freq: 86400,
|
|
|
|
|
|
params: [
|
|
|
|
|
|
("freq".into(), "日线".into()),
|
|
|
|
|
|
("max_overlap".into(), 3.into()),
|
|
|
|
|
|
("本级完整性".into(), "实".into()),
|
|
|
|
|
|
("同级完整性".into(), "合".into()),
|
|
|
|
|
|
].into_iter().collect(),
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// 自动挂载所需指标
|
|
|
|
|
|
引擎.自动挂载指标(&分析器);
|
|
|
|
|
|
|
|
|
|
|
|
// 计算信号
|
|
|
|
|
|
let 信号 = 引擎.更新_完整(&分析器);
|
|
|
|
|
|
// → { signals: { "日线_D1MO3_中枢段DEA穿越2V230602": "三买" }, market: { ... } }
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### CLI 工具
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 单周期分析 + 保存结果
|
|
|
|
|
|
cargo run -- read btcusd-3600-1000000-1100000.nb
|
|
|
|
|
|
|
|
|
|
|
|
# 多周期合成 (从文件名的周期推断周期组: N, N×5, N×30)
|
|
|
|
|
|
cargo run -- synth btcusd-14400-1753142400-1781928000.nb
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-26 19:06:28 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 数据管线
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
每收到一根新 K 线,**增量更新**所有层级(只重算末尾)。这是该库适合实时交易系统的关键设计。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
### 管线流程
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
原始K线 (K线)
|
|
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 1. 指标计算 (indicators/calculator)
|
|
|
|
|
|
│ ├─ MACD 组 (遍历 MACD_参数列表, 首次/增量)
|
|
|
|
|
|
│ ├─ RSI 组 (遍历 RSI_周期列表)
|
|
|
|
|
|
│ ├─ KDJ 组 (遍历 KDJ_参数列表)
|
|
|
|
|
|
│ ├─ BOLL 组 (遍历 BOLL_参数列表)
|
|
|
|
|
|
│ ├─ 均线组 (遍历 均线参数列表, SMA/EMA)
|
|
|
|
|
|
│ └─ 回填新指标 (回溯填充前序K线遗漏的指标)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 2. 包含处理 → 缠论K线 (缠论K线)
|
|
|
|
|
|
│ ├─ 顺序包含合并: 顺方向取极值
|
|
|
|
|
|
│ ├─ 逆序包含合并: 更新时间/标的K线
|
|
|
|
|
|
│ ├─ 方向判定: 9 种相对方向
|
|
|
|
|
|
│ └─ 合并替换模式: 原地修改 / 产出新缠K
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 3. 分型识别 → 分型 (分型)
|
|
|
|
|
|
│ ├─ 左中右三根缠K构成
|
|
|
|
|
|
│ ├─ 类型: 顶/底/上/下/散
|
|
|
|
|
|
│ └─ 分型模式开关控制缓存/实时读取
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 4. 笔划分 → 笔 (虚线, 级别=1)
|
|
|
|
|
|
│ ├─ 递归分析: 顶底分型交替验证
|
|
|
|
|
|
│ ├─ 弱化模式: ≥3 根原始K线即可成笔
|
|
|
|
|
|
│ ├─ 次级成笔: 次高/次低作为候选
|
|
|
|
|
|
│ └─ 笔内验证: 分型包含整笔 / 原始K线包含整笔
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 5. 笔中枢识别 → 笔中枢
|
|
|
|
|
|
│ └─ 虚线重叠检测 → 延伸/扩展/第三买卖点
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 6. 线段划分 → 线段 (虚线, 级别≥2), 3级递归
|
|
|
|
|
|
│ ├─ 特征序列提取 (同向笔序列)
|
|
|
|
|
|
│ ├─ 缺口处理: 有缺口(老阴老阳) / 无缺口(小阳少阴)
|
|
|
|
|
|
│ ├─ 四种修正: 缺口突破 / 非缺口下穿刺 / 缺口后紧急修正 / 短路修正
|
|
|
|
|
|
│ └─ 递归: 线段 → 线段<线段> → 线段<线段<线段>>
|
2026-05-26 19:06:28 +08:00
|
|
|
|
│
|
2026-06-16 12:01:58 +08:00
|
|
|
|
├─ 7. 扩展线段 + 混合扩展线段 (各3级递归)
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ 8. 线段中枢识别
|
|
|
|
|
|
│ └─ 多级中枢: 线段中枢 / 扩展线段中枢 / 混合扩展中枢 / ...
|
|
|
|
|
|
│
|
|
|
|
|
|
└─ 9. 买卖点生成 → 基础买卖点 (18 种类型)
|
|
|
|
|
|
├─ 6 经典: 一买/一卖/二买/二卖/三买/三卖
|
|
|
|
|
|
├─ 12 扩展: T1~T3B 各含买卖
|
|
|
|
|
|
└─ 指标匹配: MACD/KDJ/RSI 确认
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
### 流式增量处理
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`观察者.__处理数据` 每步只处理末尾几个元素,时间复杂度 **O(1) 均摊**。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**推送模式**: 调用方可通过 `add_bar_listener()` 等回调在每级结果产出时收到通知。
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
## 核心类型详解
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
### 枚举类型
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### 相对方向 (`types::direction`) — 9 变体
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 变体 | 判定条件 | 场景 |
|
|
|
|
|
|
|------|---------|------|
|
|
|
|
|
|
| `向上` | 后高>前高 且 后低>前低, 无缺口 | 正常上涨 |
|
|
|
|
|
|
| `向下` | 后高<前高 且 后低<前低, 无缺口 | 正常下跌 |
|
|
|
|
|
|
| `向上缺口` | 后低 > 前高 | 大幅高开 |
|
|
|
|
|
|
| `向下缺口` | 后高 < 前低 | 大幅低开 |
|
|
|
|
|
|
| `衔接向上` | 后低 ≈ 前高 | 精准衔接 |
|
|
|
|
|
|
| `衔接向下` | 后高 ≈ 前低 | 精准衔接 |
|
|
|
|
|
|
| `顺` | 前包含后 (前高≥后高 且 前低≤后低) | 顺序包含 |
|
|
|
|
|
|
| `逆` | 后包含前 (前高≤后高 且 前低≥后低) | 逆序包含 |
|
|
|
|
|
|
| `同` | 完全相同 | 重复数据 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
方法: `翻转()`, `是否向上()`, `是否向下()`, `是否包含()`, `是否缺口()`, `分析(前高,前低,后高,后低)`
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### 买卖点类型 (`types::bsp_type`) — 18 变体
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 类别 | 买点变体 | 卖点变体 | 说明 |
|
|
|
|
|
|
|------|---------|---------|------|
|
|
|
|
|
|
| 一类 | `一买` | `一卖` | 中枢背驰后第一类 |
|
|
|
|
|
|
| 二类 | `二买` | `二卖` | 回调到中枢内第二类 |
|
|
|
|
|
|
| 三类 | `三买` | `三卖` | 离开中枢不回第三类 |
|
|
|
|
|
|
| T1 | `T1买` | `T1卖` | 事后确认型 |
|
|
|
|
|
|
| T1P | `T1P买` | `T1P卖` | 事后确认型+ |
|
|
|
|
|
|
| T2 | `T2买` | `T2卖` | 中枢回调型,破位值判定 |
|
|
|
|
|
|
| T2S | `T2S买` | `T2S卖` | 中枢回调次级 |
|
|
|
|
|
|
| T3A | `T3A买` | `T3A卖` | 第三类扩展A |
|
|
|
|
|
|
| T3B | `T3B买` | `T3B卖` | 第三类扩展B |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
方法: `是买点()`, `是卖点()`
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### 分型结构 (`types::fractal`) — 5 变体
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 变体 | 左中右关系 | 图示 |
|
|
|
|
|
|
|------|-----------|------|
|
|
|
|
|
|
| `上` | 向上 + 向上 | ↗↗ |
|
|
|
|
|
|
| `下` | 向下 + 向下 | ↘↘ |
|
|
|
|
|
|
| `顶` | 向上 + 向下 | ↗↘ (Λ) |
|
|
|
|
|
|
| `底` | 向下 + 向上 | ↘↗ (V) |
|
|
|
|
|
|
| `散` | 逆包含 + 逆包含 | 扩散 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
### 数据结构详解
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### K线 (`kline::bar`)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
K线 {
|
|
|
|
|
|
标识, 序号, 周期, 时间戳,
|
|
|
|
|
|
高, 低, 开盘价, 收盘价, 成交量,
|
2026-06-16 12:01:58 +08:00
|
|
|
|
指标: RwLock<指标容器>, // MACD/RSI/KDJ/BOLL/均线
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- `创建普K()` 工厂方法, `相等()` 结构化校验
|
|
|
|
|
|
- `to_bytes()` → 48 字节大端序列化, `读取大端字节数组()` 反序列化
|
|
|
|
|
|
- `获取MACD()` — 两K线间 MACD 柱面积 (阳/阴/合/总)
|
|
|
|
|
|
- 实现 `Clone` (深拷贝, 包括指标容器)
|
|
|
|
|
|
|
|
|
|
|
|
#### 缠论K线 (`kline::chan_kline`)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
缠论K线 {
|
2026-06-16 12:01:58 +08:00
|
|
|
|
序号: AtomicI64, 时间戳: AtomicI64,
|
|
|
|
|
|
高: SyncF64, 低: SyncF64, // 包含处理可能拉高/压低
|
|
|
|
|
|
方向: RwLock<相对方向>, 分型: RwLock<Option<分型结构>>,
|
|
|
|
|
|
分型特征值: SyncF64, // 历史极值
|
|
|
|
|
|
周期, 标识, 原始起始序号, 原始结束序号: AtomicI64,
|
|
|
|
|
|
标的K线: RwLock<Arc<K线>>, 买卖点信息: RwLock<HashSet<String>>,
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- `_兼并()` — 顺序/逆序包含合并, 重复提交检测, 原地修改
|
|
|
|
|
|
- `分析()` — 完整普K→缠K+分型管线
|
|
|
|
|
|
- 指标匹配: `与MACD柱子匹配()` / `与RSI匹配()` / `与KDJ匹配()`
|
|
|
|
|
|
- `相等()` — 20+ 字段递归校验
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 虚线 (`structure::dash_line`) — 笔和线段的通用数据结构
|
|
|
|
|
|
```
|
|
|
|
|
|
虚线 {
|
2026-06-16 12:01:58 +08:00
|
|
|
|
标识: RwLock<String>, // "笔"/"线段"/"扩展线段"/"线段<线段>" 等
|
|
|
|
|
|
级别: AtomicI64, // 笔=1, 线段=2, 递归递增
|
|
|
|
|
|
文: Arc<分型>, // 起点(不可变)
|
|
|
|
|
|
武: RwLock<Arc<分型>>, // 终点(可变,动态更新)
|
|
|
|
|
|
基础序列: RwLock<Vec<Arc<虚线>>>, // 子级虚线序列
|
|
|
|
|
|
实/虚/合_中枢序列, // 三类中枢序列
|
|
|
|
|
|
确认K线, 模式, 缺口处理, 短路修正,
|
|
|
|
|
|
...
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- 静态工厂: `创建笔()`(级别=1), `创建线段()`(级别递增)
|
|
|
|
|
|
- 属性: `方向()`, `高()`, `低()`, `之前是()`, `之后是()`
|
|
|
|
|
|
- 数据遍历: `获取普K序列()`, `获取缠K序列()`, `获取_武()`(递归到底层笔)
|
|
|
|
|
|
- MACD 分析: `计算MACD柱子均值()`, `统计MACD行为()`, `计算K线序列MACD趋向背驰()`
|
|
|
|
|
|
- 核心判断: `买卖意义()` — LRU 缓存 128 条目
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 中枢 (`algorithm::hub`)
|
|
|
|
|
|
```
|
|
|
|
|
|
中枢 {
|
2026-06-16 12:01:58 +08:00
|
|
|
|
基础序列: RwLock<Vec<Arc<虚线>>>, // ≥3根, 延伸可达 9+
|
2026-06-07 13:08:19 +08:00
|
|
|
|
第三买卖线: RwLock<Option<Arc<虚线>>>,
|
|
|
|
|
|
本级_第三买卖线: RwLock<Option<Arc<虚线>>>,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
- `高()` / `低()` — 前三根虚线的最大/最小重叠区域
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- `文()` → `武()` → `方向()`
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- 中枢延伸 → 扩展 (≥9段) → 第三买卖点确立 → 新中枢开始
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 基础买卖点 (`business::bsp`)
|
|
|
|
|
|
```
|
|
|
|
|
|
基础买卖点 {
|
2026-06-16 12:01:58 +08:00
|
|
|
|
类型: 买卖点类型, 买卖点分型: Arc<分型>,
|
|
|
|
|
|
买卖点K线, 当前K线, 失效K线, 终结K线,
|
|
|
|
|
|
破位值, 结构, 偏移量,
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
- `偏移()` — 当前缠K序号与买卖点K线序号的差
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- `有效性()` — 失效K线存在则无效
|
|
|
|
|
|
- 18 种类型由 `买卖点工厂` 统一生成, 含背驰确认+指标匹配
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
### 服务类型
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 类型 | 职责 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `观察者` | 单周期流式分析器, 维护全层级序列, 3级递归线段分析 |
|
|
|
|
|
|
| `K线合成器` | 小周期→大周期合成, 高取max/低取min/量求和 |
|
|
|
|
|
|
| `立体分析器` | 多周期联立, 内含合成器+每周期一个观察者 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
### 静态算法类
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 类型 | 职责 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `笔` | 分型→笔 (递归+弱化+次级+实际高低点) |
|
|
|
|
|
|
| `线段` | 笔→线段 (特征序列+缺口+四种修正+扩展分析) |
|
|
|
|
|
|
| `中枢` | 虚线→中枢 (重叠+延伸/扩展+第三买卖点) |
|
|
|
|
|
|
| `背驰分析` | MACD/斜率/测度 + 全量/任意/配置/相对组合 |
|
|
|
|
|
|
| `指标计算器` | 增量计算 MACD/RSI/KDJ/BOLL + 回填 + 均线 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 配置体系
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`缠论配置` 是一个 serde 驱动的结构体,**44 个字段**全部带默认值,支持 JSON 往返和部分反序列化容错。
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
### 完整配置表
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 基础设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `标识` | `String` | `"bar"` | 品种标识 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 缠K设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `缠K合并替换` | `bool` | `false` | false=原地修改, true=产出新缠K |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 笔设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `笔内元素数量` | `i64` | `5` | 成笔最低缠K数(含端点) |
|
|
|
|
|
|
| `笔内相同终点取舍` | `bool` | `false` | false=取first, true=取last |
|
|
|
|
|
|
| `笔内起始分型包含整笔` | `bool` | `false` | 起点分型区间必须包含整笔 |
|
|
|
|
|
|
| `笔内起始分型包含整笔_包括右` | `bool` | `false` | 同上+包含右端点 |
|
|
|
|
|
|
| `笔内原始K线包含整笔` | `bool` | `false` | 原始K线区间必须包含整笔 |
|
|
|
|
|
|
| `笔次级成笔` | `bool` | `false` | 允许在非分型处成笔 |
|
|
|
|
|
|
| `笔弱化` | `bool` | `false` | 放宽成笔条件 |
|
|
|
|
|
|
| `笔弱化_原始数量` | `i64` | `3` | 弱化模式最小原始K线数 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 线段设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `线段_非缺口下穿刺` | `bool` | `false` | 非缺口下的穿刺处理 |
|
|
|
|
|
|
| `线段_特征序列忽视老阴老阳` | `bool` | `false` | 缺口时不严格处理包含 |
|
|
|
|
|
|
| `线段_缺口后紧急修正` | `bool` | `true` | 缺口后自动修正 |
|
|
|
|
|
|
| `线段_修正` | `bool` | `false` | 短路修正(≥9笔快速完成) |
|
|
|
|
|
|
| `线段内部中枢图显` | `bool` | `true` | 线段内部中枢图表显示 |
|
|
|
|
|
|
| `扩展线段_当下分析` | `bool` | `false` | 扩展线段实时分析模式 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 分析开关
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 |
|
|
|
|
|
|
|------|------|--------|
|
|
|
|
|
|
| `分析笔` | `bool` | `true` |
|
|
|
|
|
|
| `分析线段` | `bool` | `true` |
|
|
|
|
|
|
| `分析扩展线段` | `bool` | `true` |
|
|
|
|
|
|
| `分析笔中枢` | `bool` | `true` |
|
|
|
|
|
|
| `分析线段中枢` | `bool` | `true` |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 终止
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `手动终止` | `String` | `""` | 手动终止时间字符串,非空时生效 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
#### 指标设置
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `计算指标` | `bool` | `true` | 是否计算技术指标 |
|
|
|
|
|
|
| `指标计算方式` | `String` | `"收"` | 开/高/低/收/高低均值/高低收均值/开高低收均值 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### 指标参数列表(多参数变体)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 字段 | 类型 | 默认值 |
|
|
|
|
|
|
|------|------|--------|
|
|
|
|
|
|
| `MACD_参数列表` | `Vec<(String, String, i64, i64, i64)>` | `[("macd","收",13,31,11)]` |
|
|
|
|
|
|
| `RSI_周期列表` | `Vec<(String, String, i64, i64, f64, f64)>` | `[("rsi","收",14,13,75,25)]` |
|
|
|
|
|
|
| `KDJ_参数列表` | `Vec<(String, String, i64, i64, i64, f64, f64)>` | `[("kdj","收",13,5,5,80,20)]` |
|
|
|
|
|
|
| `BOLL_参数列表` | `Vec<(String, String, i64, f64)>` | `[("boll","收",20,2.0)]` |
|
|
|
|
|
|
| `均线参数列表` | `Vec<(String, String, String, i64)>` | `[]` |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 推送/图表显示
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `图表展示` | `bool` | `true` | 全局图表显示开关 |
|
|
|
|
|
|
| `图表展示标签` | `Option<Vec<String>>` | `None` | None=全部展示, `[]`=不展示 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 买卖点设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `买卖点偏移` | `i64` | `1` | 买卖点与当前K线的最大允许偏移 |
|
|
|
|
|
|
| `买卖点激进识别` | `bool` | `false` | 是否激进识别买卖点 |
|
|
|
|
|
|
| `买卖点与MACD柱强相关` | `bool` | `false` | 买卖点须MACD柱确认 |
|
|
|
|
|
|
| `买卖点错过误差值` | `f64` | `0.01` | 价格误差容忍度 |
|
|
|
|
|
|
| `买卖点_指标模式` | `String` | `"配置"` | 任意/配置/全量/相对 |
|
|
|
|
|
|
| `买卖点_指标匹配_MACD` | `bool` | `true` | MACD柱子匹配确认 |
|
|
|
|
|
|
| `买卖点_指标匹配_KDJ` | `bool` | `true` | KDJ匹配确认 |
|
|
|
|
|
|
| `买卖点_指标匹配_RSI` | `bool` | `true` | RSI匹配确认 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 背驰设置
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `线段内部背驰_MACD` | `bool` | `true` | 使用 MACD 背驰 |
|
|
|
|
|
|
| `线段内部背驰_斜率` | `bool` | `true` | 使用斜率背驰 |
|
|
|
|
|
|
| `线段内部背驰_测度` | `bool` | `true` | 使用测度背驰 |
|
|
|
|
|
|
| `线段内部背驰_模式` | `String` | `"相对"` | 任意/配置/全量/相对 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
#### 文件
|
2026-06-16 12:01:58 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
|
| `加载文件路径` | `String` | `""` | 数据文件路径 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
### 配置方法
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
// JSON 往返
|
2026-06-16 12:01:58 +08:00
|
|
|
|
let json = config.to_json(); // 序列化 → String
|
2026-06-07 13:08:19 +08:00
|
|
|
|
let config2 = 缠论配置::from_json(&json)?; // 反序列化
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// to_dict / from_dict(仅 model_fields 中的字段)
|
|
|
|
|
|
let dict = config.to_dict(); // → serde_json::Value (Object)
|
|
|
|
|
|
let restored = 缠论配置::from_dict(&dict)?; // 过滤非模型字段,缺失回退默认值
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 文件 I/O
|
|
|
|
|
|
config.保存配置("config.json")?;
|
|
|
|
|
|
let loaded = 缠论配置::加载配置("config.json")?;
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 静默模式
|
2026-06-16 12:01:58 +08:00
|
|
|
|
let silent = config.不推送(); // 图表展示 + 线段内部中枢图显 = false
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 差异对比(仅比较 model_fields)
|
|
|
|
|
|
let diffs = config_a.对比(&config_b); // → HashMap<&str, Value> 仅差异字段
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 部分更新
|
|
|
|
|
|
let updated = config.model_copy(&[("标识", "new_id")].into()); // 深拷贝 + 更新
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// 旧版兼容:按序号前缀重组配置字典 ("1_open" → group 1)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
let configs = 缠论配置::按序号重组字典(&default_config, &raw_json);
|
2026-06-16 12:01:58 +08:00
|
|
|
|
// → Vec<(i64, 缠论配置)>
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 非法值容错
|
|
|
|
|
|
|
|
|
|
|
|
三个字符串枚举字段带自定义反序列化器,非法值自动回退默认值并发出 `warn!` 日志:
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 合法值 | 回退默认值 |
|
|
|
|
|
|
|------|--------|-----------|
|
|
|
|
|
|
| `指标计算方式` | 开/高/低/收/高低均值/高低收均值/开高低收均值 | `"收"` |
|
|
|
|
|
|
| `买卖点_指标模式` | 任意/配置/全量/相对 | `"配置"` |
|
|
|
|
|
|
| `线段内部背驰_模式` | 任意/配置/全量/相对 | `"相对"` |
|
|
|
|
|
|
|
2026-05-26 19:06:28 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 算法模块
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 笔划分 (`algorithm::bi`, ~1,009 行)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| 方法 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| `分析()` | 主算法:从分型序列递归分析生成笔 |
|
|
|
|
|
|
| `_获取缠K数量()` | 计算潜在成笔区域的缠K数(含弱化模式放宽) |
|
|
|
|
|
|
| `_实际高点()` / `_实际低点()` | 潜在成笔区域的最高/最低缠K |
|
|
|
|
|
|
| `_获取成笔核心分型()` | 弱化模式下获取次高/次低成笔的候选分型 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| `根据缠K找笔()` | 在笔序列中查找包含指定缠K的笔 |
|
|
|
|
|
|
| `是否背驰过()` | 检查笔范围内是否发生过MACD背驰 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**关键设计**:
|
|
|
|
|
|
- 笔弱化: ≥`笔弱化_原始数量`(默认3)根原始K线即可成笔
|
|
|
|
|
|
- 次级成笔: 次高/次低作为候选终点分型
|
|
|
|
|
|
- 相同终点取舍: false=取first, true=取last (对应 Python `list.index` 行为)
|
|
|
|
|
|
- 笔内验证: 起始分型包含整笔 / 原始K线包含整笔
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 线段划分 (`algorithm::segment`, ~2,078 行)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**最复杂的算法模块**。核心方法:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| 方法 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `分析()` | 主算法:从笔序列计算线段 |
|
|
|
|
|
|
| `扩展分析()` | 扩展线段分析(不同的缺口处理策略) |
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| `分割序列()` | 将特征序列分割为前/后/三/贯穿伤四个子序列 |
|
|
|
|
|
|
| `四象()` | 判断特征序列类型: 老阳/老阴/小阳/少阴 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| `获取缺口()` | 获取特征序列第一二元素间的缺口 |
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| `判断线段内部是否背驰()` | 进入段 vs 离开段背驰判断 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| `是否背驰过()` | 线段范围内是否发生过背驰 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**四种修正机制**(按优先级):
|
|
|
|
|
|
1. **`_缺口突破`** — 老阳/老阴状态 + 价格突破前线段极值 → 线段完成
|
|
|
|
|
|
2. **`_非缺口下穿刺`** — 贯穿伤存在 + 方向相同的3笔 → 线段完成
|
|
|
|
|
|
3. **`_缺口后紧急修正`** — 前一线段有缺口 + 价格反向突破 → 修正结束位置
|
|
|
|
|
|
4. **`_修正`** — 短线路径 (≥9笔) → 快速完成
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**3 级递归**: `线段` → `线段<线段>` → `线段<线段<线段>>`,每一级将前级结果作为基础序列。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 中枢识别 (`algorithm::hub`, ~1,041 行)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
| 方法 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `分析()` | 主算法:虚线→中枢,同时识别第三买卖点 |
|
|
|
|
|
|
| `线段扩展分析()` | 中枢扩展:≥9段时生成扩展中枢 |
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| `高()` / `低()` | 前三根虚线重叠区域 |
|
|
|
|
|
|
| `获取离开虚线()` | 找到离开中枢的虚线(确立第三买卖点) |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
| `获取第N买卖线()` | 获取第N个买卖点相关的虚线 |
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**识别流程**:
|
|
|
|
|
|
1. 基础检查: 三条连续虚线重叠且方向关系正确
|
|
|
|
|
|
2. 中枢延伸: 后继虚线未离开则加入基础序列
|
|
|
|
|
|
3. 第三买卖点: 虚线离开中枢且不回 → 记录 `第三买卖线`
|
|
|
|
|
|
4. 中枢完成: `第三买卖线` 确立后在上方开始新中枢
|
|
|
|
|
|
5. 多级中枢: 笔中枢(级别=1) / 线段中枢(级别=2) / 扩展线段中枢 等
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 背驰检测 (`algorithm::divergence`, ~227 行)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
三种检测方式:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 方式 | 原理 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|------|------|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| MACD 背驰 | 进入段 vs 离开段的 MACD 柱面积对比 (阳 + |阴| 绝对值和) |
|
|
|
|
|
|
| 斜率背驰 | 价格变化速率 (dy/dx) 减弱 |
|
|
|
|
|
|
| 测度背驰 | 价格-时间向量长度 (√(dx²+dy²)) 缩减 |
|
|
|
|
|
|
|
|
|
|
|
|
四种组合模式: `全量`(全满足) / `任意`(任意满足) / `配置`(按开关) / `相对`(多数投票)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 技术指标
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 统一容器 (`indicators::container`)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
注册表模式,通过 `指标值` 枚举统一管理:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
2026-06-07 13:08:19 +08:00
|
|
|
|
pub enum 指标值 {
|
|
|
|
|
|
MACD(平滑异同移动平均线),
|
|
|
|
|
|
RSI(相对强弱指数),
|
|
|
|
|
|
KDJ(随机指标),
|
|
|
|
|
|
BOLL(布林带),
|
|
|
|
|
|
均线(HashMap<String, f64>),
|
|
|
|
|
|
单值(HashMap<String, f64>),
|
2026-05-26 19:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- 预注册槽位: `macd`, `rsi`, `kdj`, `boll`, `均线`, `单值`
|
|
|
|
|
|
- 支持多参数变体: `MACD_13_31_11`, `RSI_14`, `KDJ_9_3_3` 等
|
|
|
|
|
|
- 动态注册: `注册(name, default)` / `设置(name, value)` / `获取(name)`
|
|
|
|
|
|
- K线取值 7 种方式: 开/高/低/收/高低均值/高低收均值/开高低收均值
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 指标计算器 (`indicators::calculator`, ~476 行)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`计算并挂载(全序列, 配置)` 单次周期:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
1. MACD组 → RSI组 → KDJ组 → BOLL组 → 均线组
|
|
|
|
|
|
2. 首次计算 vs 增量计算自动判定(基于前序K线是否有值)
|
|
|
|
|
|
3. 回填新指标:回溯填充前序K线遗漏的指标
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 各指标结构
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**MACD** — EMA(12/26/9) 默认
|
|
|
|
|
|
```
|
|
|
|
|
|
DIF: Option<f64>, DEA: Option<f64>, MACD柱: f64
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**RSI** — Wilder SMA 平滑
|
|
|
|
|
|
```
|
|
|
|
|
|
RSI: Option<f64>, RSI_SMA: Option<f64>, 超买/超卖阈值
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**KDJ** — RSV → K → D → J
|
|
|
|
|
|
```
|
|
|
|
|
|
K: Option<f64>, D: Option<f64>, J: Option<f64>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**BOLL** — SMA ± k·σ
|
|
|
|
|
|
```
|
|
|
|
|
|
中轨: Option<f64>, 上轨: Option<f64>, 下轨: Option<f64>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 信号框架
|
|
|
|
|
|
|
|
|
|
|
|
信号框架是缠论分析的上层应用——在已有笔/线段/中枢的基础上,通过**声明式规则匹配**产生交易信号,驱动**仓位状态机**进行多空操作。
|
|
|
|
|
|
|
|
|
|
|
|
### 信号原语
|
|
|
|
|
|
|
|
|
|
|
|
信号框架的 5 种原语(源自 czsc,Apache-2.0,已做中文命名适配与 Rust 重写):
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-06-16 12:01:58 +08:00
|
|
|
|
Signal → Factor → Event → Position (含 Operate)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Signal — 七段键信号
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
pub struct Signal {
|
|
|
|
|
|
pub k1: String, // 级别 (freq) e.g. "日线"
|
|
|
|
|
|
pub k2: String, // 信号分组 e.g. "D1MO3"
|
|
|
|
|
|
pub k3: String, // 信号名 e.g. "中枢第三买卖点V230602"
|
|
|
|
|
|
pub v1: String, // 品种 e.g. "三买"
|
|
|
|
|
|
pub v2: String, // 标记 e.g. "中枢段DEA穿越2"
|
|
|
|
|
|
pub v3: String, // 描述 e.g. "偏移3"
|
|
|
|
|
|
pub score: i32, // 0~100
|
2026-05-26 19:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- `key()` → `"k1_k2_k3"` (三段键,用于去重/查询)
|
|
|
|
|
|
- `value()` → `"v1_v2_v3"` (三段值)
|
|
|
|
|
|
- `is_match(signals: &信号字典)` → 三态: 命中→`Ok(true)`, 不匹配→`Ok(false)`, 缺键→`Err(缺键错误)`
|
|
|
|
|
|
- `空信号` → value=`"任意_任意_任意_0"`, score=0
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### Factor — 因子 = 多信号 all/not 组合
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
```rust
|
|
|
|
|
|
pub struct Factor {
|
|
|
|
|
|
pub name: String, // SHA256前4 + 自定义后缀,确定性
|
|
|
|
|
|
pub signals_all: Vec<Signal>, // 必须全部命中
|
|
|
|
|
|
pub signals_not: Vec<Signal>, // 必须全部不命中
|
2026-05-26 19:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`is_match(signals)` → 先检查全部 `signals_all` 命中, 再检查全部 `signals_not` 不命中。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`name` 使用 sha256 前 4 位十六进制,确保 Rust 与 Python 计算**确定性**相同(注意:不保证跨语言字节兼容,但同语言内一致)。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### Event — 事件 = 因子组 + 操作
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
pub struct Event {
|
|
|
|
|
|
pub name: String,
|
|
|
|
|
|
pub operate: Operate, // 匹配时执行的操作
|
|
|
|
|
|
pub factors: Vec<Factor>,
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`is_match(signals)` → 任一因子命中则为 true(OR 逻辑)。
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
#### Operate — 操作枚举
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
```rust
|
|
|
|
|
|
pub enum Operate {
|
|
|
|
|
|
开多, // LO — Long Open
|
|
|
|
|
|
平多, // LE — Long Exit
|
|
|
|
|
|
开空, // SO — Short Open
|
|
|
|
|
|
平空, // SE — Short Exit
|
|
|
|
|
|
持币, // HO — Hold (无操作)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
实现 `Ord` (LO < SO < LE < SE < HO), `Display` 中文输出。
|
|
|
|
|
|
|
|
|
|
|
|
#### Position — 仓位状态机
|
|
|
|
|
|
|
|
|
|
|
|
Position 是信号框架的最终消费者——将 Event 匹配结果转化为实际的仓位操作:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
pub struct Position {
|
|
|
|
|
|
// 配置字段
|
|
|
|
|
|
pub symbol: String,
|
|
|
|
|
|
pub opens: Vec<Event>, // 开仓事件
|
|
|
|
|
|
pub exits: Vec<Event>, // 平仓事件
|
|
|
|
|
|
pub events: Vec<Event>, // 通用事件(先于 opens/exits 匹配)
|
|
|
|
|
|
pub interval: i64, // 开仓间隔(秒),0=不限制
|
|
|
|
|
|
pub timeout: i64, // 持仓超时(K线数)
|
|
|
|
|
|
pub stop_loss: i64, // 止损阈值(BP,1/10000)
|
|
|
|
|
|
pub T0: bool, // T+0 模式
|
|
|
|
|
|
|
|
|
|
|
|
// 状态字段
|
|
|
|
|
|
pub pos: i32, // 1=多, -1=空, 0=空仓
|
|
|
|
|
|
pub pos_changed: bool, // 本轮是否发生仓位变化
|
|
|
|
|
|
pub operates: Vec<操作记录>, // 操作历史
|
|
|
|
|
|
pub holds: Vec<持仓记录>, // 持仓快照序列
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**`update(dt, price, bid, signals)` 状态机**(~200 行 Rust,与 Python 1:1 对应):
|
|
|
|
|
|
|
|
|
|
|
|
1. 时间校验: `dt <= end_dt` → 跳过(信号时间倒退)
|
|
|
|
|
|
2. 事件匹配: 遍历 `events` → `is_match(signals)` → 首个命中即break
|
|
|
|
|
|
3. **开多** (LO): pos≠1 且间隔检查通过 → pos=1; 若 pos=-1 且允许平仓 → pos=0 先平空
|
|
|
|
|
|
4. **平多** (LE): pos=1 且允许操作 → pos=0
|
|
|
|
|
|
5. **开空** (SO): 对称
|
|
|
|
|
|
6. **平空** (SE): 对称
|
|
|
|
|
|
7. **止损检查**: 多头→`price/last_price-1 < -stop_loss/10000`; 空头→`1-price/last_price < -stop_loss/10000`
|
|
|
|
|
|
8. **超时检查**: `bid - last_bid > timeout`
|
|
|
|
|
|
9. 追加持仓快照 `{dt, pos, price}`
|
|
|
|
|
|
|
|
|
|
|
|
**`pairs()` 盈亏计算** — 从 `operates` 中配对开平操作,计算每对的 BP(基点)盈亏:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
多头盈亏 = (平仓价/开仓价 - 1) * 10000
|
|
|
|
|
|
空头盈亏 = (1 - 平仓价/开仓价) * 10000
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**辅助判断**:
|
|
|
|
|
|
- `同一交易日(a, b)` — chrono 日期比较
|
|
|
|
|
|
- `间隔检查(last_dt, dt, interval)` — 距上次开仓是否超过 interval 秒
|
|
|
|
|
|
- `允许操作(T0, dt, last_dt)` — T+0 或不同交易日
|
|
|
|
|
|
|
|
|
|
|
|
### 信号注册表 (`signal::registry`)
|
|
|
|
|
|
|
|
|
|
|
|
双注册表架构,支持**编译时注册**和**运行时动态注册**:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌──────────────────────────────────────┐
|
|
|
|
|
|
│ 获取信号 │
|
|
|
|
|
|
│ get_signal(name) │
|
|
|
|
|
|
│ ├─ 1. 检查 SIGNAL_REGISTRY │ ← LazyLock<HashMap> (编译时, #[signal] 宏)
|
|
|
|
|
|
│ └─ 2. 检查 DYNAMIC_REGISTRY │ ← RwLock<HashMap> (运行时, 动态注册)
|
|
|
|
|
|
└──────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**编译时注册** — `#[signal]` 属性宏:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun_signal_macros::signal;
|
|
|
|
|
|
|
|
|
|
|
|
#[signal(
|
|
|
|
|
|
name = "my_custom_signal_V230101",
|
|
|
|
|
|
template = "{freq}_D1MO{max_overlap}_my_custom_signalV230101"
|
|
|
|
|
|
)]
|
|
|
|
|
|
fn my_custom_signal(obs: &观察者, params: &HashMap<String, Value>) -> Vec<Signal> {
|
|
|
|
|
|
// 信号逻辑...
|
|
|
|
|
|
vec![Signal::new("日线", "D1", "my_signalV230101", "三买", "", "", 80)]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
宏在编译期生成 `SignalDescriptor { name, template, func }` 并通过 `inventory::submit!` 注册。
|
|
|
|
|
|
|
|
|
|
|
|
**动态注册** — 运行时 API:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun::signal::registry::{register_signal, unregister_signal, list_signal_names};
|
|
|
|
|
|
|
|
|
|
|
|
// 注册
|
|
|
|
|
|
register_signal(
|
|
|
|
|
|
"my_signal_V230101",
|
|
|
|
|
|
"{freq}_templateV230101",
|
|
|
|
|
|
my_signal_fn, // SignalFn
|
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
// 注销
|
|
|
|
|
|
unregister_signal("my_signal_V230101")?;
|
|
|
|
|
|
|
|
|
|
|
|
// 列出所有已注册信号(编译时 + 动态)
|
|
|
|
|
|
let names: Vec<String> = list_signal_names();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**约束**: 动态注册不能覆盖编译时信号(返回 Err);同名动态信号重复注册也报错。
|
|
|
|
|
|
|
|
|
|
|
|
### 信号引擎 (`signal::engine`)
|
|
|
|
|
|
|
|
|
|
|
|
`SignalEngine` 批量执行已注册的信号函数:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
pub struct SignalEngine {
|
|
|
|
|
|
configs: Vec<SignalConfig>, // [{signal_name, freq, params}]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `自动挂载指标(分析器)` — 扫描所有 config 中的 MACD/均线关键词,为各周期 observer 自动添加所需指标参数
|
|
|
|
|
|
- `更新(分析器)` → `HashMap<String, String>` — 遍历配置,按 freq 聚合,调用注册表函数,过滤空信号
|
|
|
|
|
|
- `更新_完整(分析器)` → `完整更新结果 { signals, market }` — 附加基础周期的 OHLCV 行情数据
|
|
|
|
|
|
|
|
|
|
|
|
### 已实现的信号函数
|
|
|
|
|
|
|
|
|
|
|
|
| 信号名 | 来源 | 功能 |
|
|
|
|
|
|
|--------|------|------|
|
|
|
|
|
|
| `youwukuncheng_中枢第三买卖点_V230602` | `functions/youwukuncheng.rs` | 中枢第三买卖点 (3种变体: DEA穿越/首次穿越0轴+分型确认) |
|
|
|
|
|
|
| `bar_zdt_V230331` | `functions/demo.rs` | 涨跌停检测 |
|
|
|
|
|
|
| `macd_金叉_V260601` | `functions/demo.rs` | MACD 金叉/死叉 |
|
|
|
|
|
|
| `tas_macd_direct_V221106` | `functions/demo.rs` | MACD DIF 方向 |
|
|
|
|
|
|
| `tas_ma_base_V230313` | `functions/demo.rs` | MA 均线多空 (SMA/EMA) |
|
|
|
|
|
|
| `cxt_停顿分型_V230106` | `functions/demo.rs` | 停顿分型检测 |
|
|
|
|
|
|
| `cxt_bi_end_V230222` | `functions/demo.rs` | 笔结束辅助 (~90行) |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 插件系统
|
|
|
|
|
|
|
|
|
|
|
|
支持通过 `.so` 动态库在运行时加载第三方 Rust 信号函数。
|
|
|
|
|
|
|
|
|
|
|
|
### C-ABI 导出 (`signal::ffi`)
|
|
|
|
|
|
|
|
|
|
|
|
宿主进程导出三个 C-ABI 函数供 `.so` 插件调用:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
// 注册信号 → 0=成功, 非0=失败
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
|
pub unsafe extern "C" fn chanlun_register_signal(
|
|
|
|
|
|
name: *const c_char, template: *const c_char, func: SignalFn,
|
|
|
|
|
|
) -> i32;
|
|
|
|
|
|
|
|
|
|
|
|
// 注销信号
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
|
pub unsafe extern "C" fn chanlun_unregister_signal(name: *const c_char) -> i32;
|
|
|
|
|
|
|
|
|
|
|
|
// 查询信号总数
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
|
pub unsafe extern "C" fn chanlun_list_signal_count() -> i32;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 插件编写
|
|
|
|
|
|
|
|
|
|
|
|
**方式 A: 手动注册** — 在插件的构造函数中直接调用 `chanlun_register_signal`:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
|
pub unsafe extern "C" fn init_plugin() -> i32 {
|
|
|
|
|
|
chanlun_register_signal(
|
|
|
|
|
|
"my_signal\0".as_ptr() as *const c_char,
|
|
|
|
|
|
"template\0".as_ptr() as *const c_char,
|
|
|
|
|
|
my_signal_fn,
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**方式 B: `#[signal]` 宏** — 使用 `crate_path = "::chanlun"` 参数在外部 crate 中使用宏注册:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
use chanlun_signal_macros::signal;
|
|
|
|
|
|
|
|
|
|
|
|
#[signal(
|
|
|
|
|
|
name = "plugin_signal_V230101",
|
|
|
|
|
|
template = "{freq}_pluginV230101",
|
|
|
|
|
|
crate_path = "::chanlun" // 关键:外部 crate 需指定路径
|
|
|
|
|
|
)]
|
|
|
|
|
|
fn plugin_signal(obs: &观察者, params: &HashMap<String, Value>) -> Vec<Signal> {
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
然后在 `init_plugin()` 中遍历 `inventory::iter::<SignalDescriptor>` 批量提交。
|
|
|
|
|
|
|
|
|
|
|
|
### Python 端加载
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
import ctypes, os
|
|
|
|
|
|
|
|
|
|
|
|
# 设置全局符号可见性
|
|
|
|
|
|
sys.setdlopenflags(os.RTLD_LAZY | os.RTLD_GLOBAL)
|
|
|
|
|
|
|
|
|
|
|
|
# 加载插件
|
|
|
|
|
|
plugin = ctypes.CDLL("./libmy_plugin.so")
|
|
|
|
|
|
plugin.init_plugin() # 内部调用 chanlun_register_signal
|
|
|
|
|
|
|
|
|
|
|
|
# 此后可通过 call_signal 或 SignalEngine 使用插件信号
|
|
|
|
|
|
from chanlun._chanlun import call_signal, list_signals
|
|
|
|
|
|
print(list_signals()) # 包含插件注册的信号
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**约束**: 插件和宿主必须用**相同 Rust 编译器版本**编译,因为 `SignalFn` 使用 Rust 调用约定。
|
|
|
|
|
|
|
2026-06-07 13:08:19 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 线程安全与并发
|
|
|
|
|
|
|
|
|
|
|
|
### 内部可变性策略
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 机制 | 底层 | 适用场景 |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|------|------|---------|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| `SyncF64` | `AtomicU64` 位转换 | 价格字段 (高/低/分型特征值) |
|
|
|
|
|
|
| `AtomicI64` | `AtomicI64` | 序号/时间戳 |
|
|
|
|
|
|
| `AtomicBool` | `AtomicBool` | 有效性/短路修正/开关 |
|
|
|
|
|
|
| `RwLock<T>` | `parking_lot::RwLock` | 复杂数据 (Arc<分型>/Vec/中枢序列) |
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### Send + Sync
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
所有核心数据结构(`缠论K线`, `虚线`, `中枢`, `观察者`)均实现 `Send + Sync`,可安全跨线程:
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
// 编译期断言
|
2026-06-16 12:01:58 +08:00
|
|
|
|
fn _要求_Send_Sync<T: Send + Sync>() {}
|
|
|
|
|
|
_要求_Send_Sync::<缠论K线>();
|
|
|
|
|
|
_要求_Send_Sync::<虚线>();
|
|
|
|
|
|
_要求_Send_Sync::<中枢>();
|
|
|
|
|
|
_要求_Send_Sync::<观察者>();
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
`观察者` 使用 `Arc<RwLock<观察者>>` 模式——多线程并发读取同一观察者。
|
|
|
|
|
|
|
|
|
|
|
|
### 全局缓存
|
|
|
|
|
|
|
|
|
|
|
|
- **买卖意义缓存**: `LazyLock<Mutex<LruCache<(usize, usize), (bool, String)>>>` — 128 条目
|
|
|
|
|
|
- Python 端使用 `@lru_cache` 装饰器,Rust 使用 `LazyLock<DashMap>`(替代 `thread_local!` 解决跨线程不可见问题)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
### RwLock 死锁预防
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
Rust `RwLock` 是**非递归锁**——在持读锁时尝试获取写锁会死锁。解决:将读锁作用域化,在所有写锁调用前释放:
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
{ let prev_guard = 前序K线.指标.read(); /* 读取 */ }
|
|
|
|
|
|
// ↑ 作用域结束 → 释放读锁
|
|
|
|
|
|
Self::_回填新指标(...); // 安全:此时无读锁
|
|
|
|
|
|
```
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Python 绑定
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
通过 [`chanlun-py`](../chanlun-py/) crate(PyO3)将 Rust 核心导出为 Python `chanlun` 模块。
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd chanlun-py
|
2026-06-07 13:08:19 +08:00
|
|
|
|
maturin develop --release
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
import chanlun
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
# 配置
|
2026-05-26 19:06:28 +08:00
|
|
|
|
config = chanlun.缠论配置()
|
|
|
|
|
|
config.笔内元素数量 = 7
|
2026-06-16 12:01:58 +08:00
|
|
|
|
config.MACD_参数列表 = [("my_macd", "收", 12, 26, 9)]
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
# 观察者
|
2026-05-26 19:06:28 +08:00
|
|
|
|
obs = chanlun.观察者("BTCUSD", 3600, config)
|
|
|
|
|
|
obs.增加原始K线(k)
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
# 多周期分析器
|
|
|
|
|
|
analyzer = chanlun.立体分析器("BTCUSD", [60, 300, 1800], config, None)
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
# 信号计算
|
|
|
|
|
|
from chanlun._chanlun import 信号引擎, call_signal, list_signals
|
|
|
|
|
|
|
|
|
|
|
|
引擎 = 信号引擎([
|
|
|
|
|
|
{"name": "youwukuncheng_中枢第三买卖点_V230602",
|
|
|
|
|
|
"freq": 86400, "max_overlap": 3,
|
|
|
|
|
|
"本级完整性": "实", "同级完整性": "合"},
|
|
|
|
|
|
])
|
|
|
|
|
|
引擎.自动挂载指标(analyzer)
|
|
|
|
|
|
result = 引擎.更新_完整(analyzer) # → {"signals": {...}, "market": {...}}
|
|
|
|
|
|
|
|
|
|
|
|
# 单独调用信号
|
|
|
|
|
|
signals = call_signal("macd_金叉_V260601", obs, {"freq": "日线"})
|
|
|
|
|
|
|
|
|
|
|
|
# 查询注册表
|
|
|
|
|
|
print(list_signals()) # → ["youwukuncheng_...", "macd_金叉_...", ...]
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### 导出类映射
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| Rust 类型 | Python 类 | 说明 |
|
|
|
|
|
|
|-----------|----------|------|
|
|
|
|
|
|
| `缠论配置` | `chanlun.缠论配置` | 配置管理 |
|
|
|
|
|
|
| `K线` | `chanlun.K线` | 原始 K 线 |
|
|
|
|
|
|
| `缠论K线` | `chanlun.缠论K线` | 缠论 K 线 |
|
|
|
|
|
|
| `分型` | `chanlun.分型` | 顶底分型 |
|
|
|
|
|
|
| `虚线` | `chanlun.虚线` | 笔/线段 |
|
|
|
|
|
|
| `线段特征` | `chanlun.线段特征` | 特征序列元素 |
|
|
|
|
|
|
| `中枢` | `chanlun.中枢` | 中枢 |
|
|
|
|
|
|
| `基础买卖点` | `chanlun.基础买卖点` | 买卖点 |
|
|
|
|
|
|
| `观察者` | `chanlun.观察者` | 单周期分析器 |
|
|
|
|
|
|
| `立体分析器` | `chanlun.立体分析器` | 多周期分析器 |
|
|
|
|
|
|
| `Signal` | `chanlun._chanlun.Signal` | 信号 |
|
|
|
|
|
|
| `Factor` | `chanlun._chanlun.Factor` | 因子 |
|
|
|
|
|
|
| `Event` | `chanlun._chanlun.Event` | 事件 |
|
|
|
|
|
|
| `Position` | `chanlun._chanlun.Position` | 仓位状态机 |
|
|
|
|
|
|
| `Operate` | `chanlun._chanlun.Operate` | 操作枚举 |
|
|
|
|
|
|
| `信号引擎` | `chanlun._chanlun.信号引擎` | 信号计算引擎 |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 数据序列化
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### K线二进制格式 (.nb 文件)
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
与 Python `struct.pack(">6d")` 完全兼容,每根 K 线 **48 字节**:
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
| 偏移 | 大小 | 字段 | 字节序 |
|
|
|
|
|
|
|------|------|------|--------|
|
|
|
|
|
|
| 0 | 8 B | 时间戳 (Unix秒 as f64) | Big Endian |
|
|
|
|
|
|
| 8 | 8 B | 开盘价 | Big Endian |
|
|
|
|
|
|
| 16 | 8 B | 最高价 | Big Endian |
|
|
|
|
|
|
| 24 | 8 B | 最低价 | Big Endian |
|
|
|
|
|
|
| 32 | 8 B | 收盘价 | Big Endian |
|
|
|
|
|
|
| 40 | 8 B | 成交量 | Big Endian |
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
```rust
|
2026-06-07 13:08:19 +08:00
|
|
|
|
let bytes: [u8; 48] = k线.to_bytes();
|
2026-06-16 12:01:58 +08:00
|
|
|
|
let k线 = K线::读取大端字节数组(&bytes, 周期, 标识)?;
|
2026-06-07 13:08:19 +08:00
|
|
|
|
K线::保存到DAT文件("output.dat", &[&k1, &k2])?;
|
2026-05-26 19:06:28 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 配置 JSON
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"标识": "BTCUSD",
|
|
|
|
|
|
"笔内元素数量": 5,
|
2026-06-16 12:01:58 +08:00
|
|
|
|
"MACD_参数列表": [["macd", "收", 13, 31, 11]],
|
2026-06-07 13:08:19 +08:00
|
|
|
|
"买卖点_指标模式": "配置",
|
|
|
|
|
|
"线段内部背驰_模式": "相对"
|
2026-05-26 19:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- `#[serde(default)]` → 前向/后向兼容,缺失字段自动回退默认值
|
|
|
|
|
|
- `from_dict()` 自动过滤非 `model_fields` 字段
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
### 结构化相等校验
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
所有核心结构体实现 `相等(&self, other, 浮点容差) → (bool, String)`:
|
|
|
|
|
|
- 浮点字段容差比较(非直接 `==`)
|
|
|
|
|
|
- `Arc` 共享结构深度校验值语义
|
|
|
|
|
|
- 嵌套容器 (Vec/Option/HashMap) 逐一比对
|
|
|
|
|
|
- 返回详细差异描述
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 测试
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### Rust 核心测试
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-16 12:01:58 +08:00
|
|
|
|
cd chanlun
|
|
|
|
|
|
cargo test # 199 项测试
|
|
|
|
|
|
cargo test -- test_50线程 # 匹配模式的测试
|
|
|
|
|
|
cargo clippy # 零警告
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
**测试覆盖**:
|
|
|
|
|
|
- **配置**: 默认值 / JSON 往返 / 部分反序列化 / 非法值回退 / 不推送 / 差异对比
|
|
|
|
|
|
- **K线**: 方向判定 / 大端序列化往返
|
|
|
|
|
|
- **缠K**: 创建/包含合并/分型识别
|
|
|
|
|
|
- **笔**: 基本分析 / 弱化 / 次级成笔 / 实际高低点
|
|
|
|
|
|
- **线段**: 四种象 / 缺口 / 分割序列 / 特征序列状态
|
|
|
|
|
|
- **中枢**: 字段读写 / Clone 后指针一致 / 延伸/扩展 / 第三买卖点
|
|
|
|
|
|
- **买卖点**: 18 种类型生成 / 偏移/失效/有效性
|
|
|
|
|
|
- **指标**: MACD/RSI/KDJ/BOLL 首次+增量计算
|
|
|
|
|
|
- **观察者**: 指针一致性 / 重复计算确定性 / 重置后一致 / RefCell 安全 / 跨线程 Send/Sync
|
|
|
|
|
|
- **Position**: 28 项单元测试 — LO/SO/LE/SE 转换 / 止损/超时/间隔 / 盈亏计算
|
|
|
|
|
|
- **Registry**: 编译时/动态注册 / 归并/注销 / 冲突报错 / #[signal] 宏端到端
|
|
|
|
|
|
- **并发**: 50 线程 10,000 K线压测
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
### Python 集成测试
|
2026-06-07 13:08:19 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-16 12:01:58 +08:00
|
|
|
|
cd chanlun-py
|
|
|
|
|
|
python -m pytest tests/test_all.py -v # 107+ 项
|
|
|
|
|
|
python -m pytest tests/test_signal_primitives.py -v
|
|
|
|
|
|
python -m pytest tests/test_position_update.py -v # 24 项
|
2026-06-07 13:08:19 +08:00
|
|
|
|
```
|
2026-05-26 19:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 许可
|
|
|
|
|
|
|
|
|
|
|
|
MIT License. 详见 [LICENSE](LICENSE).
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 相关项目
|
|
|
|
|
|
|
2026-06-16 12:01:58 +08:00
|
|
|
|
- [`chan.py`](../chan.py) — Python 参考实现(~4,200 行),作为跨校验基准
|
|
|
|
|
|
- [`chanlun-py`](../chanlun-py/) — PyO3 绑定,发布为 `chanlun` PyPI 包
|
|
|
|
|
|
- [`chanlun-signal-macros`](../chanlun-signal-macros/) — `#[signal]` 属性宏 proc-macro crate
|
|
|
|
|
|
- [`main.py`](../main.py) — FastAPI Web 应用(WebSocket 实时图表 + 回测)
|
|
|
|
|
|
- [`strategies.py`](../strategies.py) — 回测策略定义(Backtrader 集成)
|
|
|
|
|
|
- [`examples/plugin-demo`](../examples/plugin-demo/) — .so 动态插件示例(两种注册方式)
|