- 新增 Vue 3 + Vuetify 前端界面 - 新增市场分析模块 (market/) - 更新主服务器和路由 - 更新 MT5 EA 文件 - 添加 .gitignore 排除临时文件
199 lines
6.3 KiB
Python
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 |