加入一个回测,
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user