加入一个回测,

This commit is contained in:
ddrwode
2026-03-09 14:44:21 +08:00
parent 34f123bcf0
commit fc06a241b6

View File

@@ -98,6 +98,7 @@ class BBDelayReversalTrader:
# 持仓状态: -1=空, 0=无, 1=多
self.position = 0
self.open_avg_price = None
self.initial_open_price = None # 固定记录首次开仓的价格,不受平半仓等影响
self.current_amount = None
self.unrealized_value = 0.0
@@ -206,6 +207,7 @@ class BBDelayReversalTrader:
if not positions:
self.position = 0
self.open_avg_price = None
self.initial_open_price = None
self.current_amount = None
self.unrealized_value = 0.0
self.has_half_closed = False
@@ -217,9 +219,14 @@ class BBDelayReversalTrader:
pos = positions[0]
self.position = 1 if pos["position_type"] == 1 else -1
self.open_avg_price = float(pos["open_avg_price"])
# 只在第一次有了仓位(或未被记录时)保存初始开仓价
if self.initial_open_price is None or self.pyramid_count == 0:
self.initial_open_price = self.open_avg_price
self.current_amount = float(pos["current_amount"])
self.unrealized_value = float(pos.get("unrealized_value", 0))
logger.debug(f"持仓: dir={self.position} price={self.open_avg_price} "
logger.debug(f"持仓: dir={self.position} price={self.open_avg_price} (初始:{self.initial_open_price}) "
f"amt={self.current_amount} upnl={self.unrealized_value:.2f}")
return True
except Exception as e:
@@ -303,6 +310,7 @@ class BBDelayReversalTrader:
def reset_position_state(self):
"""重置所有关于持仓的变量"""
self.pyramid_count = 0
self.initial_open_price = None
self.has_half_closed = False
self.highest_since_open = None
self.lowest_since_open = None
@@ -603,9 +611,9 @@ class BBDelayReversalTrader:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
# 规则 A2: 平过一半后,跌回开仓价 -> 全平反手开空
if self.has_half_closed and (cur_low <= self.open_avg_price or current_price <= self.open_avg_price):
if self.has_half_closed and self.initial_open_price and (cur_low <= self.initial_open_price or current_price <= self.initial_open_price):
if self.can_trade():
logger.info("平半仓后跌回多单开仓价,全平反手开空")
logger.info(f"平半仓后跌回多单初始开仓价({self.initial_open_price}),全平反手开空")
self.browser_close_position()
time.sleep(1)
for _ in range(10):
@@ -633,6 +641,36 @@ class BBDelayReversalTrader:
time.sleep(5)
continue
# 规则 A3: 跌到中轨且处于亏损状态 -> 全平反手开空
if self.initial_open_price and current_price < self.initial_open_price and (cur_low <= bb_mid or current_price <= bb_mid):
if self.can_trade():
logger.info(f"多单跌回中轨且处于亏损(成本:{self.initial_open_price}),全平反手开空")
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, "多单亏损时跌触中轨")
page_start = True
try: self.page.close()
except: pass
self.page = None
time.sleep(5)
continue
elif self.position == -1 and self.open_avg_price:
# 记录持有期内的最低价 (包含当前实时价和当前K线最低价)
current_min = min(current_price, cur_low)
@@ -686,9 +724,9 @@ class BBDelayReversalTrader:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
# 规则 B2: 平过一半后,涨回开仓价 -> 全平反手开多
if self.has_half_closed and (cur_high >= self.open_avg_price or current_price >= self.open_avg_price):
if self.has_half_closed and self.initial_open_price and (cur_high >= self.initial_open_price or current_price >= self.initial_open_price):
if self.can_trade():
logger.info("平半仓后涨回空单开仓价,全平反手开多")
logger.info(f"平半仓后涨回空单初始开仓价({self.initial_open_price}),全平反手开多")
self.browser_close_position()
time.sleep(1)
for _ in range(10):
@@ -716,6 +754,36 @@ class BBDelayReversalTrader:
time.sleep(5)
continue
# 规则 B3: 涨到中轨且处于亏损状态 -> 全平反手开多
if self.initial_open_price and current_price > self.initial_open_price and (cur_high >= bb_mid or current_price >= bb_mid):
if self.can_trade():
logger.info(f"空单涨回中轨且处于亏损(成本:{self.initial_open_price}),全平反手开多")
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, "空单亏损时涨触中轨")
page_start = True
try: self.page.close()
except: pass
self.page = None
time.sleep(5)
continue
# 6. 基本信号判断 (上轨空/下轨多)
kline_id = current_kline["id"]
if kline_id == last_kline_id: