在 `user_data_stream.py` 中为 `ORDER_TRADE_UPDATE` 和 `ALGO_UPDATE` 事件添加了日志记录功能,确保在接收到相关推送时能够记录事件信息。这一改进提升了系统的可追踪性和调试能力。
85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
"""
|
||
币安订单推送事件日志:将 ORDER_TRADE_UPDATE / ALGO_UPDATE 等写入日志文件,便于与 DB 对账。
|
||
每行一条 JSON,含 event_type、account_id、时间、关键字段,方便 grep / 脚本分析。
|
||
"""
|
||
import json
|
||
import logging
|
||
import os
|
||
import time
|
||
from pathlib import Path
|
||
from typing import Any, Dict, Optional
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
_LOG_DIR: Optional[Path] = None
|
||
_LOG_PATH: Optional[Path] = None
|
||
|
||
|
||
def _get_log_path() -> Optional[Path]:
|
||
global _LOG_DIR, _LOG_PATH
|
||
if _LOG_PATH is not None:
|
||
return _LOG_PATH
|
||
try:
|
||
root = Path(__file__).resolve().parent.parent
|
||
_LOG_DIR = root / "logs"
|
||
_LOG_DIR.mkdir(parents=True, exist_ok=True)
|
||
_LOG_PATH = _LOG_DIR / "binance_order_events.log"
|
||
return _LOG_PATH
|
||
except Exception as e:
|
||
logger.debug(f"binance_order_event_logger 无法创建日志路径: {e}")
|
||
return None
|
||
|
||
|
||
def _default_serializer(obj):
|
||
if hasattr(obj, "isoformat"):
|
||
return obj.isoformat()
|
||
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
|
||
|
||
|
||
def log_order_event(account_id: int, event_type: str, event_time_ms: Optional[int], data: Dict[str, Any]) -> None:
|
||
"""
|
||
将币安订单推送事件写入日志文件(每行一条 JSON)。
|
||
|
||
Args:
|
||
account_id: 账号 ID
|
||
event_type: ORDER_TRADE_UPDATE / ALGO_UPDATE 等
|
||
event_time_ms: 事件时间(毫秒)
|
||
data: 原始 payload(如 o 或 a 部分),会提取关键字段
|
||
"""
|
||
path = _get_log_path()
|
||
if not path:
|
||
return
|
||
try:
|
||
# 提取关键字段便于对账
|
||
row = {
|
||
"ts": int(time.time() * 1000),
|
||
"event_type": event_type,
|
||
"account_id": account_id,
|
||
"E": event_time_ms,
|
||
}
|
||
if event_type == "ORDER_TRADE_UPDATE" and data:
|
||
o = data
|
||
row["symbol"] = (o.get("s") or "").strip()
|
||
row["orderId"] = o.get("i")
|
||
row["clientOrderId"] = (o.get("c") or "").strip() or None
|
||
row["event"] = (o.get("x") or "").strip() # NEW/TRADE/CANCELED
|
||
row["status"] = (o.get("X") or "").strip() # NEW/FILLED/CANCELED
|
||
row["reduceOnly"] = o.get("R") is True
|
||
if row["status"] == "FILLED":
|
||
row["avgPrice"] = o.get("ap")
|
||
row["executedQty"] = o.get("z")
|
||
row["realizedPnl"] = o.get("rp")
|
||
elif event_type == "ALGO_UPDATE" and data:
|
||
o = data
|
||
row["symbol"] = (o.get("s") or "").strip()
|
||
row["algoId"] = o.get("i")
|
||
row["algoStatus"] = (o.get("X") or "").strip() # TRIGGERED/FINISHED
|
||
row["triggeredOrderId"] = o.get("ai") # 触发后的普通订单 id
|
||
else:
|
||
row["raw"] = data
|
||
line = json.dumps(row, ensure_ascii=False, default=_default_serializer) + "\n"
|
||
with open(path, "a", encoding="utf-8") as f:
|
||
f.write(line)
|
||
except Exception as e:
|
||
logger.debug(f"binance_order_event_logger 写入失败: {e}")
|