在 `models.py` 中新增 `update_entry_order_id` 方法,用于补全或更新开仓订单号,提升交易记录的完整性。更新 `set_exit_order_id_for_open_trade` 方法以支持按 `entry_order_id` 精确匹配,优化平仓订单的回写逻辑。在 `position_manager.py` 中添加对 `entry_order_id` 的处理,确保在保存交易记录时能够及时补全。更新 `user_data_stream.py` 中的日志记录,提供更详细的状态信息,增强系统的可追溯性与调试能力。
97 lines
3.6 KiB
Python
97 lines
3.6 KiB
Python
"""
|
||
User Data Stream 诊断工具:检查 listenKey 创建和 WS 连接状态
|
||
"""
|
||
import asyncio
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 添加路径
|
||
project_root = Path(__file__).parent.parent
|
||
sys.path.insert(0, str(project_root / "trading_system"))
|
||
sys.path.insert(0, str(project_root / "backend"))
|
||
|
||
async def check_user_data_stream():
|
||
"""检查 User Data Stream 状态"""
|
||
import os
|
||
from binance_client import BinanceClient
|
||
import config
|
||
|
||
account_id = int(os.getenv("ATS_ACCOUNT_ID") or os.getenv("ACCOUNT_ID") or "1")
|
||
print(f"检查账号 {account_id} 的 User Data Stream 状态...")
|
||
|
||
# 初始化客户端
|
||
client = BinanceClient(
|
||
api_key=config.BINANCE_API_KEY,
|
||
api_secret=config.BINANCE_API_SECRET,
|
||
testnet=config.USE_TESTNET
|
||
)
|
||
await client.connect()
|
||
|
||
print("\n1. 检查 listenKey 创建...")
|
||
listen_key = await client.create_futures_listen_key()
|
||
if listen_key:
|
||
print(f" ✓ listenKey 创建成功: {listen_key[:20]}...")
|
||
else:
|
||
print(" ❌ listenKey 创建失败")
|
||
print(" 可能原因:")
|
||
print(" - API Key 权限不足(需要启用 'Enable Reading' 和 'Enable Futures')")
|
||
print(" - 网络连接问题")
|
||
print(" - IP 白名单限制")
|
||
return
|
||
|
||
print("\n2. 检查 WebSocket 连接...")
|
||
try:
|
||
import aiohttp
|
||
ws_url = f"wss://fstream.binance.com/ws/{listen_key}"
|
||
print(f" 连接地址: {ws_url[:50]}...")
|
||
|
||
async with aiohttp.ClientSession() as session:
|
||
async with session.ws_connect(
|
||
ws_url,
|
||
heartbeat=50,
|
||
timeout=aiohttp.ClientTimeout(total=10)
|
||
) as ws:
|
||
print(" ✓ WebSocket 连接成功")
|
||
print(" 等待接收推送消息(10秒)...")
|
||
|
||
received_messages = []
|
||
try:
|
||
async with asyncio.timeout(10):
|
||
async for msg in ws:
|
||
if msg.type == aiohttp.WSMsgType.TEXT:
|
||
received_messages.append(msg.data)
|
||
print(f" ✓ 收到消息: {msg.data[:100]}...")
|
||
elif msg.type == aiohttp.WSMsgType.ERROR:
|
||
print(f" ❌ WebSocket 错误: {msg}")
|
||
break
|
||
elif msg.type in (aiohttp.WSMsgType.CLOSED, aiohttp.WSMsgType.CLOSE):
|
||
print(" ⚠ WebSocket 已关闭")
|
||
break
|
||
except asyncio.TimeoutError:
|
||
pass
|
||
|
||
if received_messages:
|
||
print(f"\n ✓ 成功收到 {len(received_messages)} 条推送消息")
|
||
else:
|
||
print("\n ⚠ 10秒内未收到任何推送消息(可能当前无订单/持仓变化)")
|
||
print(" 这是正常的,如果有订单成交或持仓变化,会收到推送")
|
||
except Exception as e:
|
||
print(f" ❌ WebSocket 连接失败: {e}")
|
||
print(f" 错误类型: {type(e).__name__}")
|
||
|
||
print("\n3. 检查 keepalive...")
|
||
ok, code_1125 = await client.keepalive_futures_listen_key(listen_key)
|
||
if ok:
|
||
print(" ✓ keepalive 成功")
|
||
else:
|
||
if code_1125:
|
||
print(" ❌ keepalive 返回 -1125(listenKey 不存在或已过期)")
|
||
else:
|
||
print(" ❌ keepalive 失败")
|
||
|
||
await client.disconnect()
|
||
print("\n检查完成")
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(check_user_data_stream())
|