添加klu的3种形态识别

This commit is contained in:
jackyu66git
2025-11-01 02:50:44 +08:00
parent 8bb3798a7c
commit 8e21ecb057
8 changed files with 287 additions and 117 deletions
+258 -10
View File
@@ -123,17 +123,25 @@ class TF_DF():
return klu_state_list
def check_fx(self, klc):
if klc.pre and klc.next:
if klc.high > klc.pre.high and klc.high > klc.next.high and klc.low > klc.pre.low and klc.low > klc.next.low:
if klc.high > klc.pre.high and klc.high > klc.next.high and klc.low > klc.pre.low and klc.low > klc.next.low and klc.next.klc_dir == Chan_KLINE_DIR.DOWN:
#if (klc.close > klc.ema52 or klc.next.close > klc.next.ema52) and klc.macd > 0 and klc.macd > klc.macdhist:
klc.set_fx(Chan_FX_TYPE.TOP)
#print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "TOP")
return Chan_FX_TYPE.TOP
elif klc.low < klc.pre.low and klc.low < klc.next.low and klc.high < klc.pre.high and klc.high < klc.next.high:
elif klc.low < klc.pre.low and klc.low < klc.next.low and klc.high < klc.pre.high and klc.high < klc.next.high and klc.next.klc_dir == Chan_KLINE_DIR.UP:
#if (klc.close < klc.ema52 or klc.next.close < klc.next.ema52) and klc.macd < 0 and klc.macd < klc.macdhist:
klc.set_fx(Chan_FX_TYPE.BOTTOM)
#print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "BOTTOM")
return Chan_FX_TYPE.BOTTOM
return Chan_FX_TYPE.UNKNOWN
def check_fx_pattern(self, klc):
klu_list = klc.pre.klu_list + klc.klu_list + klc.next.klu_list
self.cal_klu_pattern(klu_list)
p = ""
for klu in klu_list:
p += klu.to_string()
#print(p)
def cal_volume_ratio(self, dataframe, window=10):
df = dataframe.copy()
# 计算过去N根K线的平均成交量
@@ -914,6 +922,7 @@ class TF_DF():
last_top = klc
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 1")
klc.set_klc_fx_type(Chan_KLC_FX.TOP1)
self.check_fx_pattern(klc)
#print(klc.end_time, klc.fx, "一类卖点Sell 1")
#klc.set_fx(fx)
#klc.set_state("10")
@@ -968,6 +977,7 @@ class TF_DF():
last_top = klc
#print(klc.end_time, klc.fx, bi_list[-1].dir, "Last Top Change 2")
klc.set_klc_fx_type(Chan_KLC_FX.TOP2)
self.check_fx_pattern(klc)
#klc.set_state('30')
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
@@ -1040,6 +1050,7 @@ class TF_DF():
last_bottom = klc
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 1")
klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM1)
self.check_fx_pattern(klc)
#print(klc.start_time, klc.fx, "一类买点Buy 1")
#klc.set_state("-10")
bi_list[-1].add_klc(klc)
@@ -1095,6 +1106,7 @@ class TF_DF():
last_bottom = klc
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 2")
klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2)
self.check_fx_pattern(klc)
#klc.set_state('-30')
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
@@ -1354,10 +1366,11 @@ class TF_DF():
def get_klu_list(self, dataframe):
klu_list = self.get_kl_data(dataframe)
return self.cal_klu_pattern(klu_list)
#klu_list = self.cal_klu_pattern(klu_list)
return klu_list
def cal_klu_pattern(self, klu_list):
"""
计算裸K的pattern - 识别反转形态
计算裸K的pattern - 识别反转形态
"""
if not klu_list or len(klu_list) < 3:
return klu_list
@@ -1365,8 +1378,17 @@ class TF_DF():
for i, klu in enumerate(klu_list):
# 单根K线反转模式识别
self._detect_single_reversal_pattern(klu)
# 双根K线形态识别
if i >= 1:
self._detect_double_pattern(klu_list[i-1], klu)
# 三根K线形态识别
if i >= 2:
self._detect_triple_pattern(klu_list[i-2], klu_list[i-1], klu)
if klu.pattern != Chan_KLU_PATTERN.UNKNOWN:
print(klu.time, klu.pattern)
print(klu.time, klu.pattern, klu.lower_shadow_ratio, klu.upper_shadow_ratio, klu.body_ratio, klu.lower_shadow_ratio/klu.body_ratio, klu.upper_shadow_ratio/klu.body_ratio)
return klu_list
def _detect_single_reversal_pattern(self, klu):
@@ -1383,23 +1405,23 @@ class TF_DF():
body_ratio = body / total_range
upper_ratio = upper_shadow / total_range
lower_ratio = lower_shadow / total_range
#print(klu.time, upper_ratio, lower_ratio, body_ratio, upper_ratio/body_ratio, lower_ratio/body_ratio)
# 锤子线/上吊线 - 反转信号
if lower_ratio / body_ratio >= 2:
# 锤子线:底部反转,需要前面一段
if klu.close > klu.open and klu.pre and klu.pre.close < klu.pre.open:
if klu.close > klu.open and klu.pre:
klu.set_pattern(Chan_KLU_PATTERN.HAMMER) # 底部反转
# 上吊线:顶部反转,需要前一根是上涨趋势
elif klu.close < klu.open and klu.pre and klu.pre.close > klu.pre.open:
elif klu.close < klu.open and klu.pre:
klu.set_pattern(Chan_KLU_PATTERN.HANGING_MAN) # 顶部反转
# 倒锤子线/射击之星 - 反转信号
elif upper_ratio / body_ratio >= 2:
# 倒锤子线:底部反转,需要前一根是下跌趋势
if klu.close > klu.open and klu.pre and klu.pre.close < klu.pre.open:
if klu.close > klu.open and klu.pre:
klu.set_pattern(Chan_KLU_PATTERN.INVERTED_HAMMER) # 底部反转
# 射击之星:顶部反转,需要前一根是上涨趋势
elif klu.close < klu.open and klu.pre and klu.pre.close > klu.pre.open:
elif klu.close < klu.open and klu.pre:
klu.set_pattern(Chan_KLU_PATTERN.SHOOTING_STAR) # 顶部反转
# 十字星 - 反转信号
@@ -1417,5 +1439,231 @@ class TF_DF():
else:
klu.set_pattern(Chan_KLU_PATTERN.DOJI) # 一般反转信号
def _detect_double_pattern(self, prev_klu, curr_klu):
"""检测两根K线形成的形态
包括:吞没形态(看涨/看跌)、乌云盖顶、曙光初现
"""
# 如果前一根K线已经有形态,不再识别双K线形态
if prev_klu.pattern != Chan_KLU_PATTERN.UNKNOWN:
return
# 计算K线实体
prev_body = abs(prev_klu.close - prev_klu.open)
curr_body = abs(curr_klu.close - curr_klu.open)
# 判断K线颜色(阴阳)
prev_bullish = prev_klu.close > prev_klu.open
curr_bullish = curr_klu.close > curr_klu.open
# 检查是否存在长期趋势(至少需要5根K线的趋势)
def check_long_trend(klu, bullish_trend=True, min_bars=5):
"""检查是否存在长期趋势
bullish_trend=True: 检查上涨趋势
bullish_trend=False: 检查下跌趋势
min_bars: 最少需要多少根K线形成趋势
"""
if not klu or not klu.pre:
return False
return True
# 使用EMA指标判断长期趋势
if klu.ema52 > 0:
if bullish_trend and klu.close < klu.ema52:
return False
if not bullish_trend and klu.close > klu.ema52:
return False
# 检查连续的K线方向
count = 0
current = klu.pre
while current and count < min_bars:
if not current.pre:
break
if bullish_trend:
# 上涨趋势:当前收盘价高于前一根收盘价
if current.close <= current.pre.close:
break
else:
# 下跌趋势:当前收盘价低于前一根收盘价
if current.close >= current.pre.close:
break
count += 1
current = current.pre
return count >= min_bars
# 1. 看涨吞没形态:前阴后阳,后者完全吞没前者
# 要求前面有明显的下跌趋势
if not prev_bullish and curr_bullish and \
abs(curr_klu.open - prev_klu.close) < 10 and \
curr_klu.close > prev_klu.open and \
check_long_trend(prev_klu, bullish_trend=False, min_bars=5):
curr_klu.set_pattern(Chan_KLU_PATTERN.BULLISH_ENGULFING)
return
# 2. 看跌吞没形态:前阳后阴,后者完全吞没前者
# 要求前面有明显的上涨趋势
if prev_bullish and not curr_bullish and \
abs(curr_klu.open - prev_klu.close) < 10 and \
curr_klu.close < prev_klu.open and \
check_long_trend(prev_klu, bullish_trend=True, min_bars=5):
curr_klu.set_pattern(Chan_KLU_PATTERN.BEARISH_ENGULFING)
return
# 3. 乌云盖顶:前阳后阴,后者开盘价高于前者最高价,收盘价在前者实体中部以下
# 要求前面有明显的上涨趋势
if prev_bullish and not curr_bullish and \
curr_klu.open > prev_klu.high and \
curr_klu.close < (prev_klu.open + prev_klu.close) / 2 and \
curr_klu.close > prev_klu.open and \
check_long_trend(prev_klu, bullish_trend=True, min_bars=5):
curr_klu.set_pattern(Chan_KLU_PATTERN.DARK_CLOUD_COVER)
return
# 4. 曙光初现:前阴后阳,后者开盘价低于前者最低价,收盘价在前者实体中部以上
# 要求前面有明显的下跌趋势
if not prev_bullish and curr_bullish and \
curr_klu.open < prev_klu.low and \
curr_klu.close > (prev_klu.open + prev_klu.close) / 2 and \
curr_klu.close < prev_klu.open and \
check_long_trend(prev_klu, bullish_trend=False, min_bars=5):
curr_klu.set_pattern(Chan_KLU_PATTERN.PIERCING_LINE)
return
# 平顶和平底移至三根K线形态中判断
def _detect_triple_pattern(self, first_klu, second_klu, third_klu):
"""检测三根K线形成的形态
包括:早晨之星、黄昏之星、平顶、平底
"""
# 如果前两根K线已经有形态,不再识别三K线形态
if first_klu.pattern != Chan_KLU_PATTERN.UNKNOWN or \
second_klu.pattern != Chan_KLU_PATTERN.UNKNOWN:
return
# 判断K线颜色(阴阳)
first_bullish = first_klu.close > first_klu.open
second_bullish = second_klu.close > second_klu.open
third_bullish = third_klu.close > third_klu.open
# 计算实体大小
first_body = abs(first_klu.close - first_klu.open)
second_body = abs(second_klu.close - second_klu.open)
third_body = abs(third_klu.close - third_klu.open)
# 检查是否存在长期趋势(至少需要5根K线的趋势)
def check_long_trend(klu, bullish_trend=True, min_bars=5):
"""检查是否存在长期趋势
bullish_trend=True: 检查上涨趋势
bullish_trend=False: 检查下跌趋势
min_bars: 最少需要多少根K线形成趋势
"""
if not klu or not klu.pre:
return False
# 使用EMA指标判断长期趋势
if klu.ema52 > 0:
if bullish_trend and klu.close < klu.ema52:
return False
if not bullish_trend and klu.close > klu.ema52:
return False
# 检查连续的K线方向
count = 0
current = klu.pre
while current and count < min_bars:
if not current.pre:
break
if bullish_trend:
# 上涨趋势:当前收盘价高于前一根收盘价
if current.close <= current.pre.close:
break
else:
# 下跌趋势:当前收盘价低于前一根收盘价
if current.close >= current.pre.close:
break
count += 1
current = current.pre
return count >= min_bars
# 1. 早晨之星:第一根阴线,第二根十字星或小实体,第三根阳线
# 要求前面有明显的下跌趋势
if not first_bullish and third_bullish and \
second_body < first_body * 0.3 and \
third_body > first_body * 0.5 and \
max(second_klu.open, second_klu.close) < first_klu.close and \
min(second_klu.open, second_klu.close) < third_klu.open and \
third_klu.close > (first_klu.open + first_klu.close) / 2 and \
check_long_trend(first_klu, bullish_trend=False, min_bars=7):
third_klu.set_pattern(Chan_KLU_PATTERN.MORNING_STAR)
return
# 2. 黄昏之星:第一根阳线,第二根十字星或小实体,第三根阴线
# 要求前面有明显的上涨趋势
if first_bullish and not third_bullish and \
second_body < first_body * 0.3 and \
third_body > first_body * 0.5 and \
min(second_klu.open, second_klu.close) > first_klu.close and \
max(second_klu.open, second_klu.close) > third_klu.open and \
third_klu.close < (first_klu.open + first_klu.close) / 2 and \
check_long_trend(first_klu, bullish_trend=True, min_bars=7):
third_klu.set_pattern(Chan_KLU_PATTERN.EVENING_STAR)
return
# 3. 平顶:三根K线的最高点几乎相同(上升趋势中更有意义)
# 要求前面有明显的上涨趋势
if (abs(first_klu.high - second_klu.high) / first_klu.high < 0.0002 and
abs(second_klu.high - third_klu.high) / second_klu.high < 0.0002 and
check_long_trend(first_klu, bullish_trend=True, min_bars=7)):
# 额外确认:价格接近阻力位或关键技术指标
is_near_resistance = False
# 检查是否接近EMA52阻力位
if first_klu.ema52 > 0:
resistance_level = first_klu.ema52
if abs(first_klu.high - resistance_level) / resistance_level < 0.01:
is_near_resistance = True
# 检查是否有成交量确认(成交量减少表示上涨动能减弱)
volume_confirmation = False
if (first_klu.volume > 0 and second_klu.volume > 0 and third_klu.volume > 0 and
third_klu.volume < second_klu.volume and second_klu.volume < first_klu.volume):
volume_confirmation = True
if is_near_resistance or volume_confirmation:
third_klu.set_pattern(Chan_KLU_PATTERN.TWEEZER_TOP)
return
# 4. 平底:三根K线的最低点几乎相同(下降趋势中更有意义)
# 要求前面有明显的下跌趋势
if (abs(first_klu.low - second_klu.low) / first_klu.low < 0.0002 and
abs(second_klu.low - third_klu.low) / second_klu.low < 0.0002 and
check_long_trend(first_klu, bullish_trend=False, min_bars=7)):
# 额外确认:价格接近支撑位或关键技术指标
is_near_support = False
# 检查是否接近EMA52支撑位
if first_klu.ema52 > 0:
support_level = first_klu.ema52
if abs(first_klu.low - support_level) / support_level < 0.01:
is_near_support = True
# 检查是否有成交量确认(成交量减少表示下跌动能减弱)
volume_confirmation = False
if (first_klu.volume > 0 and second_klu.volume > 0 and third_klu.volume > 0 and
third_klu.volume < second_klu.volume and second_klu.volume < first_klu.volume):
volume_confirmation = True
if is_near_support or volume_confirmation:
third_klu.set_pattern(Chan_KLU_PATTERN.TWEEZER_BOTTOM)
return
def get_decimal(self, value):
return Decimal("{:.2f}".format(value))