From 6a6d24f60138c471350906fe9395260fb8daf5c8 Mon Sep 17 00:00:00 2001 From: Porter Date: Sun, 5 Apr 2026 11:43:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=AD=E6=9E=A2=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E5=9C=A8klc=E5=92=8C=E7=AC=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanBI.py | 5 ++++ ChanBIZS.py | 3 ++ ChanEnum.py | 4 +++ ChanKLC.py | 35 ++++++++++++++++++++-- ChanLun.py | 4 +-- ChanSEG.py | 65 ++++++++++++++++++++++------------------ TF_DF.py | 9 +++--- web/app.py | 2 +- web/templates/index.html | 6 +--- 9 files changed, 89 insertions(+), 44 deletions(-) diff --git a/ChanBI.py b/ChanBI.py index 99c0fc7..73c6743 100644 --- a/ChanBI.py +++ b/ChanBI.py @@ -20,6 +20,11 @@ class ChanBI(): self.macd_hist = 0 self.macd_div = 0 self.seg = None + 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 def set_macdhist(self, macd_hist): diff --git a/ChanBIZS.py b/ChanBIZS.py index 459a6c9..17c6b85 100644 --- a/ChanBIZS.py +++ b/ChanBIZS.py @@ -21,11 +21,13 @@ class ChanBIZS(): self.sure_time = None self.end_klc = None self.zs_type = Chan_ZS_TYPE.NORMAL + start_bi.set_bi_zs(self) def set_end_bi(self, end_bi, sure_time): self.end_bi = end_bi self.set_end_time(end_bi.end_klc.end_time) self.is_sure = True self.sure_time = sure_time + end_bi.set_bi_zs(self) #print(self.start_time, self.is_sure, len(self.bi_list), self.dir, self.zs_type) def set_end_time(self, end_time): self.end_time = end_time @@ -40,6 +42,7 @@ class ChanBIZS(): def add_bi(self, bi: ChanBI): if bi: self.bi_list.append(bi) + bi.set_bi_zs(self) self.classify_zs() def set_pre(self, pre): self.pre = pre diff --git a/ChanEnum.py b/ChanEnum.py index 52d582b..9164374 100644 --- a/ChanEnum.py +++ b/ChanEnum.py @@ -167,6 +167,10 @@ class Chan_FX_TYPE(Enum): BB = auto() PTOP = auto() PBOTTOM = auto() +class Chan_FX(Enum): + CONTINUATION = auto() + REVERSAL = auto() + UNKNOWN = auto() class Chan_PRICE_TREND(Enum): UP = auto() DOWN = auto() diff --git a/ChanKLC.py b/ChanKLC.py index 7d09b97..8b76b3c 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -1,7 +1,9 @@ import copy from typing import Dict, Optional -from ChanEnum import Chan_FX_TYPE, Chan_KLINE_DIR, Chan_BI_DIR, Chan_KLC_FX, Chan_K_DIR, Chan_MACD_STATE, Chan_PRICE_TREND, Chan_EMA_POS, Chan_EMA_SEMANTIC, Chan_BSP_TYPE, Chan_KLC_STATE +from ChanEnum import Chan_FX_TYPE, Chan_KLINE_DIR, Chan_BI_DIR, Chan_KLC_FX +from ChanEnum import Chan_K_DIR, Chan_MACD_STATE, Chan_PRICE_TREND, Chan_EMA_POS +from ChanEnum import Chan_EMA_SEMANTIC, Chan_BSP_TYPE, Chan_KLC_STATE, Chan_FX import ChanKLU import ChanCTime import Chan_FX_Box @@ -41,8 +43,8 @@ class ChanKLC(): self.candle_dir = klu.candle_dir self.range = klu.range self.bb_out = True - self.macd = 0 - self.signal = 0 + self.macd = klu.macd + self.signal = klu.signal self.state = Chan_MACD_STATE.UNKNOWN self.continue_div = False self.separate_div = False @@ -73,6 +75,14 @@ class ChanKLC(): self.fx_box = None self.in_fx = False self.fx_confirmed = False + self.ema52_dis = klu.high - klu.ema52 if klu.close > klu.ema52 else klu.ema52 - klu.low + self.ema26_dis = klu.high - klu.ema26 if klu.close > klu.ema26 else klu.ema26 - klu.low + self.macd_signal_dis = abs(klu.macd - klu.signal) + self.ema52_ema26_dis = abs(klu.ema52 - klu.ema26) + self.fx_type = Chan_FX.UNKNOWN + self.bi_zs = None + self.seg_zs = None + self.last_bi_zs = None # ==================== EMA 通用计算方法 ==================== @staticmethod @@ -315,6 +325,9 @@ class ChanKLC(): price_diff = getattr(self, 'price_diff', None) out += str(start) + " " + str(end) + " " + str(self.close) + " " + str(self.ema24) + " " + str(self.ema52) + " " + str(self.trend) + " " + str(self.close - self.ema52) return out + def set_bi_zs(self, bi_zs): + if bi_zs: + self.bi_zs = bi_zs def set_klc_fx_type(self, klc_fx_type): #print(self.start_time, klc_fx_type, self.get_feature_data()['klu_macd'], self.get_feature_data()['klu_macdhist'], self.get_feature_data()['klu_rsi']) self.klc_fx_type = klc_fx_type @@ -328,6 +341,22 @@ class ChanKLC(): #print(self.pre.start_time, self.next.end_time, self.klc_fx_type) if klc_fx_type == Chan_KLC_FX.TOP1 or klc_fx_type == Chan_KLC_FX.TOP2 or klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc_fx_type == Chan_KLC_FX.BOTTOM2: self.cal_fx_box() + self.cal_fx_type() + def cal_fx_type(self): + if self.fx == Chan_FX_TYPE.TOP and self.next: + if self.ema52_dis > self.ema26_dis: + if self.pre.macd < self.macd and self.macd < self.next.macd: + self.fx_type = Chan_FX.CONTINUATION + else: + self.fx_type = Chan_FX.REVERSAL + elif self.fx == Chan_FX_TYPE.BOTTOM and self.next: + if self.ema52_dis < self.ema26_dis: + if self.pre.macd > self.macd and self.macd > self.next.macd: + self.fx_type = Chan_FX.CONTINUATION + else: + self.fx_type = Chan_FX.REVERSAL + if self.fx_type != Chan_FX.UNKNOWN and self.fx_type != Chan_FX.CONTINUATION: + print(self.end_time, self.fx_type) def cal_fx_box(self): # 每次重算前先清空,避免旧box残留 self.fx_box = None diff --git a/ChanLun.py b/ChanLun.py index 2bb5d6b..2eeee78 100644 --- a/ChanLun.py +++ b/ChanLun.py @@ -141,8 +141,8 @@ class ChanLun(): return self.tf_df.cal_kl_data(dataframe) def cal_volume_ratio(self, dataframe, window=10): return self.tf_df.cal_volume_ratio(dataframe, window) - def calculate_zs(self, bi_list, seg_list): - return self.get_zs_list(bi_list, seg_list) + def calculate_seg_zs(self, bi_list, seg_list): + return self.get_seg_zs_list(bi_list, seg_list) def get_seg_list(self, bi_list): return self.tf_df.get_seg_list(bi_list) def cal_trend(self, klc_list): diff --git a/ChanSEG.py b/ChanSEG.py index 230931d..67eda1c 100644 --- a/ChanSEG.py +++ b/ChanSEG.py @@ -91,41 +91,44 @@ class ChanSEG(): zs_list = [] if len(self.bi_list) > 3: last_zs = None - zs_count = 0 if self.dir == Chan_SEG_DIR.UP: for index in range(1, len(self.bi_list)): bi = self.bi_list[index] + if bi.next == None or bi.next.next == None: + continue + bi2 = bi.next + bi3 = bi.next.next if len(zs_list) == 0 or (last_zs and last_zs.is_sure): - if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.DOWN: - zg = min(bi.high, bi.next.high, bi.next.next.high) - zd = max(bi.low, bi.next.low, bi.next.next.low) - gg = max(bi.high, bi.next.high, bi.next.next.high) - dd = min(bi.low, bi.next.low, bi.next.next.low) + if bi3.is_sure and bi3.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.DOWN: + zg = min(bi.high, bi2.high, bi3.high) + zd = max(bi.low, bi2.low, bi3.low) + gg = max(bi.high, bi2.high, bi3.high) + dd = min(bi.low, bi2.low, bi3.low) zs = ChanBIZS(bi, len(zs_list), Chan_ZS_DIR.UP) zs.set_zg(zg) zs.set_zd(zd) zs.set_gg(gg) zs.set_dd(dd) - zs.add_bi(bi.next) - zs.add_bi(bi.next.next) + zs.add_bi(bi2) + zs.add_bi(bi3) zs_list.append(zs) last_zs = zs else: if bi.index > last_zs.bi_list[-1].index and bi.dir == Chan_BI_DIR.DOWN and bi.is_sure: if bi.low > last_zs.zg or bi.high < last_zs.zd: last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) - if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.DOWN: - zg = min(bi.high, bi.next.high, bi.next.next.high) - zd = max(bi.low, bi.next.low, bi.next.next.low) - gg = max(bi.high, bi.next.high, bi.next.next.high) - dd = min(bi.low, bi.next.low, bi.next.next.low) + if bi3.is_sure and bi3.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.DOWN: + zg = min(bi.high, bi2.high, bi3.high) + zd = max(bi.low, bi2.low, bi3.low) + gg = max(bi.high, bi2.high, bi3.high) + dd = min(bi.low, bi2.low, bi3.low) zs = ChanBIZS(bi, len(zs_list), Chan_ZS_DIR.UP) zs.set_zg(zg) zs.set_zd(zd) zs.set_gg(gg) zs.set_dd(dd) - zs.add_bi(bi.next) - zs.add_bi(bi.next.next) + zs.add_bi(bi2) + zs.add_bi(bi3) zs_list.append(zs) last_zs = zs else: @@ -137,37 +140,41 @@ class ChanSEG(): else: for index in range(1, len(self.bi_list)): bi = self.bi_list[index] + if bi.next == None or bi.next.next == None: + continue + bi2 = bi.next + bi3 = bi.next.next if len(zs_list) == 0 or (last_zs and last_zs.is_sure): - if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.UP: - zg = min(bi.high, bi.next.high, bi.next.next.high) - zd = max(bi.low, bi.next.low, bi.next.next.low) - gg = max(bi.high, bi.next.high, bi.next.next.high) - dd = min(bi.low, bi.next.low, bi.next.next.low) + if bi3.is_sure and bi3.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.UP: + zg = min(bi.high, bi2.high, bi3.high) + zd = max(bi.low, bi2.low, bi3.low) + gg = max(bi.high, bi2.high, bi3.high) + dd = min(bi.low, bi2.low, bi3.low) zs = ChanBIZS(bi, len(zs_list), Chan_ZS_DIR.DOWN) zs.set_zg(zg) zs.set_zd(zd) zs.set_gg(gg) zs.set_dd(dd) - zs.add_bi(bi.next) - zs.add_bi(bi.next.next) + zs.add_bi(bi2) + zs.add_bi(bi3) zs_list.append(zs) last_zs = zs else: if bi.index > last_zs.bi_list[-1].index and bi.dir == Chan_BI_DIR.UP and bi.is_sure: if bi.low > last_zs.zg or bi.high < last_zs.zd: last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) - if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.UP: - zg = min(bi.high, bi.next.high, bi.next.next.high) - zd = max(bi.low, bi.next.low, bi.next.next.low) - gg = max(bi.high, bi.next.high, bi.next.next.high) - dd = min(bi.low, bi.next.low, bi.next.next.low) + if bi3.is_sure and bi3.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.UP: + zg = min(bi.high, bi2.high, bi3.high) + zd = max(bi.low, bi2.low, bi3.low) + gg = max(bi.high, bi2.high, bi3.high) + dd = min(bi.low, bi2.low, bi3.low) zs = ChanBIZS(bi, len(zs_list), Chan_ZS_DIR.DOWN) zs.set_zg(zg) zs.set_zd(zd) zs.set_gg(gg) zs.set_dd(dd) - zs.add_bi(bi.next) - zs.add_bi(bi.next.next) + zs.add_bi(bi2) + zs.add_bi(bi3) zs_list.append(zs) last_zs = zs else: diff --git a/TF_DF.py b/TF_DF.py index e130cbb..9890d8a 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -1262,7 +1262,7 @@ class TF_DF(): if (last_top.low < klc.pre.high or last_top.low < klc.next.high) and (klc.index - last_top.index < 10): return False return True - + # 建议用这种方式生成笔中枢 def cal_bi_zs(self, seg_list): bi_zs_list = [] for seg in seg_list: @@ -1270,6 +1270,7 @@ class TF_DF(): if len(zs_list) > 0: bi_zs_list = list(bi_zs_list) + list(zs_list) return bi_zs_list + # 这个种方式不是很好,会有很多重叠的 def cal_bi_zs_list(self, bi_list): """ 根据缠论笔中枢定义计算中枢(参照 get_zs_list 线段中枢判断规则) @@ -1714,9 +1715,9 @@ class TF_DF(): bsp_list.append(bsp) return bsp_list - def calculate_zs(self, seg_list): - return self.get_zs_list(seg_list) - def get_zs_list(self, seg_list): + def calculate_seg_zs(self, seg_list): + return self.get_seg_zs_list(seg_list) + def get_seg_zs_list(self, seg_list): """ 根据缠论线段中枢定义计算中枢 从第4根线段开始(索引3),每3根线段为一组检查 diff --git a/web/app.py b/web/app.py index 70ac6f7..d29d29a 100644 --- a/web/app.py +++ b/web/app.py @@ -534,7 +534,7 @@ def analyze_chan(df, symbol=None, timeframe=None): #for index in range(0, 10): #print(bi_list[index].start_time, bi_list[index].start_klc.end_time, bi_list[index].dir) seg_list = chan.get_seg_list(bi_list) - zs_list = chan.calculate_zs(seg_list) + zs_list = chan.calculate_seg_zs(seg_list) # 计算笔中枢(BI中枢)并拍平成列表 #bi_zs_list = chan.cal_bi_zs_list(bi_list) diff --git a/web/templates/index.html b/web/templates/index.html index 9940e5c..4646ee0 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -767,11 +767,7 @@ -
-
-
缠论分析系统
-
- +