Files
AI-Trader/market/pending_orders.py
T
guaiwoluo2020 51b2f30748 feat: 添加前端界面和市场分析模块
- 新增 Vue 3 + Vuetify 前端界面
- 新增市场分析模块 (market/)
- 更新主服务器和路由
- 更新 MT5 EA 文件
- 添加 .gitignore 排除临时文件
2026-03-10 17:38:13 +08:00

199 lines
6.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
待确认订单管理模块
存储交易员待确认的交易指令
"""
from collections import defaultdict
from typing import List, Dict, Optional, Callable
from datetime import datetime, timedelta
import threading
import uuid
class PendingOrderManager:
"""待确认订单管理器"""
# 订单超时时间(秒)
ORDER_TIMEOUT = 180 # 3分钟
def __init__(self):
# 待确认订单: {SYMBOL: [Order, ...]}
self._pending_orders = defaultdict(list)
self._lock = threading.RLock()
# 订单ID到订单的映射
self._order_by_id = {}
# 订单确认回调(确认后将订单加入交易队列)
self._confirm_callback: Optional[Callable] = None
# 启动超时清理线程
self._start_cleanup_thread()
print("[PendingOrderManager] 待确认订单管理器已初始化")
def set_confirm_callback(self, callback: Callable):
"""设置订单确认回调函数"""
self._confirm_callback = callback
def _start_cleanup_thread(self):
"""启动超时清理线程"""
def cleanup_loop():
while True:
try:
self._cleanup_expired_orders()
except Exception as e:
print(f"[PendingOrderManager] 清理线程异常: {e}")
threading.Event().wait(10) # 每10秒检查一次
thread = threading.Thread(target=cleanup_loop, daemon=True)
thread.start()
def _cleanup_expired_orders(self):
"""清理超时订单"""
current_time = datetime.now()
expired_orders = []
with self._lock:
for order_id, order in list(self._order_by_id.items()):
created_at = datetime.fromisoformat(order['created_at'])
elapsed = (current_time - created_at).total_seconds()
if elapsed > self.ORDER_TIMEOUT:
expired_orders.append(order_id)
for order_id in expired_orders:
order = self._order_by_id[order_id]
symbol = order.get('symbol', 'UNKNOWN')
self._pending_orders[symbol] = [
o for o in self._pending_orders[symbol] if o['order_id'] != order_id
]
del self._order_by_id[order_id]
print(f"[PendingOrderManager] 订单超时自动移除: {order_id}")
def add_order(self, order: Dict) -> str:
"""
添加待确认订单
Args:
order: 订单信息
Returns:
订单ID
"""
# 生成订单ID
order_id = str(uuid.uuid4())[:8]
order_with_id = {
**order,
"order_id": order_id,
"status": "pending",
"created_at": datetime.now().isoformat(),
"expires_at": (datetime.now() + timedelta(seconds=self.ORDER_TIMEOUT)).isoformat()
}
symbol = order.get('symbol', 'UNKNOWN')
with self._lock:
self._pending_orders[symbol].append(order_with_id)
self._order_by_id[order_id] = order_with_id
print(f"[PendingOrderManager] 添加待确认订单: {order_id} {symbol} {order.get('action')}")
return order_id
def confirm_order(self, order_id: str) -> Optional[Dict]:
"""
确认订单(交易员确认后调用)
Returns:
确认后的订单,用于加入正式交易队列
"""
with self._lock:
if order_id not in self._order_by_id:
return None
order = self._order_by_id[order_id]
symbol = order.get('symbol', 'UNKNOWN')
# 从待确认列表中移除
self._pending_orders[symbol] = [
o for o in self._pending_orders[symbol] if o['order_id'] != order_id
]
del self._order_by_id[order_id]
# 标记为已确认
order['status'] = 'confirmed'
order['confirmed_at'] = datetime.now().isoformat()
print(f"[PendingOrderManager] 订单已确认: {order_id}")
# 调用确认回调(将订单加入交易队列)
if self._confirm_callback:
try:
self._confirm_callback(order)
print(f"[PendingOrderManager] 订单已加入交易队列: {order_id}")
except Exception as e:
print(f"[PendingOrderManager] 加入交易队列失败: {e}")
return order
def reject_order(self, order_id: str) -> bool:
"""
拒绝订单(交易员点击放弃)
Returns:
是否成功
"""
with self._lock:
if order_id not in self._order_by_id:
return False
order = self._order_by_id[order_id]
symbol = order.get('symbol', 'UNKNOWN')
# 从待确认列表中移除
self._pending_orders[symbol] = [
o for o in self._pending_orders[symbol] if o['order_id'] != order_id
]
del self._order_by_id[order_id]
print(f"[PendingOrderManager] 订单已拒绝: {order_id}")
return True
def get_pending_orders(self, symbol: str = None) -> List[Dict]:
"""获取待确认订单列表"""
with self._lock:
if symbol:
return list(self._pending_orders.get(symbol, []))
else:
# 返回所有
orders = []
for sym, order_list in self._pending_orders.items():
orders.extend(order_list)
return sorted(orders, key=lambda x: x['created_at'], reverse=True)
def get_order_by_id(self, order_id: str) -> Optional[Dict]:
"""根据ID获取订单"""
with self._lock:
return self._order_by_id.get(order_id)
def get_pending_count(self, symbol: str = None) -> int:
"""获取待确认订单数量"""
with self._lock:
if symbol:
return len(self._pending_orders.get(symbol, []))
return len(self._order_by_id)
def clear_all(self) -> int:
"""清空所有待确认订单"""
with self._lock:
count = len(self._order_by_id)
self._pending_orders.clear()
self._order_by_id.clear()
return count