976 lines
37 KiB
Markdown
976 lines
37 KiB
Markdown
# chan.py — 缠论技术分析库 AI 技能
|
||
|
||
> 约 6900 行 Python,从原始 K 线到买卖点的全链路流式缠论分析。所有标识符使用中文。
|
||
|
||
---
|
||
|
||
## Q1: 如何从 .nb 文件加载数据并完成分析?
|
||
|
||
```python
|
||
from chanlun import chan
|
||
|
||
config = chan.缠论配置(标识="btcusd")
|
||
obs = chan.观察者.读取数据文件("btcusd-300-xxx.nb", 配置=config)
|
||
|
||
# 加载即完成全部分析,直接读取结果
|
||
obs.笔序列 # List[虚线],标识="笔"
|
||
obs.线段序列 # List[虚线],标识="线段"
|
||
obs.中枢序列 # List[中枢],标识="线段中枢"
|
||
obs.笔_中枢序列 # List[中枢],标识="笔中枢"
|
||
obs.分型序列 # List[分型]
|
||
obs.缠论K线序列 # List[缠论K线]
|
||
|
||
# 高级层级
|
||
obs.扩展线段序列 # 标识="扩展线段"
|
||
obs.扩展中枢序列 # 标识="扩展线段中枢"
|
||
obs.线段_线段序列 # 线段作为笔再划分
|
||
obs.扩展线段序列_扩展线段 # 扩展线段作为笔再划分
|
||
```
|
||
|
||
`.nb` 文件格式:每根 K 线 48 字节大端 `struct.pack(">6d")`,依次为 时间戳/开/高/低/收/量(均为 float64)。
|
||
|
||
---
|
||
|
||
## Q2: 如何流式实时分析?
|
||
|
||
```python
|
||
obs = chan.观察者(符号="btcusd", 周期=300, 配置=config)
|
||
|
||
# 方式一:投喂原始数据
|
||
obs.投喂原始数据(时间戳=datetime.now(), 开=50000, 高=50100, 低=49900, 收=50050, 量=100)
|
||
|
||
# 方式二:投喂预构建 K 线对象
|
||
obs.增加原始K线(k线对象)
|
||
|
||
# 每次投喂都增量更新全链路:缠K → 分型 → 笔 → 线段 → 中枢
|
||
# 结果即刻可用
|
||
```
|
||
|
||
---
|
||
|
||
## Q3: 如何做多周期立体分析?
|
||
|
||
```python
|
||
ma = chan.立体分析器(
|
||
符号="btcusd",
|
||
周期组=[300, 1800], # [输入周期, 显示周期]
|
||
配置=config,
|
||
配置组={1800: chan.缠论配置(笔内元素数量=7)}, # 可选:按周期覆盖配置
|
||
)
|
||
|
||
# 只投喂最小周期 K 线,合成器自动合成大周期
|
||
for kline in klines_300:
|
||
ma.投喂K线(kline)
|
||
|
||
# 获取各周期结果
|
||
obs_300 = ma._单体分析器[300]
|
||
obs_1800 = ma._单体分析器[1800]
|
||
```
|
||
|
||
内部机制:
|
||
- 内置 `K线合成器` 将小周期 K 线合成为大周期
|
||
- 合成器事件回调 → 大周期 K 线完成 → 触发对应 `观察者.__处理数据`
|
||
- 非显示周期的 `基础缠K序列` 引用显示周期的 `缠论K线序列`
|
||
|
||
---
|
||
|
||
## Q4: 如何单独使用 K 线合成器?
|
||
|
||
```python
|
||
def 回调(信号类型, 标识, 周期, 完成K线):
|
||
"""信号类型: "K线完成" """
|
||
print(f"{标识} {周期}s 完成一根K线: {完成K线.收盘价}")
|
||
|
||
synth = chan.K线合成器(标识="btcusd", 周期组=[300, 900, 1800], 事件回调=回调)
|
||
|
||
# 投喂最小周期数据
|
||
synth.投喂(时间戳, 开, 高, 低, 收, 量)
|
||
# 或
|
||
synth.投喂K线(普K)
|
||
|
||
# 查询当前合成中的 K 线
|
||
k = synth.获取当前K线(周期=900)
|
||
|
||
# 支持后续设置回调
|
||
synth.设置事件回调(新回调函数)
|
||
```
|
||
|
||
合成器按 `(时间戳 // 周期) * 周期` 对齐时间戳到周期边界。
|
||
|
||
---
|
||
|
||
## Q5: 缠论配置有哪些关键参数?
|
||
|
||
```python
|
||
config = chan.缠论配置(
|
||
标识="btcusd",
|
||
|
||
# ---- 分析开关(按需关闭以跳过某层级)----
|
||
分析笔=True, # 是否分析笔
|
||
分析线段=True, # 是否分析线段
|
||
分析扩展线段=True, # 是否分析扩展线段
|
||
分析笔中枢=True, # 是否分析笔中枢
|
||
分析线段中枢=True, # 是否分析线段中枢
|
||
计算指标=True, # 是否计算技术指标
|
||
|
||
# ---- 笔参数(影响笔划分粒度)----
|
||
笔内元素数量=5, # 笔内最少缠K数(含端点)
|
||
笔内相同终点取舍=False, # True=取最后, False=取第一个
|
||
笔内起始分型包含整笔=False,
|
||
笔弱化=False, # 笔弱化开关
|
||
笔弱化_原始数量=3, # 弱化参考原始K线数量
|
||
笔次级成笔=False, # 次级成笔
|
||
|
||
# ---- 线段参数 ----
|
||
线段_非缺口下穿刺=False, # 非缺口状态的贯穿伤回退
|
||
线段_特征序列忽视老阴老阳=False, # True=忽视缺口全以无缺口对待
|
||
线段_缺口后紧急修正=True, # 缺口后紧急修正
|
||
线段_修正=False, # 短路修正(不建议使用)
|
||
线段内部中枢图显=True, # 显示线段内部中枢
|
||
扩展线段_当下分析=False, # True=以当下分析, False=以事后分析
|
||
|
||
# ---- 指标参数 ----
|
||
指标计算方式="收", # "开"/"高"/"低"/"收"/"高低均值"/"高低收均值"/"开高低收均值"
|
||
平滑异同移动平均线_快线周期=13,
|
||
平滑异同移动平均线_慢线周期=31,
|
||
平滑异同移动平均线_信号周期=11,
|
||
相对强弱指数_周期=13,
|
||
相对强弱指数_超买阈值=75,
|
||
相对强弱指数_超卖阈值=25,
|
||
随机指标_RSV周期=13,
|
||
随机指标_K值平滑周期=5,
|
||
随机指标_D值平滑周期=5,
|
||
随机指标_超买阈值=80,
|
||
随机指标_超卖阈值=20,
|
||
计算BOLL=False, # 是否计算布林带
|
||
布林带_周期=20,
|
||
布林带_标准差倍数=2.0,
|
||
|
||
# ---- 多指标参数列表 ----
|
||
MACD_参数列表=[], # [(key, 快线, 慢线, 信号), ...]
|
||
RSI_周期列表=[], # [(key, 周期), ...]
|
||
KDJ_参数列表=[], # [(key, RSV周期, K平滑, D平滑), ...]
|
||
BOLL_参数列表=[], # [(key, 周期, 标准差倍数), ...]
|
||
均线_类型列表=[], # SMA/EMA 类型列表
|
||
均线_周期列表=[], # 对应周期列表
|
||
|
||
# ---- 买卖点 ----
|
||
买卖点偏移=1, # 最大偏移量
|
||
买卖点激进识别=False, # 激进模式不检查分型完整性
|
||
买卖点与MACD柱强相关=False, # True=卖点需正值 买点需负值
|
||
买卖点错过误差值=0.01, # 距离买卖点值的容差
|
||
买卖点_指标模式="配置", # "任意"/"配置"/"全量"/"相对"
|
||
买卖点_指标匹配_MACD=True,
|
||
买卖点_指标匹配_KDJ=True,
|
||
买卖点_指标匹配_RSI=True,
|
||
|
||
# ---- 线段内部背驰 ----
|
||
线段内部背驰_MACD=True,
|
||
线段内部背驰_斜率=True,
|
||
线段内部背驰_测度=True,
|
||
线段内部背驰_模式="相对", # "任意"/"配置"/"全量"/"相对"
|
||
|
||
# ---- 推送/图显 ----
|
||
推送K线=True, 推送笔=True, 推送线段=True, 推送中枢=True,
|
||
# ...另有 图表展示, 图表展示_笔, _线段, _中枢_* 等 20+ 图显字段
|
||
)
|
||
```
|
||
|
||
全部 74 个字段通过 `config.model_fields()` 获取。
|
||
|
||
---
|
||
|
||
## Q6: 如何创建和对比配置?
|
||
|
||
```python
|
||
# 构造
|
||
c1 = chan.缠论配置(笔内元素数量=5, 线段_缺口后紧急修正=True)
|
||
c2 = chan.缠论配置(笔内元素数量=7, 线段_缺口后紧急修正=False)
|
||
|
||
# 差异对比 → {字段名: 新值}
|
||
c1.对比(c2) # {"笔内元素数量": 7}
|
||
|
||
# 深拷贝 + 部分更新
|
||
c3 = c1.model_copy(update={"笔内元素数量": 8}, deep=True)
|
||
|
||
# 创建不推送变体(所有推送标志 = False)
|
||
c_no_push = c1.不推送()
|
||
|
||
# 序列化
|
||
c1.to_dict() # dict
|
||
c1.to_json() # JSON 字符串
|
||
c1.保存配置("path.json")
|
||
|
||
# 反序列化
|
||
chan.缠论配置.from_dict(data)
|
||
chan.缠论配置.from_json(json_str)
|
||
chan.缠论配置.加载配置("path.json")
|
||
|
||
# 按序号重组(兼容旧版扁平键名:"1_笔模式" → {1: {笔模式: ...}})
|
||
chan.缠论配置.按序号重组字典(默认配置, 原始字典)
|
||
```
|
||
|
||
---
|
||
|
||
## Q7: 虚线的标识有哪些?如何区分笔和线段?
|
||
|
||
`虚线` 是笔和线段的通用数据结构:
|
||
|
||
```python
|
||
虚线(序号, 标识, 文, 武, 级别, 有效性=True)
|
||
# 文=起点分型, 武=终点分型
|
||
|
||
# 标识类型
|
||
"笔" # 来自 笔.分析
|
||
"线段" # 来自 线段.分析
|
||
"扩展线段" # 来自 线段.扩展分析
|
||
"线段_线段" # 线段再做一次线段分析
|
||
"扩展线段_扩展线段" # 扩展线段再做一次线段分析
|
||
```
|
||
|
||
关键属性和方法:
|
||
```python
|
||
seg.方向 # 相对方向.向上 / 相对方向.向下
|
||
seg.高 / seg.低 # max(文,武).高 / min(文,武).低
|
||
seg.文 / seg.武 # 起点分型 / 终点分型
|
||
seg.笔序列 # 内部笔序列(仅线段有)
|
||
seg.之前是(prev) # prev.武 == seg.文 ?
|
||
seg.之后是(next) # seg.武 == next.文 ?
|
||
seg.获取普K序列(观察员) # 虚线覆盖的原始K线区间
|
||
seg.获取缠K序列(观察员) # 虚线覆盖的缠论K线区间
|
||
```
|
||
|
||
笔和线段类本身只包含 `@staticmethod` 算法方法,不实例化:
|
||
```python
|
||
笔.分析(当前分型, 分型序列, 笔序列, 缠K序列, 普K序列, 层级, 配置)
|
||
线段.分析(笔序列, 线段序列, 配置, 层级=0)
|
||
```
|
||
|
||
---
|
||
|
||
## Q8: 如何判断背驰?
|
||
|
||
```python
|
||
# 需要离开段和进入段(都是虚线对象)
|
||
进入段 = obs.线段序列[-2] # 倒数第二段
|
||
离开段 = obs.线段序列[-1] # 最后一段
|
||
|
||
# 单项背驰
|
||
chan.背驰分析.MACD背驰(进入段, 离开段, obs.普通K线序列, 方式="总")
|
||
chan.背驰分析.斜率背驰(进入段, 离开段)
|
||
chan.背驰分析.测度背驰(进入段, 离开段)
|
||
|
||
# 组合背驰
|
||
chan.背驰分析.全量背驰(进入段, 离开段, obs.普通K线序列) # 三项全满足
|
||
chan.背驰分析.任意背驰(进入段, 离开段, obs.普通K线序列) # 至少一项
|
||
chan.背驰分析.任选背驰(进入段, 离开段, obs.普通K线序列) # 至少两项
|
||
|
||
# 按配置组合
|
||
chan.背驰分析.配置背驰(进入段, 离开段, obs.普通K线序列, config)
|
||
chan.背驰分析.背驰模式(进入段, 离开段, obs.普通K线序列, config, "全量")
|
||
|
||
# 判断线段内部是否背驰
|
||
chan.线段.判断线段内部是否背驰(离开段, obs) # 分析段内中枢背驰
|
||
```
|
||
|
||
MACD 背驰也可通过虚线的类方法直接判断:
|
||
```python
|
||
chan.虚线.武之全量MACD均值(obs.普通K线序列, 离开段) # 武端MACD < 均值?
|
||
chan.虚线.武之MACD均值(obs.普通K线序列, 离开段) # 按方向比较
|
||
chan.虚线.武之MACD极值(obs.普通K线序列, 离开段) # 武端是否为极值?
|
||
chan.虚线.买卖意义(离开段, obs) # 盘整背驰 → (bool, 描述)
|
||
```
|
||
|
||
---
|
||
|
||
## Q9: 中枢如何操作?
|
||
|
||
```python
|
||
# 中枢 = 三段连续虚线重叠区间
|
||
hub = chan.中枢.创建(左段, 中段, 右段, 级别=0, 标识="线段中枢")
|
||
|
||
# 属性
|
||
hub.方向 # 基础序列[0].方向.翻转()
|
||
hub.高 / hub.低 # 中枢区间: min(前三段.高) / max(前三段.低)
|
||
hub.高高 / hub.低低 # 全部延伸段的最高/最低
|
||
hub.离开段 # 基础序列[-1]
|
||
hub.第三买卖线 # 第三类买卖点参考线
|
||
hub.当前状态() # "中枢之中" / "中枢之上" / "中枢之下"
|
||
|
||
# 延伸与扩展
|
||
hub._添加虚线(新段) # 中枢延伸
|
||
hub.获取扩展中枢(扩展中枢列表, config) # 9段以上获得扩展中枢
|
||
|
||
# 类方法
|
||
chan.中枢.基础检查(左, 中, 右) # 三段是否首尾相连
|
||
chan.中枢.从序列中获取中枢(虚线序列, 起始方向, 标识)
|
||
chan.中枢.分析(虚线序列, 中枢序列) # 自动识别中枢
|
||
```
|
||
|
||
---
|
||
|
||
## Q10: 如何判断中枢的第三类买卖点?
|
||
|
||
第三类买卖点出自中枢"离开-回抽不破":
|
||
|
||
```python
|
||
# 分割序列获取第三买卖线
|
||
前, 后, 第三买卖线, 贯穿伤 = chan.线段.分割序列(离开段, 所属中枢=hub)
|
||
# 第三买卖线 != None → 存在第三类买卖点
|
||
|
||
# 或通过中枢完整性验证
|
||
hub.完整性(虚实="实") # 验证第三买卖点是否有效
|
||
```
|
||
|
||
---
|
||
|
||
## Q11: 买卖点如何生成?
|
||
|
||
`观察者.识别买卖点()` 当前为空实现(`pass`)。买卖点类型已定义,可手动创建:
|
||
|
||
```python
|
||
# 买卖点类型枚举 (18种)
|
||
chan.买卖点类型.一买 / chan.买卖点类型.一卖
|
||
chan.买卖点类型.二买 / chan.买卖点类型.二卖
|
||
chan.买卖点类型.三买 / chan.买卖点类型.三卖
|
||
chan.买卖点类型.类一买 / chan.买卖点类型.类一卖
|
||
chan.买卖点类型.类二买 / chan.买卖点类型.类二卖
|
||
chan.买卖点类型.T1B买 / chan.买卖点类型.T1B卖
|
||
chan.买卖点类型.T2B买 / chan.买卖点类型.T2B卖
|
||
chan.买卖点类型.T3B买 / chan.买卖点类型.T3B卖
|
||
|
||
# 工厂方法
|
||
chan.买卖点.一买点(买卖点分型, 当前K线, 标识, 备注, 中枢破位值)
|
||
chan.买卖点.一卖点(买卖点分型, 当前K线, 标识, 备注, 中枢破位值)
|
||
# ... 二买点 / 二卖点 / 三买点 / 三卖点 / ...
|
||
|
||
# 属性
|
||
bsp.类型 # 买卖点类型枚举
|
||
bsp.当前K线 # 关联K线
|
||
bsp.买卖点分型 # 关联分型
|
||
bsp.破位值 # 中枢破位值
|
||
bsp.有效性 # 是否有效
|
||
bsp.偏移 / bsp.失效偏移
|
||
```
|
||
|
||
---
|
||
|
||
## Q12: 技术指标如何计算和访问?
|
||
|
||
指标通过 `指标计算器` 自动挂载到每根 K 线的 `指标` 容器:
|
||
|
||
```python
|
||
# 自动挂载(观察者内部调用)
|
||
指标计算器.计算并挂载(当前K线, 全序列, config)
|
||
|
||
# 访问指标
|
||
k线.指标.macd # 平滑异同移动平均线 或 None
|
||
k线.指标.rsi # 相对强弱指数 或 None
|
||
k线.指标.kdj # 随机指标 或 None
|
||
k线.指标.boll # 布林带 或 None
|
||
|
||
# MACD 字段
|
||
macd.DIF / macd.DEA / macd.MACD柱 / macd.快线EMA / macd.慢线EMA
|
||
|
||
# 手动计算(不依赖观察者)
|
||
macd1 = 平滑异同移动平均线.首次计算(收盘价, 时间戳, 快线周期=12, 慢线周期=26, 信号周期=9)
|
||
macd2 = 平滑异同移动平均线.增量计算(macd1, 新收盘价, 新时间戳)
|
||
# 或从 K 线直接计算
|
||
macd = 平滑异同移动平均线.首次计算_K线(k线, 计算方式="收盘价")
|
||
macd = 平滑异同移动平均线.增量计算_K线(前MACD, k线, 计算方式="收盘价")
|
||
|
||
# RSI / KDJ / BOLL 同理
|
||
rsi = 相对强弱指数.首次计算(收盘价, 时间戳, 周期=14)
|
||
rsi = 相对强弱指数.增量计算(前RSI, 新收盘价, 新时间戳)
|
||
|
||
kdj = 随机指标.首次计算(最高价, 最低价, 收盘价, 时间戳, N=9, M1=3, M2=3)
|
||
kdj = 随机指标.增量计算(前KDJ, 最高价, 最低价, 收盘价, 时间戳)
|
||
|
||
boll = 布林带.首次计算(k线, 计算方式="收盘价", 周期=20, 标准差倍数=2.0)
|
||
boll = 布林带.增量计算(前BOLL, k线, 计算方式="收盘价")
|
||
```
|
||
|
||
配置变更后需回填指标:
|
||
```python
|
||
指标计算器._回填新指标(全序列, config) # 重算所有K线的指标
|
||
```
|
||
|
||
---
|
||
|
||
## Q13: 如何验证双端(Rust/Python)分析结果一致?
|
||
|
||
```python
|
||
from chanlun import chan as chan_rs # Rust 绑定
|
||
from chanlun import chan as chan_py # Python 参考
|
||
|
||
# 逐类型相等性检查(返回 (bool, 原因))
|
||
chan.K线相等(k_rs, k_py, 浮点容差=1e-9)
|
||
chan.缠论K线相等(ck_rs, ck_py, 浮点容差=1e-9)
|
||
chan.分型相等(fx_rs, fx_py, 浮点容差=1e-9)
|
||
chan.虚线相等(dl_rs, dl_py, 浮点容差=1e-9)
|
||
chan.中枢相等(hub_rs, hub_py, 浮点容差=1e-9)
|
||
chan.观察者相等(obs_rs, obs_py, 浮点容差=1e-9)
|
||
chan.立体分析器相等(ma_rs, ma_py, 浮点容差=1e-9)
|
||
```
|
||
|
||
所有相等函数返回 `(True, "")` 或 `(False, "差异描述")`。
|
||
|
||
---
|
||
|
||
## Q14: K 线如何创建和序列化?
|
||
|
||
```python
|
||
# 创建
|
||
k = chan.K线.创建普K(
|
||
标识="btcusd", 时间戳=datetime.now(),
|
||
开盘价=50000, 最高价=50100, 最低价=49900, 收盘价=50050,
|
||
成交量=100, 序号=0, 周期=300,
|
||
)
|
||
|
||
# 属性
|
||
k.方向 # 相对方向(开盘价 vs 收盘价)
|
||
k.指标 # 指标容器
|
||
|
||
# 二进制序列化 (48字节大端,兼容 Rust)
|
||
data = bytes(k) # __bytes__ → struct.pack(">6d")
|
||
|
||
# 从二进制解析
|
||
k2 = chan.K线.读取大端字节数组(data, 周期=300, 标识="btcusd")
|
||
|
||
# 批量保存/加载
|
||
chan.K线.保存到DAT文件("output.dat", k线列表)
|
||
|
||
# 区间截取
|
||
subset = chan.K线.截取(序列, 始=k起始, 终=k结束)
|
||
|
||
# 区间MACD面积
|
||
chan.K线.获取MACD(序列, 始, 终) # {"MACD正面积": ..., "MACD负面积": ...}
|
||
```
|
||
|
||
---
|
||
|
||
## Q15: 缠论K线包含处理逻辑是什么?
|
||
|
||
```python
|
||
# 缠论K线.分析 的返回值
|
||
状态, 分型 = chan.缠论K线.分析(当前K线, 缠K序列, 普K序列, config)
|
||
|
||
# 状态值含义
|
||
"缠K完成" # 形成独立的缠论K线,可能伴随顶/底分型
|
||
"包含处理中" # 当前K线被包含处理,未形成独立缠K
|
||
"等" # 等待更多K线(如方向未确定)
|
||
```
|
||
|
||
缠K 方向由包含处理决定,有向上和向下两种状态。包含处理规则:
|
||
- 同向:取 高者之高、低者之低(向上)/ 高者之低、低者之高(向下)
|
||
- 异向:先确定方向,再按方向处理
|
||
|
||
---
|
||
|
||
## Q16: 分型如何识别?
|
||
|
||
```python
|
||
# 分型由左中右三根缠K构成
|
||
fx = chan.分型(左=缠K_左, 中=缠K_中, 右=缠K_右)
|
||
fx.结构 # 分型结构.顶分型 / 分型结构.底分型 / 分型结构.三连向上 / 分型结构.三连向下
|
||
|
||
# 分型结构分析
|
||
chan.分型结构.分析(左, 中, 右, 可以逆序包含=False, 忽视顺序包含=False)
|
||
# 返回: 三连向上 / 三连向下 / 顶分型 / 底分型 / 向右扩散 / None
|
||
|
||
# 分型辅助方法
|
||
chan.分型.判断分型(左分型, 右分型, 模式="中")
|
||
chan.分型.从缠K序列中获取分型(缠K序列, 中间缠K)
|
||
chan.分型.向序列中添加(分型序列, 新分型) # 自动处理冲突
|
||
|
||
# 分型属性
|
||
fx.分型特征值 # 中.高 + 中.低 * sign(顶=-1, 底=+1)
|
||
fx.关系组 # (左→中, 中→右, 左→右) 相对方向元组
|
||
fx.强度 # 高低差比例
|
||
```
|
||
|
||
---
|
||
|
||
## Q17: 如何获取虚线范围内的所有停顿位置?
|
||
|
||
```python
|
||
# 获取线段中所有笔的端点停顿位置
|
||
停顿 = chan.线段.获取所有停顿位置(段, 观察员)
|
||
# 返回笔级虚线列表,可用于判断中枢区间
|
||
|
||
# 四象归类
|
||
象 = chan.线段.四象(段)
|
||
# "老阳" / "小阳" / "少阴" / "老阴"
|
||
```
|
||
|
||
---
|
||
|
||
## Q18: 数据如何保存和恢复?
|
||
|
||
```python
|
||
# 观察者保存到 .nb 文件(48字节/根格式)
|
||
path = obs.测试_保存数据(root="/tmp") # 返回文件路径
|
||
|
||
# 从 .nb 文件恢复
|
||
obs.加载本地数据(path)
|
||
|
||
# 立体分析器保存
|
||
ma.测试_保存数据(root="/tmp")
|
||
|
||
# 静态重新分析(从已有K线全量重建所有序列)
|
||
obs.静态重新分析()
|
||
```
|
||
|
||
---
|
||
|
||
## Q19: 相对方向的判断逻辑?
|
||
|
||
```python
|
||
chan.相对方向.分析(前高, 前低, 后高, 后低)
|
||
# 返回: 向上 / 向下 / 包含 / 向上缺口 / 向下缺口 / 衔接
|
||
|
||
# 方向翻转
|
||
方向.翻转() # 向上 ←→ 向下
|
||
|
||
# 判断方法
|
||
方向.是否向上() / 方向.是否向下()
|
||
方向.是否包含() / 方向.是否缺口() / 方向.是否衔接()
|
||
```
|
||
|
||
---
|
||
|
||
## Q20: 常见错误排查
|
||
|
||
| 现象 | 可能原因 |
|
||
|------|----------|
|
||
| 笔序列为空 | `配置.分析笔=False` 或笔内缠K不足(需 ≥ 笔内元素数量) |
|
||
| 线段序列为空 | `配置.分析线段=False` 或笔序列长度不足 |
|
||
| 中枢序列为空 | 虚线序列长度不足 3 段,或三段不重叠 |
|
||
| 指标为 None | 指标未挂载,需先调用 `指标计算器.计算并挂载` |
|
||
| 配置变更不生效 | 需要 `指标计算器._回填新指标(全序列, 配置)` 和 `obs.静态重新分析()` |
|
||
| 买卖点序列为空 | `识别买卖点()` 是空实现,需自行调用 `买卖点.生成买卖点` |
|
||
| 多周期结果不一致 | 检查 `配置组` 是否覆盖了对应周期的配置 |
|
||
| 浮点比较不通过 | 双端一致性测试使用 `浮点容差=1e-9` |
|
||
|
||
---
|
||
|
||
## Q21: 三个线段序列组有什么不同?分别用于什么场景?
|
||
|
||
`观察者` 内部有三条并行的多级序列树,每条树有 3 层(由 `线段分析层次=3` 控制):
|
||
|
||
```python
|
||
# 1. 线段序列组 — 标准线段递归
|
||
obs.线段序列组[0] # 标识="线段" 笔→线段(标准)
|
||
obs.线段序列组[1] # 标识="线段<线段>" 线段→线段(段作为笔再划段)
|
||
obs.线段序列组[2] # 标识="线段<线段<线段>" 再递归一层
|
||
|
||
# 2. 扩展线段序列组 — 扩展分析递归
|
||
obs.扩展线段序列组[0] # 标识="扩展线段" 笔→扩展线段
|
||
obs.扩展线段序列组[1] # 标识="扩展线段<扩展线段>" 扩展段→段
|
||
obs.扩展线段序列组[2] # 标识="扩展线段<扩展线段<扩展线段>>" 再递归
|
||
|
||
# 3. 混合扩展线段序列组 — 混合递归(扩展线段分析标准线段)
|
||
obs.混合扩展线段序列组[0] # 标识="扩展线段<线段>" 线段→扩展线段
|
||
obs.混合扩展线段序列组[1] # 标识="扩展线段<线段<线段>>" 线段<线段>→扩展线段
|
||
obs.混合扩展线段序列组[2] # 标识="扩展线段<线段<线段<线段>>>" 再递归
|
||
```
|
||
|
||
**生成流程**(`静态重新分析` 中可见):
|
||
1. 笔序列 → `线段.分析()` → 线段序列组[0]
|
||
2. 线段序列组[0] → `线段.分析()` → 线段序列组[1](线段作为笔再划分)
|
||
3. 线段序列组[1] → `线段.分析()` → 线段序列组[2]
|
||
4. 笔序列 → `线段.扩展分析()` → 扩展线段序列组[0]
|
||
5. 扩展线段序列组[0] → `线段.扩展分析()` → 扩展线段序列组[1]
|
||
6. 扩展线段序列组[1] → `线段.扩展分析()` → 扩展线段序列组[2]
|
||
7. 线段序列组[i] → `线段.扩展分析()` → 混合扩展线段序列组[i]
|
||
|
||
**实际验证**(2500 根 BTCUSD 300s K 线):
|
||
```
|
||
线段序列组: 26段, 3段<线段>, 无更高级
|
||
扩展线段序列组: 48段, 14段<扩展>, 4段<扩展<扩展>>
|
||
混合扩展线段组: 8段<线段>, 1段<线段<线段>>
|
||
```
|
||
|
||
**关键差异**:
|
||
- `线段.分析` 要求笔/线段之间**方向交替**(上下上下)
|
||
- `线段.扩展分析` 允许**同向连续**(将同向虚线合并处理),因此产生更多扩展段
|
||
|
||
等效属性访问(@property):
|
||
```python
|
||
obs.线段序列 = obs.线段序列组[0]
|
||
obs.线段_线段序列 = obs.线段序列组[1]
|
||
obs.扩展线段序列 = obs.扩展线段序列组[0]
|
||
obs.扩展线段序列_扩展线段 = obs.扩展线段序列组[1]
|
||
obs.混合扩展线段序列 = obs.混合扩展线段序列组[0]
|
||
```
|
||
|
||
---
|
||
|
||
## Q22: 特征序列是什么?老阴/老阳/小阳/少阴如何区分?
|
||
|
||
**特征序列**是线段划分算法的核心概念。当从笔划分线段时,每根笔的方向与线段方向之间有一个关系:
|
||
- **线段方向向上** → 特征序列取每笔的"向下"特征(特征方向=向下)
|
||
- **线段方向向下** → 特征序列取每笔的"向上"特征(特征方向=向上)
|
||
|
||
特征序列用于处理**缺口**和**包含**:多笔同特征方向的要素需要先做包含处理,再通过特征序列的分型来判断线段是否终结。
|
||
|
||
**线段特征**(`线段特征` 类)是对应笔的抽象:
|
||
```python
|
||
线段特征(标识, 基础序列, 线段方向)
|
||
# 持有一组同向虚线(笔),是线段划分的中间结构
|
||
# 特征.方向 = 线段方向的翻转
|
||
# 特征.高/特征.低 → 按线段方向取极值
|
||
```
|
||
|
||
**四象**描述线段与缺口的关系:
|
||
```python
|
||
线段.四象(段)
|
||
# "老阳": 向下线段 + 存在前一缺口(向下线段后有向上缺口)
|
||
# "老阴": 向上线段 + 存在前一缺口(向上线段后有向下缺口)
|
||
# "小阳": 向上线段 + 无缺口(普通向上)
|
||
# "少阴": 向下线段 + 无缺口(普通向下)
|
||
```
|
||
|
||
**老阴老阳在特征序列中的作用**:
|
||
当 `线段_特征序列忽视老阴老阳=False`(默认)时:
|
||
- 老阳/老阴的特征序列**不参与**包含处理——缺口状态下的特征序列元素直接跳过包含合并
|
||
- 相当于"缺口破坏了特征序列的连续性"
|
||
|
||
当 `线段_特征序列忽视老阴老阳=True` 时:
|
||
- **忽略缺口**,所有特征序列元素都按无缺口处理(严格包含)
|
||
- 实际效果:线段和中枢数量都**增加**(更多特征序列参与包含处理,产生更多分型终结)
|
||
|
||
**验证数据**(1500 根 K 线):
|
||
```
|
||
忽视老阴老阳=False: 线段数=374, 中枢数=48
|
||
忽视老阴老阳=True: 线段数=390, 中枢数=56 (+16段, +8中枢)
|
||
```
|
||
|
||
---
|
||
|
||
## Q23: 笔弱化、笔次级成笔到底改变了什么?
|
||
|
||
### 笔弱化 (`笔弱化=True`)
|
||
|
||
当一笔只有 3 个内部缠K(`武.中.序号 - 文.中.序号 + 1 == 3`)且下一分型直接穿透它时:
|
||
- 向上笔 + 下一底分型低于该笔的低点 → 弹出这笔 → 重分析
|
||
- 向下笔 + 下一顶分型高于该笔的高点 → 弹出这笔 → 重分析
|
||
|
||
效果是**移除过短的阻挡笔**,让分型能连接更合理的笔。实测效果:
|
||
|
||
```
|
||
1500根K线:
|
||
笔弱化=False: 笔数=2796, 线段数=374
|
||
笔弱化=True: 笔数=3630, 线段数=500
|
||
|
||
5000根K线:
|
||
笔弱化=False: 笔数=9358, 线段数=1261
|
||
笔弱化=True: 笔数=11878, 线段数=1678
|
||
```
|
||
|
||
笔弱化开启后笔数和线段数都**显著增加**(~30%),因为移除阻挡笔后产生了更多有效笔和段。
|
||
|
||
### 笔弱化_原始数量 (`笔弱化_原始数量=3`)
|
||
|
||
控制笔弱化判断时参考的原始K线数量。不同的值对结果影响:
|
||
|
||
```
|
||
笔弱化_原始数量=3: 笔数=3556
|
||
笔弱化_原始数量=5: 笔数=3556 (无变化)
|
||
笔弱化_原始数量=7: 笔数=3556 (无变化)
|
||
```
|
||
|
||
当前实现中此参数变化不明显,因为笔弱化主要受"原始分型数量为3"这个硬编码条件驱动。
|
||
|
||
### 笔次级成笔 (`笔次级成笔=False`)
|
||
|
||
控制是否在笔的分析中启用次级递归成笔。默认关闭。实测效果:
|
||
|
||
```
|
||
1500根K线:
|
||
笔次级成笔=False: 笔数=2796, 线段数=374
|
||
笔次级成笔=True: 笔数=3228, 线段数=468 (+432笔, +94段)
|
||
```
|
||
|
||
开启后笔数和线段数都有明显增加,因为允许在笔内部递归划分子笔,产生更多有效分型。
|
||
|
||
---
|
||
|
||
## Q24: 线段修正算法 _修正 / _缺口突破 / _非缺口下穿刺 做什么?
|
||
|
||
### _修正 (短路修正, 配置.线段_修正)
|
||
|
||
当线段基础序列 ≥ 9 且后半段满足特定条件时,将一段拆分为两段:
|
||
1. 分割序列 → 前段+后段
|
||
2. 后段 ≥ 6 个元素且偶数
|
||
3. 后段倒数第3和第1元素方向 = 线段方向
|
||
4. 满足条件 → 拆分为 新段1(后段[:-3]) + 新段2(后段[-3:])
|
||
5. 标记 `短路修正=True`,清空老阴老阳段的缺口
|
||
|
||
### _缺口突破 (缺省启用,无配置开关)
|
||
|
||
处理有缺口的线段序列:
|
||
- 当前线段特征序列右元素 ≠ None
|
||
- 特征序列方向与线段方向匹配
|
||
- 连续特征序列长度 ≥ 5 且奇数
|
||
- 弹出当前段 → 根据特征分型终结点切分为两段
|
||
|
||
### _非缺口下穿刺 (配置.线段_非缺口下穿刺)
|
||
|
||
处理"贯穿伤":当一段线段的基础序列被另一段完全穿透时修复。只有在小阳/少阴(非缺口)状态下才触发。
|
||
|
||
---
|
||
|
||
## Q25: 买卖点的实际集成路径是什么?为什么识别买卖点()是空的?
|
||
|
||
`观察者.识别买卖点()` 是 `pass` 占位——具体买卖点识别逻辑**原本计划实现但未在 chan.py 中完成**。
|
||
|
||
但这不意味着买卖点不可用——可以通过以下路径手动生成:
|
||
|
||
```python
|
||
# 路径1:手动创建(已有工厂方法)
|
||
bsp = chan.买卖点.一卖点(
|
||
买卖点分型=obs.分型序列[-1], # 或中枢离开段终点的分型
|
||
当前K线=obs.普通K线序列[-1],
|
||
标识="btcusd-300",
|
||
备注="第一类卖点",
|
||
中枢破位值=hub.低, # 中枢下沿
|
||
)
|
||
|
||
# 路径2:通过生成买卖点路由
|
||
chan.买卖点.生成买卖点(
|
||
特征="一卖", # 特征字符串路由到工厂
|
||
序号="1",
|
||
级别="线段",
|
||
买卖点分型=fx,
|
||
当前缠K=ck,
|
||
)
|
||
|
||
# 路径3:中枢完整性验证 → 判断第三买卖点
|
||
hub.完整性(虚实="实") # 检查是否有第三买卖点条件
|
||
```
|
||
|
||
买卖点类型的完整列表(18种):
|
||
```
|
||
一买/一卖 第一类(中枢背驰转折)
|
||
二买/二卖 第二类(回抽不进中枢)
|
||
三买/三卖 第三类(离开后回抽不破中枢)
|
||
T1买/T1卖 第一类扩展
|
||
T1P买/T1P卖 盘整型第一类
|
||
T2买/T2卖 第二类扩展
|
||
T2S买/T2S卖 强势第二类
|
||
T3A买/T3A卖 第三类A型
|
||
T3B买/T3B卖 第三类B型
|
||
```
|
||
|
||
Rust 绑定层(`chanlun-py`)中的 `识别买卖点` 已实现完整逻辑,使用 `生成买卖点` 路由。
|
||
|
||
---
|
||
|
||
## 内部算法机制
|
||
|
||
以下方法不是公开 API,但理解它们的逻辑才能理解线段为什么这样划分、中枢为什么这样识别。
|
||
|
||
### 线段.分割序列 — 用终点切开基础序列
|
||
|
||
```
|
||
输入: 段 (虚线), 所属中枢 (可选)
|
||
输出: (前序列, 后序列, 第三买卖线列表, 贯穿伤)
|
||
```
|
||
|
||
**切割规则**:遍历段.基础序列,找到第一笔满足 `笔.文 is 段.武` 的位置——从此笔开始全部归入"后",之前的归入"前"。
|
||
|
||
**为什么**:线段的终点分型(武)同时是下一笔的起点分型(文)。段.武 为起点的笔暂挂在当前段的基础序列里,但它已属于"下一段"范畴。分割序列区分"已确认"和"暂挂"。
|
||
|
||
**9 处调用各自取什么**:
|
||
|
||
| 调用方 | 取值 | 用途 |
|
||
|--------|------|------|
|
||
| `获取内部中枢序列` | 前, 后 | 分别在前后找中枢 |
|
||
| `_缺口突破` | `[0]` 前 | 只在确认部分判断缺口 |
|
||
| `_缺口后紧急修正` | `[1]` 后 | 检查暂挂部分是否需要修正 |
|
||
| `_修正` | 前, 后 | 后≥6且方向一致 → 拆段 |
|
||
| `分析`(递归)| `[1]` 后 | 用暂挂部分做下一轮划分 |
|
||
| `判断线段内部是否背驰` | 前=阳, 后=阴 | 进入段 vs 离开段 |
|
||
| `获取所有停顿位置` | 前, 后 | 前后端点都算停顿 |
|
||
| `获取数据文本` | 全部 | 格式化输出 |
|
||
|
||
**贯穿伤**:后[0].武 穿透了 段.文——向上段的"后"终点比"文"还低、或向下段的"后"终点比"文"还高。意味着这段根本没真正转折。
|
||
|
||
### 线段.获取内部中枢序列 — 阴阳合三套中枢
|
||
|
||
```
|
||
输入: 段, 配置
|
||
输出: (虚中枢列表, 实中枢列表, 合中枢列表) # 注释: 阴 阳 合
|
||
```
|
||
|
||
先用 `分割序列` 把线段基础序列切成"前"(确认部分)和"后"(暂挂部分),然后分别在三块区域跑中枢识别:
|
||
|
||
| 返回值 | 别称 | 识别范围 | 含义 |
|
||
|--------|------|----------|------|
|
||
| `实中枢序列` | 阳 | 分割序列的"前" | 段已确认部分的中枢——段主体运行阶段形成的 |
|
||
| `虚中枢序列` | 阴 | 分割序列的"后" | 段暂挂部分的中枢——离开段所在的 |
|
||
| `合中枢序列` | 合 | 整个基础序列(前+后) | 全景视角——但跨了段边界,含下一段笔 |
|
||
|
||
**核心用途**:给 `判断线段内部是否背驰` 提供判定依据。
|
||
|
||
背驰判断的三种情况(对照 `判断线段内部是否背驰` 源码):
|
||
|
||
1. **有阴**(暂挂部分非空)→ 段还未确认终点,不判断背驰(直接返回 False)
|
||
2. **有实中枢** → 检查最后一笔是否在末个阳中枢里:
|
||
- 在:取中枢起点前一笔作进入段,最后一笔作离开段 → 按配置模式判断背驰
|
||
- 不在但末中枢有第三买卖线:取倒数第三笔和倒数第一笔比较 → 判断盘整背驰
|
||
3. **无中枢** → 只有 3 笔时判断盘整背驰
|
||
|
||
**阴阳为什么分开**:同一个段内,前半(阳)是已完成的走势,后半(阴)是终点出现后的暂挂部分。背驰判断时,取阳中枢的起点前一笔作"进入段"、阳的最后一笔作"离开段",比较两者是否发生趋势衰减——这是段内部是否背驰的判定基础。
|
||
|
||
实测验证(2000 根 K 线):
|
||
```
|
||
段6 [向上] 10笔: 实中枢1个[114596-114189] 虚中枢1个[115382-114523] 合中枢1个[114596-114189]
|
||
段7 [向下] 10笔: 实中枢1个[115382-114523] 虚中枢0个 合中枢2个[115382-114523][113297-112218]
|
||
段8 [向上] 8笔: 实中枢0个 虚中枢1个[111409-111008] 合中枢2个[113641-112754][111409-111008]
|
||
```
|
||
|
||
注意段7:虚中枢为空但合中枢有2个——因为跨"前/后"边界的笔凑出了合中枢里的第二个。但后部的笔属于下一段,这个中枢不应该算在此段头上。**判断单段是否趋势,应该用实中枢,不能用合中枢**:实中枢只看"前"(本段自己的笔),不会混入下一段的结构。
|
||
|
||
实测对比(2000根K线):
|
||
```
|
||
段7: 实中枢=1(盘整) vs 合中枢=2(趋势) ← 合中枢误判
|
||
段8: 实中枢=0(盘整) vs 合中枢=2(趋势) ← 合中枢误判
|
||
```
|
||
两例都被合中枢误标为趋势,实际是盘整。
|
||
|
||
---
|
||
|
||
## Q26: 如何判断线段内部是趋势还是盘整?
|
||
|
||
```python
|
||
虚, 实, 合 = chan.线段.获取内部中枢序列(段, 观察员.配置)
|
||
|
||
if len(实) >= 2:
|
||
if 段.方向.是否向上():
|
||
return "上涨趋势"
|
||
else:
|
||
return "下跌趋势"
|
||
else:
|
||
return "盘整"
|
||
```
|
||
|
||
趋势必须有方向——段方向是向上 + 实中枢≥2 = 上涨趋势,段方向向下 + 实中枢≥2 = 下跌趋势。
|
||
|
||
**为什么是实中枢,不是合中枢?**
|
||
|
||
`分割序列` 把基础序列切成"前"(本段)和"后"(下一段起始)。合中枢在"前+后"上跑,会混入下一段的笔。段7 前7笔只有1个实中枢,但跨边界的笔在合中枢凑出第2个——这个多出来的中枢不属于此段。
|
||
|
||
**辅助信号**:
|
||
|
||
| 信号 | 上涨趋势 | 下跌趋势 | 盘整 |
|
||
|------|---------|---------|------|
|
||
| 段.方向 | 向上 | 向下 | 皆可 |
|
||
| 实中枢数 | ≥2 | ≥2 | ≤1 |
|
||
| `买卖意义` | 可能 False | 可能 False | 可能 True(盘整背驰) |
|
||
| `判断线段内部是否背驰` | 可能 True | 可能 True | True=盘整衰竭 |
|
||
|
||
### 线段._刷新特征序列 — 线段级别包含处理
|
||
|
||
```
|
||
输入: 段, 配置
|
||
```
|
||
|
||
1. 取段.基础序列,若存在 `前一结束位置` 则从此位置-1处截取
|
||
2. 调用 `线段特征.静态分析(基础序列, 段.方向, 四象, 忽视老阴老阳)` — 将笔序列做包含处理得到特征序列
|
||
3. 从特征序列提取分型序列
|
||
4. 若首分型方向与段.方向相同(特征分型终结条件)→ 截取基础序列到特征分型终点 + 调用 `_设置特征序列`
|
||
|
||
**特征序列方向 = 线段方向的翻转**。向上线段取向下的特征(调整段),向下线段取向上的特征(反弹段)。
|
||
|
||
### 线段特征.静态分析 — 笔的包含处理
|
||
|
||
将多笔同向特征元素做包含处理(与缠K的包含处理原理相同,但在笔级别操作):
|
||
- 同向特征:取极值合并
|
||
- 反向特征:独立成新元素
|
||
- 老阴/老阳(有缺口)且不忽视时:跳过包含处理
|
||
|
||
输出一段 `List[线段特征]`,每个特征持有一组被合并的笔。
|
||
|
||
### 线段._武斗 — 线段终结判断
|
||
|
||
```
|
||
输入: 段, 特征, 行号
|
||
```
|
||
|
||
当特征序列右元素 ≠ None 时,判断线段是否被终结:
|
||
1. 特征序列方向应与线段方向相同(特征分型终结)
|
||
2. 检查特征分型是否有效(顶底交替,特征序列包含处理完毕)
|
||
3. 满足条件 → 用 `_武终` 终结线段,重置基础序列,开启新段
|
||
|
||
### 线段._添加线段 — 含缺口处理
|
||
|
||
```
|
||
输入: 线段序列, 待添加线段, 配置, 行号
|
||
```
|
||
|
||
在追加线段前,检查前一段的缺口状态:
|
||
- 若前一段 `短路修正=True` → 缺口 = None
|
||
- 否则 → 调用 `获取缺口(前一段)`
|
||
- 将缺口存入新段的 `前一缺口`
|
||
|
||
缺口影响四象判断和后续的特征序列包含处理。
|
||
|
||
### 笔._相对关系 — 判断笔是否反向
|
||
|
||
```
|
||
输入: 筆, 配置
|
||
```
|
||
|
||
验证笔的方向是否"真正"匹配分型方向。如果 `笔内起始分型包含整笔=True`,会用分型的左中右三根缠K构造缺口区间,判断区间方向与笔方向是否一致。防止"分型形态在但实际价格不匹配"的假笔。
|
||
|
||
### 笔弱化触发条件
|
||
|
||
```
|
||
if 配置.笔弱化 and 笔序列:
|
||
前一笔.武.中.序号 - 前一笔.文.中.序号 + 1 == 3: # 只有3根内部缠K
|
||
if (向上笔 and 前一笔.低 > 当前分型.分型特征值 and 当前分型是底) or
|
||
(向下笔 and 前一笔.高 < 当前分型.分型特征值 and 当前分型是顶):
|
||
弹出旧笔 → 递归重分析
|
||
```
|
||
|
||
只有**最短的笔(3缠K)**且被下一分型**完全穿透**时才会触发弱化。这就是为什么笔弱化能增加 30% 的笔——它移除了那些"看起来像笔但实际上阻挡了更合理划分"的过短笔。
|
||
|
||
### 中枢._校验合法性 — 确保中枢不包含已删除的元素
|
||
|
||
遍历中枢.基础序列,检查每个元素是否仍存在于源序列中。如果某段已被线段修正删除,中枢需要修剪。这保证了中枢始终反映当前有效的线段结构。
|
||
|
||
### 中枢.当前状态 — 判断价格相对中枢的位置
|
||
|
||
```python
|
||
if 中枢.高 >= 尾部.分型特征值 >= 中枢.低 → "中枢之中"
|
||
elif 中枢.高 < 尾部.分型特征值 → "中枢之上"
|
||
elif 中枢.低 > 尾部.分型特征值 → "中枢之下"
|
||
```
|
||
|
||
第三买卖点判断依赖此状态——只有离开中枢(之上/之下)后才可能产生第三类买卖点。
|
||
|
||
---
|
||
|
||
## 类型速查
|
||
|
||
| 类型 | 职责 | 关键方法 |
|
||
|------|------|----------|
|
||
| `K线` | OHLCV 数据 + 指标容器 | `创建普K`, `读取大端字节数组`, `截取` |
|
||
| `缠论K线` | 包含处理后的K线 | `分析`, `创建缠K`, `与MACD柱子匹配` |
|
||
| `分型` | 顶/底分型 | `从缠K序列中获取分型`, `向序列中添加` |
|
||
| `分型结构` | 分型形态枚举 | `分析` |
|
||
| `虚线` | 笔/线段数据结构 | `创建笔`, `创建线段`, `买卖意义`, `武之MACD极值` |
|
||
| `笔` | 笔算法 (@staticmethod) | `分析` |
|
||
| `线段` | 线段算法 (@staticmethod) | `分析`, `扩展分析`, `判断线段内部是否背驰` |
|
||
| `中枢` | 三段重叠区间 | `创建`, `分析`, `获取扩展中枢`, `当前状态` |
|
||
| `买卖点` | 买卖点工厂 | `一买点`~`T3B卖点` 18 个工厂方法 |
|
||
| `背驰分析` | 背驰判断 (@staticmethod) | `MACD背驰`, `斜率背驰`, `测度背驰`, `全量背驰` |
|
||
| `观察者` | 单周期分析器 | `投喂原始数据`, `读取数据文件`, `静态重新分析` |
|
||
| `立体分析器` | 多周期分析器 | `投喂K线`, `_单体分析器` |
|
||
| `K线合成器` | 周期合成 | `投喂`, `投喂K线`, `获取当前K线` |
|
||
| `缠论配置` | 全局参数 | `to_dict`, `from_dict`, `model_copy`, `对比`, `不推送` |
|
||
| `指标计算器` | 指标挂载 | `计算并挂载`, `_回填新指标` |
|
||
| `均线工具` | SMA/EMA 辅助 | `增量SMA`, `增量EMA` |
|