#!/usr/bin/env python3 """ 检查数据库中的异常订单 用于调试莫名奇妙出现的平仓消息问题 """ import sys import os # 添加项目路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from app.services.db_service import db_service from app.models.paper_trading import PaperOrder, OrderStatus from sqlalchemy import text from datetime import datetime, timedelta def check_abnormal_orders(): """检查所有异常订单""" db = db_service.get_session() print("=" * 80) print("异常订单检查报告") print("=" * 80) print(f"检查时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print() # 1. 检查 OPEN 状态但 filled_price 为 0 或 None 的订单 print("【1】OPEN 状态但成交价无效的订单(可能导致错误平仓):") print("-" * 80) invalid_filled_orders = db.query(PaperOrder).filter( PaperOrder.status == OrderStatus.OPEN, (PaperOrder.filled_price == None) | (PaperOrder.filled_price == 0) ).all() if invalid_filled_orders: for order in invalid_filled_orders: print(f" ⚠️ 订单ID: {order.order_id}") print(f" 交易对: {order.symbol}") print(f" 方向: {order.side.value}") print(f" 状态: {order.status.value}") print(f" 入场价: {order.entry_price}") print(f" 成交价: {order.filled_price} ❌ 无效") print(f" 创建时间: {order.created_at}") print() else: print(" ✅ 无异常订单") print() # 2. 检查 PENDING 状态但已有成交价的订单 print("【2】PENDING 状态但有成交价的订单(状态不一致):") print("-" * 80) pending_with_filled = db.query(PaperOrder).filter( PaperOrder.status == OrderStatus.PENDING, PaperOrder.filled_price != None, PaperOrder.filled_price > 0 ).all() if pending_with_filled: for order in pending_with_filled: print(f" ⚠️ 订单ID: {order.order_id}") print(f" 交易对: {order.symbol}") print(f" 成交价: {order.filled_price}") print(f" 状态: PENDING(应该是 OPEN)") print() else: print(" ✅ 无异常订单") print() # 3. 检查最近1小时内平仓的订单(入场价或出场价为0) print("【3】最近平仓订单中价格异常的记录:") print("-" * 80) one_hour_ago = datetime.now() - timedelta(hours=1) closed_abnormal = db.query(PaperOrder).filter( PaperOrder.status.in_([ OrderStatus.CLOSED_TP, OrderStatus.CLOSED_SL, OrderStatus.CLOSED_BE, OrderStatus.CLOSED_MANUAL ]), PaperOrder.closed_at >= one_hour_ago, ( (PaperOrder.filled_price == None) | (PaperOrder.filled_price == 0) | (PaperOrder.exit_price == None) | (PaperOrder.exit_price == 0) ) ).all() if closed_abnormal: for order in closed_abnormal: print(f" ⚠️ 订单ID: {order.order_id}") print(f" 交易对: {order.symbol}") print(f" 成交价: {order.filled_price}") print(f" 出场价: {order.exit_price}") print(f" 平仓时间: {order.closed_at}") print(f" 平仓原因: {order.status.value}") print() else: print(" ✅ 无异常记录") print() # 4. 检查所有活跃订单的状态统计 print("【4】活跃订单状态统计:") print("-" * 80) active_stats = db.execute(text(""" SELECT status, COUNT(*) as count, SUM(CASE WHEN filled_price IS NULL OR filled_price = 0 THEN 1 ELSE 0 END) as invalid_count FROM paper_orders WHERE status IN ('PENDING', 'OPEN') GROUP BY status """)) for row in active_stats: status_name = row[0] count = row[1] invalid = row[2] print(f" {status_name}: {count} 个(异常: {invalid} 个)") print() # 5. 检查重复订单 print("【5】可能重复的订单(同一交易对、同一方向、相近创建时间):") print("-" * 80) duplicates = db.execute(text(""" SELECT symbol, side, created_at, order_id, entry_price FROM paper_orders WHERE status IN ('PENDING', 'OPEN') AND created_at >= datetime('now', '-1 hour') ORDER BY symbol, side, created_at DESC """)).fetchall() # 简单的重复检测:同一交易对+方向在1分钟内创建 seen = {} duplicate_found = False for row in duplicates: key = (row[0], row[1]) # symbol + side if key in seen: prev_time = seen[key] if abs((row[2] - prev_time).total_seconds()) < 60: print(f" ⚠️ 可能重复: {row[0]} {row[1]}") print(f" 订单ID: {row[3]}") print(f" 时间: {row[2]}") duplicate_found = True seen[key] = row[2] if not duplicate_found: print(" ✅ 无明显重复") print() # 6. 最近的活动日志 print("【6】最近10条订单变更记录(按时间倒序):") print("-" * 80) # 使用 COALESCE 来优先显示 closed_at,其次 opened_at,最后 created_at recent_orders = db.execute(text(""" SELECT COALESCE(closed_at, opened_at, created_at) as last_time, symbol, side, status, entry_price, filled_price FROM paper_orders ORDER BY last_time DESC LIMIT 10 """)).fetchall() for order in recent_orders: last_time = order[0] symbol = order[1] side = order[2] status = order[3] entry_price = order[4] filled_price = order[5] # last_time 是字符串,直接格式化 if last_time: if isinstance(last_time, str): time_str = last_time[11:19] # 提取 HH:MM:SS 部分 else: time_str = last_time.strftime('%H:%M:%S') else: time_str = 'N/A' filled_str = f"{filled_price:.2f}" if filled_price else "NULL" entry_str = f"{entry_price:.2f}" if entry_price else "NULL" print(f" {time_str} | {symbol} | {side:4s} | {status:15s} | " f"入场:{entry_str} 成交:{filled_str}") print() print("=" * 80) print("检查完成") print("=" * 80) # 输出清理建议 if invalid_filled_orders: print() print("🔧 发现异常订单!建议执行以下操作:") print() print("1. 删除 OPEN 状态但成交价无效的订单:") for order in invalid_filled_orders: print(f" DELETE FROM paper_orders WHERE order_id = '{order.order_id}';") print() print("2. 或者运行 python fix_abnormal_orders.py 自动修复") db.close() if __name__ == "__main__": check_abnormal_orders()