Add Continue Div and Cross Div
This commit is contained in:
+3
-1
@@ -96,7 +96,9 @@ class Chan_MACD_STATE(Enum):
|
||||
RETURN_ZERO = auto() # 归零轴:能量柱呈现一根比一根短的排列方式
|
||||
RZ_UP = auto() # 归零轴后的零轴上涨
|
||||
RZ_DOWN = auto() # 归零轴后的零轴下跌
|
||||
|
||||
UP = auto() # 穿零轴后向上
|
||||
DOWN = auto() # 穿零轴后向下
|
||||
PEAK = auto() # 峰值:MACD白线处于高位
|
||||
# 基础状态
|
||||
UNKNOWN = auto() # 未知
|
||||
START = auto() # 开始
|
||||
|
||||
+79
-50
@@ -52,6 +52,8 @@ class ChanKLU:
|
||||
self.candle_dir = Chan_K_DIR.CROSS if self.close == self.open else Chan_K_DIR.BULL if self.close > self.open else Chan_K_DIR.BEAR
|
||||
self.strength = 0 if self.candle_dir == Chan_K_DIR.CROSS else self.cal_klu_strength()
|
||||
|
||||
self.continue_div = False
|
||||
self.separate_div = False
|
||||
self.ema52 = 0
|
||||
self.ema24 = 0
|
||||
self.macd_slop = 0
|
||||
@@ -73,6 +75,8 @@ class ChanKLU:
|
||||
self.div_type = "none" # {bearish, bullish, hidden_bearish, hidden_bullish, none}
|
||||
self.div_score = 0.0 # 背离强度(0-100)
|
||||
#print(self.open, self.close, self.high, self.low, self.candle_dir, self.strength)
|
||||
def set_macd_state(self, state):
|
||||
self.macd_state = state
|
||||
def cal_klu_strength(self):
|
||||
strength = 0
|
||||
if range != 0:
|
||||
@@ -608,7 +612,9 @@ class ChanKLU:
|
||||
self.ma5 = float(item['ma5']) if 'ma5' in item and item['ma5'] else 0
|
||||
self.ma10 = float(item['ma10']) if 'ma10' in item and item['ma10'] else 0
|
||||
self.ma30 = float(item['ma30']) if 'ma30' in item and item['ma30'] else 0
|
||||
|
||||
self.ema52 = float(item['ema52']) if 'ema52' in item and item['ema52'] else 0
|
||||
self.ema24 = float(item['ema24']) if 'ema24' in item and item['ema24'] else 0
|
||||
|
||||
# 安全检查 ma250、ma50 和 ma200
|
||||
self.ma250 = float(item['ma250']) if 'ma250' in item and item['ma250'] else 0
|
||||
self.ma50 = float(item['ma50']) if 'ma50' in item and item['ma50'] else 0
|
||||
@@ -645,70 +651,93 @@ class ChanKLU:
|
||||
self.macd_state = Chan_MACD_STATE.UNKNOWN
|
||||
return self.macd_state
|
||||
|
||||
# 调试:当前值
|
||||
#print(f"DEBUG: MACD值检查 - 时间: {self.time}, MACD: {self.macd:.4f}, Signal: {self.signal:.4f}, 前一根Signal: {self.pre.signal:.4f}")
|
||||
|
||||
# 3) CROSS0 仅以 Signal 穿越零轴判定
|
||||
if self.pre.signal >= 0 and self.signal < 0:
|
||||
self.macd_state = Chan_MACD_STATE.CROSS0_DOWN
|
||||
#print(f"DEBUG: CROSS0触发(向下) - 时间: {self.time}, Signal: {self.pre.signal:.4f}->{self.signal:.4f}")
|
||||
return self.macd_state
|
||||
if self.pre.signal <= 0 and self.signal > 0:
|
||||
self.macd_state = Chan_MACD_STATE.CROSS0_UP
|
||||
#print(f"DEBUG: CROSS0触发(向上) - 时间: {self.time}, Signal: {self.pre.signal:.4f}->{self.signal:.4f}")
|
||||
return self.macd_state
|
||||
|
||||
# 4) 高位状态的位置状态, 高位,高位空,归零轴
|
||||
position_state = Chan_MACD_STATE.UNKNOWN
|
||||
if abs(self.macd) > 50:
|
||||
position_state = self._cal_position_state()
|
||||
if position_state != Chan_MACD_STATE.UNKNOWN:
|
||||
self.macd_state = position_state
|
||||
#print(f"DEBUG: 位置状态设置 - 时间: {self.time}, 状态: {self.macd_state}, MACD: {self.macd:.4f}, Signal: {self.signal:.4f}")
|
||||
return self.macd_state
|
||||
|
||||
# 5) 趋近零轴:任一线接近零轴即可,无限接近零轴,EMA52没有加
|
||||
# 6) 趋近零轴:任一线接近零轴即可,无限接近零轴,EMA52没有加
|
||||
NEAR0_EPS = 15
|
||||
if abs(self.macd) <= NEAR0_EPS or abs(self.signal) <= NEAR0_EPS:
|
||||
self.macd_state = Chan_MACD_STATE.NEAR0
|
||||
#print(f"DEBUG: 趋近零轴触发 - 时间: {self.time}, MACD: {self.macd:.4f}, Signal: {self.signal:.4f}")
|
||||
return self.macd_state
|
||||
# 6) 离开0轴开始上涨或者下跌阶段,高位之前的
|
||||
if self.macd_state == Chan_MACD_STATE.UNKNOWN:
|
||||
if self.macd > 0 and self.pre:
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.NEAR0 or self.pre.macd_state == Chan_MACD_STATE.RZ_UP) and self.signal > self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.RZ_UP
|
||||
if self.macd > 0 and abs(self.low - self.ema52) <= NEAR0_EPS:
|
||||
self.macd_state = Chan_MACD_STATE.NEAR0
|
||||
return self.macd_state
|
||||
if self.macd < 0 and abs(self.high - self.ema52) <= NEAR0_EPS:
|
||||
self.macd_state = Chan_MACD_STATE.NEAR0
|
||||
return self.macd_state
|
||||
# 4) 穿零轴后离开零轴
|
||||
if self.pre.macd_state == Chan_MACD_STATE.CROSS0_UP and self.macd > self.pre.macd and self.signal < self.macdhist:
|
||||
self.macd_state = Chan_MACD_STATE.UP
|
||||
return self.macd_state
|
||||
if self.pre.macd_state == Chan_MACD_STATE.CROSS0_DOWN and self.macd < self.pre.macd and self.signal > self.macdhist:
|
||||
self.macd_state = Chan_MACD_STATE.DOWN
|
||||
return self.macd_state
|
||||
if self.pre.macd_state == Chan_MACD_STATE.UP and self.macd > self.pre.macd and self.signal > self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.UP
|
||||
return self.macd_state
|
||||
if self.pre.macd_state == Chan_MACD_STATE.DOWN and self.macd < self.pre.macd and self.signal < self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.DOWN
|
||||
return self.macd_state
|
||||
# 5) 高位状态的位置状态, 高位,高位空,归零轴
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.UP or self.pre.macd_state == Chan_MACD_STATE.HIGH or self.pre.macd_state == Chan_MACD_STATE.RZ_UP) and self.macd > 0:
|
||||
if abs(self.pre.macd - self.macd) < 10:
|
||||
self.macd_state = Chan_MACD_STATE.HIGH
|
||||
return self.macd_state
|
||||
else:
|
||||
if self.macd > self.pre.macd and self.signal > self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.UP
|
||||
return self.macd_state
|
||||
elif self.macd < 0 and self.pre:
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.NEAR0 or self.pre.macd_state == Chan_MACD_STATE.RZ_DOWN) and self.signal < self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.RZ_DOWN
|
||||
elif self.macd < self.pre.macd and self.signal < self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.RETURN_ZERO
|
||||
return self.macd_state
|
||||
# 7) 其余情况
|
||||
self.macd_state = Chan_MACD_STATE.UNKNOWN
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.DOWN or self.pre.macd_state == Chan_MACD_STATE.HIGH or self.pre.macd_state == Chan_MACD_STATE.RZ_DOWN) and self.macd < 0:
|
||||
if abs(self.pre.macd - self.macd) < 10:
|
||||
self.macd_state = Chan_MACD_STATE.HIGH
|
||||
return self.macd_state
|
||||
else:
|
||||
if self.macd > self.pre.macd and self.signal > self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.RETURN_ZERO
|
||||
return self.macd_state
|
||||
elif self.macd < self.pre.macd and self.signal < self.pre.signal:
|
||||
self.macd_state = Chan_MACD_STATE.DOWN
|
||||
return self.macd_state
|
||||
|
||||
# 7) 离开0轴开始上涨或者下跌阶段,高位之前的
|
||||
if self.macd > 0 and self.pre:
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.NEAR0 or self.pre.macd_state == Chan_MACD_STATE.RZ_UP) and (self.signal > self.pre.signal or self.close > self.ema52):
|
||||
self.macd_state = Chan_MACD_STATE.RZ_UP
|
||||
return self.macd_state
|
||||
elif self.macd < 0 and self.pre:
|
||||
if (self.pre.macd_state == Chan_MACD_STATE.NEAR0 or self.pre.macd_state == Chan_MACD_STATE.RZ_DOWN) and (self.signal < self.pre.signal or self.close < self.ema52):
|
||||
self.macd_state = Chan_MACD_STATE.RZ_DOWN
|
||||
return self.macd_state
|
||||
# 8) 归零轴走势
|
||||
if self.pre.macd_state == Chan_MACD_STATE.RETURN_ZERO:
|
||||
if self.macd > 0:
|
||||
if self.pre.macd > self.macd:
|
||||
self.macd_state = Chan_MACD_STATE.RETURN_ZERO
|
||||
return self.macd_state
|
||||
else:
|
||||
if self.pre.macd < self.macd:
|
||||
self.macd_state = Chan_MACD_STATE.RETURN_ZERO
|
||||
return self.macd_state
|
||||
# 9) 其余情况
|
||||
if self.pre.macd_state == Chan_MACD_STATE.UNKNOWN:
|
||||
if self.macd > 0 and self.close > self.ema52 and self.pre.pre and (self.pre.pre.macd_state == Chan_MACD_STATE.UP or self.pre.pre.macd_state == Chan_MACD_STATE.RZ_UP):
|
||||
self.macd_state = self.pre.pre.macd_state
|
||||
return self.macd_state
|
||||
elif self.macd < 0 and self.close < self.ema52 and self.pre.pre and (self.pre.pre.macd_state == Chan_MACD_STATE.DOWN or self.pre.pre.macd_state == Chan_MACD_STATE.RZ_DOWN):
|
||||
self.macd_state = self.pre.pre.macd_state
|
||||
return self.macd_state
|
||||
else:
|
||||
self.macd_state = Chan_MACD_STATE.UNKNOWN
|
||||
return self.macd_state
|
||||
return self.macd_state
|
||||
|
||||
def _cal_position_state(self):
|
||||
"""计算MACD位置状态:高位、高位空、归零轴"""
|
||||
if not hasattr(self, 'pre') or self.pre is None:
|
||||
return Chan_MACD_STATE.UNKNOWN
|
||||
pre_hist = abs(self.pre.macdhist)
|
||||
cur_hist = abs(self.macdhist)
|
||||
if self.next:
|
||||
next_hist = abs(self.next.macdhist)
|
||||
if cur_hist > pre_hist and cur_hist > next_hist:
|
||||
return Chan_MACD_STATE.HIGH
|
||||
if self.pre.macd_state == Chan_MACD_STATE.HIGH or self.pre.macd_state == Chan_MACD_STATE.HIGH_EMPTY:
|
||||
if self.macd > 0:
|
||||
if self.macd > self.signal:
|
||||
return Chan_MACD_STATE.HIGH_EMPTY
|
||||
else:
|
||||
return Chan_MACD_STATE.RETURN_ZERO
|
||||
elif self.macd < 0:
|
||||
if self.macd < self.signal:
|
||||
return Chan_MACD_STATE.HIGH_EMPTY
|
||||
else:
|
||||
return Chan_MACD_STATE.RETURN_ZERO
|
||||
return Chan_MACD_STATE.UNKNOWN
|
||||
def get_feature_data(self):
|
||||
features = dict()
|
||||
features['klu_close'] = self.close
|
||||
|
||||
+1
-1
@@ -1161,7 +1161,7 @@ class ChanLun():
|
||||
klc_list = []
|
||||
last_klu = None
|
||||
macd = ChanMACD(klu_list)
|
||||
klu_list = macd.cal_macd()
|
||||
klu_list = macd.cal_macd_state()
|
||||
for klu in klu_list:
|
||||
if len(klc_list) > 0:
|
||||
last_klc = klc_list[-1]
|
||||
|
||||
+126
-13
@@ -17,7 +17,125 @@ class ChanMACD():
|
||||
self.cross0_up_list = [] # 向上穿越零轴列表
|
||||
self.cross0_down_list = [] # 向下穿越零轴列表
|
||||
# 计算段 / UnitTF / HistSet 及状态标记
|
||||
self.cal_macd()
|
||||
self.cal_macd_state()
|
||||
def cal_macd_state(self):
|
||||
last_seg = None
|
||||
last_unittf = None
|
||||
last_histset = None
|
||||
last_klu = None
|
||||
for klu in self.klu_list:
|
||||
# initialise first histset
|
||||
if klu.macd == 0 and klu.signal == 0 and klu.macdhist == 0:
|
||||
continue
|
||||
if last_histset is None:
|
||||
if klu.macdhist > 0:
|
||||
last_histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, None, Chan_MACDHISTSET_DIR.ABOVE)
|
||||
self.histset_list.append(last_histset)
|
||||
else:
|
||||
last_histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, None, Chan_MACDHISTSET_DIR.UNDER)
|
||||
self.histset_list.append(last_histset)
|
||||
else:
|
||||
# initialise first seg and unittf
|
||||
if last_seg is None:
|
||||
# create histset afterwards
|
||||
if last_histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE:
|
||||
if klu.macdhist > 0:
|
||||
last_histset.add_klu(klu)
|
||||
else:
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.UNDER)
|
||||
self.histset_list.append(histset)
|
||||
last_histset.set_next(histset)
|
||||
histset.set_pre(last_histset)
|
||||
last_histset.set_end_klu(last_klu)
|
||||
last_histset = histset
|
||||
else:
|
||||
if klu.macdhist < 0:
|
||||
last_histset.add_klu(klu)
|
||||
else:
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE)
|
||||
self.histset_list.append(histset)
|
||||
last_histset.set_next(histset)
|
||||
histset.set_pre(last_histset)
|
||||
last_histset.set_end_klu(last_klu)
|
||||
last_histset = histset
|
||||
if last_klu.signal >= 0 and klu.signal < 0:
|
||||
last_unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, None, Chan_MACDUNITTF_DIR.UNDER, Chan_MACDUNITTF_TYPE.CROSS0, last_histset)
|
||||
self.unittf_list.append(last_unittf)
|
||||
last_seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, None, Chan_MACDSEG_DIR.UNDER, last_unittf)
|
||||
self.seg_list.append(last_seg)
|
||||
elif last_klu.signal <= 0 and klu.signal > 0:
|
||||
last_unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, None, Chan_MACDUNITTF_DIR.ABOVE, Chan_MACDUNITTF_TYPE.CROSS0, last_histset)
|
||||
self.unittf_list.append(last_unittf)
|
||||
last_seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, None, Chan_MACDSEG_DIR.ABOVE, last_unittf)
|
||||
self.seg_list.append(last_seg)
|
||||
# after the first seg and unittf
|
||||
else:
|
||||
# create histset afterwards
|
||||
if last_histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE:
|
||||
if klu.macdhist > 0:
|
||||
last_histset.add_klu(klu)
|
||||
else:
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.UNDER)
|
||||
self.histset_list.append(histset)
|
||||
last_histset.set_next(histset)
|
||||
histset.set_pre(last_histset)
|
||||
last_histset.set_end_klu(last_klu)
|
||||
last_histset = histset
|
||||
if last_unittf:
|
||||
last_unittf.add_histset(last_histset)
|
||||
else:
|
||||
if klu.macdhist < 0:
|
||||
last_histset.add_klu(klu)
|
||||
else:
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE)
|
||||
self.histset_list.append(histset)
|
||||
last_histset.set_next(histset)
|
||||
histset.set_pre(last_histset)
|
||||
last_histset.set_end_klu(last_klu)
|
||||
last_histset = histset
|
||||
if last_unittf:
|
||||
last_unittf.add_histset(last_histset)
|
||||
if last_klu.signal >= 0 and klu.signal < 0:
|
||||
last_unittf.set_end_klu(last_klu, Chan_MACDUNITTF_TYPE.CROSS0)
|
||||
unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, last_unittf, Chan_MACDUNITTF_DIR.UNDER, Chan_MACDUNITTF_TYPE.CROSS0, last_histset)
|
||||
self.unittf_list.append(unittf)
|
||||
last_unittf.set_next(unittf)
|
||||
last_seg.set_end_klu(last_klu)
|
||||
seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, last_seg, Chan_MACDSEG_DIR.UNDER, unittf)
|
||||
self.seg_list.append(seg)
|
||||
last_seg.set_next(seg)
|
||||
last_seg = seg
|
||||
last_unittf = unittf
|
||||
elif last_klu.signal <= 0 and klu.signal > 0:
|
||||
last_unittf.set_end_klu(last_klu, Chan_MACDUNITTF_TYPE.CROSS0)
|
||||
unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, last_unittf, Chan_MACDUNITTF_DIR.ABOVE, Chan_MACDUNITTF_TYPE.CROSS0, last_histset)
|
||||
self.unittf_list.append(unittf)
|
||||
last_unittf.set_next(unittf)
|
||||
last_seg.set_end_klu(last_klu)
|
||||
seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, last_seg, Chan_MACDSEG_DIR.ABOVE, unittf)
|
||||
self.seg_list.append(seg)
|
||||
last_seg.set_next(seg)
|
||||
last_seg = seg
|
||||
last_unittf = unittf
|
||||
elif last_unittf.is_end and last_klu.macd < klu.macd and klu.macd > klu.signal:
|
||||
unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, last_unittf, Chan_MACDUNITTF_DIR.ABOVE, Chan_MACDUNITTF_TYPE.NEAR0, last_histset)
|
||||
self.unittf_list.append(unittf)
|
||||
last_unittf.set_next(unittf)
|
||||
last_seg.add_unittf(unittf)
|
||||
last_unittf = unittf
|
||||
last_seg.add_klu(klu)
|
||||
else:
|
||||
if not last_unittf.is_end:
|
||||
last_unittf.add_klu(klu)
|
||||
last_seg.add_klu(klu)
|
||||
last_klu = klu
|
||||
if last_histset:
|
||||
last_histset.set_end_klu(last_klu)
|
||||
if last_unittf:
|
||||
last_unittf.set_end_klu(last_klu, None)
|
||||
if last_seg:
|
||||
last_seg.set_end_klu(last_klu)
|
||||
return self.klu_list
|
||||
def cal_macd(self):
|
||||
last_seg = None
|
||||
last_unittf = None
|
||||
@@ -26,6 +144,7 @@ class ChanMACD():
|
||||
last_klu = None
|
||||
for klu in self.klu_list:
|
||||
klu.cal_macd_state()
|
||||
print(klu.time, klu.macd_state)
|
||||
# 1) 只有当 MACD 已可用(非 UNKNOWN)时,才开始初始化段/单元
|
||||
if last_seg is None:
|
||||
if klu.macd_state != Chan_MACD_STATE.UNKNOWN:
|
||||
@@ -39,10 +158,9 @@ class ChanMACD():
|
||||
|
||||
# 初始化首段
|
||||
seg_dir = Chan_MACDSEG_DIR.ABOVE if klu.signal >= 0 else Chan_MACDSEG_DIR.UNDER
|
||||
seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, None, seg_dir)
|
||||
seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, None, seg_dir, last_unittf)
|
||||
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
|
||||
@@ -61,13 +179,11 @@ class ChanMACD():
|
||||
# 结束旧 histset(以前一根结束更合理)
|
||||
if last_histset and last_klu:
|
||||
last_histset.set_end_klu(last_klu)
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE)
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE if klu.macdhist >= 0 else 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)
|
||||
else:
|
||||
@@ -77,13 +193,11 @@ class ChanMACD():
|
||||
# 结束旧 histset(以前一根结束更合理)
|
||||
if last_histset and last_klu:
|
||||
last_histset.set_end_klu(last_klu)
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.UNDER)
|
||||
histset = ChanMACDHistSet(len(self.histset_list), klu.time, klu, last_histset, Chan_MACDHISTSET_DIR.ABOVE if klu.macdhist >= 0 else 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)
|
||||
# 2) 过零切段(使用KLU中的穿越状态)
|
||||
@@ -92,7 +206,7 @@ class ChanMACD():
|
||||
# 结束旧 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
|
||||
new_dir = Chan_MACDUNITTF_DIR.ABOVE if klu.signal >= 0 else Chan_MACDUNITTF_DIR.UNDER
|
||||
unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, last_unittf, new_dir, Chan_MACDUNITTF_TYPE.CROSS0, histset)
|
||||
self.unittf_list.append(unittf)
|
||||
last_unittf.set_next(unittf)
|
||||
@@ -101,11 +215,10 @@ class ChanMACD():
|
||||
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(len(self.seg_list), klu.time, klu, last_seg, new_dir)
|
||||
seg = ChanMACDSeg(len(self.seg_list), klu.time, klu, last_seg, new_dir, last_unittf)
|
||||
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的归零轴
|
||||
@@ -121,7 +234,7 @@ class ChanMACD():
|
||||
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 klu.signal >= 0 else Chan_MACDUNITTF_DIR.ABOVE
|
||||
new_dir = Chan_MACDUNITTF_DIR.ABOVE if klu.signal >= 0 else Chan_MACDUNITTF_DIR.UNDER
|
||||
unittf = ChanMACDUnitTF(len(self.unittf_list), klu.time, klu, last_unittf, new_dir, Chan_MACDUNITTF_TYPE.NEAR0, histset)
|
||||
self.unittf_list.append(unittf)
|
||||
last_unittf.set_next(unittf)
|
||||
|
||||
+40
-47
@@ -11,18 +11,17 @@ class ChanMACDHistSet():
|
||||
self.next = None
|
||||
self.pre = pre_histset
|
||||
self.peak_klu = None
|
||||
self.second_peak_klu = None
|
||||
self.area = start_klu.macdhist
|
||||
self.unittf_div = Chan_MACDUNITTF_DIV.UNDIV
|
||||
self.middle_klu = None
|
||||
self.middle_peak = None
|
||||
self.second_middle_peak = None
|
||||
self.div_count = 0
|
||||
self.last_klu = start_klu
|
||||
self.low_klu = None
|
||||
self.start_klu = start_klu
|
||||
self.peak_div_list = []
|
||||
def set_next(self, next_histset):
|
||||
self.next = next_histset
|
||||
def set_pre(self, pre_histset):
|
||||
self.pre = pre_histset
|
||||
def set_middle_klu(self, middle_klu):
|
||||
self.middle_klu = middle_klu
|
||||
def set_unittf_div(self, unittf_div):
|
||||
@@ -35,44 +34,42 @@ class ChanMACDHistSet():
|
||||
self.low_klu = None
|
||||
self.peak_klu = None
|
||||
self.div_count = 0
|
||||
self.peak_div_list = []
|
||||
else:
|
||||
if self.last_klu:
|
||||
self.cal_peak_klu(klu)
|
||||
self.cal_macdhist_klu(klu)
|
||||
self.last_klu = klu
|
||||
def cal_peak_klu(self, klu):
|
||||
def cal_macdhist_klu(self, klu):
|
||||
if self.middle_klu:
|
||||
if self.low_klu is None and abs(klu.macdhist) > abs(self.last_klu.macdhist):
|
||||
self.low_klu = self.last_klu
|
||||
return
|
||||
else:
|
||||
if self.peak_klu is None and self.low_klu and abs(klu.macdhist) < abs(self.last_klu.macdhist):
|
||||
self.peak_klu = self.last_klu
|
||||
self.low_klu = None
|
||||
elif self.low_klu and self.peak_klu:
|
||||
if abs(self.last_klu.macdhist) > abs(self.peak_klu.macdhist):
|
||||
self.peak_klu = self.last_klu
|
||||
self.low_klu = None
|
||||
elif abs(self.last_klu.macdhist) > abs(klu.macdhist):
|
||||
self.second_peak_klu = self.last_klu
|
||||
self.div_count += 1
|
||||
self.low_klu = None
|
||||
if klu.index >= self.middle_klu.index + 2:
|
||||
if klu.pre.pre:
|
||||
if abs(klu.pre.macdhist) > abs(klu.pre.pre.macdhist) and abs(klu.pre.macdhist) > abs(klu.macdhist):
|
||||
if self.peak_klu:
|
||||
if abs(klu.pre.macdhist) > abs(self.peak_klu.macdhist):
|
||||
self.peak_klu = klu.pre
|
||||
self.div_count = 0
|
||||
self.peak_div_list = []
|
||||
else:
|
||||
self.peak_div_list.append(klu.pre)
|
||||
self.div_count += 1
|
||||
klu.pre.continue_div = True
|
||||
else:
|
||||
self.peak_klu = klu.pre
|
||||
else:
|
||||
if self.peak_klu is None and abs(klu.macdhist) < abs(self.last_klu.macdhist):
|
||||
self.peak_klu = self.last_klu
|
||||
return
|
||||
else:
|
||||
if self.low_klu is None and self.peak_klu and abs(klu.macdhist) > abs(self.last_klu.macdhist):
|
||||
self.low_klu = self.last_klu
|
||||
return
|
||||
else:
|
||||
if self.peak_klu and self.low_klu:
|
||||
if abs(self.last_klu.macdhist) > abs(self.peak_klu.macdhist):
|
||||
self.peak_klu = self.last_klu
|
||||
self.low_klu = None
|
||||
elif abs(self.last_klu.macdhist) > abs(klu.macdhist):
|
||||
self.second_peak_klu = self.last_klu
|
||||
self.div_count += 1
|
||||
self.low_klu = None
|
||||
if len(self.klu_list) >= 3:
|
||||
if klu.pre.pre:
|
||||
if abs(klu.pre.macdhist) > abs(klu.pre.pre.macdhist) and abs(klu.pre.macdhist) > abs(klu.macdhist):
|
||||
if self.peak_klu:
|
||||
if abs(klu.pre.macdhist) > abs(self.peak_klu.macdhist):
|
||||
self.peak_klu = klu.pre
|
||||
self.div_count = 0
|
||||
self.peak_div_list = []
|
||||
else:
|
||||
self.peak_div_list.append(klu.pre)
|
||||
self.div_count += 1
|
||||
klu.pre.continue_div = True
|
||||
else:
|
||||
self.peak_klu = klu.pre
|
||||
def set_end_klu(self, end_klu):
|
||||
self.end_klu = end_klu
|
||||
self.end_time = end_klu.time
|
||||
@@ -83,13 +80,9 @@ class ChanMACDHistSet():
|
||||
self.peak_klu = self.start_klu
|
||||
else:
|
||||
self.peak_klu = end_klu
|
||||
#if self.div_count > 0:
|
||||
#print("Continue:", self.index, self.start_time, self.second_peak_klu.time, self.div_count)
|
||||
"""
|
||||
if self.div_klu:
|
||||
print(self.start_time, self.peak_klu.time, self.div_klu.time, self.klu_list[-1].time, len(self.klu_list), self.histset_dir)
|
||||
elif self.peak_klu:
|
||||
print(self.start_time, "Peak:", self.peak_klu.time, self.klu_list[-1].time, len(self.klu_list), self.histset_dir)
|
||||
else:
|
||||
print(self.start_time, "None", self.klu_list[-1].time, len(self.klu_list), self.histset_dir)
|
||||
"""
|
||||
peak_str = ""
|
||||
for peak_div in self.peak_div_list:
|
||||
peak_str += f"{peak_div.time}, "
|
||||
if self.peak_klu and len(self.peak_div_list) > 0:
|
||||
print("Continue Div: ",self.start_time, "Peak:", self.peak_klu.time, "Div: ", peak_str, self.histset_dir, self.div_count)
|
||||
|
||||
+4
-5
@@ -2,7 +2,7 @@ from ChanEnum import Chan_MACDSEG_DIR
|
||||
|
||||
|
||||
class ChanMACDSeg():
|
||||
def __init__(self, index, start_time, start_klu, pre_seg, seg_dir):
|
||||
def __init__(self, index, start_time, start_klu, pre_seg, seg_dir, start_unittf):
|
||||
self.index = index
|
||||
self.start_time = start_time
|
||||
self.end_time = None
|
||||
@@ -11,15 +11,17 @@ class ChanMACDSeg():
|
||||
self.klu_list = []
|
||||
self.klu_list.append(start_klu)
|
||||
self.unittf_list = []
|
||||
self.hist_set = []
|
||||
self.seg_dir = seg_dir
|
||||
self.pre = pre_seg
|
||||
self.next = None
|
||||
self.high_klu = start_klu
|
||||
self.low_klu = start_klu
|
||||
self.ref_klu = None
|
||||
self.unittf_list.append(start_unittf)
|
||||
def set_next(self, next_seg):
|
||||
self.next = next_seg
|
||||
def set_pre(self, pre_seg):
|
||||
self.pre = pre_seg
|
||||
def add_klu(self, klu):
|
||||
if klu:
|
||||
self.klu_list.append(klu)
|
||||
@@ -41,9 +43,6 @@ class ChanMACDSeg():
|
||||
def add_unittf(self, unittf):
|
||||
self.unittf_list.append(unittf)
|
||||
unittf.set_next(self)
|
||||
def add_histset(self, histset):
|
||||
self.hist_set.append(histset)
|
||||
histset.set_next(self)
|
||||
def set_end_klu(self, end_klu):
|
||||
self.add_klu(end_klu)
|
||||
self.end_klu = end_klu
|
||||
|
||||
+61
-22
@@ -1,8 +1,8 @@
|
||||
from ChanEnum import Chan_MACD_STATE, Chan_MACDUNITTF_DIR, Chan_MACDHISTSET_DIR, Chan_MACDUNITTF_DIV
|
||||
from ChanEnum import Chan_MACD_STATE, Chan_MACDUNITTF_DIR, Chan_MACDHISTSET_DIR, Chan_MACDUNITTF_DIV, Chan_MACDUNITTF_TYPE
|
||||
|
||||
|
||||
class ChanMACDUnitTF():
|
||||
def __init__(self, index, start_time, start_klu, pre_unittf, dir, start_type, start_histset):
|
||||
def __init__(self, index, start_time, start_klu, pre_unittf, unittf_dir, start_type, start_histset):
|
||||
self.index = index
|
||||
self.start_time = start_time
|
||||
self.end_time = None
|
||||
@@ -16,26 +16,26 @@ class ChanMACDUnitTF():
|
||||
start_histset.set_middle_klu(start_klu)
|
||||
self.next = None
|
||||
self.pre = pre_unittf
|
||||
self.unittf_dir = dir
|
||||
self.unittf_dir = unittf_dir
|
||||
self.start_type = start_type
|
||||
self.end_type = None
|
||||
self.peak_klu = None
|
||||
self.div_type = Chan_MACDUNITTF_DIV.UNDIV
|
||||
self.div_peak_list = []
|
||||
self.div_low_list = []
|
||||
self.rev_low_klu = None
|
||||
self.is_end = False
|
||||
def set_next(self, next_unittf):
|
||||
self.next = next_unittf
|
||||
def set_pre(self, pre_unittf):
|
||||
self.pre = pre_unittf
|
||||
def add_histset(self, histset):
|
||||
self.histset_list.append(histset)
|
||||
def add_klu(self, klu):
|
||||
self.klu_list.append(klu)
|
||||
self.cal_peak_div()
|
||||
self.cal_macd_state()
|
||||
def cal_peak_div(self):
|
||||
self.div_count = 0
|
||||
self.div_peak_list = []
|
||||
self.div_low_list = []
|
||||
self.rev_low_klu = None
|
||||
self.peak_klu = None
|
||||
if len(self.histset_list) == 0:
|
||||
return
|
||||
@@ -59,26 +59,66 @@ class ChanMACDUnitTF():
|
||||
else:
|
||||
if histset.peak_klu:
|
||||
self.peak_klu = histset.peak_klu
|
||||
else:
|
||||
if self.rev_low_klu:
|
||||
if histset.low_klu:
|
||||
if abs(histset.low_klu.macdhist) < abs(self.rev_low_klu.macdhist):
|
||||
self.rev_low_klu = histset.low_klu
|
||||
self.div_low_list.append(histset.low_klu)
|
||||
else:
|
||||
if histset.low_klu:
|
||||
self.rev_low_klu = histset.low_klu
|
||||
self.div_low_list.append(histset.low_klu)
|
||||
def cal_macd_state(self):
|
||||
if len(self.klu_list) > 0:
|
||||
last_klu = self.klu_list[0]
|
||||
macd_peak_klu = None
|
||||
signal_peak_klu = None
|
||||
for index in range(1, len(self.klu_list)):
|
||||
klu = self.klu_list[index]
|
||||
if klu.macd == 0 and klu.signal == 0 and klu.macdhist == 0:
|
||||
continue
|
||||
if self.start_type == Chan_MACDUNITTF_TYPE.CROSS0 or self.start_type == Chan_MACDUNITTF_TYPE.NEAR0:
|
||||
if self.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE:
|
||||
if macd_peak_klu is None:
|
||||
if last_klu.macd < klu.macd:
|
||||
if last_klu.signal < last_klu.macdhist:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.UP)
|
||||
else:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
else:
|
||||
macd_peak_klu = last_klu
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.PEAK)
|
||||
elif klu.macd > macd_peak_klu.macd:
|
||||
macd_peak_klu = None
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
elif last_klu.signal < klu.signal:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH_EMPTY)
|
||||
elif signal_peak_klu is None:
|
||||
signal_peak_klu = last_klu
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH_EMPTY)
|
||||
elif klu.signal > signal_peak_klu.signal:
|
||||
signal_peak_klu = None
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
elif last_klu.macd < last_klu.signal:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.RETURN_ZERO)
|
||||
if self.return_zero(last_klu, klu):
|
||||
self.end_type = Chan_MACDUNITTF_TYPE.NEAR0
|
||||
self.is_end = True
|
||||
self.end_klu = klu
|
||||
self.end_time = klu.time
|
||||
klu.set_macd_state(Chan_MACD_STATE.NEAR0)
|
||||
#print(self.index, last_klu.time, last_klu.macd, last_klu.signal, last_klu.macd_state, klu.macd_state)
|
||||
break
|
||||
#print(self.index, last_klu.time, last_klu.macd, last_klu.signal, last_klu.macd_state)
|
||||
last_klu = klu
|
||||
|
||||
def return_zero(self, last_klu, klu):
|
||||
return_zero = False
|
||||
if last_klu.close < last_klu.ema52 and klu.close > klu.ema52:
|
||||
return_zero = True
|
||||
return return_zero
|
||||
def same_dir(self, histset):
|
||||
if self.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE:
|
||||
return histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE
|
||||
else:
|
||||
return histset.histset_dir == Chan_MACDHISTSET_DIR.UNDER
|
||||
def set_end_klu(self, end_klu, end_type):
|
||||
self.add_klu(end_klu)
|
||||
self.end_type = end_type
|
||||
self.end_klu = end_klu
|
||||
self.end_time = end_klu.time
|
||||
self.is_end = True
|
||||
self.cal_macd_state()
|
||||
div_time = ""
|
||||
for div in self.div_peak_list:
|
||||
div_time += f"{div.time}, "
|
||||
@@ -86,8 +126,7 @@ class ChanMACDUnitTF():
|
||||
for histset in self.histset_list:
|
||||
histset_time += f"{histset.start_time}, "
|
||||
|
||||
if self.peak_klu:
|
||||
print(self.index, self.start_klu.time, self.peak_klu.time, self.div_count, self.div_type, div_time, len(self.histset_list))
|
||||
else:
|
||||
print(self.index, "None", len(self.histset_list))
|
||||
if self.peak_klu and self.div_type == Chan_MACDUNITTF_DIV.DISCRETE:
|
||||
print("Cross Div: ", self.start_klu.time, self.peak_klu.time, self.div_count, self.div_type, self.unittf_dir, div_time, len(self.histset_list))
|
||||
|
||||
|
||||
@@ -5081,7 +5081,7 @@
|
||||
if (fx.fx_strength < 1.0) { // 降低阈值,让更多分型显示
|
||||
displayText = fx.fx_strength >= 0.8 ? '' : '' // 0.8以上显示点,0.8以下不显示文本
|
||||
}
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("4", "").replace("5", "");
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("41", "").replace("51", "");
|
||||
// 添加标记配置
|
||||
const markerConfig = {
|
||||
time: timestamp,
|
||||
@@ -5145,7 +5145,7 @@
|
||||
if (fx.fx_strength < 1.0) { // 降低阈值,让更多分型显示
|
||||
displayText = fx.fx_strength >= 1.5 ? '' : '' // 0.8以上显示点,0.8以下不显示文本
|
||||
}
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("4", "").replace("5", "");
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("41", "").replace("51", "");
|
||||
// 添加标记配置
|
||||
const markerConfig = {
|
||||
time: timestamp,
|
||||
@@ -5229,7 +5229,7 @@
|
||||
if (fx.fx_strength < 1.0){ // 调整小周期阈值
|
||||
displayText = fx.fx_strength >= 0.6 ? '' : '' // 0.6以上显示点
|
||||
}
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("4", "").replace("5", "");
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("41", "").replace("51", "");
|
||||
// 小周期分型标记配置
|
||||
const markerConfig = {
|
||||
time: timestamp,
|
||||
@@ -5285,7 +5285,7 @@
|
||||
if (fx.fx_strength < 2.0){ // 调整小周期阈值
|
||||
displayText = fx.fx_strength >= 1.5 ? '' : '' // 0.6以上显示点
|
||||
}
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("4", "").replace("5", "");
|
||||
displayText = fx.fx_type.replace("TOP", "").replace("BOTTOM", "").replace("11", "").replace("21", "").replace("31", "").replace("41", "").replace("51", "");
|
||||
// 小周期KLU分型标记配置
|
||||
const markerConfig = {
|
||||
time: timestamp,
|
||||
|
||||
Reference in New Issue
Block a user