新的策略,先开单,明天继续添加条件

This commit is contained in:
jackyu66git
2025-10-16 02:44:21 +08:00
parent eb3f394386
commit a1f8c6c605
6 changed files with 579 additions and 55 deletions
+204 -5
View File
@@ -75,6 +75,26 @@ class ChanLun():
if len(self.tf_df_dict) > 0:
return {key: self.tf_df_dict[key].get_ema24() for key in self.ema_symbols}
return None
def get_klu_state(self, dataframe):
klc_list = self.get_klc_list(dataframe)
bi_list = self.cal_bi_list(klc_list)
klu_state_list = []
klc_index = 0
for index in range(0, len(dataframe)):
if klc_index == len(klc_list):
klc_index = len(klc_list) - 1
klc = klc_list[klc_index]
if klc.end_klu and klc.end_klu.idx == index:
if klc.klc_fx_type == Chan_KLC_FX.TOP4:
klu_state_list.append("10")
elif klc.klc_fx_type == Chan_KLC_FX.BOTTOM4:
klu_state_list.append("-10")
else:
klu_state_list.append("00")
klc_index += 1
else:
klu_state_list.append("00")
return klu_state_list
def get_current_klc_dict(self):
if len(self.tf_df_dict) > 0:
return {key: self.tf_df_dict[key].get_current_klc() for key in self.ema_symbols}
@@ -94,7 +114,7 @@ class ChanLun():
#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 add_indicators(self, df):
def add_indicators1(self, df):
fast = 12
slow = 26
period = 9
@@ -474,6 +494,9 @@ class ChanLun():
if not klc_list:
return klc_list
last_trend = Chan_PRICE_TREND.UNKNOWN
# 趋势延续性:参考近 N 根已完成的KLC
lookback_n = 5
prev_klcs = []
for klc in klc_list:
price = getattr(klc, 'close', None)
ema24 = getattr(klc, 'ema24', None)
@@ -514,6 +537,76 @@ class ChanLun():
spread_now = ema24 - ema52
spread_pre = pre_ema24 - pre_ema52
score += 1 if spread_now >= spread_pre else -1
# 3.1) MACD柱体动量趋势:考虑 macdhist 的斜率与过零
pre_hist = getattr(pre, 'macdhist', None)
if pre_hist is not None and hist is not None:
# 柱体斜率:上升加分,下降减分
if hist > pre_hist:
score += 1
elif hist < pre_hist:
score -= 1
# 过零加权:负转正更偏多,正转负更偏空
if pre_hist < 0 and hist > 0:
score += 1
elif pre_hist > 0 and hist < 0:
score -= 1
# 3.2) EMA52 突破/跌破加权
if ema52_valid and price_valid and pre_close is not None and pre_ema52 not in (None, 0):
# 看多突破:从均线下方上破且动量配合
if pre_close <= pre_ema52 and price > ema52 and (hist is None or pre_hist is None or hist >= pre_hist):
score += 1
# 看空跌破:从均线上方下破且动量配合
if pre_close >= pre_ema52 and price < ema52 and (hist is None or pre_hist is None or hist <= pre_hist):
score -= 1
# 3.3) EMA52 支撑/阻力触碰(非强穿越)
if ema52_valid and price_valid:
low_v = getattr(klc, 'low', None)
high_v = getattr(klc, 'high', None)
if low_v is not None and high_v is not None and ema52 not in (None, 0):
# 触碰容差(相对EMA52的0.15%
touch_tol = 0.0015
# 作为支撑:收盘在上,最低靠近EMA52
near_support_touch = (price > ema52) and (abs(low_v - ema52) / abs(ema52) <= touch_tol)
# 作为阻力:收盘在下,最高靠近EMA52
near_resistance_touch = (price < ema52) and (abs(high_v - ema52) / abs(ema52) <= touch_tol)
if near_support_touch:
# 若动量不弱,则更偏多
score += 1 if (hist is None or pre_hist is None or hist >= pre_hist) else 0
if near_resistance_touch:
# 若动量不强,则更偏空
score -= 1 if (hist is None or pre_hist is None or hist <= pre_hist) else 0
# 3.4) 多次对 EMA52 的“拒绝”配合 MACD 逆向:易形成压/支并反向
# 统计近窗口内的上/下拒绝次数:
# - 上拒绝:价格位于 EMA52 下方,最高触及/越过 EMA52 但收盘仍在下方
# - 下拒绝:价格位于 EMA52 上方,最低触及/跌破 EMA52 但收盘仍在上方
recent_up_rejects = 0
recent_down_rejects = 0
if ema52_valid:
window_rej = prev_klcs[-lookback_n:] if len(prev_klcs) > 0 else []
rej_tol = 0.0015
for wk in window_rej:
wk_close = getattr(wk, 'close', None)
wk_ema52 = getattr(wk, 'ema52', None)
wk_high = getattr(wk, 'high', None)
wk_low = getattr(wk, 'low', None)
if wk_close is None or wk_ema52 in (None, 0):
continue
# 上拒绝(阻力):下方多次试图上破但未站上
if wk_close < wk_ema52 and wk_high is not None:
if wk_high >= wk_ema52 or abs(wk_high - wk_ema52) / abs(wk_ema52) <= rej_tol:
recent_up_rejects += 1
# 下拒绝(支撑):上方多次试图下破但未跌破
if wk_close > wk_ema52 and wk_low is not None:
if wk_low <= wk_ema52 or abs(wk_low - wk_ema52) / abs(wk_ema52) <= rej_tol:
recent_down_rejects += 1
# 定义 MACD 的方向偏好
macd_bias_up = (macd >= signal) and (hist is None or pre_hist is None or hist >= pre_hist)
macd_bias_down = (macd <= signal) and (hist is None or pre_hist is None or hist <= pre_hist)
# 若多次上拒绝且 MACD 偏空,则更偏向下行;若多次下拒绝且 MACD 偏多,则更偏向上行
if recent_up_rejects >= 2 and macd_bias_down:
score -= 2
if recent_down_rejects >= 2 and macd_bias_up:
score += 2
# 4) RSI 辅助
if rsi is not None:
if rsi >= 55:
@@ -551,17 +644,121 @@ class ChanLun():
near_macd = abs(macd - signal) <= (abs(price) * 0.00005 if price_valid else 0)
near_flat = near_ema52 and near_macd
# 7) 动态阈值 + 趋势记忆(更强粘滞:趋势中容忍小幅反分)
# 引入过去 N 根KLC 的趋势延续性来动态调整翻转阈值,并结合 EMA52 支撑/阻力触碰强化门槛
force_flip_down = False
force_flip_up = False
if near_flat:
trend = Chan_PRICE_TREND.FLAT
else:
if last_trend == Chan_PRICE_TREND.UP:
# 仅当出现明显反向才翻转,否则维持UP
if score <= -2:
# 计算过去窗口的趋势一致性
window = prev_klcs[-lookback_n:] if len(prev_klcs) > 0 else []
persist_up = 0
persist_down = 0
for wk in window:
if getattr(wk, 'trend', None) == Chan_PRICE_TREND.UP:
persist_up += 1
elif getattr(wk, 'trend', None) == Chan_PRICE_TREND.DOWN:
persist_down += 1
persist_ratio_up = (persist_up / len(window)) if len(window) > 0 else 0
persist_ratio_down = (persist_down / len(window)) if len(window) > 0 else 0
# 基准阈值
down_flip_threshold = -2
up_flip_threshold = 2
# 若最近多为UP,则从UP翻转需更强反向信号;同理对DOWN
if last_trend == Chan_PRICE_TREND.UP and persist_ratio_up >= 0.6:
down_flip_threshold = -3
elif last_trend == Chan_PRICE_TREND.DOWN and persist_ratio_down >= 0.6:
up_flip_threshold = 3
# EMA52 触碰强化门槛:UP时若出现支撑触碰,下翻更难;DOWN时若出现阻力触碰,上翻更难
if ema52_valid and price_valid:
low_v = getattr(klc, 'low', None)
high_v = getattr(klc, 'high', None)
if low_v is not None and high_v is not None and ema52 not in (None, 0):
touch_tol = 0.0015
near_support_touch = (price > ema52) and (abs(low_v - ema52) / abs(ema52) <= touch_tol)
near_resistance_touch = (price < ema52) and (abs(high_v - ema52) / abs(ema52) <= touch_tol)
if last_trend == Chan_PRICE_TREND.UP and near_support_touch:
# 强化维持UP:进一步降低向下翻转阈值
down_flip_threshold = min(down_flip_threshold - 1, -3)
if last_trend == Chan_PRICE_TREND.DOWN and near_resistance_touch:
# 强化维持DOWN:进一步提高向上翻转阈值
up_flip_threshold = max(up_flip_threshold + 1, 3)
# 7.1) 复合拐头信号:MACD/Signal 同向拐头 + hist 连续减弱 + 多次未能越过 EMA52
pre_macd = getattr(pre, 'macd', None) if pre else None
pre_signal = getattr(pre, 'signal', None) if pre else None
macd_slope = (macd - pre_macd) if (pre_macd is not None and macd is not None) else 0
signal_slope = (signal - pre_signal) if (pre_signal is not None and signal is not None) else 0
# hist 连续减弱(绝对值缩小)
hist_seq = []
for wk in prev_klcs[-2:]:
val = getattr(wk, 'macdhist', None)
if val is not None:
hist_seq.append(val)
if hist is not None:
hist_seq.append(hist)
weaken_steps = 0
for i in range(1, len(hist_seq)):
if abs(hist_seq[i]) < abs(hist_seq[i-1]):
weaken_steps += 1
# 近窗口对 EMA52 的“未能站上/跌破”统计(放宽窗口与条件)
window_ema = prev_klcs[-4:] if len(prev_klcs) > 0 else []
no_up_break = False
no_down_break = False
if ema52_valid:
# 未能有效上破:最近若干根收盘大多数不在 EMA52 上方,且高点多次触及/接近
cnt_touch_up = 0
cnt_close_above = 0
for wk in window_ema:
wk_close = getattr(wk, 'close', None)
wk_high = getattr(wk, 'high', None)
wk_ema = getattr(wk, 'ema52', None)
if wk_close is not None and wk_ema not in (None, 0):
if wk_close > wk_ema:
cnt_close_above += 1
if wk_high is not None and (wk_high >= wk_ema or abs(wk_high - wk_ema) / abs(wk_ema) <= 0.0015):
cnt_touch_up += 1
no_up_break = (cnt_close_above <= 1 and cnt_touch_up >= 1 and price <= ema52)
# 未能有效下破:最近若干根收盘大多数不在 EMA52 下方,且低点多次触及/接近
cnt_touch_down = 0
cnt_close_below = 0
for wk in window_ema:
wk_close = getattr(wk, 'close', None)
wk_low = getattr(wk, 'low', None)
wk_ema = getattr(wk, 'ema52', None)
if wk_close is not None and wk_ema not in (None, 0):
if wk_close < wk_ema:
cnt_close_below += 1
if wk_low is not None and (wk_low <= wk_ema or abs(wk_low - wk_ema) / abs(wk_ema) <= 0.0015):
cnt_touch_down += 1
no_down_break = (cnt_close_below <= 1 and cnt_touch_down >= 1 and price >= ema52)
# 若当前为UP趋势,出现明显拐头+hist减弱+未能上破EMA52,则加速看空
if last_trend == Chan_PRICE_TREND.UP and macd_slope < 0 and signal_slope < 0 and weaken_steps >= 1 and no_up_break and macd_bias_down:
score -= 3
down_flip_threshold = max(down_flip_threshold, 0)
force_flip_down = True
# 若当前为DOWN趋势,出现明显拐头+hist减弱+未能下破EMA52,则加速看多
if last_trend == Chan_PRICE_TREND.DOWN and macd_slope > 0 and signal_slope > 0 and weaken_steps >= 1 and no_down_break and macd_bias_up:
score += 3
up_flip_threshold = min(up_flip_threshold, 0)
force_flip_up = True
# 多次对 EMA52 的拒绝配合 MACD 逆向:加速反向翻转(降低相反方向阈值)
if recent_up_rejects >= 2 and macd_bias_down:
# 从 UP 向 DOWN 的翻转更容易
down_flip_threshold = max(down_flip_threshold, -1)
if recent_down_rejects >= 2 and macd_bias_up:
# 从 DOWN 向 UP 的翻转更容易
up_flip_threshold = min(up_flip_threshold, 1)
if force_flip_down:
trend = Chan_PRICE_TREND.DOWN
elif force_flip_up:
trend = Chan_PRICE_TREND.UP
elif last_trend == Chan_PRICE_TREND.UP:
if score <= down_flip_threshold:
trend = Chan_PRICE_TREND.DOWN
else:
trend = Chan_PRICE_TREND.UP
elif last_trend == Chan_PRICE_TREND.DOWN:
if score >= 2:
if score >= up_flip_threshold:
trend = Chan_PRICE_TREND.UP
else:
trend = Chan_PRICE_TREND.DOWN
@@ -583,6 +780,8 @@ class ChanLun():
else:
setattr(klc, 'trend', trend)
last_trend = trend
# 更新滑窗:仅向后看
prev_klcs.append(klc)
price_diff = klc.close - klc.pre.close if klc.pre else 0
#if klc.index > len(klc_list) - 10:
#print(klc.start_time, klc.end_time, klc.close, klc.ema24, klc.ema52, klc.macd, klc.signal, klc.macdhist, klc.trend, price_diff, score)