移除 配置兼容

This commit is contained in:
YuWuKunCheng
2026-06-19 20:59:25 +08:00
parent 0f69cfda79
commit 9c972c2673
10 changed files with 377 additions and 790 deletions
+113 -212
View File
@@ -846,7 +846,7 @@ class 缠论配置:
**[线段]** 线段_特征序列忽视老阴老阳, 线段_缺口后紧急修正, 线段内部中枢图显 \\
**[分析开关]** 分析笔, 分析线段, 分析扩展线段, 分析笔中枢, 分析线段中枢 \\
**[指标]** 计算指标, 指标计算方式, MACD/RSI/KDJ 参数 \\
**[推送/显示]** 图表展示, 推送K线//线段/中枢 \\
**[推送/显示]** 图表展示 (主开关), 图表展示标签 (标签列表) \\
**[买卖点]** 买卖点偏移, 买卖点激进识别, 买卖点_背离率, 买卖点_计算方式 \\
**[背驰]** 线段内部背驰_MACD, 线段内部背驰_斜率 \\
**[其他]** 手动终止, 加载文件路径
@@ -885,45 +885,15 @@ class 缠论配置:
分析线段中枢: bool = True,
手动终止: str = "", # 2099-12-31 00:00:00
计算指标: bool = True,
指标计算方式: str = "", # (开, 高, 低, 收, 高低均值, 高低收均值, 开高低收均值), 默认 收盘价
平滑异同移动平均线_快线周期: int = 13,
平滑异同移动平均线_慢线周期: int = 31,
平滑异同移动平均线_信号周期: int = 11,
相对强弱指数_周期: int = 13,
相对强弱指数_移动平均线周期: int = 13,
相对强弱指数_超买阈值: float = 75.0,
相对强弱指数_超卖阈值: float = 25.0,
随机指标_RSV周期: int = 13,
随机指标_K值平滑周期: int = 5,
随机指标_D值平滑周期: int = 5,
随机指标_超买阈值: float = 80.0,
随机指标_超卖阈值: float = 20.0,
计算BOLL: bool = False,
布林带_周期: int = 20,
布林带_标准差倍数: float = 2.0,
均线_类型列表: List[str] = None,
均线_周期列表: List[int] = None,
指标计算方式: str = "", # 均线计算方式
均线参数列表: List[tuple] = None, # [(key, 计算方式, 类型, 周期), ...]
# 多参数指标列表(None/空列表 = 使用默认单参数)
MACD_参数列表: List[tuple] = None, # [(key, 快线, 慢线, 信号), ...]
RSI_周期列表: List[tuple] = None, # [(key, 周期), ...]
KDJ_参数列表: List[tuple] = None, # [(key, RSV周期, K平滑, D平滑), ...]
BOLL_参数列表: List[tuple] = None, # [(key, 周期, 标准差倍数), ...]
图表展示: bool = True,
推送K线: bool = True,
推送笔: bool = True,
推送线段: bool = True,
推送中枢: bool = True,
图表展示_笔: bool = True,
图表展示_线段: bool = True,
图表展示_扩展线段: bool = True,
图表展示_扩展线段_线段: bool = True,
图表展示_线段_线段: bool = True,
图表展示_中枢_笔: bool = True,
图表展示_中枢_线段: bool = True,
图表展示_中枢_扩展线段: bool = True,
图表展示_中枢_扩展线段_线段: bool = True,
图表展示_中枢_线段_线段: bool = True,
图表展示_中枢_线段内部: bool = True,
MACD_参数列表: List[tuple] = None, # [(key, 计算方式, 快线, 慢线, 信号), ...]
RSI_周期列表: List[tuple] = None, # [(key, 计算方式, 周期), ...]
KDJ_参数列表: List[tuple] = None, # [(key, 计算方式, RSV周期, K平滑, D平滑), ...]
BOLL_参数列表: List[tuple] = None, # [(key, 计算方式, 周期, 标准差倍数), ...]
图表展示: bool = True, # 图表系统主开关
图表展示标签: Optional[List[str]] = None, # None=全部展示, []=不展示, [\"笔\",\"线段\"]=指定
买卖点偏移: int = 1, # 最大偏移
买卖点激进识别: bool = False, # 激进模式下将不考虑分型的完整性
买卖点与MACD柱强相关: bool = False, # True: 卖点需正值 买点需负值
@@ -963,43 +933,13 @@ class 缠论配置:
self.手动终止 = 手动终止
self.计算指标 = 计算指标
self.指标计算方式 = 指标计算方式
self.平滑异同移动平均线_快线周期 = 平滑异同移动平均线_快线周期
self.平滑异同移动平均线_慢线周期 = 平滑异同移动平均线_慢线周期
self.平滑异同移动平均线_信号周期 = 平滑异同移动平均线_信号周期
self.相对强弱指数_周期 = 相对强弱指数_周期
self.相对强弱指数_移动平均线周期 = 相对强弱指数_移动平均线周期
self.相对强弱指数_超买阈值 = 相对强弱指数_超买阈值
self.相对强弱指数_超卖阈值 = 相对强弱指数_超卖阈值
self.随机指标_RSV周期 = 随机指标_RSV周期
self.随机指标_K值平滑周期 = 随机指标_K值平滑周期
self.随机指标_D值平滑周期 = 随机指标_D值平滑周期
self.随机指标_超买阈值 = 随机指标_超买阈值
self.随机指标_超卖阈值 = 随机指标_超卖阈值
self.计算BOLL = 计算BOLL
self.布林带_周期 = 布林带_周期
self.布林带_标准差倍数 = 布林带_标准差倍数
self.均线_类型列表 = 均线_类型列表 if 均线_类型列表 is not None else []
self.均线_周期列表 = 均线_周期列表 if 均线_周期列表 is not None else []
self.MACD_参数列表 = MACD_参数列表 if MACD_参数列表 is not None else []
self.RSI_周期列表 = RSI_周期列表 if RSI_周期列表 is not None else []
self.KDJ_参数列表 = KDJ_参数列表 if KDJ_参数列表 is not None else []
self.BOLL_参数列表 = BOLL_参数列表 if BOLL_参数列表 is not None else []
self.均线参数列表 = 均线参数列表 if 均线参数列表 is not None else []
self.MACD_参数列表 = MACD_参数列表 if MACD_参数列表 is not None else [("macd", "", 13, 31, 11)]
self.RSI_周期列表 = RSI_周期列表 if RSI_周期列表 is not None else [("rsi", "", 14, 13, 75.0, 25.0)]
self.KDJ_参数列表 = KDJ_参数列表 if KDJ_参数列表 is not None else [("kdj", "", 13, 5, 5, 80.0, 20.0)]
self.BOLL_参数列表 = BOLL_参数列表 if BOLL_参数列表 is not None else [("boll", "", 20, 2.0)]
self.图表展示 = 图表展示
self.推送K线 = 推送K线
self.推送笔 = 推送笔
self.推送线段 = 推送线段
self.推送中枢 = 推送中枢
self.图表展示_笔 = 图表展示_笔
self.图表展示_线段 = 图表展示_线段
self.图表展示_扩展线段 = 图表展示_扩展线段
self.图表展示_扩展线段_线段 = 图表展示_扩展线段_线段
self.图表展示_线段_线段 = 图表展示_线段_线段
self.图表展示_中枢_笔 = 图表展示_中枢_笔
self.图表展示_中枢_线段 = 图表展示_中枢_线段
self.图表展示_中枢_扩展线段 = 图表展示_中枢_扩展线段
self.图表展示_中枢_扩展线段_线段 = 图表展示_中枢_扩展线段_线段
self.图表展示_中枢_线段_线段 = 图表展示_中枢_线段_线段
self.图表展示_中枢_线段内部 = 图表展示_中枢_线段内部
self.图表展示标签 = set(图表展示标签) if 图表展示标签 is not None else None
self.买卖点偏移 = 买卖点偏移
self.买卖点激进识别 = 买卖点激进识别
self.买卖点与MACD柱强相关 = 买卖点与MACD柱强相关
@@ -1049,43 +989,13 @@ class 缠论配置:
"手动终止": {"annotation": str, "default": ""},
"计算指标": {"annotation": bool, "default": True},
"指标计算方式": {"annotation": str, "default": ""},
"平滑异同移动平均线_快线周期": {"annotation": int, "default": 13},
"平滑异同移动平均线_慢线周期": {"annotation": int, "default": 31},
"平滑异同移动平均线_信号周期": {"annotation": int, "default": 11},
"相对强弱指数_周期": {"annotation": int, "default": 13},
"相对强弱指数_移动平均线周期": {"annotation": int, "default": 13},
"相对强弱指数_超买阈值": {"annotation": float, "default": 75.0},
"相对强弱指数_超卖阈值": {"annotation": float, "default": 25.0},
"随机指标_RSV周期": {"annotation": int, "default": 13},
"随机指标_K值平滑周期": {"annotation": int, "default": 5},
"随机指标_D值平滑周期": {"annotation": int, "default": 5},
"随机指标_超买阈值": {"annotation": float, "default": 80.0},
"随机指标_超卖阈值": {"annotation": float, "default": 20.0},
"计算BOLL": {"annotation": bool, "default": False},
"布林带_周期": {"annotation": int, "default": 20},
"布林带_标准差倍数": {"annotation": float, "default": 2.0},
"均线_类型列表": {"annotation": List[str], "default": []},
"均线_周期列表": {"annotation": List[int], "default": []},
"MACD_参数列表": {"annotation": List[tuple], "default": []},
"RSI_周期列表": {"annotation": List[tuple], "default": []},
"KDJ_参数列表": {"annotation": List[tuple], "default": []},
"BOLL_参数列表": {"annotation": List[tuple], "default": []},
"均线参数列表": {"annotation": List[tuple], "default": []},
"MACD_参数列表": {"annotation": List[tuple], "default": [("macd", "", 13, 31, 11)]},
"RSI_周期列表": {"annotation": List[tuple], "default": [("rsi", "", 14, 13, 75.0, 25.0)]},
"KDJ_参数列表": {"annotation": List[tuple], "default": [("kdj", "", 13, 5, 5, 80.0, 20.0)]},
"BOLL_参数列表": {"annotation": List[tuple], "default": [("boll", "", 20, 2.0)]},
"图表展示": {"annotation": bool, "default": True},
"推送K线": {"annotation": bool, "default": True},
"推送笔": {"annotation": bool, "default": True},
"推送线段": {"annotation": bool, "default": True},
"推送中枢": {"annotation": bool, "default": True},
"图表展示_笔": {"annotation": bool, "default": True},
"图表展示_线段": {"annotation": bool, "default": True},
"图表展示_扩展线段": {"annotation": bool, "default": True},
"图表展示_扩展线段_线段": {"annotation": bool, "default": True},
"图表展示_线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_笔": {"annotation": bool, "default": True},
"图表展示_中枢_线段": {"annotation": bool, "default": True},
"图表展示_中枢_扩展线段": {"annotation": bool, "default": True},
"图表展示_中枢_扩展线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_线段内部": {"annotation": bool, "default": True},
"图表展示标签": {"annotation": Optional[List[str]], "default": None},
"买卖点偏移": {"annotation": int, "default": 1},
"买卖点激进识别": {"annotation": bool, "default": False},
"买卖点与MACD柱强相关": {"annotation": bool, "default": False},
@@ -1137,27 +1047,45 @@ class 缠论配置:
logger.warning(f"[{fname}] = {value} 解析失败,使用默认值:{default}")
setattr(self, fname, default)
# ---- 参数列表解析:多参数列表为空时回退到默认单参数 ----
def 设置指标(
self,
*,
均线: List[tuple] = None,
MACD: List[tuple] = None,
RSI: List[tuple] = None,
KDJ: List[tuple] = None,
BOLL: List[tuple] = None,
):
"""统一设置所有指标参数。
def _解析MACD参数列表(self) -> List[tuple]:
if self.MACD_参数列表:
return self.MACD_参数列表
return [("macd", self.平滑异同移动平均线_快线周期, self.平滑异同移动平均线_慢线周期, self.平滑异同移动平均线_信号周期)]
元组格式 ``(key, 计算方式, *params)``
- 均线: ``("SMA_5", "", "SMA", 5)`` key/计算方式/类型/周期
- MACD: ``("默认", "", 13, 31, 11)`` 快线/慢线/信号
- RSI: ``("默认", "", 14, 13, 75, 25)`` 周期/MA周期/超买/超卖
- KDJ: ``("默认", "", 13, 5, 5, 80, 20)`` RSV/K平滑/D平滑/超买/超卖
- BOLL: ``("默认", "", 20, 2.0)`` 周期/标准差倍数
def _解析RSI周期列表(self) -> List[tuple]:
if self.RSI_周期列表:
return self.RSI_周期列表
return [("rsi", self.相对强弱指数_周期)]
:param 均线: key 即均线名 ``"SMA_5"``同时编码类型和周期
:param MACD: 首个 key 同时写入 ``"macd"`` 兼容槽位
:param BOLL: BOLL 参数元组列表为空则不计算
"""
self.计算指标 = True
if 均线 is not None:
self.均线参数列表 = 均线
if MACD is not None:
self.MACD_参数列表 = MACD
if RSI is not None:
self.RSI_周期列表 = RSI
if KDJ is not None:
self.KDJ_参数列表 = KDJ
if BOLL is not None:
self.BOLL_参数列表 = BOLL
def _解析KDJ参数列表(self) -> List[tuple]:
if self.KDJ_参数列表:
return self.KDJ_参数列表
return [("kdj", self.随机指标_RSV周期, self.随机指标_K值平滑周期, self.随机指标_D值平滑周期)]
def _解析BOLL参数列表(self) -> List[tuple]:
if self.BOLL_参数列表:
return self.BOLL_参数列表
return [("boll", self.布林带_周期, self.布林带_标准差倍数)]
def 展示标签(self, 标签: str) -> bool:
"""判断指定标签是否应展示。None = 全部展示,空列表 = 全部隐藏。"""
if self.图表展示标签 is None:
return True
return 标签 in self.图表展示标签
@classmethod
def 兼容旧版本配置(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -1190,7 +1118,13 @@ class 缠论配置:
:return: 包含所有配置字段的字典
"""
return {k: getattr(self, k) for k in self.model_fields().keys()}
result = {}
for k in self.model_fields().keys():
v = getattr(self, k)
if isinstance(v, set):
v = list(v)
result[k] = v
return result
def to_json(self) -> str:
"""将配置序列化为 JSON 字符串。
@@ -1246,21 +1180,7 @@ class 缠论配置:
return cls(
线段内部中枢图显=False,
图表展示=False,
推送K线=False,
推送笔=False,
推送线段=False,
推送中枢=False,
图表展示_笔=False,
图表展示_线段=False,
图表展示_扩展线段=False,
图表展示_扩展线段_线段=False,
图表展示_线段_线段=False,
图表展示_中枢_笔=False,
图表展示_中枢_线段=False,
图表展示_中枢_扩展线段=False,
图表展示_中枢_扩展线段_线段=False,
图表展示_中枢_线段_线段=False,
图表展示_中枢_线段内部=False,
图表展示标签=[],
)
def model_copy(self, update: dict = None, deep: bool = True):
@@ -2479,19 +2399,21 @@ class 指标计算器:
@staticmethod
def _计算MACD组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, , , 信号 in 配置._解析MACD参数列表():
for i, (key, 计算方式, *params) in enumerate(配置.MACD_参数列表):
, , 信号 = params[0], params[1], params[2]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 平滑异同移动平均线.增量计算_K线(prev_val, 当前K线, 计算方式)
else:
idx[key] = 平滑异同移动平均线.首次计算_K线(当前K线, 计算方式, , , 信号)
if i == 0:
idx["macd"] = idx[key]
@staticmethod
def _计算RSI组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, 周期 in 配置._解析RSI周期列表():
for key, 计算方式, *params in 配置.RSI_周期列表:
周期, MA周期, 超买, 超卖 = params[0], params[1], params[2], params[3]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 相对强弱指数.增量计算_K线(prev_val, 当前K线, 计算方式)
@@ -2500,16 +2422,16 @@ class 指标计算器:
当前K线,
计算方式,
周期,
配置.相对强弱指数_超买阈值,
配置.相对强弱指数_超卖阈值,
配置.相对强弱指数_移动平均线周期,
超买,
超卖,
MA周期,
)
@staticmethod
def _计算KDJ组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, rsv, k平滑, d平滑 in 配置._解析KDJ参数列表():
for key, 计算方式, *params in 配置.KDJ_参数列表:
rsv, k平滑, d平滑, 超买, 超卖 = params[0], params[1], params[2], params[3], params[4]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 随机指标.增量计算_K线(prev_val, 当前K线, 计算方式)
@@ -2520,15 +2442,15 @@ class 指标计算器:
rsv,
k平滑,
d平滑,
配置.随机指标_超买阈值,
配置.随机指标_超卖阈值,
超买,
超卖,
)
@staticmethod
def _计算BOLL组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, 周期, 标准差倍数 in 配置._解析BOLL参数列表():
for key, 计算方式, *params in 配置.BOLL_参数列表:
周期, 标准差倍数 = params[0], params[1]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 布林带.增量计算(prev_val, 当前K线, 计算方式)
@@ -2537,18 +2459,16 @@ class 指标计算器:
@staticmethod
def _更新均线(当前K线: K线, 普K序列: List[K线], 配置: 缠论配置):
if not 配置.均线_类型列表 or not 配置.均线_周期列表:
if not 配置.均线参数列表:
return
for ma_type in 配置.均线_类型列表:
for period in 配置.均线_周期列表:
key = f"{ma_type}_{period}"
if ma_type == "SMA":
当前K线.指标.均线[key] = 均线工具.增量SMA(普K序列, period, 配置.指标计算方式)
elif ma_type == "EMA":
前值 = None
if len(普K序列) >= 2:
前值 = 普K序列[-2].指标.均线.get(key)
当前K线.指标.均线[key] = 均线工具.增量EMA(普K序列, period, 配置.指标计算方式, 前值)
for key, 计算方式, ma_type, period in 配置.均线参数列表:
if ma_type == "SMA":
当前K线.指标.均线[key] = 均线工具.增量SMA(普K序列, period, 计算方式)
elif ma_type == "EMA":
前值 = None
if len(普K序列) >= 2:
前值 = 普K序列[-2].指标.均线.get(key)
当前K线.指标.均线[key] = 均线工具.增量EMA(普K序列, period, 计算方式, 前值)
@staticmethod
def _回填新指标(全序列: List[K线], 配置: 缠论配置):
@@ -2570,16 +2490,14 @@ class 指标计算器:
新参数.append(params)
return 新参数
新MACD = _新键(尾K指标, 首K指标, 配置._解析MACD参数列表())
新RSI = _新键(尾K指标, 首K指标, 配置._解析RSI周期列表())
新KDJ = _新键(尾K指标, 首K指标, 配置._解析KDJ参数列表())
新BOLL = _新键(尾K指标, 首K指标, 配置._解析BOLL参数列表())
新MACD = _新键(尾K指标, 首K指标, 配置.MACD_参数列表)
新RSI = _新键(尾K指标, 首K指标, 配置.RSI_周期列表)
新KDJ = _新键(尾K指标, 首K指标, 配置.KDJ_参数列表)
新BOLL = _新键(尾K指标, 首K指标, 配置.BOLL_参数列表)
if not (新MACD or 新RSI or 新KDJ or 新BOLL):
return
计算方式 = 配置.指标计算方式
for i, k线 in enumerate(全序列):
if k线.指标 is None:
k线.指标 = 指标容器()
@@ -2587,43 +2505,32 @@ class 指标计算器:
idx = k线.指标
prev = 全序列[i - 1].指标 if i > 0 else None
for key, , , 信号 in 新MACD:
for key, 计算方式, *params in 新MACD:
, , 信号 = params[0], params[1], params[2]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 平滑异同移动平均线.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 平滑异同移动平均线.首次计算_K线(k线, 计算方式, , , 信号)
for key, 周期 in 新RSI:
for key, 计算方式, *params in 新RSI:
周期, MA周期, 超买, 超卖 = params[0], params[1], params[2], params[3]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 相对强弱指数.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 相对强弱指数.首次计算_K线(
k线,
计算方式,
周期,
配置.相对强弱指数_超买阈值,
配置.相对强弱指数_超卖阈值,
配置.相对强弱指数_移动平均线周期,
)
idx[key] = 相对强弱指数.首次计算_K线(k线, 计算方式, 周期, 超买, 超卖, MA周期)
for key, rsv, k平滑, d平滑 in 新KDJ:
for key, 计算方式, *params in 新KDJ:
rsv, k平滑, d平滑, 超买, 超卖 = params[0], params[1], params[2], params[3], params[4]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 随机指标.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 随机指标.首次计算_K线(
k线,
计算方式,
rsv,
k平滑,
d平滑,
配置.随机指标_超买阈值,
配置.随机指标_超卖阈值,
)
idx[key] = 随机指标.首次计算_K线(k线, 计算方式, rsv, k平滑, d平滑, 超买, 超卖)
for key, 周期, 标准差倍数 in 新BOLL:
for key, 计算方式, *params in 新BOLL:
周期, 标准差倍数 = params[0], params[1]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 布林带.增量计算(prev_val, k线, 计算方式)
@@ -4292,23 +4199,24 @@ class 虚线:
dif_up = dif_down = dea_up = dea_down = 0
for i in range(1, len(普K序列)):
pre, cur = 普K序列[i - 1].macd, 普K序列[i].macd
if pre.DIF is None or cur.DIF is None:
if pre is None or cur is None or pre.DIF is None or cur.DIF is None:
continue
if pre.DIF < 0 <= cur.DIF:
dif_up += 1
elif pre.DIF > 0 >= cur.DIF:
dif_down += 1
if pre.DEA < 0 <= cur.DEA:
dea_up += 1
elif pre.DEA > 0 >= cur.DEA:
dea_down += 1
if pre.DEA is not None and cur.DEA is not None:
if pre.DEA < 0 <= cur.DEA:
dea_up += 1
elif pre.DEA > 0 >= cur.DEA:
dea_down += 1
# 2. DIF与DEA交叉(带标记)
golden = death = 0
交叉标记 = [0] # 第0个位置无前值,先填0
for i in range(1, len(普K序列)):
pre, cur = 普K序列[i - 1].macd, 普K序列[i].macd
if pre.DIF is None or cur.DIF is None or pre.DEA is None or cur.DEA is None:
if pre is None or cur is None or pre.DIF is None or cur.DIF is None or pre.DEA is None or cur.DEA is None:
交叉标记.append(0)
continue
if pre.DIF <= pre.DEA and cur.DIF > cur.DEA:
@@ -7030,20 +6938,13 @@ class 立体分析器:
for 周期 in self.周期组:
临时配置 = 配置组.get(周期, 配置)
当前配置 = 临时配置.model_copy(
update={
"推送K线": False,
# "推送笔": False,
"推送线段": False,
# "图表展示": False,
},
update={"图表展示标签": []},
deep=True,
)
self._单体分析器[周期] = 观察者(符号=符号, 周期=周期, 配置=当前配置)
self._单体分析器[self.__显示周期].配置.推送K线 = True
self._单体分析器[self.__显示周期].配置.推送笔 = True
self._单体分析器[self.__显示周期].配置.推送线段 = True
self._单体分析器[self.__显示周期].配置.图表展示 = True
self._单体分析器[self.__显示周期].配置.图表展示标签 = None # None = 全部展示
self._单体分析器[self.__显示周期].重置基础序列()
for 周期 in self.周期组: # 将不同周期对其至显示周期
@@ -7156,7 +7057,7 @@ def 测试_指标挂载(配置: 缠论配置):
size = struct.calcsize(">6d")
for i in range(len(buffer) // size):
if i == 500:
配置.MACD_参数列表 = [("macd", 配置.平滑异同移动平均线_快线周期, 配置.平滑异同移动平均线_慢线周期, 配置.平滑异同移动平均线_信号周期)]
配置.MACD_参数列表 = [("macd", "", 13, 31, 11)]
配置.MACD_参数列表.append(("macd_12_26_9", 12, 26, 9))
k线 = K线.读取大端字节数组(buffer[i * size : i * size + size], 周期, 符号)
观察员.增加原始K线(k线)
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "chanlun-py"
version = "26.6.77"
version = "26.6.87"
edition = "2024"
description = "缠论技术分析库 — Rust 高性能 Python 绑定"
authors = ["YuYuKunKun"]
+1
View File
@@ -886,6 +886,7 @@ class 缠论配置:
def from_json(cls, json_str: str) -> 缠论配置: ...
@classmethod
def 不推送(cls) -> 缠论配置: ...
def 展示标签(self, 标签: str) -> bool: ...
@classmethod
def 按序号重组字典(cls, 默认配置: Any, 原始字典: Dict[str, Any]) -> Dict[str, Any]: ...
def __str__(self) -> str: ...
+1
View File
@@ -886,6 +886,7 @@ class 缠论配置:
def from_json(cls, json_str: str) -> 缠论配置: ...
@classmethod
def 不推送(cls) -> 缠论配置: ...
def 展示标签(self, 标签: str) -> bool: ...
@classmethod
def 按序号重组字典(cls, 默认配置: Any, 原始字典: Dict[str, Any]) -> Dict[str, Any]: ...
def __str__(self) -> str: ...
+113 -212
View File
@@ -846,7 +846,7 @@ class 缠论配置:
**[线段]** 线段_特征序列忽视老阴老阳, 线段_缺口后紧急修正, 线段内部中枢图显 \\
**[分析开关]** 分析笔, 分析线段, 分析扩展线段, 分析笔中枢, 分析线段中枢 \\
**[指标]** 计算指标, 指标计算方式, MACD/RSI/KDJ 参数 \\
**[推送/显示]** 图表展示, 推送K线//线段/中枢 \\
**[推送/显示]** 图表展示 (主开关), 图表展示标签 (标签列表) \\
**[买卖点]** 买卖点偏移, 买卖点激进识别, 买卖点_背离率, 买卖点_计算方式 \\
**[背驰]** 线段内部背驰_MACD, 线段内部背驰_斜率 \\
**[其他]** 手动终止, 加载文件路径
@@ -885,45 +885,15 @@ class 缠论配置:
分析线段中枢: bool = True,
手动终止: str = "", # 2099-12-31 00:00:00
计算指标: bool = True,
指标计算方式: str = "", # (开, 高, 低, 收, 高低均值, 高低收均值, 开高低收均值), 默认 收盘价
平滑异同移动平均线_快线周期: int = 13,
平滑异同移动平均线_慢线周期: int = 31,
平滑异同移动平均线_信号周期: int = 11,
相对强弱指数_周期: int = 13,
相对强弱指数_移动平均线周期: int = 13,
相对强弱指数_超买阈值: float = 75.0,
相对强弱指数_超卖阈值: float = 25.0,
随机指标_RSV周期: int = 13,
随机指标_K值平滑周期: int = 5,
随机指标_D值平滑周期: int = 5,
随机指标_超买阈值: float = 80.0,
随机指标_超卖阈值: float = 20.0,
计算BOLL: bool = False,
布林带_周期: int = 20,
布林带_标准差倍数: float = 2.0,
均线_类型列表: List[str] = None,
均线_周期列表: List[int] = None,
指标计算方式: str = "", # 均线计算方式
均线参数列表: List[tuple] = None, # [(key, 计算方式, 类型, 周期), ...]
# 多参数指标列表(None/空列表 = 使用默认单参数)
MACD_参数列表: List[tuple] = None, # [(key, 快线, 慢线, 信号), ...]
RSI_周期列表: List[tuple] = None, # [(key, 周期), ...]
KDJ_参数列表: List[tuple] = None, # [(key, RSV周期, K平滑, D平滑), ...]
BOLL_参数列表: List[tuple] = None, # [(key, 周期, 标准差倍数), ...]
图表展示: bool = True,
推送K线: bool = True,
推送笔: bool = True,
推送线段: bool = True,
推送中枢: bool = True,
图表展示_笔: bool = True,
图表展示_线段: bool = True,
图表展示_扩展线段: bool = True,
图表展示_扩展线段_线段: bool = True,
图表展示_线段_线段: bool = True,
图表展示_中枢_笔: bool = True,
图表展示_中枢_线段: bool = True,
图表展示_中枢_扩展线段: bool = True,
图表展示_中枢_扩展线段_线段: bool = True,
图表展示_中枢_线段_线段: bool = True,
图表展示_中枢_线段内部: bool = True,
MACD_参数列表: List[tuple] = None, # [(key, 计算方式, 快线, 慢线, 信号), ...]
RSI_周期列表: List[tuple] = None, # [(key, 计算方式, 周期), ...]
KDJ_参数列表: List[tuple] = None, # [(key, 计算方式, RSV周期, K平滑, D平滑), ...]
BOLL_参数列表: List[tuple] = None, # [(key, 计算方式, 周期, 标准差倍数), ...]
图表展示: bool = True, # 图表系统主开关
图表展示标签: Optional[List[str]] = None, # None=全部展示, []=不展示, [\"笔\",\"线段\"]=指定
买卖点偏移: int = 1, # 最大偏移
买卖点激进识别: bool = False, # 激进模式下将不考虑分型的完整性
买卖点与MACD柱强相关: bool = False, # True: 卖点需正值 买点需负值
@@ -963,43 +933,13 @@ class 缠论配置:
self.手动终止 = 手动终止
self.计算指标 = 计算指标
self.指标计算方式 = 指标计算方式
self.平滑异同移动平均线_快线周期 = 平滑异同移动平均线_快线周期
self.平滑异同移动平均线_慢线周期 = 平滑异同移动平均线_慢线周期
self.平滑异同移动平均线_信号周期 = 平滑异同移动平均线_信号周期
self.相对强弱指数_周期 = 相对强弱指数_周期
self.相对强弱指数_移动平均线周期 = 相对强弱指数_移动平均线周期
self.相对强弱指数_超买阈值 = 相对强弱指数_超买阈值
self.相对强弱指数_超卖阈值 = 相对强弱指数_超卖阈值
self.随机指标_RSV周期 = 随机指标_RSV周期
self.随机指标_K值平滑周期 = 随机指标_K值平滑周期
self.随机指标_D值平滑周期 = 随机指标_D值平滑周期
self.随机指标_超买阈值 = 随机指标_超买阈值
self.随机指标_超卖阈值 = 随机指标_超卖阈值
self.计算BOLL = 计算BOLL
self.布林带_周期 = 布林带_周期
self.布林带_标准差倍数 = 布林带_标准差倍数
self.均线_类型列表 = 均线_类型列表 if 均线_类型列表 is not None else []
self.均线_周期列表 = 均线_周期列表 if 均线_周期列表 is not None else []
self.MACD_参数列表 = MACD_参数列表 if MACD_参数列表 is not None else []
self.RSI_周期列表 = RSI_周期列表 if RSI_周期列表 is not None else []
self.KDJ_参数列表 = KDJ_参数列表 if KDJ_参数列表 is not None else []
self.BOLL_参数列表 = BOLL_参数列表 if BOLL_参数列表 is not None else []
self.均线参数列表 = 均线参数列表 if 均线参数列表 is not None else []
self.MACD_参数列表 = MACD_参数列表 if MACD_参数列表 is not None else [("macd", "", 13, 31, 11)]
self.RSI_周期列表 = RSI_周期列表 if RSI_周期列表 is not None else [("rsi", "", 14, 13, 75.0, 25.0)]
self.KDJ_参数列表 = KDJ_参数列表 if KDJ_参数列表 is not None else [("kdj", "", 13, 5, 5, 80.0, 20.0)]
self.BOLL_参数列表 = BOLL_参数列表 if BOLL_参数列表 is not None else [("boll", "", 20, 2.0)]
self.图表展示 = 图表展示
self.推送K线 = 推送K线
self.推送笔 = 推送笔
self.推送线段 = 推送线段
self.推送中枢 = 推送中枢
self.图表展示_笔 = 图表展示_笔
self.图表展示_线段 = 图表展示_线段
self.图表展示_扩展线段 = 图表展示_扩展线段
self.图表展示_扩展线段_线段 = 图表展示_扩展线段_线段
self.图表展示_线段_线段 = 图表展示_线段_线段
self.图表展示_中枢_笔 = 图表展示_中枢_笔
self.图表展示_中枢_线段 = 图表展示_中枢_线段
self.图表展示_中枢_扩展线段 = 图表展示_中枢_扩展线段
self.图表展示_中枢_扩展线段_线段 = 图表展示_中枢_扩展线段_线段
self.图表展示_中枢_线段_线段 = 图表展示_中枢_线段_线段
self.图表展示_中枢_线段内部 = 图表展示_中枢_线段内部
self.图表展示标签 = set(图表展示标签) if 图表展示标签 is not None else None
self.买卖点偏移 = 买卖点偏移
self.买卖点激进识别 = 买卖点激进识别
self.买卖点与MACD柱强相关 = 买卖点与MACD柱强相关
@@ -1049,43 +989,13 @@ class 缠论配置:
"手动终止": {"annotation": str, "default": ""},
"计算指标": {"annotation": bool, "default": True},
"指标计算方式": {"annotation": str, "default": ""},
"平滑异同移动平均线_快线周期": {"annotation": int, "default": 13},
"平滑异同移动平均线_慢线周期": {"annotation": int, "default": 31},
"平滑异同移动平均线_信号周期": {"annotation": int, "default": 11},
"相对强弱指数_周期": {"annotation": int, "default": 13},
"相对强弱指数_移动平均线周期": {"annotation": int, "default": 13},
"相对强弱指数_超买阈值": {"annotation": float, "default": 75.0},
"相对强弱指数_超卖阈值": {"annotation": float, "default": 25.0},
"随机指标_RSV周期": {"annotation": int, "default": 13},
"随机指标_K值平滑周期": {"annotation": int, "default": 5},
"随机指标_D值平滑周期": {"annotation": int, "default": 5},
"随机指标_超买阈值": {"annotation": float, "default": 80.0},
"随机指标_超卖阈值": {"annotation": float, "default": 20.0},
"计算BOLL": {"annotation": bool, "default": False},
"布林带_周期": {"annotation": int, "default": 20},
"布林带_标准差倍数": {"annotation": float, "default": 2.0},
"均线_类型列表": {"annotation": List[str], "default": []},
"均线_周期列表": {"annotation": List[int], "default": []},
"MACD_参数列表": {"annotation": List[tuple], "default": []},
"RSI_周期列表": {"annotation": List[tuple], "default": []},
"KDJ_参数列表": {"annotation": List[tuple], "default": []},
"BOLL_参数列表": {"annotation": List[tuple], "default": []},
"均线参数列表": {"annotation": List[tuple], "default": []},
"MACD_参数列表": {"annotation": List[tuple], "default": [("macd", "", 13, 31, 11)]},
"RSI_周期列表": {"annotation": List[tuple], "default": [("rsi", "", 14, 13, 75.0, 25.0)]},
"KDJ_参数列表": {"annotation": List[tuple], "default": [("kdj", "", 13, 5, 5, 80.0, 20.0)]},
"BOLL_参数列表": {"annotation": List[tuple], "default": [("boll", "", 20, 2.0)]},
"图表展示": {"annotation": bool, "default": True},
"推送K线": {"annotation": bool, "default": True},
"推送笔": {"annotation": bool, "default": True},
"推送线段": {"annotation": bool, "default": True},
"推送中枢": {"annotation": bool, "default": True},
"图表展示_笔": {"annotation": bool, "default": True},
"图表展示_线段": {"annotation": bool, "default": True},
"图表展示_扩展线段": {"annotation": bool, "default": True},
"图表展示_扩展线段_线段": {"annotation": bool, "default": True},
"图表展示_线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_笔": {"annotation": bool, "default": True},
"图表展示_中枢_线段": {"annotation": bool, "default": True},
"图表展示_中枢_扩展线段": {"annotation": bool, "default": True},
"图表展示_中枢_扩展线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_线段_线段": {"annotation": bool, "default": True},
"图表展示_中枢_线段内部": {"annotation": bool, "default": True},
"图表展示标签": {"annotation": Optional[List[str]], "default": None},
"买卖点偏移": {"annotation": int, "default": 1},
"买卖点激进识别": {"annotation": bool, "default": False},
"买卖点与MACD柱强相关": {"annotation": bool, "default": False},
@@ -1137,27 +1047,45 @@ class 缠论配置:
logger.warning(f"[{fname}] = {value} 解析失败,使用默认值:{default}")
setattr(self, fname, default)
# ---- 参数列表解析:多参数列表为空时回退到默认单参数 ----
def 设置指标(
self,
*,
均线: List[tuple] = None,
MACD: List[tuple] = None,
RSI: List[tuple] = None,
KDJ: List[tuple] = None,
BOLL: List[tuple] = None,
):
"""统一设置所有指标参数。
def _解析MACD参数列表(self) -> List[tuple]:
if self.MACD_参数列表:
return self.MACD_参数列表
return [("macd", self.平滑异同移动平均线_快线周期, self.平滑异同移动平均线_慢线周期, self.平滑异同移动平均线_信号周期)]
元组格式 ``(key, 计算方式, *params)``
- 均线: ``("SMA_5", "", "SMA", 5)`` key/计算方式/类型/周期
- MACD: ``("默认", "", 13, 31, 11)`` 快线/慢线/信号
- RSI: ``("默认", "", 14, 13, 75, 25)`` 周期/MA周期/超买/超卖
- KDJ: ``("默认", "", 13, 5, 5, 80, 20)`` RSV/K平滑/D平滑/超买/超卖
- BOLL: ``("默认", "", 20, 2.0)`` 周期/标准差倍数
def _解析RSI周期列表(self) -> List[tuple]:
if self.RSI_周期列表:
return self.RSI_周期列表
return [("rsi", self.相对强弱指数_周期)]
:param 均线: key 即均线名 ``"SMA_5"``同时编码类型和周期
:param MACD: 首个 key 同时写入 ``"macd"`` 兼容槽位
:param BOLL: BOLL 参数元组列表为空则不计算
"""
self.计算指标 = True
if 均线 is not None:
self.均线参数列表 = 均线
if MACD is not None:
self.MACD_参数列表 = MACD
if RSI is not None:
self.RSI_周期列表 = RSI
if KDJ is not None:
self.KDJ_参数列表 = KDJ
if BOLL is not None:
self.BOLL_参数列表 = BOLL
def _解析KDJ参数列表(self) -> List[tuple]:
if self.KDJ_参数列表:
return self.KDJ_参数列表
return [("kdj", self.随机指标_RSV周期, self.随机指标_K值平滑周期, self.随机指标_D值平滑周期)]
def _解析BOLL参数列表(self) -> List[tuple]:
if self.BOLL_参数列表:
return self.BOLL_参数列表
return [("boll", self.布林带_周期, self.布林带_标准差倍数)]
def 展示标签(self, 标签: str) -> bool:
"""判断指定标签是否应展示。None = 全部展示,空列表 = 全部隐藏。"""
if self.图表展示标签 is None:
return True
return 标签 in self.图表展示标签
@classmethod
def 兼容旧版本配置(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -1190,7 +1118,13 @@ class 缠论配置:
:return: 包含所有配置字段的字典
"""
return {k: getattr(self, k) for k in self.model_fields().keys()}
result = {}
for k in self.model_fields().keys():
v = getattr(self, k)
if isinstance(v, set):
v = list(v)
result[k] = v
return result
def to_json(self) -> str:
"""将配置序列化为 JSON 字符串。
@@ -1246,21 +1180,7 @@ class 缠论配置:
return cls(
线段内部中枢图显=False,
图表展示=False,
推送K线=False,
推送笔=False,
推送线段=False,
推送中枢=False,
图表展示_笔=False,
图表展示_线段=False,
图表展示_扩展线段=False,
图表展示_扩展线段_线段=False,
图表展示_线段_线段=False,
图表展示_中枢_笔=False,
图表展示_中枢_线段=False,
图表展示_中枢_扩展线段=False,
图表展示_中枢_扩展线段_线段=False,
图表展示_中枢_线段_线段=False,
图表展示_中枢_线段内部=False,
图表展示标签=[],
)
def model_copy(self, update: dict = None, deep: bool = True):
@@ -2479,19 +2399,21 @@ class 指标计算器:
@staticmethod
def _计算MACD组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, , , 信号 in 配置._解析MACD参数列表():
for i, (key, 计算方式, *params) in enumerate(配置.MACD_参数列表):
, , 信号 = params[0], params[1], params[2]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 平滑异同移动平均线.增量计算_K线(prev_val, 当前K线, 计算方式)
else:
idx[key] = 平滑异同移动平均线.首次计算_K线(当前K线, 计算方式, , , 信号)
if i == 0:
idx["macd"] = idx[key]
@staticmethod
def _计算RSI组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, 周期 in 配置._解析RSI周期列表():
for key, 计算方式, *params in 配置.RSI_周期列表:
周期, MA周期, 超买, 超卖 = params[0], params[1], params[2], params[3]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 相对强弱指数.增量计算_K线(prev_val, 当前K线, 计算方式)
@@ -2500,16 +2422,16 @@ class 指标计算器:
当前K线,
计算方式,
周期,
配置.相对强弱指数_超买阈值,
配置.相对强弱指数_超卖阈值,
配置.相对强弱指数_移动平均线周期,
超买,
超卖,
MA周期,
)
@staticmethod
def _计算KDJ组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, rsv, k平滑, d平滑 in 配置._解析KDJ参数列表():
for key, 计算方式, *params in 配置.KDJ_参数列表:
rsv, k平滑, d平滑, 超买, 超卖 = params[0], params[1], params[2], params[3], params[4]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 随机指标.增量计算_K线(prev_val, 当前K线, 计算方式)
@@ -2520,15 +2442,15 @@ class 指标计算器:
rsv,
k平滑,
d平滑,
配置.随机指标_超买阈值,
配置.随机指标_超卖阈值,
超买,
超卖,
)
@staticmethod
def _计算BOLL组(当前K线: K线, prev: Optional[指标容器], 配置: 缠论配置):
idx = 当前K线.指标
计算方式 = 配置.指标计算方式
for key, 周期, 标准差倍数 in 配置._解析BOLL参数列表():
for key, 计算方式, *params in 配置.BOLL_参数列表:
周期, 标准差倍数 = params[0], params[1]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 布林带.增量计算(prev_val, 当前K线, 计算方式)
@@ -2537,18 +2459,16 @@ class 指标计算器:
@staticmethod
def _更新均线(当前K线: K线, 普K序列: List[K线], 配置: 缠论配置):
if not 配置.均线_类型列表 or not 配置.均线_周期列表:
if not 配置.均线参数列表:
return
for ma_type in 配置.均线_类型列表:
for period in 配置.均线_周期列表:
key = f"{ma_type}_{period}"
if ma_type == "SMA":
当前K线.指标.均线[key] = 均线工具.增量SMA(普K序列, period, 配置.指标计算方式)
elif ma_type == "EMA":
前值 = None
if len(普K序列) >= 2:
前值 = 普K序列[-2].指标.均线.get(key)
当前K线.指标.均线[key] = 均线工具.增量EMA(普K序列, period, 配置.指标计算方式, 前值)
for key, 计算方式, ma_type, period in 配置.均线参数列表:
if ma_type == "SMA":
当前K线.指标.均线[key] = 均线工具.增量SMA(普K序列, period, 计算方式)
elif ma_type == "EMA":
前值 = None
if len(普K序列) >= 2:
前值 = 普K序列[-2].指标.均线.get(key)
当前K线.指标.均线[key] = 均线工具.增量EMA(普K序列, period, 计算方式, 前值)
@staticmethod
def _回填新指标(全序列: List[K线], 配置: 缠论配置):
@@ -2570,16 +2490,14 @@ class 指标计算器:
新参数.append(params)
return 新参数
新MACD = _新键(尾K指标, 首K指标, 配置._解析MACD参数列表())
新RSI = _新键(尾K指标, 首K指标, 配置._解析RSI周期列表())
新KDJ = _新键(尾K指标, 首K指标, 配置._解析KDJ参数列表())
新BOLL = _新键(尾K指标, 首K指标, 配置._解析BOLL参数列表())
新MACD = _新键(尾K指标, 首K指标, 配置.MACD_参数列表)
新RSI = _新键(尾K指标, 首K指标, 配置.RSI_周期列表)
新KDJ = _新键(尾K指标, 首K指标, 配置.KDJ_参数列表)
新BOLL = _新键(尾K指标, 首K指标, 配置.BOLL_参数列表)
if not (新MACD or 新RSI or 新KDJ or 新BOLL):
return
计算方式 = 配置.指标计算方式
for i, k线 in enumerate(全序列):
if k线.指标 is None:
k线.指标 = 指标容器()
@@ -2587,43 +2505,32 @@ class 指标计算器:
idx = k线.指标
prev = 全序列[i - 1].指标 if i > 0 else None
for key, , , 信号 in 新MACD:
for key, 计算方式, *params in 新MACD:
, , 信号 = params[0], params[1], params[2]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 平滑异同移动平均线.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 平滑异同移动平均线.首次计算_K线(k线, 计算方式, , , 信号)
for key, 周期 in 新RSI:
for key, 计算方式, *params in 新RSI:
周期, MA周期, 超买, 超卖 = params[0], params[1], params[2], params[3]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 相对强弱指数.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 相对强弱指数.首次计算_K线(
k线,
计算方式,
周期,
配置.相对强弱指数_超买阈值,
配置.相对强弱指数_超卖阈值,
配置.相对强弱指数_移动平均线周期,
)
idx[key] = 相对强弱指数.首次计算_K线(k线, 计算方式, 周期, 超买, 超卖, MA周期)
for key, rsv, k平滑, d平滑 in 新KDJ:
for key, 计算方式, *params in 新KDJ:
rsv, k平滑, d平滑, 超买, 超卖 = params[0], params[1], params[2], params[3], params[4]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 随机指标.增量计算_K线(prev_val, k线, 计算方式)
else:
idx[key] = 随机指标.首次计算_K线(
k线,
计算方式,
rsv,
k平滑,
d平滑,
配置.随机指标_超买阈值,
配置.随机指标_超卖阈值,
)
idx[key] = 随机指标.首次计算_K线(k线, 计算方式, rsv, k平滑, d平滑, 超买, 超卖)
for key, 周期, 标准差倍数 in 新BOLL:
for key, 计算方式, *params in 新BOLL:
周期, 标准差倍数 = params[0], params[1]
prev_val = prev[key] if prev is not None and key in prev else None
if prev_val is not None:
idx[key] = 布林带.增量计算(prev_val, k线, 计算方式)
@@ -4292,23 +4199,24 @@ class 虚线:
dif_up = dif_down = dea_up = dea_down = 0
for i in range(1, len(普K序列)):
pre, cur = 普K序列[i - 1].macd, 普K序列[i].macd
if pre.DIF is None or cur.DIF is None:
if pre is None or cur is None or pre.DIF is None or cur.DIF is None:
continue
if pre.DIF < 0 <= cur.DIF:
dif_up += 1
elif pre.DIF > 0 >= cur.DIF:
dif_down += 1
if pre.DEA < 0 <= cur.DEA:
dea_up += 1
elif pre.DEA > 0 >= cur.DEA:
dea_down += 1
if pre.DEA is not None and cur.DEA is not None:
if pre.DEA < 0 <= cur.DEA:
dea_up += 1
elif pre.DEA > 0 >= cur.DEA:
dea_down += 1
# 2. DIF与DEA交叉(带标记)
golden = death = 0
交叉标记 = [0] # 第0个位置无前值,先填0
for i in range(1, len(普K序列)):
pre, cur = 普K序列[i - 1].macd, 普K序列[i].macd
if pre.DIF is None or cur.DIF is None or pre.DEA is None or cur.DEA is None:
if pre is None or cur is None or pre.DIF is None or cur.DIF is None or pre.DEA is None or cur.DEA is None:
交叉标记.append(0)
continue
if pre.DIF <= pre.DEA and cur.DIF > cur.DEA:
@@ -7030,20 +6938,13 @@ class 立体分析器:
for 周期 in self.周期组:
临时配置 = 配置组.get(周期, 配置)
当前配置 = 临时配置.model_copy(
update={
"推送K线": False,
# "推送笔": False,
"推送线段": False,
# "图表展示": False,
},
update={"图表展示标签": []},
deep=True,
)
self._单体分析器[周期] = 观察者(符号=符号, 周期=周期, 配置=当前配置)
self._单体分析器[self.__显示周期].配置.推送K线 = True
self._单体分析器[self.__显示周期].配置.推送笔 = True
self._单体分析器[self.__显示周期].配置.推送线段 = True
self._单体分析器[self.__显示周期].配置.图表展示 = True
self._单体分析器[self.__显示周期].配置.图表展示标签 = None # None = 全部展示
self._单体分析器[self.__显示周期].重置基础序列()
for 周期 in self.周期组: # 将不同周期对其至显示周期
@@ -7156,7 +7057,7 @@ def 测试_指标挂载(配置: 缠论配置):
size = struct.calcsize(">6d")
for i in range(len(buffer) // size):
if i == 500:
配置.MACD_参数列表 = [("macd", 配置.平滑异同移动平均线_快线周期, 配置.平滑异同移动平均线_慢线周期, 配置.平滑异同移动平均线_信号周期)]
配置.MACD_参数列表 = [("macd", "", 13, 31, 11)]
配置.MACD_参数列表.append(("macd_12_26_9", 12, 26, 9))
k线 = K线.读取大端字节数组(buffer[i * size : i * size + size], 周期, 符号)
观察员.增加原始K线(k线)
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "maturin"
[project]
name = "chanlun"
version = "2606.77"
version = "2606.87"
description = "缠论技术分析库 — Rust 高性能实现"
readme = { file = "README.md", content-type = "text/markdown" }
license = { file = "LICENSE", content-type = "text/plain" }
+5
View File
@@ -252,6 +252,11 @@ impl 缠论配置Py {
})
}
/// 判断指定标签是否应展示。None = 全部展示,空列表 = 全部隐藏。
fn (&self, : &str) -> bool {
self..lock().as_ref().map_or(true, |c| c.())
}
#[classmethod]
/// 将形如 "1_open", "1_close", "2_open", "name" 的字典重组为嵌套结构
fn (
+2 -5
View File
@@ -61,8 +61,7 @@ impl 立体分析器 {
.get(&)
.cloned()
.unwrap_or_else(|| .clone());
.K线 = false;
.线 = false;
. = Some(vec![]);
. = .clone();
let = ::new(.clone(), , );
@@ -73,9 +72,7 @@ impl 立体分析器 {
{
let = .get(&).expect("显示周期观察者不存在");
let mut guard = .write();
guard..K线 = true;
guard.. = true;
guard..线 = true;
guard.. = None; // None = 全部展示
guard.. = true;
guard.();
}
+25 -172
View File
@@ -92,103 +92,34 @@ pub struct 缠论配置 {
// ---- 指标 ----
/// 是否计算技术指标
pub : bool,
/// 是否计算布林带
pub BOLL: bool,
/// 指标计算方式(开/高/低/收/高低均值/高低收均值/开高低收均值)
/// 指标计算方式(均线使用,MACD/RSI/KDJ/BOLL 在参数元组中指定)
#[serde(deserialize_with = "deserialize_指标计算方式")]
pub : String,
// ---- MACD ----
/// MACD 快线 EMA 周期
pub 线_快线周期: i64,
/// MACD 慢线 EMA 周期
pub 线_慢线周期: i64,
/// MACD 信号线周期
pub 线_信号周期: i64,
/// MACD 多参数列表: Vec<(key, 快线, 慢线, 信号)>
/// MACD 参数列表 (key, 计算方式, 快线, 慢线, 信号)
#[serde(default)]
pub MACD_参数列表: Vec<(String, i64, i64, i64)>,
pub MACD_参数列表: Vec<(String, String, i64, i64, i64)>,
// ---- RSI ----
/// RSI 计算周期
pub _周期: i64,
/// RSI SMA 平滑周期
pub _移动平均线周期: i64,
/// RSI 超买阈值
pub _超买阈值: f64,
/// RSI 超卖阈值
pub _超卖阈值: f64,
/// RSI 多周期列表: Vec<(key, 周期)>
/// RSI 参数列表 (key, 计算方式, 周期, MA周期, 超买, 超卖)
#[serde(default)]
pub RSI_周期列表: Vec<(String, i64)>,
pub RSI_周期列表: Vec<(String, String, i64, i64, f64, f64)>,
// ---- KDJ ----
/// KDJ RSV 周期
pub _RSV周期: i64,
/// KDJ K 值平滑周期
pub _K值平滑周期: i64,
/// KDJ D 值平滑周期
pub _D值平滑周期: i64,
/// KDJ 超买阈值
pub _超买阈值: f64,
/// KDJ 超卖阈值
pub _超卖阈值: f64,
/// KDJ 多参数列表: Vec<(key, RSV周期, K平滑, D平滑)>
/// KDJ 参数列表 (key, 计算方式, RSV, K平滑, D平滑, 超买, 超卖)
#[serde(default)]
pub KDJ_参数列表: Vec<(String, i64, i64, i64)>,
pub KDJ_参数列表: Vec<(String, String, i64, i64, i64, f64, f64)>,
// ---- BOLL ----
/// 布林带周期
pub _周期: i64,
/// 布林带标准差倍数
pub _标准差倍数: f64,
/// BOLL 多参数列表: Vec<(key, 周期, 标准差倍数)>
/// BOLL 参数列表 (key, 计算方式, 周期, 标准差倍数)
#[serde(default)]
pub BOLL_参数列表: Vec<(String, i64, f64)>,
pub BOLL_参数列表: Vec<(String, String, i64, f64)>,
// ---- 均线 ----
/// 均线类型列表: ["SMA", "EMA", ...]
/// 均线参数列表 (key, 计算方式, 类型, 周期) — 如 ("SMA_5", "收", "SMA", 5)
#[serde(default)]
pub 线_类型列表: Vec<String>,
/// 均线周期列表: [5, 10, 20, ...]
#[serde(default)]
pub 线_周期列表: Vec<i64>,
pub 线: Vec<(String, String, String, i64)>,
// ---- 推送/显示 ----
/// 是否启用图表展示
pub : bool,
/// 是否推送K线
pub K线: bool,
/// 是否推送笔
pub : bool,
/// 是否推送线段
pub 线: bool,
/// 是否推送中枢
pub : bool,
// ---- 图表展示细分 ----
/// 图表展示笔
pub _笔: bool,
/// 图表展示线段
pub _线段: bool,
/// 图表展示扩展线段
pub _扩展线段: bool,
/// 图表展示扩展线段(线段级)
pub _扩展线段_线段: bool,
/// 图表展示线段之线段
pub _线段_线段: bool,
/// 图表展示笔中枢
pub _中枢_笔: bool,
/// 图表展示线段中枢
pub _中枢_线段: bool,
/// 图表展示扩展中枢
pub _中枢_扩展线段: bool,
/// 图表展示扩展中枢(线段级)
pub _中枢_扩展线段_线段: bool,
/// 图表展示线段之中枢
pub _中枢_线段_线段: bool,
/// 图表展示线段内部中枢
pub _中枢_线段内部: bool,
/// 图表展示标签: None=全部, [] = 不展示
pub : Option<Vec<String>>,
// ---- 买卖点 ----
/// 买卖点偏移量
@@ -310,44 +241,14 @@ impl Default for 缠论配置 {
线: true,
: String::new(),
: true,
BOLL: false,
: "".into(),
线_快线周期: 13,
线_慢线周期: 31,
线_信号周期: 11,
_周期: 13,
_移动平均线周期: 13,
_超买阈值: 75.0,
_超卖阈值: 25.0,
_RSV周期: 13,
_K值平滑周期: 5,
_D值平滑周期: 5,
_超买阈值: 80.0,
_超卖阈值: 20.0,
MACD_参数列表: Vec::new(),
RSI_周期列表: Vec::new(),
KDJ_参数列表: Vec::new(),
_周期: 20,
_标准差倍数: 2.0,
BOLL_参数列表: Vec::new(),
线_类型列表: Vec::new(),
线_周期列表: Vec::new(),
MACD_参数列表: vec![("macd".into(), "".into(), 13, 31, 11)],
RSI_周期列表: vec![("rsi".into(), "".into(), 14, 13, 75.0, 25.0)],
KDJ_参数列表: vec![("kdj".into(), "".into(), 13, 5, 5, 80.0, 20.0)],
BOLL_参数列表: vec![("boll".into(), "".into(), 20, 2.0)],
线: Vec::new(),
: true,
K线: true,
: true,
线: true,
: true,
_笔: true,
_线段: true,
_扩展线段: true,
_扩展线段_线段: true,
_线段_线段: true,
_中枢_笔: true,
_中枢_线段: true,
_中枢_扩展线段: true,
_中枢_扩展线段_线段: true,
_中枢_线段_线段: true,
_中枢_线段内部: true,
: None,
: 1,
: false,
MACD柱强相关: false,
@@ -366,46 +267,12 @@ impl Default for 缠论配置 {
}
impl {
/// 解析MACD参数列表 — 如果列表非空则使用列表,否则返回默认单组
pub fn _解析MACD参数列表(&self) -> Vec<(String, i64, i64, i64)> {
if !self.MACD_参数列表.is_empty() {
return self.MACD_参数列表.clone();
/// 展示标签判定 — None=全部, [] = 全关
pub fn (&self, : &str) -> bool {
match &self. {
None => true,
Some(tags) => tags.iter().any(|t| t == ),
}
vec![(
"macd".into(),
self.线_快线周期,
self.线_慢线周期,
self.线_信号周期,
)]
}
/// 解析RSI周期列表 — 如果列表非空则使用列表,否则返回默认单组
pub fn _解析RSI周期列表(&self) -> Vec<(String, i64)> {
if !self.RSI_周期列表.is_empty() {
return self.RSI_周期列表.clone();
}
vec![("rsi".into(), self._周期)]
}
/// 解析KDJ参数列表 — 如果列表非空则使用列表,否则返回默认单组
pub fn _解析KDJ参数列表(&self) -> Vec<(String, i64, i64, i64)> {
if !self.KDJ_参数列表.is_empty() {
return self.KDJ_参数列表.clone();
}
vec![(
"kdj".into(),
self._RSV周期,
self._K值平滑周期,
self._D值平滑周期,
)]
}
/// 解析BOLL参数列表 — 如果列表非空则使用列表,否则返回默认单组
pub fn _解析BOLL参数列表(&self) -> Vec<(String, i64, f64)> {
if !self.BOLL_参数列表.is_empty() {
return self.BOLL_参数列表.clone();
}
vec![("boll".into(), self._周期, self._标准差倍数)]
}
/// 序列化为 JSON 字典(对应 Python to_dict,仅返回 model_fields 中的字段)
@@ -576,21 +443,7 @@ impl 缠论配置 {
Self {
线: false,
: false,
K线: false,
: false,
线: false,
: false,
_笔: false,
_线段: false,
_扩展线段: false,
_扩展线段_线段: false,
_线段_线段: false,
_中枢_笔: false,
_中枢_线段: false,
_中枢_扩展线段: false,
_中枢_扩展线段_线段: false,
_中枢_线段_线段: false,
_中枢_线段内部: false,
: Some(vec![]),
..self.clone()
}
}
+115 -187
View File
@@ -56,7 +56,7 @@ impl 指标计算器 {
Self::_计算KDJ组(K线, prev, );
Self::_计算BOLL组(K线, prev, );
}
Self::_更新均线(K线, , );
Self::_更新均线(K线, , ); // 当前K线在 全序列[n-1], 现有序列不含它
has_prev = n > 1;
} // prev_guard dropped here
@@ -66,10 +66,9 @@ impl 指标计算器 {
}
fn _计算MACD组(K线: &K线, prev: Option<&>, : &) {
let = &.;
for (i, (key, , , )) in ._解析MACD参数列表().into_iter().enumerate()
for (i, (key, , , , )) in .MACD_参数列表.iter().enumerate()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.(&key)) {
let val = if let Some(prev_val) = prev.and_then(|p| p.(key)) {
if let ::MACD(prev_macd) = prev_val {
::MACD(线::(
prev_macd,
@@ -95,21 +94,18 @@ impl 指标计算器 {
,
),
K线.,
,
,
,
*,
*,
*,
))
};
K线..write().(&key, val.clone());
if i == 0 {
K线..write().("macd", val);
}
K线..write().(key, val.clone());
}
}
fn _计算RSI组(K线: &K线, prev: Option<&>, : &) {
let = &.;
for (i, (key, )) in ._解析RSI周期列表().into_iter().enumerate() {
for (key, , , ma周期, , ) in .RSI_周期列表.iter()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.(&key)) {
if let ::RSI(prev_rsi) = prev_val {
::RSI(::(
@@ -136,23 +132,19 @@ impl 指标计算器 {
,
),
K线.,
,
._超买阈值,
._超卖阈值,
Some(._移动平均线周期),
*,
*,
*,
Some(*ma周期),
))
};
K线..write().(&key, val.clone());
if i == 0 {
K线..write().("rsi", val);
}
}
}
fn _计算KDJ组(K线: &K线, prev: Option<&>, : &) {
for (i, (key, rsv, k平滑, d平滑)) in ._解析KDJ参数列表().into_iter().enumerate()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.(&key)) {
for (key, _fm, rsv, k平滑, d平滑, , ) in .KDJ_参数列表.iter() {
let val = if let Some(prev_val) = prev.and_then(|p| p.(key)) {
if let ::KDJ(prev_kdj) = prev_val {
::KDJ(::(
prev_kdj,
@@ -170,24 +162,19 @@ impl 指标计算器 {
K线.,
K线.,
K线.,
rsv,
k平滑,
d平滑,
._超买阈值,
._超卖阈值,
*rsv,
*k平滑,
*d平滑,
*,
*,
))
};
K线..write().(&key, val.clone());
if i == 0 {
K线..write().("kdj", val);
}
K线..write().(key, val.clone());
}
}
fn _计算BOLL组(K线: &K线, prev: Option<&>, : &) {
let = &.;
for (i, (key, , )) in ._解析BOLL参数列表().into_iter().enumerate()
{
for (key, , , ) in .BOLL_参数列表.iter() {
let val = if let Some(prev_val) = prev.and_then(|p| p.(&key)) {
if let ::BOLL(prev_boll) = prev_val {
::BOLL(::(
@@ -214,22 +201,37 @@ impl 指标计算器 {
K线.,
,
),
as usize,
,
* as usize,
*,
))
};
K线..write().(&key, val.clone());
if i == 0 {
K线..write().("boll", val);
}
}
}
fn _更新均线(K线: &K线, : &[Arc<K线>], : &) {
if .线_类型列表.is_empty() || .线_周期列表.is_empty() {
if .线.is_empty() {
return;
}
let = &.;
for (key, , ma_type, period) in &.线 {
let = match ma_type.as_str() {
"SMA" => Self::_增量SMA(K线, , , *period, key),
"EMA" => Self::_增量EMA(K线, , , *period, key),
_ => continue,
};
if let Some(线_map) = K线..write().线_mut() {
线_map.insert(key.clone(), );
}
}
}
fn _增量SMA(
K线: &K线,
: &[Arc<K线>],
: &str,
period: i64,
prev_key: &str,
) -> f64 {
let = super::K线取值(
K线.,
K线.,
@@ -237,46 +239,20 @@ impl 指标计算器 {
K线.,
,
);
for ma_type in &.线_类型列表 {
for period in &.线_周期列表 {
let key = format!("{}_{}", ma_type, period);
let = match ma_type.as_str() {
"SMA" => Self::_增量SMA(, , *period, , &key),
"EMA" => Self::_增量EMA(, , *period, , &key),
_ => continue,
};
if let Some(线_map) = K线..write().线_mut() {
线_map.insert(key, );
}
}
}
}
/// 增量 SMA: 现有序列 (不含当前K线) + 当前价
fn _增量SMA(
: &[Arc<K线>],
: f64,
period: i64,
: &str,
prev_key: &str,
) -> f64 {
let existing_len = .len();
let p = period as usize;
// 现有序列 + 当前 = total_len
let total_len = existing_len + 1;
if total_len <= p {
let mut sum: f64 = [existing_len.saturating_sub(p.saturating_sub(1))..]
if existing_len + 1 <= p {
let sum: f64 =
.iter()
.map(|k| super::K线取值(k., k., k., k., ))
.sum();
sum += ;
return sum / (total_len as f64).max(1.0);
.sum::<f64>()
+ ;
return sum / ((existing_len + 1) as f64).max(1.0);
}
// 尝试从前一根K线获取缓存的SMA
if let Some(prev) = .last().and_then(|k| {
let guard = k..read();
guard.线().and_then(|m| m.get(prev_key)).copied()
}) {
if let Some(prev_sma) =
.last()
.and_then(|k| k..read().线().and_then(|m| m.get(prev_key)).copied())
{
let oldest = super::K线取值(
[existing_len - p].,
[existing_len - p].,
@@ -284,29 +260,33 @@ impl 指标计算器 {
[existing_len - p].,
,
);
return prev + ( - oldest) / period as f64;
return prev_sma + ( - oldest) / period as f64;
}
// 回退:完整计算
let mut sum: f64 = [existing_len.saturating_sub(p.saturating_sub(1))..]
let sum: f64 = [existing_len.saturating_sub(p.saturating_sub(1))..]
.iter()
.map(|k| super::K线取值(k., k., k., k., ))
.sum();
sum += ;
sum / (total_len as f64).min(p as f64)
.sum::<f64>()
+ ;
sum / ((existing_len + 1) as f64).min(p as f64)
}
/// 增量 EMA: 现有序列 (不含当前K线) + 当前价
fn _增量EMA(
K线: &K线,
: &[Arc<K线>],
: f64,
: &str,
period: i64,
_计算方式: &str,
prev_key: &str,
) -> f64 {
let = .last().and_then(|k| {
let guard = k..read();
guard.线().and_then(|m| m.get(prev_key)).copied()
});
let = super::K线取值(
K线.,
K线.,
K线.,
K线.,
,
);
let =
.last()
.and_then(|k| k..read().线().and_then(|m| m.get(prev_key)).copied());
match {
None => ,
Some(prev) => {
@@ -318,42 +298,40 @@ impl 指标计算器 {
/// 运行中新增指标参数时,回填所有历史K线
fn _回填新指标(: &[Arc<K线>], : &) {
// 作用域化首尾读锁:在回填写循环之前释放,避免读锁与写锁冲突
let (MACD, RSI, KDJ, BOLL) = {
let K_guard = [0]..read();
let K_guard = [.len() - 1]..read();
let MACD: Vec<_> =
._解析MACD参数列表()
.into_iter()
.filter(|(key, _, _, _)| K_guard.(key) && !K_guard.(key))
.MACD_参数列表
.iter()
.filter(|(key, ..)| K_guard.(key) && !K_guard.(key))
.cloned()
.collect();
let RSI: Vec<_> =
._解析RSI周期列表()
.into_iter()
.filter(|(key, _)| K_guard.(key) && !K_guard.(key))
.RSI_周期列表
.iter()
.filter(|(key, ..)| K_guard.(key) && !K_guard.(key))
.cloned()
.collect();
let KDJ: Vec<_> =
._解析KDJ参数列表()
.into_iter()
.filter(|(key, _, _, _)| K_guard.(key) && !K_guard.(key))
.KDJ_参数列表
.iter()
.filter(|(key, ..)| K_guard.(key) && !K_guard.(key))
.cloned()
.collect();
let BOLL: Vec<_> =
._解析BOLL参数列表()
.into_iter()
.filter(|(key, _, _)| K_guard.(key) && !K_guard.(key))
.BOLL_参数列表
.iter()
.filter(|(key, ..)| K_guard.(key) && !K_guard.(key))
.cloned()
.collect();
(MACD, RSI, KDJ, BOLL)
}; // 首K_guard, 尾K_guard dropped here
};
if MACD.is_empty() && RSI.is_empty() && KDJ.is_empty() && BOLL.is_empty() {
return;
}
let = &.;
// 从第一根K线开始逐根回填,每次只持有一根prev读锁
for i in 0...len() {
let k线 = &[i];
let prev_guard = if i > 0 {
@@ -362,112 +340,62 @@ impl 指标计算器 {
None
};
for (key, , , ) in &MACD {
let val = if let Some(ref prev) = prev_guard {
if let Some(::MACD(prev_macd)) = prev.(key) {
::MACD(线::_K线(
prev_macd,
k线,
,
))
} else {
::MACD(线::_K线(
k线,
,
*,
*,
*,
))
}
} else {
::MACD(线::_K线(
for (key, , , , ) in &MACD {
let val = match prev_guard.as_ref().and_then(|p| p.(key)) {
Some(::MACD(prev_macd)) => ::MACD(
线::_K线(prev_macd, k线, ),
),
_ => ::MACD(线::_K线(
k线,
,
*,
*,
*,
))
)),
};
k线..write().(key, val);
}
for (key, ) in &RSI {
let val = if let Some(ref prev) = prev_guard {
if let Some(::RSI(prev_rsi)) = prev.(key) {
::RSI(::_K线(
prev_rsi,
k线,
,
))
} else {
::RSI(::_K线(
k线,
,
*,
._超买阈值,
._超卖阈值,
Some(._移动平均线周期),
))
}
} else {
::RSI(::_K线(
for (key, , , ma周期, , ) in &RSI {
let val = match prev_guard.as_ref().and_then(|p| p.(key)) {
Some(::RSI(prev_rsi)) => ::RSI(
::_K线(prev_rsi, k线, ),
),
_ => ::RSI(::_K线(
k线,
,
*,
._超买阈值,
._超卖阈值,
Some(._移动平均线周期),
))
*,
*,
Some(*ma周期),
)),
};
k线..write().(key, val);
}
for (key, rsv, k平滑, d平滑) in &KDJ {
let val = if let Some(ref prev) = prev_guard {
if let Some(::KDJ(prev_kdj)) = prev.(key) {
for (key, _fm, rsv, k平滑, d平滑, , ) in &KDJ {
let val = match prev_guard.as_ref().and_then(|p| p.(key)) {
Some(::KDJ(prev_kdj)) => {
::KDJ(::_K线(prev_kdj, k线))
} else {
::KDJ(::_K线(
k线,
*rsv,
*k平滑,
*d平滑,
._超买阈值,
._超卖阈值,
))
}
} else {
::KDJ(::_K线(
k线,
*rsv,
*k平滑,
*d平滑,
._超买阈值,
._超卖阈值,
))
_ => ::KDJ(::_K线(
k线, *rsv, *k平滑, *d平滑, *, *,
)),
};
k线..write().(key, val);
}
for (key, , ) in &BOLL {
let val = if let Some(ref prev) = prev_guard {
if let Some(::BOLL(prev_boll)) = prev.(key) {
for (key, , , ) in &BOLL {
let val = match prev_guard.as_ref().and_then(|p| p.(key)) {
Some(::BOLL(prev_boll)) => {
::BOLL(::_K线(prev_boll, k线, ))
} else {
::BOLL(::_K线(
k线,
,
* as usize,
*,
))
}
} else {
::BOLL(::_K线(
_ => ::BOLL(::_K线(
k线,
,
* as usize,
*,
))
)),
};
k线..write().(key, val);
}