From cc9dc1f79ff8894961290aad58d878630c424340 Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Tue, 24 Mar 2026 01:24:34 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=88=E4=BA=8E=E6=90=9E=E5=AE=9A=E4=B8=AD?= =?UTF-8?q?=E6=9E=A2=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanKLC.py | 8 +-- TF_DF.py | 173 ++++++++++++++++++----------------------------------- 缠论.txt | 38 ++++-------- 3 files changed, 72 insertions(+), 147 deletions(-) diff --git a/ChanKLC.py b/ChanKLC.py index fd97864..91680d1 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -365,24 +365,24 @@ class ChanKLC(): last_top.fx_confirmed = True if last_top.fx_box: last_top.fx_box.end_time = self.end_time - print(self.end_time, "fx_confirmed top") + #print(self.end_time, "fx_confirmed top") else: high = last_top.high low = self.low last_top.fx_box = Chan_FX_Box.Chan_FX_Box(last_top.pre.end_time, self.end_time, high, low) - print(self.end_time, "fx_confirmed new box top") + #print(self.end_time, "fx_confirmed new box top") elif self.in_fx == False and last_bottom.fx_confirmed == False: pre = last_bottom.pre if pre.high < self.close: last_bottom.fx_confirmed = True if last_bottom.fx_box: last_bottom.fx_box.end_time = self.end_time - print(self.end_time, "fx_confirmed bottom") + #print(self.end_time, "fx_confirmed bottom") else: high = self.high low = last_bottom.low last_bottom.fx_box = Chan_FX_Box.Chan_FX_Box(last_bottom.pre.end_time, self.end_time, high, low) - print(self.end_time, "fx_confirmed new box bottom") + #print(self.end_time, "fx_confirmed new box bottom") def add_klu(self, klu): self.klu_list.append(klu) def set_end_klu(self, klu): diff --git a/TF_DF.py b/TF_DF.py index e38f98b..875e2c6 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -1576,9 +1576,10 @@ class TF_DF(): """ 根据缠论线段中枢定义计算中枢 从第4根线段开始(索引3),每3根线段为一组检查 - 后一个中枢比前一个高 -> 上涨中枢,以下跌开始、以下跌结束 - 后一个中枢比前一个低 -> 下跌中枢,以上涨开始、以上涨结束 - 中枢可以扩展到5根、7根... + 上涨中枢:后中枢 zd > 前中枢 zg(不重叠上移) + 下跌中枢:后中枢 zg < 前中枢 zd(不重叠下移) + 盘整/扩张:后中枢与前中枢整体区间(GG/DD)有交集 + 中枢可按两段一组继续扩展到5根、7根... """ zs_list = [] if len(seg_list) < 3: @@ -1609,32 +1610,34 @@ class TF_DF(): if zg <= zd: start_idx += 1 + #print(seg1.start_bi.start_klc.end_time, "not valid", zg, zd) continue - # 判断中枢类型 - # 上涨中枢:以下跌开始、以下跌结束(下跌+上涨+下跌) - # 下跌中枢:以上涨开始、以上涨结束(上涨+下跌+上涨) + # 判断中枢类型(按注释定义) + # 上涨中枢:后中枢 zd > 前中枢 zg(不重叠上移) + # 下跌中枢:后中枢 zg < 前中枢 zd(不重叠下移) + # 盘整/扩张:后中枢与前中枢区间有交集 if last_zs is None: - # 第一个中枢 + # 第一个中枢仅按线段形态判定方向 if seg1.dir == Chan_SEG_DIR.DOWN: - # 下跌开始 -> 上涨中枢 - zs_dir = Chan_ZS_DIR.DOWN - # 验证模式:下跌+上涨+下跌 + # 下跌+上涨+下跌,对应上涨中枢 + zs_dir = Chan_ZS_DIR.UP valid = (seg2.dir == Chan_SEG_DIR.UP and seg3.dir == Chan_SEG_DIR.DOWN) else: - # 上涨开始 -> 下跌中枢 - zs_dir = Chan_ZS_DIR.UP - # 验证模式:上涨+下跌+上涨 + # 上涨+下跌+上涨,对应下跌中枢 + zs_dir = Chan_ZS_DIR.DOWN valid = (seg2.dir == Chan_SEG_DIR.DOWN and seg3.dir == Chan_SEG_DIR.UP) else: - # 根据与前一个中枢的高低比较判断 - if zg > last_zs.zg: - # 上涨中枢:以下跌开始、以下跌结束 - zs_dir = Chan_ZS_DIR.DOWN - valid = (seg1.dir == Chan_SEG_DIR.DOWN and seg2.dir == Chan_SEG_DIR.UP and seg3.dir == Chan_SEG_DIR.DOWN) - else: - # 下跌中枢:以上涨开始、以上涨结束 + is_up_zs = zd > last_zs.zg + is_down_zs = zg < last_zs.zd + + if is_up_zs: + # 不重叠上移 zs_dir = Chan_ZS_DIR.UP + valid = (seg1.dir == Chan_SEG_DIR.DOWN and seg2.dir == Chan_SEG_DIR.UP and seg3.dir == Chan_SEG_DIR.DOWN) + elif is_down_zs: + # 不重叠下移 + zs_dir = Chan_ZS_DIR.DOWN valid = (seg1.dir == Chan_SEG_DIR.UP and seg2.dir == Chan_SEG_DIR.DOWN and seg3.dir == Chan_SEG_DIR.UP) # 验证是否有效 @@ -1642,98 +1645,6 @@ class TF_DF(): start_idx += 1 continue - # 检查是否与前一个中枢重叠 - if last_zs: - # 判断是否有重叠 - overlap = (zg >= last_zs.zd and zd <= last_zs.zg) - - if overlap: - # 有重叠,扩展中枢到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): - next_seg = seg_list[cur_idx] - if not next_seg.is_sure: - break - - # 扩展条件:新线段与中枢区间 [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 - 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_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) - - # 下一组从「裁剪后保留的最后一段」的下一条线段开始,被裁掉的线段会参与下一组 3 根,避免漏到下一中枢 - last_kept_idx = cur_idx - 1 - for i in range(len(seg_list)): - if seg_list[i] == last_seg: - last_kept_idx = i - break - start_idx = last_kept_idx + 1 - continue - else: - # 本组3段整体与前中枢不重叠,仍逐根检查:若某线段与 [zd,zg] 重叠(如离开后回抽回到前中枢)则并入扩展,不直接新中枢 - added_after_leave = [] - for k in range(start_idx, min(start_idx + 3, len(seg_list))): - s = seg_list[k] - if not s.is_sure: - break - sh = max(s.start_bi.high, s.end_bi.high) if s.end_bi else s.start_bi.high - sl = min(s.start_bi.low, s.end_bi.low) if s.end_bi else s.start_bi.low - if sh >= last_zs.zd and sl <= last_zs.zg: - added_after_leave.append(s) - else: - break - if added_after_leave: - segs_for_zs = list(last_zs.seg_list) + list(added_after_leave) - 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() - seg_highs = [s.high for s in segs_for_zs] - seg_lows = [s.low for s in segs_for_zs] - 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 = start_idx + len(added_after_leave) - continue - # 没有任何线段与前中枢重叠,确认前中枢结束并创建新中枢 - if last_zs.seg_list and len(last_zs.seg_list) > 0: - prev_zs_last_seg = last_zs.seg_list[-1] - if prev_zs_last_seg.end_bi: - last_zs.set_end_klc(prev_zs_last_seg.end_bi.end_klc, prev_zs_last_seg.sure_time, 0, prev_zs_last_seg) - last_zs.set_end_seg(prev_zs_last_seg) - last_zs.is_sure = True - # 创建新中枢 gg = max(seg1.high, seg2.high, seg3.high) dd = min(seg1.low, seg2.low, seg3.low) @@ -1743,11 +1654,41 @@ class TF_DF(): zs.set_zd(zd) zs.set_gg(gg) zs.set_dd(dd) - zs.set_end_klc(seg3.end_bi.end_klc, seg3.sure_time, 0, seg3) - zs.set_end_seg(seg3) zs.is_sure = False zs.seg_list = [seg1, seg2, seg3] - + # 若第二线段与 [zd,zg] 重叠(如离开后回抽回到前中枢)则并入扩展 + added_after_leave = [] + leave_index = start_idx + 4 + while leave_index < len(seg_list): + s = seg_list[leave_index] + if not s.is_sure: + break + sh = max(s.start_bi.high, s.end_bi.high) if s.end_bi else s.start_bi.high + sl = min(s.start_bi.low, s.end_bi.low) if s.end_bi else s.start_bi.low + if sh >= zs.zd and sl <= zs.zg: + added_after_leave.append(s.pre) + added_after_leave.append(s) + else: + break + leave_index += 2 + if added_after_leave: + #print(len(added_after_leave)) + segs_for_zs = list(zs.seg_list) + list(added_after_leave) + seg_highs = [s.high for s in segs_for_zs] + seg_lows = [s.low for s in segs_for_zs] + zs.set_gg(max(seg_highs)) + zs.set_dd(min(seg_lows)) + zs.seg_list = segs_for_zs + seg = segs_for_zs[-1] + if seg.end_bi: + zs.set_end_klc(seg.end_bi.end_klc, seg.sure_time, 0, seg) + zs.set_end_seg(seg) + zs.is_sure = True + start_idx = start_idx + len(added_after_leave) + else: + zs.set_end_klc(seg3.end_bi.end_klc, seg3.sure_time, 0, seg3) + zs.set_end_seg(seg3) + zs.is_sure = True if last_zs: last_zs.set_next(zs) zs.set_pre(last_zs) @@ -1756,7 +1697,7 @@ class TF_DF(): last_zs = zs # 移动到下一组 - start_idx += 3 + start_idx += 4 # 处理最后一个未确认的中枢 - 不自动扩展,保持未完成状态 if last_zs and not last_zs.is_sure: diff --git a/缠论.txt b/缠论.txt index 0f1f44b..3cb91ec 100644 --- a/缠论.txt +++ b/缠论.txt @@ -1,7 +1,7 @@ ### 缠论中枢识别核心逻辑(按代码实现) 1. **基础中枢生成规则** - - 从第4根线段起,每连续3段已确认的线段为一组;方向严格交替:上涨中枢 down→up→down,下跌中枢 up→down→up; + - 从第4根线段起,每连续3段已确认的线段为一组; - 3段线段极值须有重叠(min(三高点) > max(三低点)),否则跳过本组; - 中枢核心区间(只读、扩展时不变): - zg = 初始3段高点的最小值(重叠区间上沿); @@ -9,38 +9,22 @@ - 中枢极值(扩展时可更新): - GG = 参与中枢的所有线段的高点最大值; - DD = 参与中枢的所有线段的低点最小值。 + - 上涨中枢:后中枢 zd > 前中枢 zg(后中枢整体上移且与前中枢不重叠); + - 下跌中枢:后中枢 zg < 前中枢 zd(后中枢整体下移且与前中枢不重叠); + - 方向严格交替:上涨中枢 down→up→down,下跌中枢 up→down→up; 2. **中枢扩展规则** - - 若下一组3段的区间 [zd,zg] 与当前中枢区间有重叠(zg≥当前zd 且 zd≤当前zg),则进行扩展,不新建中枢; - - 若本组3段整体与前中枢不重叠(例如已离开后新中枢区间在上/下方),仍逐根检查:只要某线段与当前中枢 [zd,zg] 有重叠(例如离开后的回抽段又回到前中枢内),则将该线段并入前中枢扩展,不因此直接新建中枢;从第一根不重叠的线段起再考虑新中枢; - - 扩展时:先将本组3段并入(或逐根并入见上),再向后逐根线段判断;线段与当前中枢 [zd,zg] 有重叠(线段区间与 [zd,zg] 相交)则并入,遇首根不重叠则停止扩展; - - 线段区间用该线段的起止笔极值:seg_high = max(start_bi.high, end_bi.high),seg_low = min(start_bi.low, end_bi.low); - - 扩展后裁剪:中枢参与线段的结束段方向须与形成时一致——上涨中枢结束于 down 段,下跌中枢结束于 up 段;从末尾向前 pop 至满足为止; + - 当形成三段中枢后,找到中枢后已完成的两段线段为一组看是否满足中枢扩展规则 + - 若下一组两段的第二段与当前中枢区间有重叠(第二段高点≥当前zd且第二段低点≤当前zg),则进行扩展,不新建中枢; + - 若下一组两段的第二段与当前中枢区间没有重叠,那么这两段都不并入当前中枢,当前中枢结束;从该两段组的第二段开始作为后续扫描起点,按中枢离开判断规则和新中枢生成规则继续; - 扩展时仅更新 GG、DD 和 seg_list;zg、zd 永不修改; - - 下一组起点:从「裁剪后保留的最后一段」的下一条线段开始,被裁掉的线段参与下一组3根,避免漏入错误中枢。 -3. **中枢离开判定规则** - - 向上离开:up 方向完成线段的 low > 原中枢 zg;强离开标注(非判定条件):up 线段 high > 原中枢 GG; - - 向下离开:down 方向完成线段的 high < 原中枢 zd;强离开标注(非判定条件):down 线段 low < 原中枢 DD; - - 有效离开(触发第三类买卖点): - - 向上有效离开:up 离开后,down 方向回抽线段的 low > 原中枢 zg 不进原中枢,触发第三类买点; - - 向下有效离开:down 离开后,up 方向回抽线段的 high < 原中枢 zd 不进原中枢,触发第三类卖点; - - 无效离开:回抽线段进入原中枢 [zd, zg] 区间,不触发第三类买卖点。 - -4. **新中枢生成规则** - - 若下一组3段与当前中枢区间不重叠,且本组内逐根检查后没有任何线段与前中枢 [zd,zg] 重叠(即没有“离开后回抽回到前中枢”),则当前中枢确认结束,本组3段生成新中枢; - - 新中枢类型与区间:后中枢 zg > 前中枢 zg → 上涨中枢(down→up→down);否则为下跌中枢(up→down→up); +3. **新中枢生成规则** + - 若下一组3段与当前中枢区间不重叠,且本组内逐根检查后没有任何线段与前中枢 [zd,zg] 重叠(即没有“离开后回抽回到前中枢”)但是需要满足上涨中枢和下跌中枢的规则; + - 新中枢类型按区间关系判定:后中枢 zd > 前中枢 zg → 上涨中枢(down→up→down);后中枢 zg < 前中枢 zd → 下跌中枢(up→down→up); - 新中枢的 zg/zd/GG/DD 仅基于自身初始3段计算;zg、zd 之后不再修改。 + -5. **中枢趋势判定规则** - - 上涨中枢:后中枢 zg > 前中枢 zg(即后中枢 zd > 前中枢 zg 的等价表述); - - 下跌中枢:后中枢 zg < 前中枢 zg; - - 盘整/扩张:后中枢与前中枢区间重叠(后 zd < 前 zg 且 后 zg > 前 zd)。 - -6. **大级别中枢(扩张)** - - 多个笔/线段中枢若区间两两重叠,可合并为一个大级别中枢; - - 重叠定义:两中枢 [zd,zg] 有交集,即 (zs_i.zg >= zs_j.zd and zs_i.zd <= zs_j.zg); - - 大级别中枢的 zd/zg 取子中枢的并集(包住所有子中枢),用于显示更大级别震荡区间。 线段高低点的判断 注意,这里必须提醒一句,就是这在以前也曾说过,就是,如果线段中,最高或最低点不是线段的端点,那么,在任何以线段为基础的分析中,例如把线段为基础构成最小级别的中枢等,都可以把该线段标准化为最高低点都在端点。因为, 在以线段为基础的分析中,都把线段当成一个没有内部 结构的基本部件,所以,只需要关心这线段的实际区间就可以,这样就可以只看其高低点。 经过标准化处理后,所有向上线段都是以最低点开始最高点结束,向下线段都是以最高点开始最低点结束,这样,所以线段的连接,就形成一条延续不断、首尾相连的折线,这样,复杂的图形,就会十分地标准化,也为后面的中枢、走势类型等分析提供了最标准且基础的部件。