refactor: 缠论引擎迁入 chan/ 分层解耦,指标外置

将核心结构、指标与分析拆到 chan/{core,indicators,analysis,pipeline};
根目录保留兼容 shim;strategies 改为从 chan 包导入;买卖点经 bsp_macd 与 MACD 接合。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Porter
2026-08-03 14:47:13 +08:00
co-authored by Cursor
parent 2e905e7238
commit 2c1232555e
90 changed files with 9067 additions and 8535 deletions
+135
View File
@@ -0,0 +1,135 @@
from decimal import Decimal
from . import ChanKLC
from .ChanEnum import Chan_BI_DIR
class ChanBI():
def __init__(self, klc: ChanKLC, index, ddir=Chan_BI_DIR.UP):
self.start_klc = klc
self.end_klc = klc
self.next = None
self.pre = None
self.dir = ddir
self.index = index
self.is_sure = False
self.high = klc.high
self.low = klc.low
self.sure_time = None
self.klc_list = []
self.klc_list.append(klc)
self.end_time = klc.end_time
self.start_time = klc.start_time
# macd_hist:由 analysis.bsp_macd / cal_macdhist 填充,非结构固有字段
self.macd_hist = 0
self.macd_div = 0
self.seg = None
self.height = 0
self.width = 0
self.slop = 0
self.fib_list = []
self.seg_index = 0
self.bi_zs = None
self.seg_zs = None
def set_bi_zs(self, bi_zs):
for klc in self.klc_list:
klc.set_bi_zs(bi_zs)
def set_seg(self, seg):
self.seg = seg
self.seg_index = len(seg.bi_list)-1
def set_macdhist(self, macd_hist):
self.macd_hist = macd_hist
def set_macd_div(self, macd_div):
self.macd_div = macd_div
def cal_macd_div(self):
self.macd_div = 0.0
if self.pre and self.pre.pre:
if self.pre.pre.macd_hist == 0:
self.macd_div = 0.0
else:
self.macd_div = self.macd_hist / self.pre.pre.macd_hist
#print(self.start_time, self.end_time, self.macd_hist, self.pre.pre.macd_hist, self.macd_div)
def cal_macdhist(self):
"""兼容:从已挂载的 klu.macdhist 累加。新代码请用 analysis.bsp_macd.bi_macd_area(bi, store)。"""
self.macd_hist = 0
for klc in self.klc_list:
for klu in klc.klu_list:
if self.dir == Chan_BI_DIR.UP and klu.macdhist > 0:
self.macd_hist += klu.macdhist
if self.dir == Chan_BI_DIR.DOWN and klu.macdhist < 0:
self.macd_hist -= klu.macdhist
return self.macd_hist
def check_bi_zs_overlap(self):
if self.next and self.next.next:
if self.dir == Chan_BI_DIR.UP:
return self.low < self.next.next.high
else:
return self.high > self.next.next.low
else:
return False
def check_overlap(self):
if self.next and self.next.next and self.next.next.is_sure:
if self.dir == Chan_BI_DIR.UP:
return self.high > self.next.low and self.high < self.next.next.high
else:
return self.high > self.next.high and self.low > self.next.next.low
else:
return False
def set_end_klc(self, klc, sure_klc):
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
self.high = klc.high
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
self.low = klc.low
self.end_klc = klc
self.set_is_sure(True, sure_klc.end_time)
self.end_time = klc.end_time
self.cal_properties()
#print(self.start_time, klc.fx, "This bi is ended", len(self.klc_list), klc.index - self.start_klc.index)
def cal_properties(self):
if self.is_sure:
self.height = float(format(self.high - self.low, ".2f"))
self.width = self.end_klc.index - self.start_klc.index
self.slop = float(format(self.height / self.width, ".2f"))
fib_list = [0.0, 0.236, 0.382, 0.5, 0.618, 0.786, 1.0]
for fib in fib_list:
self.fib_list.append(float(format(self.height * fib + self.low, ".2f")))
#print(self.end_time, self.height, self.width, self.slop, self.fib_list)
def set_is_sure(self, is_sure, time):
self.is_sure = is_sure
self.sure_time = time
def set_start_klc(self, klc, ddir):
self.start_klc = klc
self.klc_list = []
self.klc_list.append(klc)
self.high = klc.high
self.low = klc.low
self.dir = ddir
def set_pre(self, bi):
self.pre = bi
def set_next(self, bi):
self.next = bi
def add_klc(self, klc):
added = False
if len(self.klc_list) > 0:
for index in range(0, len(self.klc_list)):
if self.klc_list[index].index == klc.index:
added = True
break
if not added:
self.klc_list.append(klc)
#print(self.start_time, klc.start_time)
#print(klc.end_time, klc.index)
self.end_klc = klc
self.end_time = klc.klu_list[-1].time
self.cal_macdhist()
self.cal_macd_div()
def append_klc_list(self, klc_list):
self.klc_list.append(klc_list)
def get_decimal(self, value):
return Decimal("{:.2f}".format(value))
def update_bi(self, klc):
self.end_klc = None
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
self.high = klc.high
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
self.low = klc.low
self.is_sure = False
self.sure_time = None
#print(self.start_time, klc.start_time, klc.fx, "This bi is extended")