from ChanKLU import ChanKLU from ChanEnum import Chan_MACD_STATE, Chan_MACDSEG_DIR, Chan_MACDHISTSET_DIR, Chan_MACDUNITTF_DIR, Chan_MACDUNITTF_TYPE from ChanMACDSeg import ChanMACDSeg from ChanMACDUnitTF import ChanMACDUnitTF from ChanMACDHistSet import ChanMACDHistSet class ChanMACD(): def __init__(self, klu_list: list[ChanKLU]): self.klu_list = klu_list self.seg_list = [] self.unittf_list = [] self.histset_list = [] # 状态标记列表 self.high_position_list = [] # 高位列表 self.high_empty_list = [] # 高位空列表 self.return_zero_list = [] # 归零轴列表 self.cross0_up_list = [] # 向上穿越零轴列表 self.cross0_down_list = [] # 向下穿越零轴列表 # 计算段 / UnitTF / HistSet 及状态标记 self.cal_macd() def cal_macd(self): last_seg = None last_unittf = None last_histset = None last_klu = None for klu in self.klu_list: klu.cal_macd_state() # 1) 只有当 MACD 已可用(非 UNKNOWN)时,才开始初始化段/单元 if last_seg is None: if klu.macd_state != Chan_MACD_STATE.UNKNOWN: # 初始化首个直方图集合(根据当前柱体正负) if klu.macdhist >= 0: histset = ChanMACDHistSet(klu.time, klu, None, Chan_MACDHISTSET_DIR.ABOVE) else: histset = ChanMACDHistSet(klu.time, klu, None, Chan_MACDHISTSET_DIR.UNDER) self.histset_list.append(histset) last_histset = histset # 初始化首段 seg_dir = Chan_MACDSEG_DIR.ABOVE if klu.signal >= 0 else Chan_MACDSEG_DIR.UNDER seg = ChanMACDSeg(klu.time, klu, None, seg_dir) self.seg_list.append(seg) last_seg = seg last_seg.add_histset(histset) # 初始化首个UnitTF unittf_dir = Chan_MACDUNITTF_DIR.ABOVE if klu.signal >= 0 else Chan_MACDUNITTF_DIR.UNDER unittf = ChanMACDUnitTF(klu.time, klu, None, unittf_dir, Chan_MACDUNITTF_TYPE.START) self.unittf_list.append(unittf) unittf.add_histset(histset) last_unittf = unittf last_unittf.add_histset(histset) last_seg.add_unittf(unittf) # 未就绪则继续等下一根;已就绪亦已完成首个结构初始化,继续下一根 last_klu = klu continue # 2) 过零切段(使用KLU中的穿越状态) if (klu.macd_state == Chan_MACD_STATE.CROSS0_UP or klu.macd_state == Chan_MACD_STATE.CROSS0_DOWN): # 结束旧 unittf last_unittf.set_end_klu(last_klu, Chan_MACDUNITTF_TYPE.CROSS0) # 新的单位时间周期 new_dir = Chan_MACDUNITTF_DIR.UNDER if last_unittf.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE else Chan_MACDUNITTF_DIR.ABOVE unittf = ChanMACDUnitTF(klu.time, klu, last_unittf, new_dir, Chan_MACDUNITTF_TYPE.CROSS0) self.unittf_list.append(unittf) unittf.add_histset(last_histset) last_unittf.set_next(unittf) last_unittf = unittf # 收尾旧段 last_seg.set_end_klu(last_klu) # 新段方向取反 new_dir = Chan_MACDSEG_DIR.UNDER if last_seg.seg_dir == Chan_MACDSEG_DIR.ABOVE else Chan_MACDSEG_DIR.ABOVE seg = ChanMACDSeg(klu.time, klu, last_seg, new_dir) self.seg_list.append(seg) last_seg.set_next(seg) last_seg = seg last_seg.add_histset(last_histset) last_seg.add_unittf(unittf) else: # 4) UnitTF 状态机:用黄线Signal的归零轴 if last_klu.macd_state == Chan_MACD_STATE.NEAR0 and last_unittf.near0_count > 1: if klu.macd_state == Chan_MACD_STATE.RZ_UP: last_unittf.set_end_klu(last_klu, Chan_MACDUNITTF_TYPE.NEAR0) new_dir = Chan_MACDUNITTF_DIR.ABOVE if last_unittf.unittf_dir == Chan_MACDUNITTF_DIR.UNDER else Chan_MACDUNITTF_DIR.UNDER unittf = ChanMACDUnitTF(klu.time, klu, last_unittf, new_dir, Chan_MACDUNITTF_TYPE.NEAR0) self.unittf_list.append(unittf) unittf.add_histset(last_histset) last_unittf.set_next(unittf) last_unittf = unittf last_seg.add_unittf(unittf) elif klu.macd_state == Chan_MACD_STATE.RZ_DOWN: last_unittf.set_end_klu(last_klu, Chan_MACDUNITTF_TYPE.NEAR0) new_dir = Chan_MACDUNITTF_DIR.UNDER if last_unittf.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE else Chan_MACDUNITTF_DIR.ABOVE unittf = ChanMACDUnitTF(klu.time, klu, last_unittf, new_dir, Chan_MACDUNITTF_TYPE.NEAR0) self.unittf_list.append(unittf) unittf.add_histset(last_histset) last_unittf.set_next(unittf) last_unittf = unittf last_seg.add_unittf(unittf) else: last_unittf.add_klu(klu) last_seg.add_klu(klu) else: last_unittf.add_klu(klu) last_seg.add_klu(klu) # 3) 直方图集合(基于当前 unittf) if klu.macdhist >= 0: if last_histset and last_histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE: last_histset.add_klu(klu) else: # 结束旧 histset(以前一根结束更合理) if last_histset and last_klu: last_histset.set_end_klu(last_klu) histset = ChanMACDHistSet(klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE) self.histset_list.append(histset) if last_histset: last_histset.set_next(histset) last_histset = histset if last_seg: last_seg.add_histset(histset) if last_unittf: last_unittf.add_histset(histset) else: if last_histset and last_histset.histset_dir == Chan_MACDHISTSET_DIR.UNDER: last_histset.add_klu(klu) else: # 结束旧 histset(以前一根结束更合理) if last_histset and last_klu: last_histset.set_end_klu(last_klu) histset = ChanMACDHistSet(klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.UNDER) self.histset_list.append(histset) if last_histset: last_histset.set_next(histset) last_histset = histset if last_seg: last_seg.add_histset(histset) if last_unittf: last_unittf.add_histset(histset) last_klu = klu return self.klu_list