feat: 添加前端界面和市场分析模块
- 新增 Vue 3 + Vuetify 前端界面 - 新增市场分析模块 (market/) - 更新主服务器和路由 - 更新 MT5 EA 文件 - 添加 .gitignore 排除临时文件
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user