|
|
@@ -24,7 +24,7 @@ from decimal import Decimal
|
|
|
|
|
|
class OrderBook:
|
|
|
"""本地订单簿数据结构,支持增量更新"""
|
|
|
-
|
|
|
+
|
|
|
def __init__(self, market_index):
|
|
|
self.market_index = market_index
|
|
|
self.bids = {} # {price: size}
|
|
|
@@ -32,6 +32,9 @@ class OrderBook:
|
|
|
self.last_offset = 0
|
|
|
self.last_update_time = 0
|
|
|
self.max_levels = 100 # 最大保留的价格档位数量
|
|
|
+ self._bids_cache = None # 缓存排序后的bids
|
|
|
+ self._asks_cache = None # 缓存排序后的asks
|
|
|
+ self._cache_valid = False # 缓存是否有效
|
|
|
|
|
|
def update(self, order_book_data, offset):
|
|
|
"""更新订单簿数据"""
|
|
|
@@ -39,54 +42,58 @@ class OrderBook:
|
|
|
# 更新偏移量和时间戳
|
|
|
self.last_offset = offset
|
|
|
self.last_update_time = time.time()
|
|
|
-
|
|
|
+
|
|
|
+ # 标记缓存失效
|
|
|
+ self._cache_valid = False
|
|
|
+
|
|
|
# 处理买单
|
|
|
if 'bids' in order_book_data:
|
|
|
for bid in order_book_data['bids']:
|
|
|
if isinstance(bid, dict) and 'price' in bid and 'size' in bid:
|
|
|
price = Decimal(bid['price'])
|
|
|
size = Decimal(bid['size'])
|
|
|
-
|
|
|
+
|
|
|
if size == 0:
|
|
|
# 删除价格档位
|
|
|
self.bids.pop(price, None)
|
|
|
else:
|
|
|
# 更新价格档位
|
|
|
self.bids[price] = size
|
|
|
-
|
|
|
+
|
|
|
# 处理卖单
|
|
|
if 'asks' in order_book_data:
|
|
|
for ask in order_book_data['asks']:
|
|
|
if isinstance(ask, dict) and 'price' in ask and 'size' in ask:
|
|
|
price = Decimal(ask['price'])
|
|
|
size = Decimal(ask['size'])
|
|
|
-
|
|
|
+
|
|
|
if size == 0:
|
|
|
# 删除价格档位
|
|
|
self.asks.pop(price, None)
|
|
|
else:
|
|
|
# 更新价格档位
|
|
|
self.asks[price] = size
|
|
|
-
|
|
|
+
|
|
|
# 维护订单簿,限制档位数量
|
|
|
self._maintain_order_book()
|
|
|
-
|
|
|
+
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新订单簿失败: {e}")
|
|
|
|
|
|
def _maintain_order_book(self):
|
|
|
"""维护订单簿,清理过多的价格档位"""
|
|
|
try:
|
|
|
- # 限制买单档位数量(保留价格最高的档位)
|
|
|
+ # 只在档位数量超过限制时才进行清理,避免频繁排序
|
|
|
if len(self.bids) > self.max_levels:
|
|
|
+ # 保留价格最高的max_levels个档位
|
|
|
sorted_bids = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
self.bids = dict(sorted_bids[:self.max_levels])
|
|
|
-
|
|
|
- # 限制卖单档位数量(保留价格最低的档位)
|
|
|
+
|
|
|
if len(self.asks) > self.max_levels:
|
|
|
+ # 保留价格最低的max_levels个档位
|
|
|
sorted_asks = sorted(self.asks.items(), key=lambda x: x[0])
|
|
|
self.asks = dict(sorted_asks[:self.max_levels])
|
|
|
-
|
|
|
+
|
|
|
except Exception as e:
|
|
|
logger.error(f"维护订单簿失败: {e}")
|
|
|
|
|
|
@@ -120,13 +127,23 @@ class OrderBook:
|
|
|
|
|
|
def get_sorted_bids(self, limit=10):
|
|
|
"""获取排序后的买单(价格从高到低)"""
|
|
|
- sorted_bids = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
- return [{'price': str(price), 'size': str(size)} for price, size in sorted_bids[:limit]]
|
|
|
-
|
|
|
+ # 使用缓存避免频繁排序
|
|
|
+ if not self._cache_valid:
|
|
|
+ self._bids_cache = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
+ self._asks_cache = sorted(self.asks.items(), key=lambda x: x[0])
|
|
|
+ self._cache_valid = True
|
|
|
+
|
|
|
+ return [{'price': str(price), 'size': str(size)} for price, size in self._bids_cache[:limit]]
|
|
|
+
|
|
|
def get_sorted_asks(self, limit=10):
|
|
|
"""获取排序后的卖单(价格从低到高)"""
|
|
|
- sorted_asks = sorted(self.asks.items(), key=lambda x: x[0])
|
|
|
- return [{'price': str(price), 'size': str(size)} for price, size in sorted_asks[:limit]]
|
|
|
+ # 使用缓存避免频繁排序
|
|
|
+ if not self._cache_valid:
|
|
|
+ self._bids_cache = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
+ self._asks_cache = sorted(self.asks.items(), key=lambda x: x[0])
|
|
|
+ self._cache_valid = True
|
|
|
+
|
|
|
+ return [{'price': str(price), 'size': str(size)} for price, size in self._asks_cache[:limit]]
|
|
|
|
|
|
def is_valid(self):
|
|
|
"""验证订单簿数据的有效性"""
|
|
|
@@ -346,7 +363,7 @@ async def handle_binance_websocket(config):
|
|
|
|
|
|
if symbol and price:
|
|
|
binance_data_cache['latest_prices'][symbol] = float(price)
|
|
|
- logger.debug(f"更新Binance价格: {symbol} = {price}")
|
|
|
+ # logger.debug(f"更新Binance价格: {symbol} = {price}")
|
|
|
|
|
|
# 触发策略更新
|
|
|
await trigger_strategy_update()
|
|
|
@@ -414,7 +431,7 @@ async def handle_order_book_websocket(config):
|
|
|
if message_type == "ping":
|
|
|
pong_message = {"type": "pong"}
|
|
|
await websocket.send(json.dumps(pong_message))
|
|
|
- logger.debug("收到ping消息,已回复pong")
|
|
|
+ # logger.debug("收到ping消息,已回复pong")
|
|
|
|
|
|
# 处理连接确认消息
|
|
|
elif message_type == "connected":
|
|
|
@@ -522,6 +539,10 @@ async def main():
|
|
|
# 初始化策略,传入配置
|
|
|
trading_strategy = TradingStrategy(config)
|
|
|
logger.info("交易策略已初始化")
|
|
|
+
|
|
|
+ # 启动后台任务(账户更新和数据库刷新)
|
|
|
+ await trading_strategy.start_background_tasks()
|
|
|
+ logger.info("策略后台任务已启动")
|
|
|
|
|
|
# 添加每小时打印匹配交易对数量的变量
|
|
|
last_hourly_report_time = time.time()
|