From ea47bfe9b7c3cf794036309cbc544f379f82441a Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Wed, 11 Mar 2026 11:33:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E6=9E=A2=E7=BB=88=E4=BA=8E=E7=94=BB?= =?UTF-8?q?=E5=AF=B9=E4=BA=86=EF=BC=8C=E5=8F=AF=E4=BB=A5=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanZS.py | 21 +++++++++++++- TF_DF.py | 85 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 76 insertions(+), 30 deletions(-) diff --git a/ChanZS.py b/ChanZS.py index 367368a..dbc7ae8 100644 --- a/ChanZS.py +++ b/ChanZS.py @@ -69,4 +69,23 @@ class ChanZS(): def set_gg(self, gg): self.gg = gg def set_dd(self, dd): - self.dd = dd \ No newline at end of file + self.dd = dd + + +# 大级别中枢:由多个区间重叠(扩张)的笔/线段中枢合并而成,用于显示更大级别的震荡区间 +class ChanZS_Big(): + def __init__(self, zs_list): + assert len(zs_list) >= 1 + self.zs_list = list(zs_list) + first = self.zs_list[0] + last = self.zs_list[-1] + self.start_time = first.start_time + self.end_time = last.end_time if last.end_time else None + self.start_klc = first.start_klc + self.end_klc = last.end_klc + # 大级别区间取并集:包住所有子中枢 + self.zd = min(zs.zd for zs in self.zs_list) + self.zg = max(zs.zg for zs in self.zs_list) + self.dd = min(zs.dd for zs in self.zs_list) + self.gg = max(zs.gg for zs in self.zs_list) + self.index = 0 # 由外部设置 \ No newline at end of file diff --git a/TF_DF.py b/TF_DF.py index 6eaa3c7..7ae8313 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -6,7 +6,7 @@ from ChanKLC import ChanKLC from ChanBI import ChanBI from ChanSBI import ChanSBI from ChanSEG import ChanSEG -from ChanZS import ChanZS +from ChanZS import ChanZS, ChanZS_Big from ChanBSP import ChanBSP import talib.abstract as ta import pandas as pd @@ -46,6 +46,7 @@ class TF_DF(): self.bi_list = self.cal_bi_list(self.klc_list) self.seg_list = self.get_seg_list(self.bi_list) self.zs_list = self.get_zs_list(self.bi_list, self.seg_list) + self.big_zs_list = self.get_big_zs_list(self.zs_list) self.chanmacd = ChanMACD(self.klu_list) self.klu_list = self.chanmacd.cal_macd_state() @@ -1945,9 +1946,9 @@ class TF_DF(): overlap = (zg >= last_zs.zd and zd <= last_zs.zg) if overlap: - # 有重叠,扩展中枢到5根、7根... - # 继续往后检查是否有更多线段与中枢重叠 - seg_count = 3 + # 有重叠,扩展中枢到5根、7根...(缠论:合并为同一中枢) + # 本组先纳入当前 3 根,再向后逐根尝试;遇到与 [zd,zg] 不重叠(离开中枢)则停止扩展 + added_segs = [seg_list[start_idx], seg_list[start_idx + 1], seg_list[start_idx + 2]] cur_idx = start_idx + 3 while cur_idx < len(seg_list): @@ -1955,43 +1956,39 @@ class TF_DF(): if not next_seg.is_sure: break - # 计算包含新线段后的区间 - segs = seg_list[start_idx:start_idx + seg_count + 1] - segs.append(next_seg) - - seg_highs = [s.high for s in segs] - seg_lows = [s.low for s in segs] - new_zg = min(seg_highs) - new_zd = max(seg_lows) - - if new_zg > new_zd: - # 新线段与中枢重叠,扩展 - seg_count += 1 - cur_idx += 1 - else: + # 扩展条件:新线段与中枢区间 [zd, zg] 有重叠即并入;不重叠则停止,离开中枢的线段不包含 + # 用起止笔的极值算线段区间,避免 seg.high/seg.low 在个别线段上未同步导致的误判 + seg_high = max(next_seg.start_bi.high, next_seg.end_bi.high) if next_seg.end_bi else next_seg.start_bi.high + seg_low = min(next_seg.start_bi.low, next_seg.end_bi.low) if next_seg.end_bi else next_seg.start_bi.low + overlap_with_zs = (seg_high >= last_zs.zd and seg_low <= last_zs.zg) + if not overlap_with_zs: break - if seg_list[start_idx].dir != seg_list[start_idx + seg_count].dir: - seg_count -= 1 - print(seg_count) - # 更新中枢区间为扩展后的范围 - segs_for_zs = seg_list[start_idx:start_idx + seg_count] + added_segs.append(next_seg) + cur_idx += 1 + + # 扩展中枢 = 原中枢线段 + 本组并入的线段(缠论合并) + segs_for_zs = list(last_zs.seg_list) + list(added_segs) + + # 中枢开始与结束线段方向一致:上涨中枢结束于 DOWN,下跌中枢结束于 UP + required_end_seg_dir = Chan_SEG_DIR.DOWN if last_zs.dir == Chan_ZS_DIR.DOWN else Chan_SEG_DIR.UP + while len(segs_for_zs) >= 3 and segs_for_zs[-1].dir != required_end_seg_dir: + segs_for_zs.pop() + + # 扩展时只更新 gg、dd 和 seg_list;zg、zd 由前 3 根线段确定,不随扩展改变 seg_highs = [s.high for s in segs_for_zs] seg_lows = [s.low for s in segs_for_zs] - - last_zs.set_zg(min(seg_highs)) - last_zs.set_zd(max(seg_lows)) last_zs.set_gg(max(seg_highs)) last_zs.set_dd(min(seg_lows)) last_zs.seg_list = segs_for_zs - # 更新结束时间 + # 更新结束时间(以裁剪后的最后一段为准) last_seg = segs_for_zs[-1] if last_seg.end_bi: last_zs.set_end_klc(last_seg.end_bi.end_klc, last_seg.sure_time, 0, last_seg) last_zs.set_end_seg(last_seg) - # 跳过已处理的线段 - start_idx += 3 + # 跳过本组已扫描的线段(从 start_idx 到 cur_idx-1),下一组从 cur_idx 起可能再形成新中枢 + start_idx = cur_idx continue else: # 没有重叠,创建新中枢 @@ -2063,6 +2060,36 @@ class TF_DF(): last_zs.is_sure = True return zs_list + + def get_big_zs_list(self, zs_list): + """ + 中枢扩张:将区间重叠的连续中枢合并为大级别中枢,便于显示更大级别的震荡区间。 + 重叠定义:两中枢 [zd,zg] 有交集,即 (zs_i.zg >= zs_j.zd and zs_i.zd <= zs_j.zg)。 + """ + big_list = [] + if len(zs_list) < 2: + return big_list + i = 0 + while i < len(zs_list): + group = [zs_list[i]] + j = i + 1 + while j < len(zs_list): + cur = zs_list[j] + # 与当前组内任一中枢有重叠即算扩张(通常只需与组内最后一个比) + last_in_group = group[-1] + overlap = (last_in_group.zg >= cur.zd and last_in_group.zd <= cur.zg) + if overlap: + group.append(cur) + j += 1 + else: + break + if len(group) >= 2: + big = ChanZS_Big(group) + big.index = len(big_list) + big_list.append(big) + i = j if len(group) >= 2 else i + 1 + return big_list + def get_klu_list(self, dataframe): klu_list = self.get_kl_data(dataframe) #klu_list = self.cal_klu_pattern(klu_list)