加入一个回测,
This commit is contained in:
151
job_bitmart.py
151
job_bitmart.py
@@ -106,6 +106,11 @@ class BBDelayReversalTrader:
|
||||
self.highest_since_open = None # 持有多仓以来的最高价
|
||||
self.lowest_since_open = None # 持有空仓以来的最低价
|
||||
|
||||
# 延迟平仓(碰轨不平,回落/反弹再平)状态
|
||||
self.touched_band_price = None # 最近一次触碰轨道的触发价格
|
||||
self.touched_prev_open = None # 发生触碰时的前一根K线开盘价
|
||||
self.current_kline_id = None # 记录当前在处理的K线
|
||||
|
||||
# 加仓状态
|
||||
self.pyramid_count = 0 # 当前已加仓次数 (0=仅首次开仓)
|
||||
|
||||
@@ -206,6 +211,8 @@ class BBDelayReversalTrader:
|
||||
self.has_half_closed = False
|
||||
self.highest_since_open = None
|
||||
self.lowest_since_open = None
|
||||
self.touched_band_price = None
|
||||
self.touched_prev_open = None
|
||||
return True
|
||||
pos = positions[0]
|
||||
self.position = 1 if pos["position_type"] == 1 else -1
|
||||
@@ -299,6 +306,8 @@ class BBDelayReversalTrader:
|
||||
self.has_half_closed = False
|
||||
self.highest_since_open = None
|
||||
self.lowest_since_open = None
|
||||
self.touched_band_price = None
|
||||
self.touched_prev_open = None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 仓位操作
|
||||
@@ -539,11 +548,42 @@ class BBDelayReversalTrader:
|
||||
else:
|
||||
logger.error(f"止损平仓失败,当前仍有持仓({self.position})")
|
||||
|
||||
# 5. 极值更新与半仓/全平反手逻辑 (需求: 如果当前做多,涨破中轨后回落碰中轨平一半;再跌到开仓价平全仓反手)
|
||||
# 5. 极值更新与半仓/延迟全平反手逻辑
|
||||
if self.position == 1 and self.open_avg_price:
|
||||
if self.highest_since_open is None or current_price > self.highest_since_open:
|
||||
self.highest_since_open = current_price
|
||||
|
||||
|
||||
# 延迟平仓逻辑: 之前触碰过上轨
|
||||
if self.touched_band_price is not None:
|
||||
# 检查是否回落到 触发的上轨价格 或者 上一根K线的开盘价
|
||||
trigger_target = max(self.touched_band_price, self.touched_prev_open) if self.touched_prev_open else self.touched_band_price
|
||||
if current_price <= trigger_target or cur_low <= trigger_target:
|
||||
if self.can_trade():
|
||||
logger.info(f"多单延迟回落平仓: 当前价跌破触发点 {trigger_target:.2f} (上轨价: {self.touched_band_price}, 上根开: {self.touched_prev_open})")
|
||||
self.browser_close_position()
|
||||
time.sleep(1)
|
||||
for _ in range(10):
|
||||
if self.get_position_status() and self.position == 0: break
|
||||
time.sleep(1)
|
||||
self.reset_position_state()
|
||||
self.click_safe('x://button[normalize-space(text()) ="开仓"]')
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
order_usdt = self.calc_order_usdt()
|
||||
if order_usdt > 0:
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=order_usdt, clear=True)
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://span[normalize-space(text()) ="卖出/做空"]')
|
||||
time.sleep(3)
|
||||
self.get_position_status()
|
||||
self.write_trade_log("延迟全平反手(多转空)", current_price, bb_upper, bb_mid, bb_lower, f"多单碰上轨后回落至 {trigger_target:.2f}")
|
||||
page_start = True
|
||||
try: self.page.close()
|
||||
except: pass
|
||||
self.page = None
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# 规则 A1: 涨过中轨
|
||||
if self.highest_since_open >= bb_mid:
|
||||
# 从最高点回落触碰中轨,且未平过一半
|
||||
@@ -594,7 +634,38 @@ class BBDelayReversalTrader:
|
||||
elif self.position == -1 and self.open_avg_price:
|
||||
if self.lowest_since_open is None or current_price < self.lowest_since_open:
|
||||
self.lowest_since_open = current_price
|
||||
|
||||
|
||||
# 延迟平仓逻辑: 之前触碰过下轨
|
||||
if self.touched_band_price is not None:
|
||||
# 检查是否反弹到 触发的下轨价格 或者 上一根K线的开盘价
|
||||
trigger_target = min(self.touched_band_price, self.touched_prev_open) if self.touched_prev_open else self.touched_band_price
|
||||
if current_price >= trigger_target or cur_high >= trigger_target:
|
||||
if self.can_trade():
|
||||
logger.info(f"空单延迟反弹平仓: 当前价突破触发点 {trigger_target:.2f} (下轨价: {self.touched_band_price}, 上根开: {self.touched_prev_open})")
|
||||
self.browser_close_position()
|
||||
time.sleep(1)
|
||||
for _ in range(10):
|
||||
if self.get_position_status() and self.position == 0: break
|
||||
time.sleep(1)
|
||||
self.reset_position_state()
|
||||
self.click_safe('x://button[normalize-space(text()) ="开仓"]')
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
order_usdt = self.calc_order_usdt()
|
||||
if order_usdt > 0:
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=order_usdt, clear=True)
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://span[normalize-space(text()) ="买入/做多"]')
|
||||
time.sleep(3)
|
||||
self.get_position_status()
|
||||
self.write_trade_log("延迟全平反手(空转多)", current_price, bb_upper, bb_mid, bb_lower, f"空单碰下轨后反弹至 {trigger_target:.2f}")
|
||||
page_start = True
|
||||
try: self.page.close()
|
||||
except: pass
|
||||
self.page = None
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# 规则 B1: 跌破过中轨
|
||||
if self.lowest_since_open <= bb_mid:
|
||||
# 从最低点回升触碰中轨,且未平过一半
|
||||
@@ -656,7 +727,7 @@ class BBDelayReversalTrader:
|
||||
reason = ""
|
||||
success = False
|
||||
|
||||
# ===== 触及上轨 → 开空 / 翻转为空 / 加仓空 =====
|
||||
# ===== 触及上轨 → 等待延迟平/开空/加仓空 =====
|
||||
if touched_upper:
|
||||
if not self.can_trade():
|
||||
time.sleep(self.cfg.POLL_INTERVAL)
|
||||
@@ -666,33 +737,16 @@ class BBDelayReversalTrader:
|
||||
f"BB({self.cfg.BB_PERIOD},{self.cfg.BB_STD})")
|
||||
|
||||
if self.position == 1:
|
||||
action = "翻转: 平多→开空"
|
||||
# 在当前页面点市价平仓
|
||||
self.browser_close_position()
|
||||
time.sleep(1)
|
||||
# 等待确认平仓
|
||||
for _ in range(10):
|
||||
if self.get_position_status() and self.position == 0:
|
||||
break
|
||||
time.sleep(1)
|
||||
if self.position != 0:
|
||||
logger.warning(f"平仓后仍有持仓({self.position}),放弃开空")
|
||||
time.sleep(self.cfg.POLL_INTERVAL)
|
||||
continue
|
||||
self.reset_position_state()
|
||||
# 平仓后在同一页面直接点卖出/做空
|
||||
logger.info("平仓完成,直接开空")
|
||||
self.click_safe('x://button[normalize-space(text()) ="开仓"]')
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
order_usdt = self.calc_order_usdt()
|
||||
if order_usdt > 0:
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=order_usdt, clear=True)
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://span[normalize-space(text()) ="卖出/做空"]')
|
||||
time.sleep(3)
|
||||
if self.verify_position(-1):
|
||||
success = True
|
||||
# 延迟平仓逻辑: 记录触碰上轨的信息,等待回落后再平仓,不断创新高则更新上轨目标价
|
||||
prev_open = closed_klines[-1]["open"] if len(closed_klines) > 0 else cur_high
|
||||
if self.touched_band_price is None or bb_upper > self.touched_band_price:
|
||||
self.touched_band_price = bb_upper
|
||||
self.touched_prev_open = prev_open
|
||||
logger.info(f"多单已触碰上轨,记录延迟目标价: 轨={bb_upper:.2f}, 上根开={prev_open:.2f}。等待回落再平仓...")
|
||||
|
||||
# 特殊保护: 当前一瞬间即使碰到立刻跌下来,也要依靠下一轮的主循环去判断,防止剧烈波动同K线反复触发
|
||||
self.current_kline_id = current_kline["id"]
|
||||
|
||||
elif self.position == 0:
|
||||
action = "开空"
|
||||
self.reset_position_state()
|
||||
@@ -727,7 +781,7 @@ class BBDelayReversalTrader:
|
||||
else:
|
||||
logger.info(f"已持空仓,加仓已达上限({self.pyramid_count}/{self.cfg.PYRAMID_MAX})")
|
||||
|
||||
# ===== 触及下轨 → 开多 / 翻转为多 / 加仓多 =====
|
||||
# ===== 触及下轨 → 等待延迟平/开多/加仓多 =====
|
||||
elif touched_lower:
|
||||
if not self.can_trade():
|
||||
time.sleep(self.cfg.POLL_INTERVAL)
|
||||
@@ -737,30 +791,15 @@ class BBDelayReversalTrader:
|
||||
f"BB({self.cfg.BB_PERIOD},{self.cfg.BB_STD})")
|
||||
|
||||
if self.position == -1:
|
||||
action = "翻转: 平空→开多"
|
||||
self.browser_close_position()
|
||||
time.sleep(1)
|
||||
for _ in range(10):
|
||||
if self.get_position_status() and self.position == 0:
|
||||
break
|
||||
time.sleep(1)
|
||||
if self.position != 0:
|
||||
logger.warning(f"平仓后仍有持仓({self.position}),放弃开多")
|
||||
time.sleep(self.cfg.POLL_INTERVAL)
|
||||
continue
|
||||
self.reset_position_state()
|
||||
logger.info("平仓完成,直接开多")
|
||||
self.click_safe('x://button[normalize-space(text()) ="开仓"]')
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
order_usdt = self.calc_order_usdt()
|
||||
if order_usdt > 0:
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=order_usdt, clear=True)
|
||||
time.sleep(0.5)
|
||||
self.click_safe('x://span[normalize-space(text()) ="买入/做多"]')
|
||||
time.sleep(3)
|
||||
if self.verify_position(1):
|
||||
success = True
|
||||
# 延迟平仓逻辑: 记录触碰下轨的信息,等待反弹后再平仓,不断创新低则更新下轨目标价
|
||||
prev_open = closed_klines[-1]["open"] if len(closed_klines) > 0 else cur_low
|
||||
if self.touched_band_price is None or bb_lower < self.touched_band_price:
|
||||
self.touched_band_price = bb_lower
|
||||
self.touched_prev_open = prev_open
|
||||
logger.info(f"空单已触碰下轨,记录延迟目标价: 轨={bb_lower:.2f}, 上根开={prev_open:.2f}。等待反弹再平仓...")
|
||||
|
||||
self.current_kline_id = current_kline["id"]
|
||||
|
||||
elif self.position == 0:
|
||||
action = "开多"
|
||||
self.reset_position_state()
|
||||
|
||||
Reference in New Issue
Block a user