auto_trade_sys/trading_system/pending_reconcile.py
薇薇安 df2b8d6372 fix(config_manager, api, database, position_manager, user_data_stream): 增强配置管理和日志记录
在配置管理模块中,新增了 `ONLY_AUTO_TRADE_CREATES_RECORDS` 配置项,以控制自动开仓记录的写入行为。同时,在多个模块中优化了日志记录,确保在数据库操作和交易记录完善时提供更清晰的错误信息。这一改动旨在提升系统的稳定性和可维护性,确保交易策略的有效性与安全性。
2026-02-26 11:19:23 +08:00

94 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
正向流程加固pending 对账模块
供 sync_positions_with_binance 和 UserDataStream 重连后调用,补齐因 WS 断线/进程重启漏掉的 pending→open。
"""
import logging
logger = logging.getLogger(__name__)
DB_AVAILABLE = False
Trade = None
try:
import sys
from pathlib import Path
project_root = Path(__file__).parent.parent
backend_path = project_root / "backend"
if backend_path.exists():
sys.path.insert(0, str(backend_path))
from database.models import Trade
DB_AVAILABLE = True
except Exception:
pass
async def reconcile_pending_with_binance(client, account_id: int, limit: int = 50, max_age_sec: int = 86400) -> int:
"""
对 status=pending 记录查币安订单,若已 FILLED 则更新为 open。
返回成功对账数量。
"""
if not DB_AVAILABLE or not Trade:
return 0
try:
pending_list = Trade.get_pending_recent(account_id, limit=limit, max_age_sec=max_age_sec)
if not pending_list:
return 0
reconciled = 0
for row in pending_list:
try:
symbol = (row.get("symbol") or "").strip()
client_order_id = (row.get("client_order_id") or "").strip() or None
entry_order_id = row.get("entry_order_id")
if not symbol:
continue
order_info = None
if client_order_id and hasattr(client, "get_order_by_client_order_id"):
order_info = await client.get_order_by_client_order_id(symbol, client_order_id)
if not order_info and entry_order_id:
try:
oid = int(entry_order_id)
order_info = await client.client.futures_get_order(
symbol=symbol, orderId=oid, recvWindow=20000
)
except Exception:
pass
if not order_info or str(order_info.get("status")).upper() != "FILLED":
continue
ap = order_info.get("avgPrice") or order_info.get("price") or 0
z = order_info.get("executedQty") or 0
try:
ap_f = float(ap)
z_f = float(z)
except (TypeError, ValueError):
continue
if ap_f <= 0 or z_f <= 0:
continue
order_id = order_info.get("orderId")
if client_order_id:
ok = Trade.update_pending_to_filled(
client_order_id, account_id, order_id, ap_f, z_f
)
else:
ok = Trade.update_pending_by_entry_order_id(
symbol, account_id, order_id, ap_f, z_f
)
if ok:
reconciled += 1
logger.info(
f"[DB] [账号{account_id}] pending 对账: {symbol} client_order_id={client_order_id!r} "
f"已完善为 open (orderId={order_id} 成交价={ap_f:.4f} 数量={z_f:.4f})"
)
else:
logger.warning(
f"[DB] [账号{account_id}] pending 对账完善失败 symbol={symbol} client_order_id={client_order_id!r} orderId={order_id} "
f"(可能无对应 pending 或已非 pending 状态)"
)
except Exception as e:
logger.error(
f"[DB] [账号{account_id}] pending 对账单条异常 symbol={symbol} client_order_id={client_order_id!r} "
f"error_type={type(e).__name__} error={e}"
)
return reconciled
except Exception as e:
logger.error(f"[DB] [账号{account_id}] pending 对账异常 error_type={type(e).__name__} error={e}")
return 0