观察者 线段分析/扩展分析 支持无限递归,保留之前序列为@property 形式
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "chanlun-py"
|
||||
version = "26.6.17"
|
||||
version = "26.6.34"
|
||||
edition = "2024"
|
||||
description = "缠论技术分析库 — Rust 高性能 Python 绑定"
|
||||
authors = ["YuYuKunKun"]
|
||||
|
||||
@@ -6,8 +6,6 @@ from datetime import datetime
|
||||
|
||||
# ========== Module-level functions ==========
|
||||
|
||||
def get_rs_log_level() -> str: ...
|
||||
def set_rs_log_level(level: str) -> None: ...
|
||||
def get_log_level() -> str: ...
|
||||
def set_log_level(level: str) -> None: ...
|
||||
def get_分型模式() -> bool: ...
|
||||
|
||||
@@ -14,7 +14,6 @@ __all__ = [
|
||||
"指标容器",
|
||||
"指标计算器",
|
||||
"均线工具",
|
||||
"测试_读取数据",
|
||||
"相对强弱指数",
|
||||
"相对方向",
|
||||
"立体分析器",
|
||||
@@ -49,7 +48,7 @@ __all__ = [
|
||||
from ._chanlun import *
|
||||
from ._chanlun import set_log_level as _rs_set_log_level, get_log_level as _rs_get_log_level
|
||||
from . import chan
|
||||
from .chan import 测试_读取数据, 转化为时间戳, 转化为时间戳_数字, set_log_level, get_log_level
|
||||
from .chan import set_log_level, get_log_level
|
||||
|
||||
|
||||
def set_rs_log_level(level: str):
|
||||
|
||||
@@ -11,8 +11,6 @@ def get_log_level() -> str: ...
|
||||
def set_log_level(level: str) -> None: ...
|
||||
def get_分型模式() -> bool: ...
|
||||
def set_分型模式(value: bool) -> None: ...
|
||||
def 转化为时间戳(ts: Any) -> int: ...
|
||||
def 转化为时间戳_数字(ts: Any) -> int: ...
|
||||
def K线相等(A: K线, B: K线, 浮点容差: float = 1e-9) -> Tuple[bool, str]: ...
|
||||
def 缠论K线相等(A: 缠论K线, B: 缠论K线, 浮点容差: float = 1e-9) -> Tuple[bool, str]: ...
|
||||
def 分型相等(A: 分型, B: 分型, 浮点容差: float = 1e-9) -> Tuple[bool, str]: ...
|
||||
|
||||
+180
-133
@@ -2440,7 +2440,7 @@ class K线:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def 创建普K(cls, 标识: str, 时间戳: datetime, 开盘价: float, 最高价: float, 最低价: float, 收盘价: float, 成交量: float, 序号: int, 周期: int) -> K线:
|
||||
def 创建普K(cls, 标识: str, 时间戳: datetime | int, 开盘价: float, 最高价: float, 最低价: float, 收盘价: float, 成交量: float, 序号: int, 周期: int) -> K线:
|
||||
"""快捷构造普通K线
|
||||
|
||||
:param 标识: K线标识符
|
||||
@@ -2458,7 +2458,7 @@ class K线:
|
||||
标识=标识,
|
||||
序号=序号,
|
||||
周期=周期,
|
||||
时间戳=时间戳,
|
||||
时间戳=时间戳 if isinstance(时间戳, datetime) else 转化为时间戳(时间戳), # 注意此处只为兼容Rust绑定
|
||||
开盘价=开盘价,
|
||||
最高价=最高价,
|
||||
最低价=最低价,
|
||||
@@ -3520,7 +3520,6 @@ class 虚线:
|
||||
return 结果
|
||||
|
||||
@classmethod
|
||||
@lru_cache(maxsize=128)
|
||||
def 买卖意义(cls, 实线: 虚线, 观察员: 观察者) -> Tuple[bool, str]:
|
||||
"""
|
||||
静止是相对的,而运动是绝对的
|
||||
@@ -4775,7 +4774,7 @@ class 线段:
|
||||
@classmethod
|
||||
def _缺口突破(cls, 线段序列: List[虚线], 配置: 缠论配置, 层级: int) -> bool:
|
||||
"""内部方法:处理缺口突破修正, 正常修正
|
||||
|
||||
除此之外的修正皆为短路修正,此修正为正常处理
|
||||
:param 线段序列: 线段列表
|
||||
:param 配置: 缠论配置
|
||||
:param 层级: 递归深度
|
||||
@@ -4870,6 +4869,7 @@ class 线段:
|
||||
for 临时虚线 in 基础序列[基础序列.index(当前线段.基础序列[-1]) + 1 :]:
|
||||
线段._添加虚线(当前线段, 临时虚线)
|
||||
线段._刷新(当前线段, 配置)
|
||||
当前线段.短路修正 = True
|
||||
|
||||
if 当前线段.特征序列[2] is not None:
|
||||
段 = 虚线.创建线段([左, 中, 右])
|
||||
@@ -4991,6 +4991,12 @@ class 线段:
|
||||
return None
|
||||
# raise RuntimeError("线段分析 层级过深")
|
||||
|
||||
# if len(笔序列) < 3:return None
|
||||
try:
|
||||
笔序列[2]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
线段递归分析 = 线段.分析
|
||||
|
||||
# -------------------- 1. 初始化第一个线段 --------------------
|
||||
@@ -5200,7 +5206,7 @@ class 线段:
|
||||
if not 配置.扩展线段_当下分析:
|
||||
左, 中, 右 = 当前线段.基础序列[:3]
|
||||
if not 相对方向.分析(左.高, 左.低, 右.高, 右.低).是否缺口():
|
||||
当前线段.基础序列[:] = 当前线段.笔序列[:3]
|
||||
当前线段.基础序列[:] = 当前线段.基础序列[:3]
|
||||
线段._武终(当前线段, sys._getframe().f_lineno)
|
||||
else:
|
||||
线段._弹出扩展线段(线段序列, 当前线段, sys._getframe().f_lineno)
|
||||
@@ -5231,7 +5237,6 @@ class 线段:
|
||||
return 线段递归扩展分析(虚线序列, 线段序列, 配置)
|
||||
|
||||
@classmethod
|
||||
@lru_cache(maxsize=128)
|
||||
def 判断线段内部是否背驰(cls, 当前段: 虚线, 观察员: 观察者) -> bool:
|
||||
"""判断线段内部是否发生背驰(基于内部中枢和MACD)
|
||||
|
||||
@@ -5535,11 +5540,10 @@ class 中枢:
|
||||
线段.扩展分析(self.基础序列, 扩展线段, 配置)
|
||||
中枢.分析(扩展线段, 扩展中枢, False, f"{self.标识}_扩展中枢_")
|
||||
|
||||
def _校验合法性(self, 序列: Sequence[虚线], 中枢序列: List[中枢]) -> bool:
|
||||
def _校验合法性(self, 序列: Sequence[虚线]) -> bool:
|
||||
"""校验当前中枢在给定序列中是否仍然合法
|
||||
|
||||
:param 序列: 基础虚线序列
|
||||
:param 中枢序列: 中枢列表
|
||||
:return: 合法为True,不合法会原地裁剪基础序列
|
||||
"""
|
||||
有效序列 = self.基础序列[:]
|
||||
@@ -5754,7 +5758,7 @@ class 中枢:
|
||||
|
||||
当前中枢 = 中枢序列[-1]
|
||||
|
||||
if not 当前中枢._校验合法性(虚线序列, 中枢序列):
|
||||
if not 当前中枢._校验合法性(虚线序列):
|
||||
中枢._从中枢序列尾部弹出(中枢序列, 当前中枢)
|
||||
return 中枢递归分析(虚线序列, 中枢序列, 跳过首部, 标识, 层级 + 1)
|
||||
|
||||
@@ -5829,8 +5833,41 @@ class 观察者:
|
||||
self.配置: 缠论配置 = 配置
|
||||
self.__终止时间戳: Optional[datetime] = 转化为时间戳(self.配置.手动终止) if self.配置.手动终止 else None
|
||||
|
||||
self.线段分析层次 = 3
|
||||
self.扩展线段分析层次 = 3
|
||||
self.混合扩展线段分析层次 = 3
|
||||
self.重置基础序列()
|
||||
|
||||
def 重置基础序列(self):
|
||||
"""清空所有分析序列,重置为初始状态"""
|
||||
self.基础缠K序列: List[缠论K线] = []
|
||||
|
||||
self.普通K线序列: List[K线] = []
|
||||
self.缠论K线序列: List[缠论K线] = []
|
||||
|
||||
self.分型序列: List[分型] = []
|
||||
|
||||
self.笔序列: List[虚线] = []
|
||||
self.笔_中枢序列: List[中枢] = []
|
||||
|
||||
self.线段序列组: List[List[虚线],] = [] # 线段, 线段<线段>,线段<线段<线段>>...
|
||||
self.中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.线段分析层次):
|
||||
self.线段序列组.append(list())
|
||||
self.中枢序列组.append(list())
|
||||
|
||||
self.扩展线段序列组: List[List[虚线],] = [] # 扩展线段, 扩展线段<扩展线段>, 扩展线段<扩展线段<扩展线段>>...
|
||||
self.扩展中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.扩展线段分析层次):
|
||||
self.扩展线段序列组.append(list())
|
||||
self.扩展中枢序列组.append(list())
|
||||
|
||||
self.混合扩展线段序列组: List[List[虚线],] = [] # 扩展线段<线段>, 扩展线段<线段<线段>>, 扩展线段<线段<线段<线段>>>...
|
||||
self.混合扩展中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.混合扩展线段分析层次):
|
||||
self.混合扩展线段序列组.append(list())
|
||||
self.混合扩展中枢序列组.append(list())
|
||||
|
||||
@property
|
||||
def 观察员(self):
|
||||
"""观察员(自引用)"""
|
||||
@@ -5857,32 +5894,45 @@ class 观察者:
|
||||
"""
|
||||
return self.缠论K线序列[-1] if self.缠论K线序列 else None
|
||||
|
||||
def 重置基础序列(self):
|
||||
"""清空所有分析序列,重置为初始状态"""
|
||||
self.基础缠K序列: List[缠论K线] = []
|
||||
@property
|
||||
def 线段序列(self) -> List[虚线]:
|
||||
return self.线段序列组[0]
|
||||
|
||||
self.普通K线序列: List[K线] = []
|
||||
self.缠论K线序列: List[缠论K线] = []
|
||||
@property
|
||||
def 中枢序列(self) -> List[中枢]:
|
||||
return self.中枢序列组[0]
|
||||
|
||||
self.分型序列: List[分型] = []
|
||||
@property
|
||||
def 扩展线段序列(self) -> List[虚线]:
|
||||
return self.扩展线段序列组[0]
|
||||
|
||||
self.笔序列: List[虚线] = []
|
||||
self.笔_中枢序列: List[中枢] = []
|
||||
@property
|
||||
def 扩展中枢序列(self) -> List[中枢]:
|
||||
return self.扩展中枢序列组[0]
|
||||
|
||||
self.线段序列: List[虚线] = []
|
||||
self.中枢序列: List[中枢] = []
|
||||
@property
|
||||
def 扩展线段序列_线段(self) -> List[虚线]:
|
||||
return self.混合扩展线段序列组[0]
|
||||
|
||||
self.扩展线段序列: List[虚线] = []
|
||||
self.扩展中枢序列: List[中枢] = []
|
||||
@property
|
||||
def 扩展中枢序列_线段(self) -> List[中枢]:
|
||||
return self.混合扩展中枢序列组[0]
|
||||
|
||||
self.扩展线段序列_线段: List[虚线] = []
|
||||
self.扩展中枢序列_线段: List[中枢] = []
|
||||
@property
|
||||
def 线段_线段序列(self) -> List[虚线]:
|
||||
return self.线段序列组[1]
|
||||
|
||||
self.线段_线段序列: List[虚线] = []
|
||||
self.线段_中枢序列: List[中枢] = []
|
||||
@property
|
||||
def 线段_中枢序列(self) -> List[中枢]:
|
||||
return self.中枢序列组[1]
|
||||
|
||||
self.扩展线段序列_扩展线段: List[虚线] = []
|
||||
self.扩展中枢序列_扩展线段: List[中枢] = []
|
||||
@property
|
||||
def 扩展线段序列_扩展线段(self) -> List[虚线]:
|
||||
return self.扩展线段序列组[1]
|
||||
|
||||
@property
|
||||
def 扩展中枢序列_扩展线段(self) -> List[中枢]:
|
||||
return self.扩展中枢序列组[1]
|
||||
|
||||
def 投喂原始数据(self, 时间戳: datetime, 开: float, 高: float, 低: float, 收: float, 量: float):
|
||||
"""便捷入口,直接从 OHLCV 创建 K线 并投喂
|
||||
@@ -5912,28 +5962,33 @@ class 观察者:
|
||||
if 当前分型 is None:
|
||||
return
|
||||
|
||||
self.配置.分析笔 and 笔.分析(当前分型, self.分型序列, self.笔序列, self.缠论K线序列, self.普通K线序列, 0, self.配置)
|
||||
笔.分析(当前分型, self.分型序列, self.笔序列, self.缠论K线序列, self.普通K线序列, 0, self.配置)
|
||||
if not self.分型序列:
|
||||
return
|
||||
|
||||
self.配置.分析笔中枢 and 中枢.分析(self.笔序列, self.笔_中枢序列)
|
||||
中枢.分析(self.笔序列, self.笔_中枢序列, True, "", 0)
|
||||
if not self.笔序列:
|
||||
return
|
||||
|
||||
self.配置.分析线段 and 线段.分析(self.笔序列, self.线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.线段序列, self.中枢序列)
|
||||
for i in range(self.线段分析层次):
|
||||
if i == 0:
|
||||
线段.分析(self.笔序列, self.线段序列组[i], self.配置)
|
||||
中枢.分析(self.线段序列组[i], self.中枢序列组[i], True, "", 0)
|
||||
continue
|
||||
线段.分析(self.线段序列组[i - 1], self.线段序列组[i], self.配置)
|
||||
中枢.分析(self.线段序列组[i], self.中枢序列组[i], True, "", 0)
|
||||
|
||||
self.配置.分析扩展线段 and 线段.扩展分析(self.笔序列, self.扩展线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.扩展线段序列, self.扩展中枢序列)
|
||||
for i in range(self.扩展线段分析层次):
|
||||
if i == 0:
|
||||
线段.扩展分析(self.笔序列, self.扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.扩展线段序列组[i], self.扩展中枢序列组[i], True, "", 0)
|
||||
continue
|
||||
线段.扩展分析(self.扩展线段序列组[i - 1], self.扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.扩展线段序列组[i], self.扩展中枢序列组[i], True, "", 0)
|
||||
|
||||
self.配置.分析扩展线段 and 线段.扩展分析(self.线段序列, self.扩展线段序列_线段, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.扩展线段序列_线段, self.扩展中枢序列_线段)
|
||||
|
||||
self.配置.分析线段 and 线段.分析(self.线段序列, self.线段_线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.线段_线段序列, self.线段_中枢序列)
|
||||
|
||||
self.配置.分析扩展线段 and 线段.扩展分析(self.扩展线段序列, self.扩展线段序列_扩展线段, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.扩展线段序列_扩展线段, self.扩展中枢序列_扩展线段)
|
||||
for i in range(self.混合扩展线段分析层次):
|
||||
线段.扩展分析(self.线段序列组[i], self.混合扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.混合扩展线段序列组[i], self.混合扩展中枢序列组[i], True, "", 0)
|
||||
|
||||
def 测试_保存数据(self, root: str = None) -> str:
|
||||
"""拆分各序列数据,单独存文件,文件名为对应变量名
|
||||
@@ -5941,30 +5996,15 @@ class 观察者:
|
||||
:param root: 保存根目录(可选)
|
||||
:return: 保存目录
|
||||
"""
|
||||
# 提取各类文本数据
|
||||
笔序列_文本数据 = [筆.获取数据文本() for 筆 in self.笔序列]
|
||||
线段序列_文本数据 = [实线.获取数据文本() for 实线 in self.线段序列]
|
||||
扩展线段序列_数据文本 = [实线.获取数据文本() for 实线 in self.扩展线段序列]
|
||||
扩展线段序列_线段_数据文本 = [实线.获取数据文本() for 实线 in self.扩展线段序列_线段]
|
||||
线段_线段序列_数据文本 = [实线.获取数据文本() for 实线 in self.线段_线段序列]
|
||||
扩展线段序列_扩展线段_数据文本 = [实线.获取数据文本() for 实线 in self.扩展线段序列_扩展线段]
|
||||
|
||||
笔_中枢序列_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.笔_中枢序列]
|
||||
中枢序列_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.中枢序列]
|
||||
扩展中枢序列_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.扩展中枢序列]
|
||||
扩展中枢序列_线段_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.扩展中枢序列_线段]
|
||||
线段_中枢序列_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.线段_中枢序列]
|
||||
扩展中枢序列_扩展线段_数据文本 = [当前中枢.获取数据文本() for 当前中枢 in self.扩展中枢序列_扩展线段]
|
||||
|
||||
# ===================== 优化点:优先使用传入的 root 目录 =====================
|
||||
if root is not None:
|
||||
# 使用用户指定的根目录
|
||||
根目录 = Path(root)
|
||||
else:
|
||||
# 默认:当前脚本所在目录
|
||||
根目录 = Path(__file__).parent
|
||||
# 默认:系统临时目录
|
||||
根目录 = tempfile.gettempdir()
|
||||
|
||||
# 生成子目录名称(不变)
|
||||
# 生成子目录名称
|
||||
起始时间 = int(self.普通K线序列[0].时间戳.timestamp())
|
||||
结束时间 = int(self.普通K线序列[-1].时间戳.timestamp())
|
||||
目录标识 = f"Py_{self.标识}_{起始时间}_{结束时间}"
|
||||
@@ -5973,28 +6013,29 @@ class 观察者:
|
||||
保存路径 = 根目录 / 目录标识
|
||||
保存路径.mkdir(exist_ok=True, parents=True) # parents=True 支持多级目录自动创建
|
||||
|
||||
# 映射:变量名 -> 数据列表
|
||||
数据映射 = [
|
||||
("笔序列_文本数据", 笔序列_文本数据),
|
||||
("线段序列_文本数据", 线段序列_文本数据),
|
||||
("扩展线段序列_数据文本", 扩展线段序列_数据文本),
|
||||
("扩展线段序列_线段_数据文本", 扩展线段序列_线段_数据文本),
|
||||
("线段_线段序列_数据文本", 线段_线段序列_数据文本),
|
||||
("扩展线段序列_扩展线段_数据文本", 扩展线段序列_扩展线段_数据文本),
|
||||
("笔_中枢序列_数据文本", 笔_中枢序列_数据文本),
|
||||
("中枢序列_数据文本", 中枢序列_数据文本),
|
||||
("扩展中枢序列_数据文本", 扩展中枢序列_数据文本),
|
||||
("扩展中枢序列_线段_数据文本", 扩展中枢序列_线段_数据文本),
|
||||
("线段_中枢序列_数据文本", 线段_中枢序列_数据文本),
|
||||
("扩展中枢序列_扩展线段_数据文本", 扩展中枢序列_扩展线段_数据文本),
|
||||
]
|
||||
|
||||
# 逐个写入独立文件
|
||||
for 文件名, 数据列表 in 数据映射:
|
||||
def 保存序列(序列):
|
||||
if len(序列) == 0:
|
||||
return
|
||||
数据列表 = [对象.获取数据文本() for 对象 in 序列]
|
||||
文件名 = 序列[0].标识
|
||||
文件全路径 = 保存路径 / f"{文件名}.txt"
|
||||
# 逐个写入独立文件
|
||||
with open(文件全路径, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(数据列表))
|
||||
f.write("\n") # 向 C99 对齐
|
||||
|
||||
保存序列(self.笔序列)
|
||||
保存序列(self.笔_中枢序列)
|
||||
for i in range(self.线段分析层次):
|
||||
保存序列(self.线段序列组[i])
|
||||
保存序列(self.中枢序列组[i])
|
||||
for i in range(self.扩展线段分析层次):
|
||||
保存序列(self.扩展线段序列组[i])
|
||||
保存序列(self.扩展中枢序列组[i])
|
||||
for i in range(self.线段分析层次):
|
||||
保存序列(self.混合扩展线段序列组[i])
|
||||
保存序列(self.混合扩展中枢序列组[i])
|
||||
|
||||
logger.warning(f"全部数据拆分保存完成,目录:{保存路径.resolve()}")
|
||||
return str(保存路径.resolve())
|
||||
|
||||
@@ -6003,44 +6044,55 @@ class 观察者:
|
||||
pass
|
||||
|
||||
def 静态重新分析(self):
|
||||
"""静态重新分析(占位方法)"""
|
||||
"""静态重新分析"""
|
||||
self.分型序列: List[分型] = []
|
||||
|
||||
self.笔序列: List[虚线] = []
|
||||
self.笔_中枢序列: List[中枢] = []
|
||||
|
||||
self.线段序列: List[虚线] = []
|
||||
self.中枢序列: List[中枢] = []
|
||||
self.线段序列组: List[List[虚线],] = [] # 线段, 线段<线段>,线段<线段<线段>>...
|
||||
self.中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.线段分析层次):
|
||||
self.线段序列组.append(list())
|
||||
self.中枢序列组.append(list())
|
||||
|
||||
self.扩展线段序列: List[虚线] = []
|
||||
self.扩展中枢序列: List[中枢] = []
|
||||
self.扩展线段序列组: List[List[虚线],] = [] # 扩展线段, 扩展线段<扩展线段>, 扩展线段<扩展线段<扩展线段>>...
|
||||
self.扩展中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.扩展线段分析层次):
|
||||
self.扩展线段序列组.append(list())
|
||||
self.扩展中枢序列组.append(list())
|
||||
|
||||
self.扩展线段序列_线段: List[虚线] = []
|
||||
self.扩展中枢序列_线段: List[中枢] = []
|
||||
|
||||
self.线段_线段序列: List[虚线] = []
|
||||
self.线段_中枢序列: List[中枢] = []
|
||||
|
||||
self.扩展线段序列_扩展线段: List[虚线] = []
|
||||
self.扩展中枢序列_扩展线段: List[中枢] = []
|
||||
self.混合扩展线段序列组: List[List[虚线],] = [] # 扩展线段<线段>, 扩展线段<线段<线段>>, 扩展线段<线段<线段<线段>>>...
|
||||
self.混合扩展中枢序列组: List[List[中枢],] = []
|
||||
for i in range(self.混合扩展线段分析层次):
|
||||
self.混合扩展线段序列组.append(list())
|
||||
self.混合扩展中枢序列组.append(list())
|
||||
|
||||
for i in range(1, len(self.缠论K线序列) - 1):
|
||||
当前分型 = 分型(self.缠论K线序列[i - 1], self.缠论K线序列[i], self.缠论K线序列[i + 1])
|
||||
笔.分析(当前分型, self.分型序列, self.笔序列, self.缠论K线序列, self.普通K线序列, 0, self.配置)
|
||||
|
||||
self.配置.分析笔中枢 and 中枢.分析(self.笔序列, self.笔_中枢序列)
|
||||
中枢.分析(self.笔序列, self.笔_中枢序列, True, "", 0)
|
||||
|
||||
self.配置.分析线段 and 线段.分析(self.笔序列, self.线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.线段序列, self.中枢序列)
|
||||
for i in range(self.线段分析层次):
|
||||
if i == 0:
|
||||
线段.分析(self.笔序列, self.线段序列组[i], self.配置)
|
||||
中枢.分析(self.线段序列组[i], self.中枢序列组[i], True, "", 0)
|
||||
continue
|
||||
线段.分析(self.线段序列组[i - 1], self.线段序列组[i], self.配置)
|
||||
中枢.分析(self.线段序列组[i], self.中枢序列组[i], True, "", 0)
|
||||
|
||||
self.配置.分析扩展线段 and 线段.扩展分析(self.笔序列, self.扩展线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.扩展线段序列, self.扩展中枢序列)
|
||||
for i in range(self.扩展线段分析层次):
|
||||
if i == 0:
|
||||
线段.扩展分析(self.笔序列, self.扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.扩展线段序列组[i], self.扩展中枢序列组[i], True, "", 0)
|
||||
continue
|
||||
线段.扩展分析(self.扩展线段序列组[i - 1], self.扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.扩展线段序列组[i], self.扩展中枢序列组[i], True, "", 0)
|
||||
|
||||
self.配置.分析扩展线段 and 线段.扩展分析(self.线段序列, self.扩展线段序列_线段, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.扩展线段序列_线段, self.扩展中枢序列_线段)
|
||||
|
||||
self.配置.分析线段 and 线段.分析(self.线段序列, self.线段_线段序列, self.配置)
|
||||
self.配置.分析线段中枢 and 中枢.分析(self.线段_线段序列, self.线段_中枢序列)
|
||||
for i in range(self.混合扩展线段分析层次):
|
||||
线段.扩展分析(self.线段序列组[i], self.混合扩展线段序列组[i], self.配置)
|
||||
中枢.分析(self.混合扩展线段序列组[i], self.混合扩展中枢序列组[i], True, "", 0)
|
||||
|
||||
def 加载本地数据(self, 文件路径: str):
|
||||
"""重置基础序列后加载数据文件
|
||||
@@ -6417,7 +6469,6 @@ def K线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
return True, "K线:全部字段结构、数值校验完全一致"
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
def 缠论K线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
"""缠论K线:基础字段+标的K线递归校验"""
|
||||
比对字段 = ["序号", "时间戳", "高", "低", "方向", "分型", "周期", "标识", "分型特征值", "原始起始序号", "原始结束序号", "标的K线", "买卖点信息"]
|
||||
@@ -6470,7 +6521,6 @@ def 缠论K线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
return True, "缠论K线:全部字段、嵌套原始K线校验一致"
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
def 分型相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
"""分型:左/中/右缠论K线递归 + 自有字段"""
|
||||
比对字段 = ["左", "中", "右", "_结构", "_时间戳", "_分型特征值"]
|
||||
@@ -6542,18 +6592,17 @@ def 缺口相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
return True, "缺口:上下沿价格校验完全一致"
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
def 线段特征相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
"""线段特征:基础序列虚线列表逐项校验"""
|
||||
比对字段 = ["序号", "标识", "线段方向", "基础序列"]
|
||||
标签 = f"线段特征校验[A标识={A.标识}, B标识={B.标识}]"
|
||||
标签 = f"线段特征校验[A标识={A.标识},B标识={B.标识}]"
|
||||
for 字段 in 比对字段:
|
||||
a有 = hasattr(A, 字段)
|
||||
b有 = hasattr(B, 字段)
|
||||
if a有 and not b有:
|
||||
return False, f"{标签}:[{字段}]A存在、B缺失属性"
|
||||
return False, f"{标签}: [{字段}]A存在、B缺失属性"
|
||||
if not a有 and b有:
|
||||
return False, f"{标签}:[{字段}]B存在、A缺失属性"
|
||||
return False, f"{标签}: [{字段}]B存在、A缺失属性"
|
||||
if not (a有 and b有):
|
||||
continue
|
||||
|
||||
@@ -6561,7 +6610,7 @@ def 线段特征相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
valB = getattr(B, 字段)
|
||||
if 字段 == "基础序列":
|
||||
if len(valA) != len(valB):
|
||||
return False, f"{标签}:[基础序列]列表长度不一致,A长度={len(valA)},B长度={len(valB)}"
|
||||
return False, f"{标签}: [基础序列]列表长度不一致,A长度={len(valA)},B长度={len(valB)}"
|
||||
for idx, (itemA, itemB) in enumerate(zip(valA, valB)):
|
||||
eq, msg = 虚线相等(itemA, itemB, 浮点容差)
|
||||
if not eq:
|
||||
@@ -6569,25 +6618,24 @@ def 线段特征相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
|
||||
elif 字段 == "线段方向":
|
||||
if str(valA) != str(valB):
|
||||
return False, f"{标签}:[{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
return False, f"{标签}: [{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
else:
|
||||
if valA != valB:
|
||||
return False, f"{标签}:[{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
return False, f"{标签}: [{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
return True, f"{标签}:字段与内部虚线序列全部一致"
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
def 中枢相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
"""中枢:基础序列虚线列表+第三买卖线单虚线"""
|
||||
比对字段 = ["序号", "标识", "级别", "基础序列", "第三买卖线", "本级_第三买卖线"]
|
||||
标签 = f"中枢校验[A标识={A.标识}, B标识={B.标识}]"
|
||||
标签 = f"中枢校验[A标识={A.标识},B标识={B.标识}]"
|
||||
for 字段 in 比对字段:
|
||||
a有 = hasattr(A, 字段)
|
||||
b有 = hasattr(B, 字段)
|
||||
if a有 and not b有:
|
||||
return False, f"{标签}:[{字段}]A存在、B缺失属性"
|
||||
return False, f"{标签}: [{字段}]A存在、B缺失属性"
|
||||
if not a有 and b有:
|
||||
return False, f"{标签}:[{字段}]B存在、A缺失属性"
|
||||
return False, f"{标签}: [{字段}]B存在、A缺失属性"
|
||||
if not (a有 and b有):
|
||||
continue
|
||||
|
||||
@@ -6596,7 +6644,7 @@ def 中枢相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
|
||||
if 字段 == "基础序列":
|
||||
if len(valA) != len(valB):
|
||||
return False, f"{标签}:[基础序列]长度不一致 A={len(valA)},B={len(valB)}"
|
||||
return False, f"{标签}: [基础序列]长度不一致 A={len(valA)},B={len(valB)}"
|
||||
for idx, (itemA, itemB) in enumerate(zip(valA, valB)):
|
||||
eq, msg = 虚线相等(itemA, itemB, 浮点容差)
|
||||
if not eq:
|
||||
@@ -6605,29 +6653,28 @@ def 中枢相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
if valA is None and valB is None:
|
||||
continue
|
||||
if valA is None or valB is None:
|
||||
return False, f"{标签}:[{字段}]空值不一致 A={valA is None},B={valB is None}"
|
||||
return False, f"{标签}: [{字段}]空值不一致 A={valA is None},B={valB is None}"
|
||||
eq, msg = 虚线相等(valA, valB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[{字段}]子虚线异常 >> {msg}"
|
||||
return False, f"{标签}: [{字段}]子虚线异常 >> {msg}"
|
||||
else:
|
||||
if valA != valB:
|
||||
return False, f"{标签}:[{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
return False, f"{标签}: [{字段}]数值不等,A={repr(valA)},B={repr(valB)}"
|
||||
|
||||
return True, f"{标签}:基础序列+第三买卖线全部校验一致"
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
def 虚线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
"""虚线(笔/线段):全量字段、分型/缺口/K线/列表嵌套精细化报错"""
|
||||
比对字段 = ["标识", "序号", "级别", "文", "武", "有效性", "基础序列", "特征序列", "实_中枢序列", "虚_中枢序列", "合_中枢序列", "确认K线", "模式", "_特征序列_显示", "前一缺口", "前一结束位置", "短路修正"]
|
||||
标签 = f"虚线校验[A标识={A.标识}, B标识={B.标识}]"
|
||||
标签 = f"虚线校验[A标识={A.标识},B标识={B.标识}]"
|
||||
for 字段 in 比对字段:
|
||||
a有 = hasattr(A, 字段)
|
||||
b有 = hasattr(B, 字段)
|
||||
if a有 and not b有:
|
||||
return False, f"{标签}:[{字段}]A存在属性、B缺失属性"
|
||||
return False, f"{标签}: [{字段}]A存在属性、B缺失属性"
|
||||
if not a有 and b有:
|
||||
return False, f"{标签}:[{字段}]B存在属性、A缺失属性"
|
||||
return False, f"{标签}: [{字段}]B存在属性、A缺失属性"
|
||||
if not (a有 and b有):
|
||||
continue
|
||||
|
||||
@@ -6639,46 +6686,46 @@ def 虚线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
if valA is None and valB is None:
|
||||
continue
|
||||
if valA is None or valB is None:
|
||||
return False, f"{标签}:[{字段}]分型空值不一致 A={valA is None},B={valB is None}"
|
||||
return False, f"{标签}: [{字段}]分型空值不一致 A={valA is None},B={valB is None}"
|
||||
eq, msg = 分型相等(valA, valB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[{字段}]子分型异常 >> {msg}"
|
||||
return False, f"{标签}: [{字段}]子分型异常 >> {msg}"
|
||||
# 前一缺口
|
||||
elif 字段 == "前一缺口":
|
||||
if valA is None and valB is None:
|
||||
continue
|
||||
if valA is None or valB is None:
|
||||
return False, f"{标签}:[前一缺口]空值不一致 A={valA is None},B={valB is None}"
|
||||
return False, f"{标签}: [前一缺口]空值不一致 A={valA is None},B={valB is None}"
|
||||
eq, msg = 缺口相等(valA, valB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[前一缺口]子缺口异常 >> {msg}"
|
||||
return False, f"{标签}: [前一缺口]子缺口异常 >> {msg}"
|
||||
# 前一缺口
|
||||
elif 字段 == "前一结束位置":
|
||||
if valA is None and valB is None:
|
||||
continue
|
||||
if valA is None or valB is None:
|
||||
return False, f"{标签}:[前一结束位置]空值不一致 A={valA is None},B={valB is None}"
|
||||
return False, f"{标签}: [前一结束位置]空值不一致 A={valA is None},B={valB is None}"
|
||||
eq, msg = 虚线相等(valA, valB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[前一结束位置]异常 >> {msg}"
|
||||
return False, f"{标签}: [前一结束位置]异常 >> {msg}"
|
||||
# 确认K线
|
||||
elif 字段 == "确认K线":
|
||||
if valA is None and valB is None:
|
||||
continue
|
||||
if valA is None or valB is None:
|
||||
return False, f"{标签}:[确认K线]空值不一致 A={valA is None},B={valB is None}"
|
||||
return False, f"{标签}: [确认K线]空值不一致 A={valA is None},B={valB is None}"
|
||||
eq, msg = 缠论K线相等(valA, valB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[确认K线]子缠论K线异常 >> {msg}"
|
||||
return False, f"{标签}: [确认K线]子缠论K线异常 >> {msg}"
|
||||
# 各类列表
|
||||
elif 字段 in ("基础序列", "实_中枢序列", "虚_中枢序列", "合_中枢序列", "特征序列"):
|
||||
if len(valA) != len(valB):
|
||||
return False, f"{标签}:[{字段}]列表长度不一致 A={len(valA)},B={len(valB)}"
|
||||
return False, f"{标签}: [{字段}]列表长度不一致 A={len(valA)},B={len(valB)}"
|
||||
for idx, (itemA, itemB) in enumerate(zip(valA, valB)):
|
||||
if itemA is None and itemB is None:
|
||||
continue
|
||||
if itemA is None or itemB is None:
|
||||
return False, f"{标签}:[{字段}][{idx}]单项空值不一致 A={itemA is None},B={itemB is None}"
|
||||
return False, f"{标签}: [{字段}][{idx}]单项空值不一致 A={itemA is None},B={itemB is None}"
|
||||
if 字段 == "基础序列":
|
||||
eq, msg = 虚线相等(itemA, itemB, 浮点容差)
|
||||
elif "中枢" in 字段:
|
||||
@@ -6686,11 +6733,11 @@ def 虚线相等(A, B, 浮点容差: float = 1e-9) -> tuple[bool, str]:
|
||||
else:
|
||||
eq, msg = 线段特征相等(itemA, itemB, 浮点容差)
|
||||
if not eq:
|
||||
return False, f"{标签}:[{字段}][{idx}]子项异常 >> {msg}"
|
||||
return False, f"{标签}: [{字段}][{idx}]子项异常 >> {msg}"
|
||||
# 普通字段
|
||||
else:
|
||||
if valA != valB:
|
||||
return False, f"{标签}:[{字段}]数值不等 A={repr(valA)},B={repr(valB)}"
|
||||
return False, f"{标签}: [{字段}]数值不等 A={repr(valA)},B={repr(valB)}"
|
||||
|
||||
return True, f"{标签}:全字段、所有嵌套子结构校验全部一致"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "chanlun"
|
||||
version = "2606.21"
|
||||
version = "2606.34"
|
||||
description = "缠论技术分析库 — Rust 高性能实现"
|
||||
readme = { file = "README.md", content-type = "text/markdown" }
|
||||
license = { file = "LICENSE", content-type = "text/plain" }
|
||||
|
||||
+118
-10
@@ -675,6 +675,13 @@ impl 买卖点Py {
|
||||
/// 线段_线段序列 / 线段_中枢序列
|
||||
/// 扩展线段序列_扩展线段 / 扩展中枢序列_扩展线段
|
||||
///
|
||||
/// 分析层次(可读写):
|
||||
/// 线段分析层次: int (默认 3) / 扩展线段分析层次: int (默认 3) / 混合扩展线段分析层次: int (默认 3)
|
||||
///
|
||||
/// 序列组(只读,返回 list[list[...]]):
|
||||
/// 线段序列组 / 中枢序列组 / 扩展线段序列组 / 扩展中枢序列组
|
||||
/// 混合扩展线段序列组 / 混合扩展中枢序列组
|
||||
///
|
||||
/// 核心方法:
|
||||
/// 增加原始K线(普K) — 喂入一根普通K线,触发全层级增量计算
|
||||
/// 重置基础序列() — 清空所有计算状态和序列
|
||||
@@ -1040,7 +1047,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().线段序列 {
|
||||
for d in self.obs().线段序列() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1049,7 +1056,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().中枢序列 {
|
||||
for h in self.obs().中枢序列() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1058,7 +1065,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列 {
|
||||
for d in self.obs().扩展线段序列() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1067,7 +1074,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列 {
|
||||
for h in self.obs().扩展中枢序列() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1076,7 +1083,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展线段序列_线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列_线段 {
|
||||
for d in self.obs().扩展线段序列_线段() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1085,7 +1092,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展中枢序列_线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列_线段 {
|
||||
for h in self.obs().扩展中枢序列_线段() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1094,7 +1101,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 线段_线段序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().线段_线段序列 {
|
||||
for d in self.obs().线段_线段序列() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1103,7 +1110,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 线段_中枢序列(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().线段_中枢序列 {
|
||||
for h in self.obs().线段_中枢序列() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1112,7 +1119,7 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展线段序列_扩展线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for d in &self.obs().扩展线段序列_扩展线段 {
|
||||
for d in self.obs().扩展线段序列_扩展线段() {
|
||||
list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
@@ -1121,11 +1128,112 @@ impl 观察者Py {
|
||||
#[getter]
|
||||
fn 扩展中枢序列_扩展线段(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let list = pyo3::types::PyList::empty(py);
|
||||
for h in &self.obs().扩展中枢序列_扩展线段 {
|
||||
for h in self.obs().扩展中枢序列_扩展线段() {
|
||||
list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
// ---- 分析层次 getter/setter ----
|
||||
|
||||
#[getter]
|
||||
fn 线段分析层次(&self) -> usize {
|
||||
self.obs().线段分析层次
|
||||
}
|
||||
|
||||
#[setter]
|
||||
#[pyo3(name = "线段分析层次")]
|
||||
fn 设置_线段分析层次(&mut self, value: usize) {
|
||||
self.obs_mut().线段分析层次 = value;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 扩展线段分析层次(&self) -> usize {
|
||||
self.obs().扩展线段分析层次
|
||||
}
|
||||
|
||||
#[setter]
|
||||
#[pyo3(name = "扩展线段分析层次")]
|
||||
fn 设置_扩展线段分析层次(&mut self, value: usize) {
|
||||
self.obs_mut().扩展线段分析层次 = value;
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 混合扩展线段分析层次(&self) -> usize {
|
||||
self.obs().混合扩展线段分析层次
|
||||
}
|
||||
|
||||
#[setter]
|
||||
#[pyo3(name = "混合扩展线段分析层次")]
|
||||
fn 设置_混合扩展线段分析层次(&mut self, value: usize) {
|
||||
self.obs_mut().混合扩展线段分析层次 = value;
|
||||
}
|
||||
|
||||
// ---- 序列组 getters (返回 list[list[...]]) ----
|
||||
|
||||
#[getter]
|
||||
fn 线段序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._虚线序列组_to_py(&self.obs().线段序列组, py)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 中枢序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._中枢序列组_to_py(&self.obs().中枢序列组, py)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 扩展线段序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._虚线序列组_to_py(&self.obs().扩展线段序列组, py)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 扩展中枢序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._中枢序列组_to_py(&self.obs().扩展中枢序列组, py)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 混合扩展线段序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._虚线序列组_to_py(&self.obs().混合扩展线段序列组, py)
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn 混合扩展中枢序列组(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
self._中枢序列组_to_py(&self.obs().混合扩展中枢序列组, py)
|
||||
}
|
||||
}
|
||||
|
||||
impl 观察者Py {
|
||||
fn _虚线序列组_to_py(
|
||||
&self,
|
||||
组: &Vec<Vec<Arc<chanlun::structure::dash_line::虚线>>>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Py<PyAny>> {
|
||||
let outer = pyo3::types::PyList::empty(py);
|
||||
for inner_vec in 组 {
|
||||
let inner_list = pyo3::types::PyList::empty(py);
|
||||
for d in inner_vec {
|
||||
inner_list.append(dashed_to_py(py, Arc::clone(d)))?;
|
||||
}
|
||||
outer.append(inner_list)?;
|
||||
}
|
||||
Ok(outer.into())
|
||||
}
|
||||
|
||||
fn _中枢序列组_to_py(
|
||||
&self,
|
||||
组: &Vec<Vec<Arc<chanlun::algorithm::hub::中枢>>>,
|
||||
py: Python<'_>,
|
||||
) -> PyResult<Py<PyAny>> {
|
||||
let outer = pyo3::types::PyList::empty(py);
|
||||
for inner_vec in 组 {
|
||||
let inner_list = pyo3::types::PyList::empty(py);
|
||||
for h in inner_vec {
|
||||
inner_list.append(hub_to_py(py, Arc::clone(h)))?;
|
||||
}
|
||||
outer.append(inner_list)?;
|
||||
}
|
||||
Ok(outer.into())
|
||||
}
|
||||
}
|
||||
|
||||
// ========== K线合成器 ==========
|
||||
|
||||
+206
-234
@@ -538,89 +538,75 @@ fn 中枢相等(
|
||||
B: &Bound<'_, PyAny>,
|
||||
浮点容差: f64,
|
||||
) -> PyResult<(bool, String)> {
|
||||
with_cache!(
|
||||
C_HUB,
|
||||
4096,
|
||||
(
|
||||
A.as_ptr() as usize,
|
||||
B.as_ptr() as usize,
|
||||
浮点容差.to_bits() as i64
|
||||
),
|
||||
{
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
A.cast::<crate::algorithm_py::中枢Py>(),
|
||||
B.cast::<crate::algorithm_py::中枢Py>(),
|
||||
) {
|
||||
return Ok(a.borrow().inner.相等(&b.borrow().inner, 浮点容差));
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
A.cast::<crate::algorithm_py::中枢Py>(),
|
||||
B.cast::<crate::algorithm_py::中枢Py>(),
|
||||
) {
|
||||
return Ok(a.borrow().inner.相等(&b.borrow().inner, 浮点容差));
|
||||
}
|
||||
let a标识 = 尝试获取标识(A);
|
||||
let b标识 = 尝试获取标识(B);
|
||||
let 标签 = format!("中枢校验[A标识={a标识},B标识={b标识}]");
|
||||
for &字段 in &[
|
||||
"序号",
|
||||
"标识",
|
||||
"级别",
|
||||
"基础序列",
|
||||
"第三买卖线",
|
||||
"本级_第三买卖线",
|
||||
] {
|
||||
let (a有, b有) = (A.hasattr(字段)?, B.hasattr(字段)?);
|
||||
if a有 && !b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] A存在 B缺失属性")));
|
||||
}
|
||||
if !a有 && b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] B存在 A缺失属性")));
|
||||
}
|
||||
if !a有 && !b有 {
|
||||
continue;
|
||||
}
|
||||
let valA = A.getattr(字段)?;
|
||||
let valB = B.getattr(字段)?;
|
||||
|
||||
if 字段 == "基础序列" {
|
||||
let len_a: usize = valA.len()?;
|
||||
let len_b: usize = valB.len()?;
|
||||
if len_a != len_b {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: [基础序列] 长度不一致 A={len_a},B={len_b}"),
|
||||
));
|
||||
}
|
||||
let a标识 = 尝试获取标识(A);
|
||||
let b标识 = 尝试获取标识(B);
|
||||
let 标签 = format!("中枢校验[A标识={a标识},B标识={b标识}]");
|
||||
for &字段 in &[
|
||||
"序号",
|
||||
"标识",
|
||||
"级别",
|
||||
"基础序列",
|
||||
"第三买卖线",
|
||||
"本级_第三买卖线",
|
||||
] {
|
||||
let (a有, b有) = (A.hasattr(字段)?, B.hasattr(字段)?);
|
||||
if a有 && !b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] A存在 B缺失属性")));
|
||||
for idx in 0..len_a {
|
||||
let itemA = valA.get_item(idx)?;
|
||||
let itemB = valB.get_item(idx)?;
|
||||
let (eq, msg) = 虚线相等(&itemA, &itemB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: 基础序列[{idx}]虚线异常 >> {msg}")));
|
||||
}
|
||||
if !a有 && b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] B存在 A缺失属性")));
|
||||
}
|
||||
if !a有 && !b有 {
|
||||
}
|
||||
} else if 字段 == "第三买卖线" || 字段 == "本级_第三买卖线" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
let valA = A.getattr(字段)?;
|
||||
let valB = B.getattr(字段)?;
|
||||
|
||||
if 字段 == "基础序列" {
|
||||
let len_a: usize = valA.len()?;
|
||||
let len_b: usize = valB.len()?;
|
||||
if len_a != len_b {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: [基础序列] 长度不一致 A={len_a},B={len_b}"),
|
||||
));
|
||||
}
|
||||
for idx in 0..len_a {
|
||||
let itemA = valA.get_item(idx)?;
|
||||
let itemB = valB.get_item(idx)?;
|
||||
let (eq, msg) = 虚线相等(&itemA, &itemB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: 基础序列[{idx}]虚线异常 >> {msg}"),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if 字段 == "第三买卖线" || 字段 == "本级_第三买卖线" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 虚线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [{字段}]子虚线异常 >> {msg}")));
|
||||
}
|
||||
} else {
|
||||
let eq: bool = valA.eq(&valB)?;
|
||||
if !eq {
|
||||
let ra = valA.repr()?.extract::<String>().unwrap_or_default();
|
||||
let rb = valB.repr()?.extract::<String>().unwrap_or_default();
|
||||
return Ok((false, format!("{标签}: [{字段}] 数值不等 A={ra},B={rb}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((true, format!("{标签}: 基础序列+第三买卖线全部校验一致")))
|
||||
let (eq, msg) = 虚线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [{字段}]子虚线异常 >> {msg}")));
|
||||
}
|
||||
} else {
|
||||
let eq: bool = valA.eq(&valB)?;
|
||||
if !eq {
|
||||
let ra = valA.repr()?.extract::<String>().unwrap_or_default();
|
||||
let rb = valB.repr()?.extract::<String>().unwrap_or_default();
|
||||
return Ok((false, format!("{标签}: [{字段}] 数值不等 A={ra},B={rb}")));
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Ok((true, format!("{标签}: 基础序列+第三买卖线全部校验一致")))
|
||||
}
|
||||
|
||||
// ========== 虚线相等 ==========
|
||||
@@ -632,168 +618,154 @@ fn 虚线相等(
|
||||
B: &Bound<'_, PyAny>,
|
||||
浮点容差: f64,
|
||||
) -> PyResult<(bool, String)> {
|
||||
with_cache!(
|
||||
C_DASH,
|
||||
4096,
|
||||
(
|
||||
A.as_ptr() as usize,
|
||||
B.as_ptr() as usize,
|
||||
浮点容差.to_bits() as i64
|
||||
),
|
||||
{
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
A.cast::<crate::structure_py::虚线Py>(),
|
||||
B.cast::<crate::structure_py::虚线Py>(),
|
||||
) {
|
||||
return Ok(a.borrow().inner.相等(&b.borrow().inner, 浮点容差));
|
||||
}
|
||||
let a标识 = 尝试获取标识(A);
|
||||
let b标识 = 尝试获取标识(B);
|
||||
let 标签 = format!("虚线校验[A标识={a标识},B标识={b标识}]");
|
||||
let 比对字段 = [
|
||||
"标识",
|
||||
"序号",
|
||||
"级别",
|
||||
"文",
|
||||
"武",
|
||||
"有效性",
|
||||
"基础序列",
|
||||
"特征序列",
|
||||
"实_中枢序列",
|
||||
"虚_中枢序列",
|
||||
"合_中枢序列",
|
||||
"确认K线",
|
||||
"模式",
|
||||
"_特征序列_显示",
|
||||
"前一缺口",
|
||||
"前一结束位置",
|
||||
"短路修正",
|
||||
];
|
||||
for &字段 in &比对字段 {
|
||||
let (a有, b有) = (A.hasattr(字段)?, B.hasattr(字段)?);
|
||||
if a有 && !b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] A存在属性 B缺失属性")));
|
||||
}
|
||||
if !a有 && b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] B存在属性 A缺失属性")));
|
||||
}
|
||||
if !a有 && !b有 {
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
A.cast::<crate::structure_py::虚线Py>(),
|
||||
B.cast::<crate::structure_py::虚线Py>(),
|
||||
) {
|
||||
return Ok(a.borrow().inner.相等(&b.borrow().inner, 浮点容差));
|
||||
}
|
||||
let a标识 = 尝试获取标识(A);
|
||||
let b标识 = 尝试获取标识(B);
|
||||
let 标签 = format!("虚线校验[A标识={a标识},B标识={b标识}]");
|
||||
let 比对字段 = [
|
||||
"标识",
|
||||
"序号",
|
||||
"级别",
|
||||
"文",
|
||||
"武",
|
||||
"有效性",
|
||||
"基础序列",
|
||||
"特征序列",
|
||||
"实_中枢序列",
|
||||
"虚_中枢序列",
|
||||
"合_中枢序列",
|
||||
"确认K线",
|
||||
"模式",
|
||||
"_特征序列_显示",
|
||||
"前一缺口",
|
||||
"前一结束位置",
|
||||
"短路修正",
|
||||
];
|
||||
for &字段 in &比对字段 {
|
||||
let (a有, b有) = (A.hasattr(字段)?, B.hasattr(字段)?);
|
||||
if a有 && !b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] A存在属性 B缺失属性")));
|
||||
}
|
||||
if !a有 && b有 {
|
||||
return Ok((false, format!("{标签}: [{字段}] B存在属性 A缺失属性")));
|
||||
}
|
||||
if !a有 && !b有 {
|
||||
continue;
|
||||
}
|
||||
let valA = A.getattr(字段)?;
|
||||
let valB = B.getattr(字段)?;
|
||||
|
||||
// 文/武:分型
|
||||
if 字段 == "文" || 字段 == "武" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
let valA = A.getattr(字段)?;
|
||||
let valB = B.getattr(字段)?;
|
||||
|
||||
// 文/武:分型
|
||||
if 字段 == "文" || 字段 == "武" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 分型相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [{字段}]子分型异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 前一缺口
|
||||
else if 字段 == "前一缺口" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 缺口相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [前一缺口]子缺口异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 前一结束位置
|
||||
else if 字段 == "前一结束位置" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 虚线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [前一结束位置]异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 确认K线
|
||||
else if 字段 == "确认K线" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 缠论K线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [确认K线]子缠论K线异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 各类列表
|
||||
else if 字段 == "基础序列"
|
||||
|| 字段 == "实_中枢序列"
|
||||
|| 字段 == "虚_中枢序列"
|
||||
|| 字段 == "合_中枢序列"
|
||||
|| 字段 == "特征序列"
|
||||
{
|
||||
let len_a: usize = valA.len()?;
|
||||
let len_b: usize = valB.len()?;
|
||||
if len_a != len_b {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: [{字段}]列表长度不一致 A={len_a},B={len_b}"),
|
||||
));
|
||||
}
|
||||
for idx in 0..len_a {
|
||||
let itemA = valA.get_item(idx)?;
|
||||
let itemB = valB.get_item(idx)?;
|
||||
if let Some(r) =
|
||||
检查空值一致(&itemA, &itemB, &format!("{字段}[{idx}]"), &标签)
|
||||
{
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = if 字段 == "基础序列" {
|
||||
虚线相等(&itemA, &itemB, 浮点容差)?
|
||||
} else if 字段.contains("中枢") {
|
||||
中枢相等(&itemA, &itemB, 浮点容差)?
|
||||
} else {
|
||||
线段特征相等(&itemA, &itemB, 浮点容差)?
|
||||
};
|
||||
if !eq {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: [{字段}][{idx}]子项异常 >> {msg}"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 普通字段
|
||||
else {
|
||||
let eq: bool = valA.eq(&valB)?;
|
||||
if !eq {
|
||||
let ra = valA.repr()?.extract::<String>().unwrap_or_default();
|
||||
let rb = valB.repr()?.extract::<String>().unwrap_or_default();
|
||||
return Ok((false, format!("{标签}: [{字段}]数值不等 A={ra},B={rb}")));
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 分型相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [{字段}]子分型异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 前一缺口
|
||||
else if 字段 == "前一缺口" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Ok((true, format!("{标签}: 全字段所有嵌套子结构校验一致")))
|
||||
let (eq, msg) = 缺口相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [前一缺口]子缺口异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
)
|
||||
// 前一结束位置
|
||||
else if 字段 == "前一结束位置" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 虚线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [前一结束位置]异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 确认K线
|
||||
else if 字段 == "确认K线" {
|
||||
if let Some(r) = 检查空值一致(&valA, &valB, 字段, &标签) {
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = 缠论K线相等(&valA, &valB, 浮点容差)?;
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [确认K线]子缠论K线异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
// 各类列表
|
||||
else if 字段 == "基础序列"
|
||||
|| 字段 == "实_中枢序列"
|
||||
|| 字段 == "虚_中枢序列"
|
||||
|| 字段 == "合_中枢序列"
|
||||
|| 字段 == "特征序列"
|
||||
{
|
||||
let len_a: usize = valA.len()?;
|
||||
let len_b: usize = valB.len()?;
|
||||
if len_a != len_b {
|
||||
return Ok((
|
||||
false,
|
||||
format!("{标签}: [{字段}]列表长度不一致 A={len_a},B={len_b}"),
|
||||
));
|
||||
}
|
||||
for idx in 0..len_a {
|
||||
let itemA = valA.get_item(idx)?;
|
||||
let itemB = valB.get_item(idx)?;
|
||||
if let Some(r) =
|
||||
检查空值一致(&itemA, &itemB, &format!("{字段}[{idx}]"), &标签)
|
||||
{
|
||||
if !r.0 {
|
||||
return Ok((false, r.1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (eq, msg) = if 字段 == "基础序列" {
|
||||
虚线相等(&itemA, &itemB, 浮点容差)?
|
||||
} else if 字段.contains("中枢") {
|
||||
中枢相等(&itemA, &itemB, 浮点容差)?
|
||||
} else {
|
||||
线段特征相等(&itemA, &itemB, 浮点容差)?
|
||||
};
|
||||
if !eq {
|
||||
return Ok((false, format!("{标签}: [{字段}][{idx}]子项异常 >> {msg}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 普通字段
|
||||
else {
|
||||
let eq: bool = valA.eq(&valB)?;
|
||||
if !eq {
|
||||
let ra = valA.repr()?.extract::<String>().unwrap_or_default();
|
||||
let rb = valB.repr()?.extract::<String>().unwrap_or_default();
|
||||
return Ok((false, format!("{标签}: [{字段}]数值不等 A={ra},B={rb}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((true, format!("{标签}: 全字段所有嵌套子结构校验一致")))
|
||||
}
|
||||
|
||||
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
|
||||
@@ -1050,6 +1050,7 @@ impl 线段 {
|
||||
Self::_刷新(&线段序列[idx], 配置);
|
||||
|
||||
let 当前线段 = Arc::clone(&线段序列[idx]);
|
||||
当前线段.短路修正.store(true, Ordering::Relaxed);
|
||||
if 当前线段.特征序列.read().unwrap()[2].is_some() {
|
||||
let 段 = 虚线::创建线段(&[
|
||||
Arc::clone(&基础序列[基础序列.len() - 3]),
|
||||
|
||||
+291
-236
@@ -52,25 +52,22 @@ pub struct 观察者 {
|
||||
pub 笔序列: Vec<Arc<虚线>>,
|
||||
pub 笔_中枢序列: Vec<Arc<中枢>>,
|
||||
|
||||
// 线段
|
||||
pub 线段序列: Vec<Arc<虚线>>,
|
||||
pub 中枢序列: Vec<Arc<中枢>>,
|
||||
// 分析层次配置
|
||||
pub 线段分析层次: usize,
|
||||
pub 扩展线段分析层次: usize,
|
||||
pub 混合扩展线段分析层次: usize,
|
||||
|
||||
// 扩展线段(笔级)
|
||||
pub 扩展线段序列: Vec<Arc<虚线>>,
|
||||
pub 扩展中枢序列: Vec<Arc<中枢>>,
|
||||
// 线段组: [0]=线段, [1]=线段<线段>, [2]=线段<线段<线段>>
|
||||
pub 线段序列组: Vec<Vec<Arc<虚线>>>,
|
||||
pub 中枢序列组: Vec<Vec<Arc<中枢>>>,
|
||||
|
||||
// 扩展线段(线段级)
|
||||
pub 扩展线段序列_线段: Vec<Arc<虚线>>,
|
||||
pub 扩展中枢序列_线段: Vec<Arc<中枢>>,
|
||||
// 扩展线段组: [0]=扩展线段, [1]=扩展线段<扩展线段>, [2]=扩展线段<扩展线段<扩展线段>>
|
||||
pub 扩展线段序列组: Vec<Vec<Arc<虚线>>>,
|
||||
pub 扩展中枢序列组: Vec<Vec<Arc<中枢>>>,
|
||||
|
||||
// 线段之线段
|
||||
pub 线段_线段序列: Vec<Arc<虚线>>,
|
||||
pub 线段_中枢序列: Vec<Arc<中枢>>,
|
||||
|
||||
// 扩展线段之扩展线段
|
||||
pub 扩展线段序列_扩展线段: Vec<Arc<虚线>>,
|
||||
pub 扩展中枢序列_扩展线段: Vec<Arc<中枢>>,
|
||||
// 混合扩展线段组: [0]=扩展线段<线段>, [1]=扩展线段<线段<线段>>, [2]=扩展线段<线段<线段<线段>>>
|
||||
pub 混合扩展线段序列组: Vec<Vec<Arc<虚线>>>,
|
||||
pub 混合扩展中枢序列组: Vec<Vec<Arc<中枢>>>,
|
||||
|
||||
// 终止时间戳
|
||||
终止时间戳: Option<i64>,
|
||||
@@ -85,6 +82,30 @@ impl 观察者 {
|
||||
None
|
||||
};
|
||||
|
||||
let 线段分析层次 = 3usize;
|
||||
let 扩展线段分析层次 = 3usize;
|
||||
let 混合扩展线段分析层次 = 3usize;
|
||||
|
||||
let mut 线段序列组: Vec<Vec<Arc<虚线>>> = Vec::with_capacity(线段分析层次);
|
||||
let mut 中枢序列组: Vec<Vec<Arc<中枢>>> = Vec::with_capacity(线段分析层次);
|
||||
let mut 扩展线段序列组: Vec<Vec<Arc<虚线>>> = Vec::with_capacity(扩展线段分析层次);
|
||||
let mut 扩展中枢序列组: Vec<Vec<Arc<中枢>>> = Vec::with_capacity(扩展线段分析层次);
|
||||
let mut 混合扩展线段序列组: Vec<Vec<Arc<虚线>>> = Vec::with_capacity(混合扩展线段分析层次);
|
||||
let mut 混合扩展中枢序列组: Vec<Vec<Arc<中枢>>> = Vec::with_capacity(混合扩展线段分析层次);
|
||||
|
||||
for _ in 0..线段分析层次 {
|
||||
线段序列组.push(Vec::new());
|
||||
中枢序列组.push(Vec::new());
|
||||
}
|
||||
for _ in 0..扩展线段分析层次 {
|
||||
扩展线段序列组.push(Vec::new());
|
||||
扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
for _ in 0..混合扩展线段分析层次 {
|
||||
混合扩展线段序列组.push(Vec::new());
|
||||
混合扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
let mut instance = Self {
|
||||
符号: 符号.clone(),
|
||||
周期,
|
||||
@@ -95,16 +116,15 @@ impl 观察者 {
|
||||
分型序列: Vec::new(),
|
||||
笔序列: Vec::new(),
|
||||
笔_中枢序列: Vec::new(),
|
||||
线段序列: Vec::new(),
|
||||
中枢序列: Vec::new(),
|
||||
扩展线段序列: Vec::new(),
|
||||
扩展中枢序列: Vec::new(),
|
||||
扩展线段序列_线段: Vec::new(),
|
||||
扩展中枢序列_线段: Vec::new(),
|
||||
线段_线段序列: Vec::new(),
|
||||
线段_中枢序列: Vec::new(),
|
||||
扩展线段序列_扩展线段: Vec::new(),
|
||||
扩展中枢序列_扩展线段: Vec::new(),
|
||||
线段分析层次,
|
||||
扩展线段分析层次,
|
||||
混合扩展线段分析层次,
|
||||
线段序列组,
|
||||
中枢序列组,
|
||||
扩展线段序列组,
|
||||
扩展中枢序列组,
|
||||
混合扩展线段序列组,
|
||||
混合扩展中枢序列组,
|
||||
终止时间戳,
|
||||
};
|
||||
instance.配置.标识 = 符号;
|
||||
@@ -126,6 +146,58 @@ impl 观察者 {
|
||||
self.缠论K线序列.last()
|
||||
}
|
||||
|
||||
// ---- 向后兼容的属性访问器 ----
|
||||
|
||||
/// 线段序列 (线段序列组[0])
|
||||
pub fn 线段序列(&self) -> &Vec<Arc<虚线>> {
|
||||
&self.线段序列组[0]
|
||||
}
|
||||
|
||||
/// 中枢序列 (中枢序列组[0])
|
||||
pub fn 中枢序列(&self) -> &Vec<Arc<中枢>> {
|
||||
&self.中枢序列组[0]
|
||||
}
|
||||
|
||||
/// 线段_线段序列 (线段序列组[1])
|
||||
pub fn 线段_线段序列(&self) -> &Vec<Arc<虚线>> {
|
||||
&self.线段序列组[1]
|
||||
}
|
||||
|
||||
/// 线段_中枢序列 (中枢序列组[1])
|
||||
pub fn 线段_中枢序列(&self) -> &Vec<Arc<中枢>> {
|
||||
&self.中枢序列组[1]
|
||||
}
|
||||
|
||||
/// 扩展线段序列 (扩展线段序列组[0])
|
||||
pub fn 扩展线段序列(&self) -> &Vec<Arc<虚线>> {
|
||||
&self.扩展线段序列组[0]
|
||||
}
|
||||
|
||||
/// 扩展中枢序列 (扩展中枢序列组[0])
|
||||
pub fn 扩展中枢序列(&self) -> &Vec<Arc<中枢>> {
|
||||
&self.扩展中枢序列组[0]
|
||||
}
|
||||
|
||||
/// 扩展线段序列_扩展线段 (扩展线段序列组[1])
|
||||
pub fn 扩展线段序列_扩展线段(&self) -> &Vec<Arc<虚线>> {
|
||||
&self.扩展线段序列组[1]
|
||||
}
|
||||
|
||||
/// 扩展中枢序列_扩展线段 (扩展中枢序列组[1])
|
||||
pub fn 扩展中枢序列_扩展线段(&self) -> &Vec<Arc<中枢>> {
|
||||
&self.扩展中枢序列组[1]
|
||||
}
|
||||
|
||||
/// 扩展线段序列_线段 (混合扩展线段序列组[0])
|
||||
pub fn 扩展线段序列_线段(&self) -> &Vec<Arc<虚线>> {
|
||||
&self.混合扩展线段序列组[0]
|
||||
}
|
||||
|
||||
/// 扩展中枢序列_线段 (混合扩展中枢序列组[0])
|
||||
pub fn 扩展中枢序列_线段(&self) -> &Vec<Arc<中枢>> {
|
||||
&self.混合扩展中枢序列组[0]
|
||||
}
|
||||
|
||||
/// 重置基础序列
|
||||
pub fn 重置基础序列(&mut self) {
|
||||
self.普通K线序列.clear();
|
||||
@@ -134,16 +206,27 @@ impl 观察者 {
|
||||
self.分型序列.clear();
|
||||
self.笔序列.clear();
|
||||
self.笔_中枢序列.clear();
|
||||
self.线段序列.clear();
|
||||
self.中枢序列.clear();
|
||||
self.扩展线段序列.clear();
|
||||
self.扩展中枢序列.clear();
|
||||
self.扩展线段序列_线段.clear();
|
||||
self.扩展中枢序列_线段.clear();
|
||||
self.线段_线段序列.clear();
|
||||
self.线段_中枢序列.clear();
|
||||
self.扩展线段序列_扩展线段.clear();
|
||||
self.扩展中枢序列_扩展线段.clear();
|
||||
|
||||
self.线段序列组.clear();
|
||||
self.中枢序列组.clear();
|
||||
for _ in 0..self.线段分析层次 {
|
||||
self.线段序列组.push(Vec::new());
|
||||
self.中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
self.扩展线段序列组.clear();
|
||||
self.扩展中枢序列组.clear();
|
||||
for _ in 0..self.扩展线段分析层次 {
|
||||
self.扩展线段序列组.push(Vec::new());
|
||||
self.扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
self.混合扩展线段序列组.clear();
|
||||
self.混合扩展中枢序列组.clear();
|
||||
for _ in 0..self.混合扩展线段分析层次 {
|
||||
self.混合扩展线段序列组.push(Vec::new());
|
||||
self.混合扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
/// 增加原始K线 — 单根K线投喂入口
|
||||
@@ -166,7 +249,7 @@ impl 观察者 {
|
||||
|
||||
/// 核心数据处理管道
|
||||
fn __处理数据(&mut self, 普K: K线) {
|
||||
// Step 1: 缠论K线分析 (普K is consumed by 分析 as &mut)
|
||||
// Step 1: 缠论K线分析
|
||||
let (_, 当前分型) = 缠论K线::分析(
|
||||
普K,
|
||||
&mut self.缠论K线序列,
|
||||
@@ -178,92 +261,73 @@ impl 观察者 {
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Step 2: 笔分析
|
||||
if self.配置.分析笔 {
|
||||
笔::分析(
|
||||
当前分型,
|
||||
&mut self.分型序列,
|
||||
&mut self.笔序列,
|
||||
&self.缠论K线序列,
|
||||
&self.普通K线序列,
|
||||
0,
|
||||
&self.配置,
|
||||
);
|
||||
}
|
||||
// Step 2: 笔分析(无条件)
|
||||
笔::分析(
|
||||
当前分型,
|
||||
&mut self.分型序列,
|
||||
&mut self.笔序列,
|
||||
&self.缠论K线序列,
|
||||
&self.普通K线序列,
|
||||
0,
|
||||
&self.配置,
|
||||
);
|
||||
if self.分型序列.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3: 笔中枢分析
|
||||
if self.配置.分析笔中枢 {
|
||||
中枢::分析(&self.笔序列, &mut self.笔_中枢序列, true, "", 0);
|
||||
}
|
||||
// Step 3: 笔中枢分析(无条件)
|
||||
中枢::分析(&self.笔序列, &mut self.笔_中枢序列, true, "", 0);
|
||||
if self.笔序列.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4: 线段分析
|
||||
if self.配置.分析线段 {
|
||||
线段::分析(
|
||||
&self.笔序列,
|
||||
&mut self.线段序列,
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.线段序列, &mut self.中枢序列, true, "", 0);
|
||||
// Step 4: 线段分析 — 3 级递归
|
||||
for i in 0..self.线段分析层次 {
|
||||
if i == 0 {
|
||||
线段::分析(
|
||||
&self.笔序列,
|
||||
&mut self.线段序列组[i],
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
} else {
|
||||
let 源序列 = self.线段序列组[i - 1].clone();
|
||||
线段::分析(
|
||||
&源序列,
|
||||
&mut self.线段序列组[i],
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
中枢::分析(&self.线段序列组[i], &mut self.中枢序列组[i], true, "", 0);
|
||||
}
|
||||
|
||||
// Step 5: 扩展线段(笔级)
|
||||
if self.配置.分析扩展线段 {
|
||||
线段::扩展分析(&self.笔序列, &mut self.扩展线段序列, &self.配置);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.扩展线段序列, &mut self.扩展中枢序列, true, "", 0);
|
||||
}
|
||||
|
||||
// Step 6: 扩展线段(线段级)
|
||||
if self.配置.分析扩展线段 {
|
||||
线段::扩展分析(&self.线段序列, &mut self.扩展线段序列_线段, &self.配置);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
// Step 5: 扩展线段分析 — 3 级递归
|
||||
for i in 0..self.扩展线段分析层次 {
|
||||
if i == 0 {
|
||||
线段::扩展分析(&self.笔序列, &mut self.扩展线段序列组[i], &self.配置);
|
||||
} else {
|
||||
let 源序列 = self.扩展线段序列组[i - 1].clone();
|
||||
线段::扩展分析(&源序列, &mut self.扩展线段序列组[i], &self.配置);
|
||||
}
|
||||
中枢::分析(
|
||||
&self.扩展线段序列_线段,
|
||||
&mut self.扩展中枢序列_线段,
|
||||
&self.扩展线段序列组[i],
|
||||
&mut self.扩展中枢序列组[i],
|
||||
true,
|
||||
"",
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// Step 7: 线段之线段
|
||||
if self.配置.分析线段 {
|
||||
线段::分析(
|
||||
&self.线段序列,
|
||||
&mut self.线段_线段序列,
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.线段_线段序列, &mut self.线段_中枢序列, true, "", 0);
|
||||
}
|
||||
|
||||
// Step 8: 扩展线段之扩展线段
|
||||
if self.配置.分析扩展线段 {
|
||||
线段::扩展分析(
|
||||
&self.扩展线段序列,
|
||||
&mut self.扩展线段序列_扩展线段,
|
||||
&self.配置,
|
||||
);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
// Step 6: 混合扩展线段分析 — 3 级递归 (源 = 线段序列组[i])
|
||||
for i in 0..self.混合扩展线段分析层次 {
|
||||
let 源序列 = self.线段序列组[i].clone();
|
||||
线段::扩展分析(&源序列, &mut self.混合扩展线段序列组[i], &self.配置);
|
||||
中枢::分析(
|
||||
&self.扩展线段序列_扩展线段,
|
||||
&mut self.扩展中枢序列_扩展线段,
|
||||
&self.混合扩展线段序列组[i],
|
||||
&mut self.混合扩展中枢序列组[i],
|
||||
true,
|
||||
"",
|
||||
0,
|
||||
@@ -279,16 +343,27 @@ impl 观察者 {
|
||||
self.分型序列.clear();
|
||||
self.笔序列.clear();
|
||||
self.笔_中枢序列.clear();
|
||||
self.线段序列.clear();
|
||||
self.中枢序列.clear();
|
||||
self.扩展线段序列.clear();
|
||||
self.扩展中枢序列.clear();
|
||||
self.扩展线段序列_线段.clear();
|
||||
self.扩展中枢序列_线段.clear();
|
||||
self.线段_线段序列.clear();
|
||||
self.线段_中枢序列.clear();
|
||||
self.扩展线段序列_扩展线段.clear();
|
||||
self.扩展中枢序列_扩展线段.clear();
|
||||
|
||||
self.线段序列组.clear();
|
||||
self.中枢序列组.clear();
|
||||
for _ in 0..self.线段分析层次 {
|
||||
self.线段序列组.push(Vec::new());
|
||||
self.中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
self.扩展线段序列组.clear();
|
||||
self.扩展中枢序列组.clear();
|
||||
for _ in 0..self.扩展线段分析层次 {
|
||||
self.扩展线段序列组.push(Vec::new());
|
||||
self.扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
self.混合扩展线段序列组.clear();
|
||||
self.混合扩展中枢序列组.clear();
|
||||
for _ in 0..self.混合扩展线段分析层次 {
|
||||
self.混合扩展线段序列组.push(Vec::new());
|
||||
self.混合扩展中枢序列组.push(Vec::new());
|
||||
}
|
||||
|
||||
for i in 1..self.缠论K线序列.len() - 1 {
|
||||
let 当前分型 = 分型::new(
|
||||
@@ -307,102 +382,61 @@ impl 观察者 {
|
||||
);
|
||||
}
|
||||
|
||||
if self.配置.分析笔中枢 {
|
||||
中枢::分析(&self.笔序列, &mut self.笔_中枢序列, true, "", 0);
|
||||
中枢::分析(&self.笔序列, &mut self.笔_中枢序列, true, "", 0);
|
||||
|
||||
for i in 0..self.线段分析层次 {
|
||||
if i == 0 {
|
||||
线段::分析(
|
||||
&self.笔序列,
|
||||
&mut self.线段序列组[i],
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
} else {
|
||||
let 源序列 = self.线段序列组[i - 1].clone();
|
||||
线段::分析(
|
||||
&源序列,
|
||||
&mut self.线段序列组[i],
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
中枢::分析(&self.线段序列组[i], &mut self.中枢序列组[i], true, "", 0);
|
||||
}
|
||||
|
||||
if self.配置.分析线段 {
|
||||
线段::分析(
|
||||
&self.笔序列,
|
||||
&mut self.线段序列,
|
||||
&self.配置,
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.线段序列, &mut self.中枢序列, true, "", 0);
|
||||
}
|
||||
|
||||
if self.配置.分析扩展线段 {
|
||||
线段::扩展分析(&self.笔序列, &mut self.扩展线段序列, &self.配置);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.扩展线段序列, &mut self.扩展中枢序列, true, "", 0);
|
||||
}
|
||||
|
||||
if self.配置.分析扩展线段 {
|
||||
线段::扩展分析(&self.线段序列, &mut self.扩展线段序列_线段, &self.配置);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
for i in 0..self.扩展线段分析层次 {
|
||||
if i == 0 {
|
||||
线段::扩展分析(&self.笔序列, &mut self.扩展线段序列组[i], &self.配置);
|
||||
} else {
|
||||
let 源序列 = self.扩展线段序列组[i - 1].clone();
|
||||
线段::扩展分析(&源序列, &mut self.扩展线段序列组[i], &self.配置);
|
||||
}
|
||||
中枢::分析(
|
||||
&self.扩展线段序列_线段,
|
||||
&mut self.扩展中枢序列_线段,
|
||||
&self.扩展线段序列组[i],
|
||||
&mut self.扩展中枢序列组[i],
|
||||
true,
|
||||
"",
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
if self.配置.分析线段 {
|
||||
线段::分析(
|
||||
&self.线段序列,
|
||||
&mut self.线段_线段序列,
|
||||
&self.配置,
|
||||
for i in 0..self.混合扩展线段分析层次 {
|
||||
let 源序列 = self.线段序列组[i].clone();
|
||||
线段::扩展分析(&源序列, &mut self.混合扩展线段序列组[i], &self.配置);
|
||||
中枢::分析(
|
||||
&self.混合扩展线段序列组[i],
|
||||
&mut self.混合扩展中枢序列组[i],
|
||||
true,
|
||||
"",
|
||||
0,
|
||||
&[相对方向::向上, 相对方向::向下],
|
||||
);
|
||||
}
|
||||
if self.配置.分析线段中枢 {
|
||||
中枢::分析(&self.线段_线段序列, &mut self.线段_中枢序列, true, "", 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// 测试_保存数据 — 输出各序列数据文本到文件
|
||||
pub fn 测试_保存数据(&self, root: Option<&str>) -> String {
|
||||
let 笔序列_文本数据: Vec<String> = self.笔序列.iter().map(|b| b.获取数据文本()).collect();
|
||||
let 线段序列_文本数据: Vec<String> =
|
||||
self.线段序列.iter().map(|s| s.获取数据文本()).collect();
|
||||
let 扩展线段序列_数据文本: Vec<String> =
|
||||
self.扩展线段序列.iter().map(|s| s.获取数据文本()).collect();
|
||||
let 扩展线段序列_线段_数据文本: Vec<String> = self
|
||||
.扩展线段序列_线段
|
||||
.iter()
|
||||
.map(|s| s.获取数据文本())
|
||||
.collect();
|
||||
let 线段_线段序列_数据文本: Vec<String> = self
|
||||
.线段_线段序列
|
||||
.iter()
|
||||
.map(|s| s.获取数据文本())
|
||||
.collect();
|
||||
let 扩展线段序列_扩展线段_数据文本: Vec<String> = self
|
||||
.扩展线段序列_扩展线段
|
||||
.iter()
|
||||
.map(|s| s.获取数据文本())
|
||||
.collect();
|
||||
|
||||
let 笔_中枢序列_数据文本: Vec<String> =
|
||||
self.笔_中枢序列.iter().map(|h| h.获取数据文本()).collect();
|
||||
let 中枢序列_数据文本: Vec<String> =
|
||||
self.中枢序列.iter().map(|h| h.获取数据文本()).collect();
|
||||
let 扩展中枢序列_数据文本: Vec<String> =
|
||||
self.扩展中枢序列.iter().map(|h| h.获取数据文本()).collect();
|
||||
let 扩展中枢序列_线段_数据文本: Vec<String> = self
|
||||
.扩展中枢序列_线段
|
||||
.iter()
|
||||
.map(|h| h.获取数据文本())
|
||||
.collect();
|
||||
let 线段_中枢序列_数据文本: Vec<String> = self
|
||||
.线段_中枢序列
|
||||
.iter()
|
||||
.map(|h| h.获取数据文本())
|
||||
.collect();
|
||||
let 扩展中枢序列_扩展线段_数据文本: Vec<String> = self
|
||||
.扩展中枢序列_扩展线段
|
||||
.iter()
|
||||
.map(|h| h.获取数据文本())
|
||||
.collect();
|
||||
|
||||
// 确定根目录
|
||||
let 根目录 = match root {
|
||||
Some(r) => std::path::PathBuf::from(r),
|
||||
@@ -420,7 +454,50 @@ impl 观察者 {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
// 缠K data for debugging
|
||||
// 辅助:保存序列到文件 (Python: 保存序列(序列))
|
||||
let 保存序列 =
|
||||
|序列: &Vec<Arc<虚线>>, 保存路径: &std::path::Path| -> Result<(), std::io::Error> {
|
||||
if 序列.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let 数据列表: Vec<String> = 序列.iter().map(|d| d.获取数据文本()).collect();
|
||||
let 文件名 = format!("{}.txt", 序列[0].标识.read().unwrap());
|
||||
std::fs::write(保存路径.join(&文件名), 数据列表.join("\n") + "\n")?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let 保存中枢序列 =
|
||||
|序列: &Vec<Arc<中枢>>, 保存路径: &std::path::Path| -> Result<(), std::io::Error> {
|
||||
if 序列.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let 数据列表: Vec<String> = 序列.iter().map(|h| h.获取数据文本()).collect();
|
||||
let 文件名 = format!("{}.txt", 序列[0].标识.read().unwrap());
|
||||
std::fs::write(保存路径.join(&文件名), 数据列表.join("\n") + "\n")?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// 保存笔/笔中枢
|
||||
let _ = 保存序列(&self.笔序列, &保存路径);
|
||||
let _ = 保存中枢序列(&self.笔_中枢序列, &保存路径);
|
||||
|
||||
// 保存线段组
|
||||
for i in 0..self.线段分析层次 {
|
||||
let _ = 保存序列(&self.线段序列组[i], &保存路径);
|
||||
let _ = 保存中枢序列(&self.中枢序列组[i], &保存路径);
|
||||
}
|
||||
// 保存扩展线段组
|
||||
for i in 0..self.扩展线段分析层次 {
|
||||
let _ = 保存序列(&self.扩展线段序列组[i], &保存路径);
|
||||
let _ = 保存中枢序列(&self.扩展中枢序列组[i], &保存路径);
|
||||
}
|
||||
// 保存混合扩展线段组
|
||||
for i in 0..self.混合扩展线段分析层次 {
|
||||
let _ = 保存序列(&self.混合扩展线段序列组[i], &保存路径);
|
||||
let _ = 保存中枢序列(&self.混合扩展中枢序列组[i], &保存路径);
|
||||
}
|
||||
|
||||
// 缠K/分型 debug data
|
||||
let 缠K序列_数据文本: Vec<String> = self
|
||||
.缠论K线序列
|
||||
.iter()
|
||||
@@ -438,6 +515,11 @@ impl 观察者 {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let _ = std::fs::write(
|
||||
保存路径.join("缠K序列_数据文本.txt"),
|
||||
缠K序列_数据文本.join("\n") + "\n",
|
||||
);
|
||||
|
||||
let 分型序列_数据文本: Vec<String> = self
|
||||
.分型序列
|
||||
.iter()
|
||||
@@ -454,37 +536,10 @@ impl 观察者 {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let 数据映射: Vec<(&str, &[String])> = vec![
|
||||
("笔序列_文本数据", &笔序列_文本数据),
|
||||
("线段序列_文本数据", &线段序列_文本数据),
|
||||
("扩展线段序列_数据文本", &扩展线段序列_数据文本),
|
||||
("扩展线段序列_线段_数据文本", &扩展线段序列_线段_数据文本),
|
||||
("线段_线段序列_数据文本", &线段_线段序列_数据文本),
|
||||
(
|
||||
"扩展线段序列_扩展线段_数据文本",
|
||||
&扩展线段序列_扩展线段_数据文本,
|
||||
),
|
||||
("笔_中枢序列_数据文本", &笔_中枢序列_数据文本),
|
||||
("中枢序列_数据文本", &中枢序列_数据文本),
|
||||
("扩展中枢序列_数据文本", &扩展中枢序列_数据文本),
|
||||
("扩展中枢序列_线段_数据文本", &扩展中枢序列_线段_数据文本),
|
||||
("线段_中枢序列_数据文本", &线段_中枢序列_数据文本),
|
||||
(
|
||||
"扩展中枢序列_扩展线段_数据文本",
|
||||
&扩展中枢序列_扩展线段_数据文本,
|
||||
),
|
||||
("缠K序列_数据文本", &缠K序列_数据文本),
|
||||
("分型序列_数据文本", &分型序列_数据文本),
|
||||
];
|
||||
|
||||
for (文件名, 数据列表) in &数据映射 {
|
||||
let 文件路径 = 保存路径.join(format!("{}.txt", 文件名));
|
||||
let 内容 = 数据列表.join("\n") + "\n";
|
||||
if let Err(e) = std::fs::write(&文件路径, &内容) {
|
||||
error!("写入文件失败: {} -> {}", 文件路径.display(), e);
|
||||
}
|
||||
}
|
||||
let _ = std::fs::write(
|
||||
保存路径.join("分型序列_数据文本.txt"),
|
||||
分型序列_数据文本.join("\n") + "\n",
|
||||
);
|
||||
|
||||
info!("全部数据拆分保存完成,目录:{}", 保存路径.display());
|
||||
保存路径.display().to_string()
|
||||
@@ -672,7 +727,7 @@ mod tests {
|
||||
let obs_ref = obs.read().unwrap();
|
||||
|
||||
// 每个线段的基础序列中的笔 Rc 指针必须在 笔序列 中
|
||||
for (i, seg) in obs_ref.线段序列.iter().enumerate() {
|
||||
for (i, seg) in obs_ref.线段序列().iter().enumerate() {
|
||||
for (j, bi_in_seg) in seg.基础序列.read().unwrap().iter().enumerate() {
|
||||
let bi_ptr = Arc::as_ptr(bi_in_seg);
|
||||
let found = obs_ref.笔序列.iter().any(|b| Arc::as_ptr(b) == bi_ptr);
|
||||
@@ -706,10 +761,10 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
for (i, hub) in obs_ref.中枢序列.iter().enumerate() {
|
||||
for (i, hub) in obs_ref.中枢序列().iter().enumerate() {
|
||||
for (j, seg_in_hub) in hub.基础序列.read().unwrap().iter().enumerate() {
|
||||
let seg_ptr = Arc::as_ptr(seg_in_hub);
|
||||
let found = obs_ref.线段序列.iter().any(|s| Arc::as_ptr(s) == seg_ptr);
|
||||
let found = obs_ref.线段序列().iter().any(|s| Arc::as_ptr(s) == seg_ptr);
|
||||
if !found {
|
||||
info!("线段中枢 {} 的基础序列[{}] 不在线段序列中!", i, j);
|
||||
}
|
||||
@@ -738,8 +793,8 @@ mod tests {
|
||||
let obs = obs_ref.read().unwrap();
|
||||
(
|
||||
obs.笔序列.len(),
|
||||
obs.线段序列.len(),
|
||||
obs.中枢序列.len(),
|
||||
obs.线段序列().len(),
|
||||
obs.中枢序列().len(),
|
||||
obs.笔_中枢序列.len(),
|
||||
)
|
||||
};
|
||||
@@ -778,12 +833,12 @@ mod tests {
|
||||
}
|
||||
|
||||
let 第一次笔数 = obs_ref.read().unwrap().笔序列.len();
|
||||
let 第一次段数 = obs_ref.read().unwrap().线段序列.len();
|
||||
let 第一次段数 = obs_ref.read().unwrap().线段序列().len();
|
||||
|
||||
// 重置
|
||||
obs_ref.write().unwrap().重置基础序列();
|
||||
assert_eq!(obs_ref.read().unwrap().笔序列.len(), 0);
|
||||
assert_eq!(obs_ref.read().unwrap().线段序列.len(), 0);
|
||||
assert_eq!(obs_ref.read().unwrap().线段序列().len(), 0);
|
||||
|
||||
// 重新投喂
|
||||
for i in 0..data.len() / size {
|
||||
@@ -794,7 +849,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let 第二次笔数 = obs_ref.read().unwrap().笔序列.len();
|
||||
let 第二次段数 = obs_ref.read().unwrap().线段序列.len();
|
||||
let 第二次段数 = obs_ref.read().unwrap().线段序列().len();
|
||||
|
||||
assert_eq!(第一次笔数, 第二次笔数, "重置后重新投喂笔数不一致");
|
||||
assert_eq!(第一次段数, 第二次段数, "重置后重新投喂线段数不一致");
|
||||
@@ -831,7 +886,7 @@ mod tests {
|
||||
let _短路 = bi.短路修正.load(Ordering::Relaxed);
|
||||
let _前一缺口 = *bi.前一缺口.read().unwrap();
|
||||
}
|
||||
for seg in &obs_ref.线段序列 {
|
||||
for seg in obs_ref.线段序列() {
|
||||
let _ = seg.标识.read().unwrap().clone();
|
||||
let _ = seg.基础序列.read().unwrap().len();
|
||||
}
|
||||
|
||||
+7
-7
@@ -96,13 +96,13 @@ fn 测试_读取数据(文件路径: &str) {
|
||||
println!("分型数量: {}", 观察员.分型序列.len());
|
||||
println!("笔数量: {}", 观察员.笔序列.len());
|
||||
println!("笔中枢数量: {}", 观察员.笔_中枢序列.len());
|
||||
println!("线段数量: {}", 观察员.线段序列.len());
|
||||
println!("中枢数量: {}", 观察员.中枢序列.len());
|
||||
println!("扩展线段数量: {}", 观察员.扩展线段序列.len());
|
||||
println!("线段_线段序列数量: {}", 观察员.线段_线段序列.len());
|
||||
println!("线段数量: {}", 观察员.线段序列().len());
|
||||
println!("中枢数量: {}", 观察员.中枢序列().len());
|
||||
println!("扩展线段数量: {}", 观察员.扩展线段序列().len());
|
||||
println!("线段_线段序列数量: {}", 观察员.线段_线段序列().len());
|
||||
println!(
|
||||
"扩展线段_扩展线段数量: {}",
|
||||
观察员.扩展线段序列_扩展线段.len()
|
||||
观察员.扩展线段序列_扩展线段().len()
|
||||
);
|
||||
|
||||
println!("\n===== 保存分析数据 =====\n");
|
||||
@@ -167,8 +167,8 @@ fn 测试_周期合成(文件路径: &str) {
|
||||
观察员.缠论K线序列.len(),
|
||||
观察员.分型序列.len(),
|
||||
观察员.笔序列.len(),
|
||||
观察员.线段序列.len(),
|
||||
观察员.中枢序列.len(),
|
||||
观察员.线段序列().len(),
|
||||
观察员.中枢序列().len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,7 @@ from jinja2 import Environment, FileSystemLoader
|
||||
from pydantic import BaseModel
|
||||
import backtrader as bt
|
||||
|
||||
try:
|
||||
from chanlun import *
|
||||
except ImportError:
|
||||
from chan import *
|
||||
from chanlun import *
|
||||
|
||||
from strategies import *
|
||||
|
||||
@@ -321,471 +318,6 @@ class 时间周期:
|
||||
return 数值 * 60
|
||||
|
||||
|
||||
class BSP点:
|
||||
"""缠论买卖点(独立于旧买卖点类,对标 CBS_Point)。支持同一笔上叠加多种类型。"""
|
||||
|
||||
__slots__ = ("笔", "K线单元", "是否买点", "类型列表", "关联T1", "特征字典")
|
||||
|
||||
def __init__(self, 笔: "虚线", 是否买点: bool, 类型: "买卖点类型", 关联T1: "Optional[BSP点]" = None, 特征字典: dict = None):
|
||||
self.笔 = 笔
|
||||
self.K线单元 = 笔.武.中
|
||||
self.是否买点 = 是否买点
|
||||
self.类型列表: List["买卖点类型"] = [类型]
|
||||
self.关联T1: "Optional[BSP点]" = 关联T1
|
||||
self.特征字典 = 特征字典 or {}
|
||||
|
||||
def 添加类型(self, 类型: "买卖点类型", 关联T1: "Optional[BSP点]" = None):
|
||||
if 类型 not in self.类型列表:
|
||||
self.类型列表.append(类型)
|
||||
if self.关联T1 is None:
|
||||
self.关联T1 = 关联T1
|
||||
elif 关联T1 is not None:
|
||||
assert self.关联T1.K线单元.序号 == 关联T1.K线单元.序号
|
||||
|
||||
@property
|
||||
def 类型字符串(self) -> str:
|
||||
return ",".join([t.value for t in self.类型列表])
|
||||
|
||||
@property
|
||||
def 备注(self) -> str:
|
||||
return self.类型字符串
|
||||
|
||||
|
||||
class 买卖点识别器:
|
||||
"""缠论六类买卖点识别引擎。对标 ./对标/chan.py BuySellPoint 逻辑。"""
|
||||
|
||||
_最后确认位置: Dict[str, int] = {} # 对标 last_sure_pos
|
||||
_BSP1字典: Dict[str, Dict[int, "BSP点"]] = {} # 对标 bsp1_dict: key → 笔序号 → BSP点
|
||||
|
||||
# ================================================================
|
||||
# 主入口
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def 计算(obs: "观察者") -> None:
|
||||
if not obs.线段序列 or not obs.普通K线序列:
|
||||
return
|
||||
|
||||
key = obs.标识
|
||||
最后确认 = 买卖点识别器._最后确认位置.get(key, -1)
|
||||
|
||||
# 新确认的线段(仅用于 T1 增量识别,避免重复创建 T1)
|
||||
新确认线段 = [seg for i, seg in enumerate(obs.线段序列) if i > 最后确认 and seg.特征序列[2] is not None]
|
||||
|
||||
if not 新确认线段:
|
||||
return
|
||||
|
||||
买卖点识别器._最后确认位置[key] = obs.线段序列.index(新确认线段[-1])
|
||||
|
||||
配置 = obs.配置
|
||||
|
||||
if 配置.买卖点_计算线段BSP1:
|
||||
买卖点识别器._计算线段BSP1(obs, 新确认线段)
|
||||
|
||||
# T2 / T3 需要全部已确认线段(含历史),以便在后续笔到达后重新检查
|
||||
全部已确认 = [seg for seg in obs.线段序列 if seg.特征序列[2] is not None]
|
||||
全量T1列表 = list(买卖点识别器._BSP1字典.get(key, {}).values()) if 配置.买卖点_依赖T1 else []
|
||||
|
||||
if 配置.买卖点_处理BSP2:
|
||||
买卖点识别器._处理BSP2(obs, 全量T1列表, 全部已确认)
|
||||
|
||||
if 配置.买卖点_计算线段BSP3:
|
||||
买卖点识别器._计算线段BSP3(obs, 全量T1列表, 全部已确认)
|
||||
|
||||
# ================================================================
|
||||
# MACD 指标计算
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _计算MACD指标(笔: "虚线", K线序列: "List[K线]", 方式: str) -> float:
|
||||
始K = 笔.文.中.标的K线
|
||||
终K = 笔.武.中.标的K线
|
||||
try:
|
||||
始索引 = K线序列.index(始K)
|
||||
终索引 = K线序列.index(终K)
|
||||
except ValueError:
|
||||
return float("inf")
|
||||
|
||||
if 方式 == "峰":
|
||||
峰值 = 0.0
|
||||
for i in range(始索引, 终索引 + 1):
|
||||
k = K线序列[i]
|
||||
if k.macd and k.macd.MACD柱 is not None:
|
||||
v = abs(k.macd.MACD柱)
|
||||
if v > 峰值:
|
||||
峰值 = v
|
||||
return 峰值
|
||||
else:
|
||||
macd_dict = K线.获取MACD(K线序列, 始K, 终K)
|
||||
return abs(macd_dict.get("总", 0.0))
|
||||
|
||||
# ================================================================
|
||||
# 中枢查找工具
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _取线段内部中枢序列(段: "虚线", 来源: str) -> "List[中枢]":
|
||||
if 来源 == "实":
|
||||
return 段.实_中枢序列
|
||||
elif 来源 == "虚":
|
||||
return 段.虚_中枢序列
|
||||
else:
|
||||
return 段.合_中枢序列
|
||||
|
||||
@staticmethod
|
||||
def _找多笔中枢(中枢序列: "List[中枢]") -> "Optional[中枢]":
|
||||
for zs in reversed(中枢序列):
|
||||
if len(zs) >= 3:
|
||||
return zs
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _全局索引(笔: "虚线", 笔序列: "List[虚线]") -> int:
|
||||
"""返回笔在全局笔序列中的索引。"""
|
||||
try:
|
||||
return 笔序列.index(笔)
|
||||
except ValueError:
|
||||
return -1
|
||||
|
||||
@staticmethod
|
||||
def _笔振幅(笔: "虚线") -> float:
|
||||
"""笔的振幅 = |武分型特征值 - 文分型特征值|。对标 bi.amp()。"""
|
||||
return abs(笔.武.分型特征值 - 笔.文.分型特征值)
|
||||
|
||||
@staticmethod
|
||||
def _有重叠(低1: float, 高1: float, 低2: float, 高2: float) -> bool:
|
||||
"""两区间是否有交集。对标 has_overlap。"""
|
||||
return not (高1 < 低2 or 高2 < 低1)
|
||||
|
||||
@staticmethod
|
||||
def _段末同向笔(段: "虚线") -> "虚线":
|
||||
"""对标 seg.end_bi:当前段内最后一个与段方向相同的笔。
|
||||
|
||||
段.基础序列包含两段笔(当前段 + 后一段开头),不能直接用 [-1]/[-2]。
|
||||
必须用 分割序列 获取「前」——仅当前段的笔。
|
||||
"""
|
||||
前, _, _, _ = 线段.分割序列(段)
|
||||
for 筆 in reversed(前):
|
||||
if 筆.方向 == 段.方向:
|
||||
return 筆
|
||||
return 前[-1] # 理论上不会到这里,前[-1] 总是同向
|
||||
|
||||
# ================================================================
|
||||
# BSP 创建 / 去重 — 对标 add_bs
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _创建BSP(obs: "观察者", 类型: "买卖点类型", 笔: "虚线", 关联T1: "Optional[BSP点]" = None, 特征字典: dict = None):
|
||||
"""对标 add_bs:创建或追加 BSP 类型(支持一笔多类型叠加)。"""
|
||||
is_buy = 笔.方向.是否向下()
|
||||
if 笔.序号 in obs.BSP字典:
|
||||
exist_bsp = obs.BSP字典[笔.序号]
|
||||
assert exist_bsp.是否买点 == is_buy, f"买卖方向冲突: {exist_bsp.类型字符串} vs {类型.value}"
|
||||
exist_bsp.添加类型(类型, 关联T1)
|
||||
return exist_bsp
|
||||
|
||||
bsp = BSP点(笔=笔, 是否买点=is_buy, 类型=类型, 关联T1=关联T1, 特征字典=特征字典)
|
||||
obs.BSP字典[笔.序号] = bsp
|
||||
return bsp
|
||||
|
||||
# ================================================================
|
||||
# T1 / T1P — 对标 cal_seg_bs1point → treat_bsp1 / treat_pz_bsp1
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _计算线段BSP1(obs: "观察者", 已确认线段: "List[虚线]") -> "List[BSP点]":
|
||||
"""一类买卖点(T1中枢突破背离)和一类盘整买卖点(T1P)。对标 cal_seg_bs1point。"""
|
||||
结果: "List[BSP点]" = []
|
||||
配置 = obs.配置
|
||||
来源 = 配置.买卖点_中枢来源
|
||||
笔序列 = obs.笔序列
|
||||
|
||||
for 段 in 已确认线段:
|
||||
if not 段.基础序列 or len(段.基础序列) < 3:
|
||||
continue
|
||||
|
||||
is_buy = 段.方向.是否向下()
|
||||
if not is_buy and not 段.方向.是否向上():
|
||||
continue
|
||||
|
||||
段末笔 = 买卖点识别器._段末同向笔(段)
|
||||
|
||||
中枢序列 = 买卖点识别器._取线段内部中枢序列(段, 来源)
|
||||
|
||||
# 确定触发条件 — 对标 cal_single_bs1point
|
||||
goto_T1 = False
|
||||
相关中枢 = None
|
||||
if 中枢序列:
|
||||
相关中枢 = 中枢序列[-1] # zs_lst[-1]
|
||||
if len(相关中枢) >= 3: # not is_one_bi_zs
|
||||
进入笔全局索引 = 买卖点识别器._全局索引(相关中枢[0], 笔序列)
|
||||
if 进入笔全局索引 > 0:
|
||||
进入笔 = 笔序列[进入笔全局索引 - 1]
|
||||
段末笔全局索引 = 买卖点识别器._全局索引(段末笔, 笔序列)
|
||||
中枢末笔 = 相关中枢[-1]
|
||||
中枢末笔全局索引 = 买卖点识别器._全局索引(中枢末笔, 笔序列)
|
||||
bi_out = 笔序列[中枢末笔全局索引 + 1] if 中枢末笔全局索引 >= 0 and 中枢末笔全局索引 + 1 < len(笔序列) else None
|
||||
中枢到达段末 = (bi_out is not None and bi_out.序号 >= 段末笔.序号) or 中枢末笔.序号 >= 段末笔.序号
|
||||
if 中枢到达段末 and 段末笔.序号 - 进入笔.序号 > 2:
|
||||
goto_T1 = True
|
||||
|
||||
if goto_T1 and 相关中枢 is not None:
|
||||
# ---- T1 路径(对标 treat_bsp1)----
|
||||
进入笔全局索引 = 买卖点识别器._全局索引(相关中枢[0], 笔序列)
|
||||
进入笔 = 笔序列[进入笔全局索引 - 1]
|
||||
|
||||
# 突破检查 — 对标 end_bi_break
|
||||
if is_buy:
|
||||
if not (段末笔.低 < 相关中枢.低):
|
||||
continue
|
||||
else:
|
||||
if not (段末笔.高 > 相关中枢.高):
|
||||
continue
|
||||
|
||||
# 可选峰值条件 — 对标 out_bi_is_peak
|
||||
if 配置.买卖点_峰值条件:
|
||||
if is_buy:
|
||||
if not all(笔.低 >= 段末笔.低 for 笔 in 相关中枢 if 笔.序号 <= 段末笔.序号):
|
||||
continue
|
||||
else:
|
||||
if not all(笔.高 <= 段末笔.高 for 笔 in 相关中枢 if 笔.序号 <= 段末笔.序号):
|
||||
continue
|
||||
|
||||
# MACD背离 — 对标 is_divergence
|
||||
进入指标 = 买卖点识别器._计算MACD指标(进入笔, obs.普通K线序列, 配置.买卖点_计算方式)
|
||||
离开指标 = 买卖点识别器._计算MACD指标(段末笔, obs.普通K线序列, 配置.买卖点_计算方式)
|
||||
if not (离开指标 <= 配置.买卖点_背离率 * 进入指标):
|
||||
continue
|
||||
|
||||
类型 = 买卖点类型.T1买 if is_buy else 买卖点类型.T1卖
|
||||
bsp = 买卖点识别器._创建BSP(obs, 类型=类型, 笔=段末笔, 特征字典={"divergence_rate": 离开指标 / (进入指标 + 1e-7)})
|
||||
结果.append(bsp)
|
||||
买卖点识别器._BSP1字典.setdefault(obs.标识, {})[段末笔.序号] = bsp
|
||||
|
||||
else:
|
||||
# ---- T1P 盘整背离路径(对标 treat_pz_bsp1)----
|
||||
离开笔 = 段末笔
|
||||
段末笔全局索引 = 买卖点识别器._全局索引(段末笔, 笔序列)
|
||||
if 段末笔全局索引 < 2:
|
||||
continue
|
||||
进入笔 = 笔序列[段末笔全局索引 - 2]
|
||||
|
||||
if 离开笔.方向 != 段.方向:
|
||||
continue
|
||||
|
||||
# 创新低/高检查 — 对标 treat_pz_bsp1
|
||||
if is_buy:
|
||||
if 离开笔.低 > 进入笔.低:
|
||||
continue
|
||||
else:
|
||||
if 离开笔.高 < 进入笔.高:
|
||||
continue
|
||||
|
||||
# MACD背离 — 对标 in_metric vs out_metric
|
||||
进入指标 = 买卖点识别器._计算MACD指标(进入笔, obs.普通K线序列, 配置.买卖点_计算方式)
|
||||
离开指标 = 买卖点识别器._计算MACD指标(离开笔, obs.普通K线序列, 配置.买卖点_计算方式)
|
||||
if not (离开指标 <= 配置.买卖点_背离率 * 进入指标):
|
||||
continue
|
||||
|
||||
类型 = 买卖点类型.T1P买 if is_buy else 买卖点类型.T1P卖
|
||||
bsp = 买卖点识别器._创建BSP(obs, 类型=类型, 笔=离开笔, 特征字典={"divergence_rate": 离开指标 / (进入指标 + 1e-7)})
|
||||
结果.append(bsp)
|
||||
买卖点识别器._BSP1字典.setdefault(obs.标识, {})[段末笔.序号] = bsp
|
||||
|
||||
return 结果
|
||||
|
||||
# ================================================================
|
||||
# T2 / T2S — 对标 treat_bsp2 / treat_bsp2s
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _处理BSP2(obs: "观察者", T1列表: "List[BSP点]", 已确认线段: "List[虚线]") -> "List[BSP点]":
|
||||
"""二类买卖点(T2回调确认)和二类特殊买卖点(T2S多级次二类)。"""
|
||||
结果: "List[BSP点]" = []
|
||||
配置 = obs.配置
|
||||
阈值 = 配置.买卖点_T2_回调阈值
|
||||
最大层级 = 配置.买卖点_T2S_最大层级
|
||||
笔序列 = obs.笔序列
|
||||
|
||||
for bsp1 in T1列表:
|
||||
is_buy = bsp1.是否买点
|
||||
bsp1_笔 = bsp1.笔
|
||||
|
||||
bsp1_笔全局索引 = 买卖点识别器._全局索引(bsp1_笔, 笔序列)
|
||||
if bsp1_笔全局索引 < 0:
|
||||
continue
|
||||
|
||||
# 对标:break_bi = bi_list[bsp1_bi.idx + 1]; bsp2_bi = bi_list[bsp1_bi.idx + 2]
|
||||
if bsp1_笔全局索引 + 2 >= len(笔序列):
|
||||
continue
|
||||
突破笔 = 笔序列[bsp1_笔全局索引 + 1]
|
||||
回调笔 = 笔序列[bsp1_笔全局索引 + 2]
|
||||
|
||||
# 对标:bsp2_bi.amp() / break_bi.amp() <= max_bs2_rate
|
||||
突破振幅 = 买卖点识别器._笔振幅(突破笔)
|
||||
if 突破振幅 == 0:
|
||||
continue
|
||||
回调率 = 买卖点识别器._笔振幅(回调笔) / 突破振幅
|
||||
|
||||
if 回调率 <= 阈值:
|
||||
# ---- T2 成立 ----
|
||||
类型 = 买卖点类型.T2买 if is_buy else 买卖点类型.T2卖
|
||||
bsp = 买卖点识别器._创建BSP(obs, 类型=类型, 笔=回调笔, 关联T1=bsp1)
|
||||
结果.append(bsp)
|
||||
continue
|
||||
|
||||
# ---- T2S 多级次二类(对标 treat_bsp2s)----
|
||||
if 最大层级 is None or 最大层级 <= 0:
|
||||
continue
|
||||
|
||||
# 对标:初始重叠检查
|
||||
if not 买卖点识别器._有重叠(回调笔.低, 回调笔.高, 突破笔.低, 突破笔.高):
|
||||
continue
|
||||
|
||||
重叠区低 = max(回调笔.低, 突破笔.低) if is_buy else 回调笔.低
|
||||
重叠区高 = min(回调笔.高, 突破笔.高) if not is_buy else 回调笔.高
|
||||
|
||||
bias = 2 # 对标:从 bsp2_bi.idx + 2 开始,步进 2
|
||||
while 回调笔.序号 + bias < len(笔序列):
|
||||
bsp2s_笔 = 笔序列[买卖点识别器._全局索引(回调笔, 笔序列) + bias]
|
||||
|
||||
if 最大层级 is not None and bias // 2 > 最大层级:
|
||||
break
|
||||
|
||||
# 对标:首次重叠建立 _low/_high,之后检查
|
||||
if bias == 2:
|
||||
if not 买卖点识别器._有重叠(回调笔.低, 回调笔.高, bsp2s_笔.低, bsp2s_笔.高):
|
||||
break
|
||||
重叠区低 = max(回调笔.低, bsp2s_笔.低)
|
||||
重叠区高 = min(回调笔.高, bsp2s_笔.高)
|
||||
else:
|
||||
if not 买卖点识别器._有重叠(重叠区低, 重叠区高, bsp2s_笔.低, bsp2s_笔.高):
|
||||
break
|
||||
|
||||
# 对标:bsp2s_break_bsp1 = 不能突破突破笔极值
|
||||
if is_buy and bsp2s_笔.低 < 突破笔.低:
|
||||
break
|
||||
if not is_buy and bsp2s_笔.高 > 突破笔.高:
|
||||
break
|
||||
|
||||
# 对标:回调率检查
|
||||
bsp2s_回调率 = abs(bsp2s_笔.武.分型特征值 - 突破笔.武.分型特征值) / 突破振幅
|
||||
if bsp2s_回调率 > 阈值:
|
||||
break
|
||||
|
||||
# T2S成立
|
||||
重叠区低 = max(重叠区低, bsp2s_笔.低)
|
||||
重叠区高 = min(重叠区高, bsp2s_笔.高)
|
||||
|
||||
类型 = 买卖点类型.T2S买 if is_buy else 买卖点类型.T2S卖
|
||||
bsp = 买卖点识别器._创建BSP(obs, 类型=类型, 笔=bsp2s_笔, 关联T1=bsp1)
|
||||
结果.append(bsp)
|
||||
|
||||
bias += 2 # 对标:每次+2(同方向笔)
|
||||
|
||||
return 结果
|
||||
|
||||
# ================================================================
|
||||
# T3A / T3B — 对标 cal_seg_bs3point → treat_bsp3_after / treat_bsp3_before
|
||||
# ================================================================
|
||||
|
||||
@staticmethod
|
||||
def _计算线段BSP3(obs: "观察者", T1列表: "List[BSP点]", 已确认线段: "List[虚线]") -> None:
|
||||
"""三类买卖点:T3A(后方回踩)和T3B(前方反抽)。"""
|
||||
配置 = obs.配置
|
||||
来源 = 配置.买卖点_中枢来源
|
||||
笔序列 = obs.笔序列
|
||||
|
||||
for 段 in 已确认线段:
|
||||
seg_idx = obs.线段序列.index(段) if 段 in obs.线段序列 else -1
|
||||
is_buy = 段.方向.是否向下()
|
||||
|
||||
# ================================================================
|
||||
# T3A:后段中枢回踩 — 对标 treat_bsp3_after
|
||||
# ================================================================
|
||||
if seg_idx >= 0 and seg_idx + 1 < len(obs.线段序列):
|
||||
# 对标:if BSP_CONF.bsp3_follow_1 and bsp1_bi.idx not in bsp_store_flat_dict → skip
|
||||
bsp1_笔 = 买卖点识别器._段末同向笔(段)
|
||||
if not 配置.买卖点_依赖T1 or bsp1_笔.序号 in 买卖点识别器._BSP1字典.get(obs.标识, {}):
|
||||
后段 = obs.线段序列[seg_idx + 1]
|
||||
后段内部中枢 = 买卖点识别器._取线段内部中枢序列(后段, 来源)
|
||||
|
||||
# 对标:first_zs = next_seg.get_first_multi_bi_zs()
|
||||
for 中枢_candidate in 后段内部中枢:
|
||||
if len(中枢_candidate) < 3:
|
||||
continue
|
||||
中枢末笔全局索引 = 买卖点识别器._全局索引(中枢_candidate[-1], 笔序列)
|
||||
bi_out = 笔序列[中枢末笔全局索引 + 1] if 中枢末笔全局索引 >= 0 and 中枢末笔全局索引 + 1 < len(笔序列) else None
|
||||
if bi_out is None or 买卖点识别器._全局索引(bi_out, 笔序列) + 1 >= len(笔序列):
|
||||
continue
|
||||
|
||||
bsp3_笔 = 笔序列[买卖点识别器._全局索引(bi_out, 笔序列) + 1]
|
||||
|
||||
# 对标:bsp3_bi.dir == next_seg.dir → break
|
||||
if bsp3_笔.方向 == 后段.方向:
|
||||
break
|
||||
|
||||
# 对标:bsp3_back2zs(bsp3_bi, zs)
|
||||
if is_buy:
|
||||
if bsp3_笔.低 < 中枢_candidate.高:
|
||||
continue
|
||||
else:
|
||||
if bsp3_笔.高 > 中枢_candidate.低:
|
||||
continue
|
||||
|
||||
# 对标:bs3_peak 检查
|
||||
if 配置.买卖点_峰值条件:
|
||||
if is_buy:
|
||||
if not (bsp3_笔.高 >= 中枢_candidate.高高):
|
||||
continue
|
||||
else:
|
||||
if not (bsp3_笔.低 <= 中枢_candidate.低低):
|
||||
continue
|
||||
|
||||
类型 = 买卖点类型.T3A买 if is_buy else 买卖点类型.T3A卖
|
||||
bsp1 = 买卖点识别器._BSP1字典.get(obs.标识, {}).get(bsp1_笔.序号)
|
||||
买卖点识别器._创建BSP(obs, 类型=类型, 笔=bsp3_笔, 关联T1=bsp1)
|
||||
break # 对标:找到一个就跳出
|
||||
|
||||
# ================================================================
|
||||
# T3B:前序买卖点位置向前搜索 — 对标 treat_bsp3_before
|
||||
# ================================================================
|
||||
段末笔 = 买卖点识别器._段末同向笔(段)
|
||||
段内部中枢 = 买卖点识别器._取线段内部中枢序列(段, 来源)
|
||||
cmp_中枢 = 买卖点识别器._找多笔中枢(段内部中枢)
|
||||
if cmp_中枢 is None:
|
||||
continue
|
||||
|
||||
# 对标:if BSP_CONF.bsp3_follow_1 and bsp1_bi.idx not in bsp_store_flat_dict → skip
|
||||
if 配置.买卖点_依赖T1 and 段末笔.序号 not in 买卖点识别器._BSP1字典.get(obs.标识, {}):
|
||||
continue
|
||||
|
||||
bsp1_全局索引 = 买卖点识别器._全局索引(段末笔, 笔序列)
|
||||
if bsp1_全局索引 < 0:
|
||||
continue
|
||||
|
||||
# 对标:bsp3_peak check on cmp_zs
|
||||
# 对标:从 bsp1_bi.idx+2 开始,步进 2
|
||||
for offset in range(2, len(笔序列) - bsp1_全局索引, 2):
|
||||
bsp3_笔全局索引 = bsp1_全局索引 + offset
|
||||
if bsp3_笔全局索引 >= len(笔序列):
|
||||
break
|
||||
bsp3_笔 = 笔序列[bsp3_笔全局索引]
|
||||
|
||||
# 对标:bsp3_back2zs(bsp3_bi, cmp_zs)
|
||||
if is_buy:
|
||||
if bsp3_笔.低 < cmp_中枢.高:
|
||||
continue
|
||||
else:
|
||||
if bsp3_笔.高 > cmp_中枢.低:
|
||||
continue
|
||||
|
||||
类型 = 买卖点类型.T3B买 if is_buy else 买卖点类型.T3B卖
|
||||
bsp1 = 买卖点识别器._BSP1字典.get(obs.标识, {}).get(段末笔.序号)
|
||||
买卖点识别器._创建BSP(obs, 类型=类型, 笔=bsp3_笔, 关联T1=bsp1)
|
||||
break # 对标:找到一个就跳出
|
||||
|
||||
|
||||
class 指令:
|
||||
增: Final[str] = "APPEND"
|
||||
改: Final[str] = "MODIFY"
|
||||
@@ -823,19 +355,18 @@ class 观察者(观察者):
|
||||
self.数据队列: queue.Queue = 数据队列
|
||||
super().__init__(符号, 周期, 配置)
|
||||
self.__终止时间戳: Optional[datetime] = 转化为时间戳(self.配置.手动终止) if self.配置.手动终止 else None
|
||||
|
||||
def 识别买卖点(self):
|
||||
pass
|
||||
self.买卖点字典 = dict()
|
||||
|
||||
@final
|
||||
def 增加原始K线(self, 普K: K线):
|
||||
if self.__终止时间戳 and 普K.时间戳 > self.__终止时间戳:
|
||||
return
|
||||
|
||||
super().增加原始K线(普K)
|
||||
if self.配置.推送K线:
|
||||
self.报信(普K, 指令.添加("RawBar"), sys._getframe().f_lineno, 周期=普K.周期)
|
||||
|
||||
super().增加原始K线(普K)
|
||||
|
||||
try:
|
||||
self.数据队列 and self.数据队列.put((普K.时间戳, 普K.开盘价, 普K.高, 普K.低, 普K.收盘价, 普K.成交量, 0))
|
||||
if self.数据通道 is not None and self.配置.图表展示:
|
||||
@@ -843,8 +374,6 @@ class 观察者(观察者):
|
||||
try:
|
||||
self.图表刷新()
|
||||
self.识别买卖点()
|
||||
# 买卖点识别器.计算(self)
|
||||
# self.标注买卖点()
|
||||
except:
|
||||
print("~~~~~~~~~~~~~~", self.当前K线)
|
||||
traceback.print_exc()
|
||||
@@ -867,26 +396,12 @@ class 观察者(观察者):
|
||||
|
||||
def 重置基础序列(self):
|
||||
self.买卖点字典 = dict()
|
||||
self.BSP字典: Dict[int, "BSP点"] = dict()
|
||||
self._买卖点最后确认线段索引: int = -1
|
||||
买卖点识别器._最后确认位置.pop(self.标识, None)
|
||||
买卖点识别器._BSP1字典.pop(self.标识, None)
|
||||
self._已标注BSP序号: set = set()
|
||||
super().重置基础序列()
|
||||
|
||||
def 读取任意数据(self, 魔法, **魔法参数):
|
||||
魔法(**魔法参数)
|
||||
return self
|
||||
|
||||
def 加载本地数据(self, 文件路径: str):
|
||||
self.重置基础序列()
|
||||
with open(文件路径, "rb") as f:
|
||||
buffer = f.read()
|
||||
size = struct.calcsize(">6d")
|
||||
for i in range(len(buffer) // size):
|
||||
k线 = K线.读取大端字节数组(buffer[i * size : i * size + size], self.周期)
|
||||
self.增加原始K线(k线)
|
||||
|
||||
def 静态重新分析(self):
|
||||
self.买卖点字典 = dict()
|
||||
super().静态重新分析()
|
||||
@@ -932,50 +447,25 @@ class 观察者(观察者):
|
||||
if 当前买卖点.买卖点K线.时间戳 not in 活跃时间戳序列:
|
||||
买卖点序列.add(当前买卖点)
|
||||
当前买卖点.买卖点K线.买卖点信息.add(当前买卖点.备注)
|
||||
self.报信(当前买卖点, 指令.添加(当前买卖点.备注), sys._getframe().f_lineno)
|
||||
|
||||
def 图表刷新(self):
|
||||
# ===================== 笔(你原来的写法) =====================
|
||||
for 筆 in self.笔序列[-3:]:
|
||||
self.报信(筆, 指令.添加(筆.标识), 0)
|
||||
def 报信(序列):
|
||||
for 对象 in 序列[-3:]:
|
||||
self.报信(对象, 指令.添加(对象.标识), 0)
|
||||
|
||||
# ===================== 笔中枢 =====================
|
||||
for 中枢对象 in self.笔_中枢序列[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
报信(self.笔序列)
|
||||
报信(self.笔_中枢序列)
|
||||
|
||||
# ===================== 线段、中枢 =====================
|
||||
for 线段对象 in self.线段序列[-3:]:
|
||||
self.报信(线段对象, 指令.添加(线段对象.标识), 0)
|
||||
|
||||
for 中枢对象 in self.中枢序列[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
|
||||
# ===================== 扩展线段、扩展中枢 =====================
|
||||
for 线段对象 in self.扩展线段序列[-3:]:
|
||||
self.报信(线段对象, 指令.添加(线段对象.标识), 0)
|
||||
|
||||
for 中枢对象 in self.扩展中枢序列[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
|
||||
# ===================== 扩展线段(线段级)、扩展中枢(线段级) =====================
|
||||
for 线段对象 in self.扩展线段序列_线段[-3:]:
|
||||
self.报信(线段对象, 指令.添加(线段对象.标识), 0)
|
||||
|
||||
for 中枢对象 in self.扩展中枢序列_线段[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
|
||||
# ===================== 线段线段、线段中枢 =====================
|
||||
for 线段对象 in self.线段_线段序列[-3:]:
|
||||
self.报信(线段对象, 指令.添加(线段对象.标识), 0)
|
||||
|
||||
for 中枢对象 in self.线段_中枢序列[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
|
||||
# ===================== 扩展线段(扩展级)、扩展中枢(扩展级) =====================
|
||||
for 线段对象 in self.扩展线段序列_扩展线段[-3:]:
|
||||
self.报信(线段对象, 指令.添加(线段对象.标识), 0)
|
||||
|
||||
for 中枢对象 in self.扩展中枢序列_扩展线段[-3:]:
|
||||
self.报信(中枢对象, 指令.添加(中枢对象.标识), 0)
|
||||
for i in range(self.线段分析层次):
|
||||
报信(self.线段序列组[i])
|
||||
报信(self.中枢序列组[i])
|
||||
for i in range(self.扩展线段分析层次):
|
||||
报信(self.扩展线段序列组[i])
|
||||
报信(self.扩展中枢序列组[i])
|
||||
for i in range(self.混合扩展线段分析层次):
|
||||
报信(self.混合扩展线段序列组[i])
|
||||
报信(self.混合扩展中枢序列组[i])
|
||||
|
||||
# self.将图表数据固化到本地()
|
||||
|
||||
@@ -1022,23 +512,6 @@ class 观察者(观察者):
|
||||
"showLabel": False if 对象.偏移 <= 1 else True,
|
||||
}
|
||||
|
||||
if type(对象) is BSP点:
|
||||
message["type"] = "shape"
|
||||
message["cmd"] = 命令.指令.upper()
|
||||
message["id"] = f"BSP_{id(对象)}"
|
||||
message["name"] = "arrow_down" if not 对象.是否买点 else "arrow_up"
|
||||
k线 = 对象.K线单元
|
||||
message["points"] = [{"time": int(k线.时间戳), "price": k线.分型特征值}]
|
||||
arrowColor = "#FF2800" if not 对象.是否买点 else "#00FF22"
|
||||
text = f"{对象.类型字符串}, {对象.特征字典.get('divergence_rate', '')}"
|
||||
message["overrides"] = {
|
||||
"color": "#FFA500",
|
||||
"arrowColor": "#FFA500",
|
||||
"text": text,
|
||||
"title": 对象.类型字符串,
|
||||
"showLabel": True,
|
||||
}
|
||||
|
||||
if type(对象) is 虚线 and 对象.标识 == "笔" and not self.配置.推送笔:
|
||||
return
|
||||
|
||||
@@ -1084,8 +557,8 @@ class 观察者(观察者):
|
||||
message["name"] = "trend_line" if type(对象) is not 中枢 else "rectangle"
|
||||
if 命令.指令 != 指令.删:
|
||||
message["points"] = [
|
||||
{"time": int(缠论K线.时间戳对齐(self.缠论K线序列, 对象.文.中)), "price": 对象.文.分型特征值 if type(对象) is not 中枢 else 对象.高},
|
||||
{"time": int(缠论K线.时间戳对齐(self.缠论K线序列, 对象.武.中)), "price": 对象.武.分型特征值 if type(对象) is not 中枢 else 对象.低},
|
||||
{"time": int(缠论K线.时间戳对齐(self.基础缠K序列, 对象.文.中)), "price": 对象.文.分型特征值 if type(对象) is not 中枢 else 对象.高},
|
||||
{"time": int(缠论K线.时间戳对齐(self.基础缠K序列, 对象.武.中)), "price": 对象.武.分型特征值 if type(对象) is not 中枢 else 对象.低},
|
||||
]
|
||||
linewidths = {"笔": 1, "线段": 2, "走势": 3, "线段特征": 2}
|
||||
message["overrides"] = {
|
||||
@@ -1107,6 +580,9 @@ class 观察者(观察者):
|
||||
if type(对象) is not 线段特征:
|
||||
message["overrides"]["text"] = f"{对象.标识} {对象.序号} 周期:{self.周期} {getattr(对象, '四象', '')} {getattr(对象, '特征序列状态', '')} {getattr(对象, '级别', '')} {getattr(对象, '备注', '')}"
|
||||
|
||||
if type(对象) is 中枢:
|
||||
message["overrides"]["text"] = f"{对象.标识} {对象.序号} 周期:{self.周期} 基础序列数量: {len(对象.基础序列)}"
|
||||
|
||||
if 对象.标识 in ("线段", "线段<线段>"):
|
||||
message["overrides"]["text"] = f"{对象.标识} {对象.序号} 周期:{self.周期} {线段.四象(对象)} {线段.特征序列状态(对象)} {getattr(对象, '级别', '')} {getattr(对象, '备注', '')}"
|
||||
|
||||
@@ -1133,17 +609,6 @@ class 观察者(观察者):
|
||||
asyncio.ensure_future(self.数据通道.send_text(json.dumps(message)))
|
||||
return
|
||||
|
||||
def 标注买卖点(self):
|
||||
"""将 BSP字典 中的买卖点推送到图表。与旧的 添加买卖点/报信 独立。"""
|
||||
if not self.配置.图表展示 or self.数据通道 is None:
|
||||
return
|
||||
已标注 = getattr(self, "_已标注BSP序号", set())
|
||||
for 笔序号, bsp in self.BSP字典.items():
|
||||
if 笔序号 in 已标注:
|
||||
continue
|
||||
已标注.add(笔序号)
|
||||
self.报信(bsp, 指令.添加(bsp.备注), sys._getframe().f_lineno)
|
||||
|
||||
def 将图表数据固化到本地(self, static_shapes=None):
|
||||
template_path = "./templates/static.html"
|
||||
# 初始化 Jinja2 环境,模板目录为当前目录
|
||||
@@ -1170,7 +635,6 @@ class 观察者(观察者):
|
||||
全部 = []
|
||||
for o in self.买卖点字典.values():
|
||||
全部.extend(o)
|
||||
全部.extend(self.BSP字典.values())
|
||||
|
||||
for 对象 in 全部:
|
||||
if type(对象) in (笔, 线段, 中枢, 线段特征):
|
||||
@@ -1234,23 +698,6 @@ class 观察者(观察者):
|
||||
static_shapes.append(message)
|
||||
continue
|
||||
|
||||
if type(对象) is BSP点:
|
||||
message = dict()
|
||||
message["type"] = "shape"
|
||||
message["id"] = f"BSP_{id(对象)}"
|
||||
message["shapeType"] = "arrow_down" if not 对象.是否买点 else "arrow_up"
|
||||
k线 = 对象.K线单元
|
||||
message["points"] = [{"time": int(k线.时间戳), "price": k线.分型特征值}]
|
||||
arrowColor = "#FF2800" if not 对象.是否买点 else "#00FF22"
|
||||
text = f"{对象.类型字符串}"
|
||||
message["overrides"] = {
|
||||
"color": "#FFA500",
|
||||
"arrowColor": arrowColor,
|
||||
"text": text,
|
||||
"title": 对象.类型字符串,
|
||||
"showLabel": True,
|
||||
}
|
||||
static_shapes.append(message)
|
||||
else:
|
||||
print(type(对象), 对象)
|
||||
for item in static_shapes:
|
||||
@@ -1284,7 +731,7 @@ class 观察者(观察者):
|
||||
buffer = f.read()
|
||||
size = struct.calcsize(">6d")
|
||||
for i in range(len(buffer) // size):
|
||||
k线 = K线.读取大端字节数组(buffer[i * size : i * size + size], int(周期))
|
||||
k线 = K线.读取大端字节数组(buffer[i * size : i * size + size], int(周期), 符号)
|
||||
实例.增加原始K线(k线)
|
||||
|
||||
return 实例
|
||||
@@ -1858,7 +1305,7 @@ def 测试_随机生成(symbol: str = "btcusd", limit: int = 5000, freq: Support
|
||||
def 魔法():
|
||||
随机生成实例 = 观察者(symbol + "_gen", 周期=int(freq), 数据通道=ws, 配置=配置)
|
||||
dt = datetime(2008, 8, 8)
|
||||
原始K线 = K线.创建普K("随机", dt, 8888.55, 10000.00, 9000.22, 9527.33, 888, 0, int(freq))
|
||||
原始K线 = K线.创建普K("随机", int(dt.timestamp()), 8888.55, 10000.00, 9000.22, 9527.33, 888, 0, int(freq))
|
||||
随机生成实例.增加原始K线(原始K线)
|
||||
for 方向 in 从序列中机选(
|
||||
int(limit),
|
||||
@@ -1910,7 +1357,7 @@ class Bitstamp:
|
||||
for bar in data["data"]["ohlc"]:
|
||||
K = K线.创建普K(
|
||||
观察员.符号,
|
||||
转化为时间戳(int(bar["timestamp"])),
|
||||
int(bar["timestamp"]),
|
||||
float(bar["open"]),
|
||||
float(bar["high"]),
|
||||
float(bar["low"]),
|
||||
@@ -2779,6 +2226,7 @@ if __name__ == "__main__":
|
||||
本地随机 = random.Random(os.urandom(64))
|
||||
配置 = 随机配置(本地随机)
|
||||
print(f"[线程{线程编号:02d}] 开始 ...")
|
||||
print(f"[线程{线程编号:02d}] ", 配置.to_dict())
|
||||
测试函数 = 测试_随机生成(symbol="btcusd", limit=10000, freq=时间周期.分(5), ws=None, 配置=配置)
|
||||
结果 = 测试函数() # 实际执行
|
||||
print(f"[线程{线程编号:02d}] 完成 | 笔序列长度: {len(结果.笔序列)}")
|
||||
@@ -2786,6 +2234,7 @@ if __name__ == "__main__":
|
||||
print(f"[线程{线程编号:02d}] 异常: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
start = datetime.now()
|
||||
# 创建并启动 50 个线程
|
||||
线程列表 = []
|
||||
for i in range(1, 51):
|
||||
@@ -2797,4 +2246,4 @@ if __name__ == "__main__":
|
||||
for 线程 in 线程列表:
|
||||
线程.join()
|
||||
|
||||
print("\n全部 50 个随机回测线程已完成。")
|
||||
print("\n全部 50 个随机回测线程已完成。", datetime.now() - start)
|
||||
|
||||
+2
-2
@@ -1001,7 +1001,7 @@ class 回测(高级策略基类):
|
||||
def 检查买信号(self):
|
||||
if self.p.观察员.笔序列:
|
||||
k线 = self.p.观察员.缠论K线序列[-1]
|
||||
self.日志(f"检查买信号 当前笔 {self.p.观察员.笔序列[-1]}")
|
||||
# self.日志(f"检查买信号 当前笔 {self.p.观察员.笔序列[-1]}")
|
||||
if k线.买卖点信息:
|
||||
print(f"回测-首 {self.p.观察员.__class__.__name__}", k线.买卖点信息)
|
||||
首 = True if k线.买卖点信息 and "买" in next(iter(k线.买卖点信息)) else False
|
||||
@@ -1024,7 +1024,7 @@ class 回测(高级策略基类):
|
||||
|
||||
def 检查卖信号(self):
|
||||
if self.p.观察员.笔序列:
|
||||
self.日志(f"检查卖信号 当前笔 {self.p.观察员.笔序列[-1]}")
|
||||
# self.日志(f"检查卖信号 当前笔 {self.p.观察员.笔序列[-1]}")
|
||||
k线 = self.p.观察员.缠论K线序列[-1]
|
||||
if k线.买卖点信息:
|
||||
print(f"回测-首 {self.p.观察员.__class__.__name__}", k线.买卖点信息)
|
||||
|
||||
Reference in New Issue
Block a user