feat: 添加前端界面和市场分析模块

- 新增 Vue 3 + Vuetify 前端界面
- 新增市场分析模块 (market/)
- 更新主服务器和路由
- 更新 MT5 EA 文件
- 添加 .gitignore 排除临时文件
This commit is contained in:
guaiwoluo2020
2026-03-10 17:38:13 +08:00
parent 0c9cf048d2
commit 51b2f30748
40 changed files with 8576 additions and 151 deletions
+105 -50
View File
@@ -9,25 +9,72 @@ from typing import List, Dict, Optional
import threading
from models import TradeInstruction
from market.store import MarketStore, normalize_symbol
from market.pivot_detector import PivotDetector
from market.monitor import PivotMonitor
from market.trend_analyzer import TrendAnalyzer
from market.pending_orders import PendingOrderManager
class TradingServer:
"""交易服务主类"""
def __init__(self):
# 交易指令队列 - 按SYMBOL分类
# 结构: {"SYMBOL1": [TradeInstruction1, ...], "SYMBOL2": [...]}
self.trade_instructions = defaultdict(list)
# 平仓指令队列 - 按SYMBOL分类
# 结构: {"SYMBOL1": [ticket1, ticket2, ...], ...}
self.close_position_instructions = defaultdict(list)
# 统计数据历史 - 保留最新10条
# 结构: deque([{stat_data1}, {stat_data2}, ...], maxlen=10)
self.statistics_history = deque(maxlen=10)
# 线程锁 - 确保线程安全
self.lock = threading.RLock()
# ==================== 行情模块 ====================
# K线存储
self.market_store = MarketStore()
# 转折点检测器
self.pivot_detector = PivotDetector()
# 待确认订单管理器(需要在 PivotMonitor 之前初始化)
self.pending_orders = PendingOrderManager()
# 设置订单确认回调
self.pending_orders.set_confirm_callback(self._on_order_confirmed)
# 转折点监控器
self.pivot_monitor = PivotMonitor(self.market_store, self.pivot_detector, self.pending_orders)
# 趋势分析器
self.trend_analyzer = TrendAnalyzer()
print("[信息] 交易服务已初始化")
def _on_order_confirmed(self, order: Dict):
"""
订单确认回调 - 将确认的订单加入交易队列
"""
print(f"[TradingServer] _on_order_confirmed 被调用,订单: {order}")
try:
# 创建交易指令
instruction = TradeInstruction(
symbol=order.get('symbol', ''),
action=order.get('action', 'b'),
mount=order.get('mount', 0.01),
price=order.get('price', 0),
sl=order.get('sl', 0),
tp=order.get('tp', 0)
)
print(f"[TradingServer] 创建交易指令: symbol={instruction.symbol}, action={instruction.action}, mount={instruction.mount}, price={instruction.price}, sl={instruction.sl}, tp={instruction.tp}")
# 添加到交易队列
result = self.add_trade_instruction([instruction])
print(f"[TradingServer] 订单已加入交易队列: {result}")
except Exception as e:
print(f"[TradingServer] 加入交易队列失败: {e}")
import traceback
traceback.print_exc()
def add_trade_instruction(self, instructions: List[TradeInstruction]) -> dict:
"""
添加交易指令
@@ -76,59 +123,46 @@ class TradingServer:
return {"added": added, "rejected": rejected}
def get_trades_by_symbol(self, symbol: str, price: Optional[float] = None) -> List[Dict]:
def get_trades_by_symbol(self, symbol: str, price: Optional[float] = None) -> Dict:
"""
获取指定SYMBOL的交易指令并删除
根据价格条件过滤指令:
- 买入指令(action='b'):如果指令价格 > 当前价格,缓存(等待价格下跌到指令价格)
- 卖出指令(action='s'):如果指令价格 < 当前价格,缓存(等待价格上涨到指令价格)
返回指令列表(JSON格式)
同时检查价格是否接近转折点,如果有则添加到返回结果中
返回: {"trades": [...], "pivot_alerts": [...]}
"""
# 先检查转折点
pivot_alerts = []
if price is not None:
# 统一转换为大写进行检测
symbol_upper = symbol.upper()
pivot_alerts = self.pivot_monitor.check_and_alert(symbol_upper, price)
if pivot_alerts:
print(f"[信息] {symbol_upper} 当前价格 {price} 接近转折点")
with self.lock:
symbol = symbol.upper()
if symbol not in self.trade_instructions or len(self.trade_instructions[symbol]) == 0:
return []
# 获取所有指令
return {"trades": [], "pivot_alerts": pivot_alerts}
# 获取所有指令并直接返回(不再进行价格过滤)
trades = self.trade_instructions[symbol]
result = []
cached_trades = []
for t in trades:
should_send = True
# 如果提供了价格,进行条件检查
if price is not None:
if t.action.lower() == 'b':
# 买入指令:如果指令价格 > 当前价格,则缓存
if t.price > price:
should_send = False
cached_trades.append(t)
elif t.action.lower() == 's':
# 卖出指令:如果指令价格 < 当前价格,则缓存
if t.price < price:
should_send = False
cached_trades.append(t)
if should_send:
result.append({
"symbol": t.symbol.lower(),
"action": t.action.lower(),
"mount": t.mount,
"price": t.price,
"sl": t.sl,
"tp": t.tp
})
# 更新指令队列:移除已发送的,保留已缓存的
self.trade_instructions[symbol] = cached_trades
result = [{
"symbol": t.symbol,
"action": t.action.lower(),
"mount": t.mount,
"price": t.price,
"sl": t.sl,
"tp": t.tp
} for t in trades]
# 清空指令队列
self.trade_instructions[symbol] = []
if len(result) > 0:
print(f"[信息] 推送了 {len(result)}{symbol} 指令给EA (当前价格: {price})")
if len(cached_trades) > 0:
print(f"[信息] 缓存了 {len(cached_trades)}{symbol} 指令,等待价格条件满足")
return result
print(f"[信息] 推送了 {len(result)}{symbol} 指令给EA")
return {"trades": result, "pivot_alerts": pivot_alerts}
def save_statistics(self, stat_data: dict) -> None:
"""
@@ -157,7 +191,7 @@ class TradingServer:
for symbol, trades in self.trade_instructions.items():
result[symbol] = [
{
"symbol": t.symbol.lower(),
"symbol": t.symbol,
"action": t.action.lower(),
"mount": t.mount,
"price": t.price,
@@ -187,3 +221,24 @@ class TradingServer:
del self.trade_instructions[symbol]
print(f"[信息] 已清空 {symbol} 的交易指令,共 {count}")
return count
def add_close_position_instruction(self, symbol: str, ticket: int) -> None:
"""
添加平仓指令
"""
with self.lock:
symbol = symbol.upper()
self.close_position_instructions[symbol].append(ticket)
print(f"[信息] 添加平仓指令: {symbol} ticket={ticket}")
def get_close_position_instructions(self, symbol: str) -> List[int]:
"""
获取并清空平仓指令
"""
with self.lock:
symbol = symbol.upper()
tickets = self.close_position_instructions.get(symbol, [])
self.close_position_instructions[symbol] = []
if tickets:
print(f"[信息] 返回平仓指令: {symbol} tickets={tickets}")
return tickets