fix: a lot of things

This commit is contained in:
2025-07-20 06:52:30 +08:00
parent cef8945fe8
commit 9eaab25451

125
main.py
View File

@@ -110,9 +110,9 @@ class GridTradingBot:
side = order_response["side"] side = order_response["side"]
trade_type = "买入" if side == "BUY" else "卖出" trade_type = "买入" if side == "BUY" else "卖出"
timestamp = datetime.fromtimestamp(order_response["updateTime"] / 1000).strftime( timestamp = datetime.fromtimestamp(
"%Y-%m-%dT%H:%M" order_response["updateTime"] / 1000
) ).strftime("%Y-%m-%dT%H:%M")
row = [ row = [
timestamp, timestamp,
@@ -182,7 +182,7 @@ class GridTradingBot:
self.symbol, self.symbol,
str(e), str(e),
) )
raise return self.api_get_price()
def api_get_balances(self) -> Tuple[float, float]: def api_get_balances(self) -> Tuple[float, float]:
"""获取基础货币和报价货币的可用余额(不包括冻结金额)""" """获取基础货币和报价货币的可用余额(不包括冻结金额)"""
@@ -224,7 +224,7 @@ class GridTradingBot:
logger.error( logger.error(
"[GridTradingBot.api_get_balances] Failed to get balances: %s", str(e) "[GridTradingBot.api_get_balances] Failed to get balances: %s", str(e)
) )
raise return self.api_get_balances()
def calculate_order_value(self, price: float) -> float: def calculate_order_value(self, price: float) -> float:
"""计算订单价值 (价格 * 数量)""" """计算订单价值 (价格 * 数量)"""
@@ -360,7 +360,7 @@ class GridTradingBot:
price, price,
str(e), str(e),
) )
return None return self.api_place_order(price, side)
def api_cancel_order(self, order_id: str): def api_cancel_order(self, order_id: str):
"""取消订单""" """取消订单"""
@@ -379,6 +379,7 @@ class GridTradingBot:
order_id, order_id,
str(e), str(e),
) )
self.api_cancel_order(order_id)
def api_cancel_all_orders(self): def api_cancel_all_orders(self):
"""取消所有活跃订单""" """取消所有活跃订单"""
@@ -388,15 +389,19 @@ class GridTradingBot:
) )
try: try:
self.api_trade.delete_openorders({"symbol": self.symbol}) self.api_trade.delete_openorders({"symbol": self.symbol})
self.active_orders.clear()
logger.info( logger.info(
"[GridTradingBot.api_cancel_all_orders] Successfully canceled all open orders for %s", "[GridTradingBot.api_cancel_all_orders] Successfully canceled all open orders for %s",
self.symbol, self.symbol,
) )
self.current_buy_levels = 0
self.current_sell_levels = 0
except Exception as e: except Exception as e:
logger.error( logger.error(
"[GridTradingBot.api_cancel_all_orders] Failed to cancel all open orders: %s", "[GridTradingBot.api_cancel_all_orders] Failed to cancel all open orders: %s",
str(e), str(e),
) )
self.api_cancel_all_orders()
def api_update_order_statuses(self): def api_update_order_statuses(self):
"""更新所有活跃订单的状态""" """更新所有活跃订单的状态"""
@@ -453,6 +458,7 @@ class GridTradingBot:
order_id, order_id,
str(e), str(e),
) )
self.api_update_order_statuses()
def get_active_orders_by_side(self, side: str) -> List[Order]: def get_active_orders_by_side(self, side: str) -> List[Order]:
"""获取指定方向的所有活跃订单""" """获取指定方向的所有活跃订单"""
@@ -500,7 +506,7 @@ class GridTradingBot:
market_price, market_price,
) )
# 初始下单买1和卖1 # 初始下单: 买1和卖1
buy_price = self.calculate_grid_price(market_price, 1, "BUY") buy_price = self.calculate_grid_price(market_price, 1, "BUY")
sell_price = self.calculate_grid_price(market_price, 1, "SELL") sell_price = self.calculate_grid_price(market_price, 1, "SELL")
logger.custom_debug( logger.custom_debug(
@@ -593,14 +599,13 @@ class GridTradingBot:
self.reserve_base, self.reserve_base,
) )
for _ in range(1, self.grid_count):
self.extend_grid() self.extend_grid()
except Exception as e: except Exception as e:
logger.error( logger.error(
"[GridTradingBot.initialize_grid] Failed to initialize grid: %s", str(e) "[GridTradingBot.initialize_grid] Failed to initialize grid: %s", str(e)
) )
raise self.initialize_grid()
def extend_grid(self): def extend_grid(self):
"""扩展网格,保证两侧都有指定个数的挂单""" """扩展网格,保证两侧都有指定个数的挂单"""
@@ -613,11 +618,23 @@ class GridTradingBot:
) )
try: try:
# 如果两侧都没有挂单 (如: 插针) 则重启机器人
lowest_buy, highest_sell = self.get_extreme_prices() lowest_buy, highest_sell = self.get_extreme_prices()
base_balance, quote_balance = self.api_get_balances() if lowest_buy is None and highest_sell is None:
self.stop()
self.run()
# 扩展买单网格 (向下) # 扩展买单网格 (向下)
if lowest_buy is not None and self.current_buy_levels < self.grid_count: while self.current_buy_levels < self.grid_count:
lowest_buy, highest_sell = self.get_extreme_prices()
base_balance, quote_balance = self.api_get_balances()
if lowest_buy is None:
lowest_buy = self.calculate_grid_price(
highest_sell, self.grid_count, "BUY"
)
logger.custom_debug(
"[GridTradingBot.extend_grid] lowest_buy was None, calculating based on highest_sell"
)
new_buy_price = self.calculate_grid_price(lowest_buy, 1, "BUY") new_buy_price = self.calculate_grid_price(lowest_buy, 1, "BUY")
logger.custom_debug( logger.custom_debug(
"[GridTradingBot.extend_grid] Extending buy grid - current lowest: %f, new price: %f", "[GridTradingBot.extend_grid] Extending buy grid - current lowest: %f, new price: %f",
@@ -656,15 +673,26 @@ class GridTradingBot:
new_buy_price * self.order_amount, new_buy_price * self.order_amount,
self.min_order_value, self.min_order_value,
) )
break
else: else:
logger.error( logger.error(
"[GridTradingBot.extend_grid] Insufficient quote balance for extended buy: %f <= %f", "[GridTradingBot.extend_grid] Insufficient quote balance for extended buy: %f <= %f",
quote_balance, quote_balance,
self.reserve_quote, self.reserve_quote,
) )
break
# 扩展卖单网格 (向上) # 扩展卖单网格 (向上)
if highest_sell is not None and self.current_sell_levels < self.grid_count: while self.current_sell_levels < self.grid_count:
lowest_buy, highest_sell = self.get_extreme_prices()
base_balance, quote_balance = self.api_get_balances()
if highest_sell is None:
highest_sell = self.calculate_grid_price(
lowest_buy, self.grid_count, "SELL"
)
logger.custom_debug(
"[GridTradingBot.extend_grid] highest_sell was None, calculating based on lowest_buy"
)
new_sell_price = self.calculate_grid_price(highest_sell, 1, "SELL") new_sell_price = self.calculate_grid_price(highest_sell, 1, "SELL")
logger.custom_debug( logger.custom_debug(
"[GridTradingBot.extend_grid] Extending sell grid - current highest: %f, new price: %f", "[GridTradingBot.extend_grid] Extending sell grid - current highest: %f, new price: %f",
@@ -703,26 +731,28 @@ class GridTradingBot:
new_sell_price * self.order_amount, new_sell_price * self.order_amount,
self.min_order_value, self.min_order_value,
) )
break
else: else:
logger.error( logger.error(
"[GridTradingBot.extend_grid] Insufficient base balance for extended sell: %f <= %f", "[GridTradingBot.extend_grid] Insufficient base balance for extended sell: %f <= %f",
base_balance, base_balance,
self.reserve_base, self.reserve_base,
) )
break
except Exception as e: except Exception as e:
logger.error( logger.error(
"[GridTradingBot.extend_grid] Failed to extend grid: %s", str(e) "[GridTradingBot.extend_grid] Failed to extend grid: %s", str(e)
) )
raise self.extend_grid()
def adjust_grid(self): def adjust_grid_for_filled(self):
"""调整网格 - 优化后的对称逻辑 """调整网格 - 优化后的对称逻辑:
买单成交时 买单成交时:
1. 取消最高价卖单 1. 取消最高价卖单
2. 在卖单侧挂一个更低价的卖单卖0 2. 在卖单侧挂一个更低价的卖单卖0
3. 在买单侧挂一个更低价的买单买n 3. 在买单侧挂一个更低价的买单买n
卖单成交时 卖单成交时:
1. 取消最低价买单 1. 取消最低价买单
2. 在买单侧挂一个更高价的买单买0 2. 在买单侧挂一个更高价的买单买0
3. 在卖单侧挂一个更高价的卖单卖n""" 3. 在卖单侧挂一个更高价的卖单卖n"""
@@ -741,12 +771,10 @@ class GridTradingBot:
if order.order_id in current_order_ids and order.status == "FILLED" if order.order_id in current_order_ids and order.status == "FILLED"
] ]
if not newly_filled_orders: if newly_filled_orders:
logger.custom_debug( logger.custom_debug(
"[GridTradingBot.adjust_grid] No newly filled orders found" "[GridTradingBot.adjust_grid] Newly filled orders found"
) )
return
# 处理每个新成交的订单 # 处理每个新成交的订单
for filled_order in newly_filled_orders: for filled_order in newly_filled_orders:
filled_side = filled_order.side filled_side = filled_order.side
@@ -771,9 +799,12 @@ class GridTradingBot:
if o.side == "SELL" and o.status == "NEW" if o.side == "SELL" and o.status == "NEW"
] ]
if filled_side == "BUY":
self.current_buy_levels -= 1
elif filled_side == "SELL":
self.current_sell_levels -= 1
if filled_side == "BUY" and active_sells: if filled_side == "BUY" and active_sells:
# 买单成交时的处理逻辑 # 买单成交时的处理逻辑
self.current_buy_levels -= 1
# 1. 取消最高价卖单 # 1. 取消最高价卖单
highest_sell = max(active_sells, key=lambda x: x.price) highest_sell = max(active_sells, key=lambda x: x.price)
self.api_cancel_order(highest_sell.order_id) self.api_cancel_order(highest_sell.order_id)
@@ -785,11 +816,14 @@ class GridTradingBot:
) )
# 2. 在卖单侧挂一个更低价的卖单卖0 # 2. 在卖单侧挂一个更低价的卖单卖0
# 使用最近成交的买单价格作为基准 # 使用最近成交的买单价格作为基准
new_sell_price = self.calculate_grid_price(filled_price, 1, "SELL") new_sell_price = self.calculate_grid_price(
filled_price, 1, "SELL"
)
# 检查余额和订单价值 # 检查余额和订单价值
base_balance, _ = self.api_get_balances() base_balance, _ = self.api_get_balances()
if base_balance > self.reserve_base and self.is_order_value_valid( if (
new_sell_price base_balance > self.reserve_base
and self.is_order_value_valid(new_sell_price)
): ):
sell_order_id = self.api_place_order(new_sell_price, "SELL") sell_order_id = self.api_place_order(new_sell_price, "SELL")
if sell_order_id: if sell_order_id:
@@ -808,7 +842,6 @@ class GridTradingBot:
elif filled_side == "SELL" and active_buys: elif filled_side == "SELL" and active_buys:
# 卖单成交时的处理逻辑 # 卖单成交时的处理逻辑
self.current_sell_levels -= 1
# 1. 取消最低价买单 # 1. 取消最低价买单
lowest_buy = min(active_buys, key=lambda x: x.price) lowest_buy = min(active_buys, key=lambda x: x.price)
self.api_cancel_order(lowest_buy.order_id) self.api_cancel_order(lowest_buy.order_id)
@@ -821,7 +854,9 @@ class GridTradingBot:
) )
# 2. 在买单侧挂一个更高价的买单买0 # 2. 在买单侧挂一个更高价的买单买0
# 使用最近成交的卖单价格作为基准 # 使用最近成交的卖单价格作为基准
new_buy_price = self.calculate_grid_price(filled_price, 1, "BUY") new_buy_price = self.calculate_grid_price(
filled_price, 1, "BUY"
)
# 检查余额和订单价值 # 检查余额和订单价值
_, quote_balance = self.api_get_balances() _, quote_balance = self.api_get_balances()
if ( if (
@@ -842,12 +877,39 @@ class GridTradingBot:
new_buy_price, new_buy_price,
buy_order_id, buy_order_id,
) )
except Exception as e: except Exception as e:
logger.error( logger.error(
"[GridTradingBot.adjust_grid] Failed to adjust grid: %s", str(e) "[GridTradingBot.adjust_grid] Failed to adjust grid: %s", str(e)
) )
raise self.adjust_grid_for_filled()
def adjust_grid_for_violation(self):
try:
market_price = self.api_get_price()
lowest_buy, highest_sell = self.get_extreme_prices()
if lowest_buy is None and market_price < self.calculate_grid_price(
highest_sell, self.grid_count + 1, "BUY"
):
logger.warning(
"[GridTradingBot.adjust_grid_for_violation] Price varied too low, restarting grid."
)
self.api_cancel_all_orders()
self.initialize_grid()
elif highest_sell is None and market_price > self.calculate_grid_price(
lowest_buy, self.grid_count + 1, "SELL"
):
logger.warning(
"[GridTradingBot.adjust_grid_for_violation] Price varied too high, restarting grid."
)
self.api_cancel_all_orders()
self.initialize_grid()
except Exception as e:
logger.error(
"[GridTradingBot.adjust_grid_for_violation] Failed to adjust grid: %s",
str(e),
)
self.adjust_grid_for_violation()
def run(self): def run(self):
"""运行网格交易机器人""" """运行网格交易机器人"""
@@ -871,7 +933,8 @@ class GridTradingBot:
self.api_update_order_statuses() self.api_update_order_statuses()
# 调整网格 # 调整网格
self.adjust_grid() self.adjust_grid_for_filled()
self.adjust_grid_for_violation()
# 尝试扩展网格 # 尝试扩展网格
self.extend_grid() self.extend_grid()
@@ -885,7 +948,7 @@ class GridTradingBot:
except Exception as e: except Exception as e:
logger.error("[GridTradingBot.run] Error in main loop: %s", str(e)) logger.error("[GridTradingBot.run] Error in main loop: %s", str(e))
sleep_time = 3 sleep_time = 1
logger.custom_debug( logger.custom_debug(
"[GridTradingBot.run] Error occurred, sleeping for %d seconds", "[GridTradingBot.run] Error occurred, sleeping for %d seconds",
sleep_time, sleep_time,