fix: a lot of things

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

295
main.py
View File

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