2026-03-04 22:56:14 +08:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
"""
|
|
|
|
|
|
交易服务核心类
|
2026-03-19 09:47:41 +08:00
|
|
|
|
内部聚合信号层,对外暴露策略层
|
2026-03-04 22:56:14 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from collections import deque, defaultdict
|
2026-03-19 09:47:41 +08:00
|
|
|
|
from typing import List, Dict, Optional, Set
|
|
|
|
|
|
from datetime import datetime
|
2026-03-04 22:56:14 +08:00
|
|
|
|
import threading
|
2026-03-19 09:47:41 +08:00
|
|
|
|
import asyncio
|
|
|
|
|
|
import json
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
from models import TradeInstruction
|
2026-03-19 09:47:41 +08:00
|
|
|
|
from market.models import KlineData, PivotPoint, LLMConfig, LLMAnalysisResult
|
|
|
|
|
|
from market.models import TechTrendState, TechResonanceResult, TechTradeSuggestion
|
|
|
|
|
|
from market.models import PendingOrder, TradingInstruction, TradingSignal, TradingDecision
|
|
|
|
|
|
from market.models import StatisticsData, PositionData, TradeDeal
|
|
|
|
|
|
from market.store import KlineStore, PivotStore, LLMStore, TechStore
|
|
|
|
|
|
from market.store import PendingOrderStore, TradingInstructionStore, SignalStore, StrategyStore
|
|
|
|
|
|
from market.store import StatisticsStore, PositionStore, TradeHistoryStore
|
|
|
|
|
|
from market.services import KlineService, PivotService, LLMService, TechService
|
|
|
|
|
|
from market.services import PendingOrderService, TradingInstructionService
|
|
|
|
|
|
from market.services import SignalService, StrategyService, RiskManager
|
|
|
|
|
|
from market.services import PivotSignalGenerator, KeyLevelSignalGenerator, AIEntrySignalGenerator
|
|
|
|
|
|
from market.services import StatisticsService, PositionService, TradeHistoryService
|
|
|
|
|
|
from market.trade_config import TradeConfig
|
2026-03-17 11:32:37 +08:00
|
|
|
|
from market.llm_analyzer import LLMAnalyzer
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TradingServer:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""
|
|
|
|
|
|
交易服务主类
|
|
|
|
|
|
|
|
|
|
|
|
架构:
|
|
|
|
|
|
- 内部:行情模块 → 信号层 → 策略层 → 订单/指令
|
|
|
|
|
|
- 对外:只暴露策略服务接口
|
|
|
|
|
|
"""
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-04 22:56:14 +08:00
|
|
|
|
def __init__(self):
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 线程锁
|
|
|
|
|
|
self.lock = threading.RLock()
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 行情模块(内部) ====================
|
|
|
|
|
|
# 存储层
|
|
|
|
|
|
self.kline_store = KlineStore()
|
|
|
|
|
|
self.pivot_store = PivotStore()
|
|
|
|
|
|
self.llm_store = LLMStore()
|
|
|
|
|
|
self.tech_store = TechStore()
|
|
|
|
|
|
|
|
|
|
|
|
# 服务层
|
|
|
|
|
|
self.kline_service = KlineService(self.kline_store)
|
|
|
|
|
|
self.pivot_service = PivotService(self.pivot_store, self.kline_store)
|
|
|
|
|
|
self.llm_service = LLMService(self.llm_store, self.kline_service)
|
|
|
|
|
|
self.tech_service = TechService(self.tech_store, self.kline_store, self.pivot_store)
|
|
|
|
|
|
|
|
|
|
|
|
# LLM 分析器
|
|
|
|
|
|
self.llm_analyzer = LLMAnalyzer(self.llm_service)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 统计/持仓/交易历史模块 ====================
|
|
|
|
|
|
# 存储层
|
|
|
|
|
|
self.statistics_store = StatisticsStore()
|
|
|
|
|
|
self.position_store = PositionStore()
|
|
|
|
|
|
self.trade_history_store = TradeHistoryStore()
|
|
|
|
|
|
|
|
|
|
|
|
# 服务层
|
|
|
|
|
|
self.statistics_service = StatisticsService(self.statistics_store)
|
|
|
|
|
|
self.position_service = PositionService(self.position_store)
|
|
|
|
|
|
self.trade_history_service = TradeHistoryService(self.trade_history_store)
|
|
|
|
|
|
|
|
|
|
|
|
# TechService 使用统计服务获取价差
|
|
|
|
|
|
self.tech_service.set_statistics_service(self.statistics_service)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 信号层(内部,不暴露) ====================
|
|
|
|
|
|
# 存储层
|
|
|
|
|
|
self._signal_store = SignalStore()
|
|
|
|
|
|
|
|
|
|
|
|
# 服务层
|
|
|
|
|
|
self._signal_service = SignalService(self._signal_store)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 策略层(对外暴露) ====================
|
|
|
|
|
|
# 存储层
|
|
|
|
|
|
self._strategy_store = StrategyStore()
|
|
|
|
|
|
|
|
|
|
|
|
# 风险管理器
|
|
|
|
|
|
self._risk_manager = RiskManager()
|
|
|
|
|
|
|
|
|
|
|
|
# 服务层
|
|
|
|
|
|
self.strategy_service = StrategyService(
|
|
|
|
|
|
self._strategy_store,
|
|
|
|
|
|
self._signal_service,
|
|
|
|
|
|
self._risk_manager
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 交易配置 ====================
|
|
|
|
|
|
self.trade_config = TradeConfig.get_instance()
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 注册信号生成器
|
|
|
|
|
|
self._setup_signal_generators()
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# ==================== 订单/指令模块 ====================
|
|
|
|
|
|
# 存储层
|
|
|
|
|
|
self.pending_order_store = PendingOrderStore()
|
|
|
|
|
|
self.trading_instruction_store = TradingInstructionStore()
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 服务层
|
|
|
|
|
|
self.pending_order_service = PendingOrderService(self.pending_order_store)
|
|
|
|
|
|
self.trading_instruction_service = TradingInstructionService(self.trading_instruction_store)
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
|
|
|
|
|
# 设置订单确认回调
|
2026-03-19 09:47:41 +08:00
|
|
|
|
self.pending_order_service.set_confirm_callback(self._on_order_confirmed)
|
|
|
|
|
|
|
|
|
|
|
|
# 更新策略服务的订单服务引用
|
|
|
|
|
|
self.strategy_service.set_pending_order_service(self.pending_order_service)
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 策略服务使用持仓服务进行风险管理
|
|
|
|
|
|
self.strategy_service.set_position_service(self.position_service)
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 风险管理器使用统计服务获取账户信息
|
|
|
|
|
|
self._risk_manager.set_statistics_service(self.statistics_service)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== WebSocket 广播 ====================
|
|
|
|
|
|
self._ws_clients: Set = set()
|
|
|
|
|
|
self._ws_lock = threading.Lock()
|
|
|
|
|
|
self._main_loop = None
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 决策历史 ====================
|
|
|
|
|
|
self._decision_history: deque = deque(maxlen=50)
|
|
|
|
|
|
|
|
|
|
|
|
# 兼容旧代码的别名
|
|
|
|
|
|
self.market_store = self.kline_store
|
|
|
|
|
|
self.pivot_detector = self.pivot_service
|
|
|
|
|
|
self.trend_analyzer = self.tech_service
|
|
|
|
|
|
self.pending_orders = self.pending_order_service
|
|
|
|
|
|
self.trade_instructions = defaultdict(list)
|
|
|
|
|
|
# 统计数据历史兼容(已迁移到 statistics_store)
|
|
|
|
|
|
self.statistics_history = self.statistics_store._all_data
|
|
|
|
|
|
|
|
|
|
|
|
print("[TradingServer] 交易服务已初始化")
|
|
|
|
|
|
|
|
|
|
|
|
def _setup_signal_generators(self):
|
|
|
|
|
|
"""设置信号生成器"""
|
|
|
|
|
|
# 转折点信号生成器
|
|
|
|
|
|
pivot_generator = PivotSignalGenerator(
|
|
|
|
|
|
pivot_service=self.pivot_service,
|
|
|
|
|
|
pivot_store=self.pivot_store,
|
|
|
|
|
|
kline_store=self.kline_store
|
|
|
|
|
|
)
|
|
|
|
|
|
self._signal_service.register_generator("pivot", pivot_generator)
|
|
|
|
|
|
|
|
|
|
|
|
# 关键点位信号生成器
|
|
|
|
|
|
key_level_generator = KeyLevelSignalGenerator()
|
|
|
|
|
|
self._signal_service.register_generator("key_level", key_level_generator)
|
|
|
|
|
|
|
|
|
|
|
|
# AI入场信号生成器
|
|
|
|
|
|
ai_entry_generator = AIEntrySignalGenerator()
|
|
|
|
|
|
ai_entry_generator.set_llm_analyzer(self.llm_analyzer)
|
|
|
|
|
|
self._signal_service.register_generator("ai_entry", ai_entry_generator)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== WebSocket 管理 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def set_event_loop(self, loop):
|
|
|
|
|
|
"""设置主事件循环引用"""
|
|
|
|
|
|
self._main_loop = loop
|
|
|
|
|
|
print("[TradingServer] 已设置主事件循环")
|
|
|
|
|
|
|
|
|
|
|
|
# 同时设置内部模块的事件循环
|
|
|
|
|
|
self.llm_analyzer.set_event_loop(loop)
|
|
|
|
|
|
|
|
|
|
|
|
def add_ws_client(self, client):
|
|
|
|
|
|
"""添加WebSocket客户端"""
|
|
|
|
|
|
with self._ws_lock:
|
|
|
|
|
|
self._ws_clients.add(client)
|
|
|
|
|
|
# 同时注册到内部模块
|
|
|
|
|
|
self.llm_analyzer.add_ws_client(client)
|
|
|
|
|
|
print(f"[TradingServer] WebSocket客户端已连接, 当前连接数: {len(self._ws_clients)}")
|
|
|
|
|
|
|
|
|
|
|
|
def remove_ws_client(self, client):
|
|
|
|
|
|
"""移除WebSocket客户端"""
|
|
|
|
|
|
with self._ws_lock:
|
|
|
|
|
|
self._ws_clients.discard(client)
|
|
|
|
|
|
# 同时从内部模块移除
|
|
|
|
|
|
self.llm_analyzer.remove_ws_client(client)
|
|
|
|
|
|
print(f"[TradingServer] WebSocket客户端已断开, 当前连接数: {len(self._ws_clients)}")
|
|
|
|
|
|
|
|
|
|
|
|
def get_ws_client_count(self) -> int:
|
|
|
|
|
|
"""获取WebSocket客户端数量"""
|
|
|
|
|
|
with self._ws_lock:
|
|
|
|
|
|
return len(self._ws_clients)
|
|
|
|
|
|
|
|
|
|
|
|
def _broadcast(self, data: Dict):
|
|
|
|
|
|
"""广播数据到所有WebSocket客户端"""
|
|
|
|
|
|
message = json.dumps(data, ensure_ascii=False)
|
|
|
|
|
|
|
|
|
|
|
|
with self._ws_lock:
|
|
|
|
|
|
clients = list(self._ws_clients)
|
|
|
|
|
|
|
|
|
|
|
|
if not clients:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if self._main_loop and self._main_loop.is_running():
|
|
|
|
|
|
for client in clients:
|
|
|
|
|
|
try:
|
|
|
|
|
|
asyncio.run_coroutine_threadsafe(
|
|
|
|
|
|
self._send_to_client(client, message),
|
|
|
|
|
|
self._main_loop
|
|
|
|
|
|
)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"[TradingServer] 发送WebSocket消息失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
async def _send_to_client(self, client, message: str):
|
|
|
|
|
|
"""发送消息到客户端"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
await client.send_text(message)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"[TradingServer] 发送消息到客户端失败: {e}")
|
|
|
|
|
|
with self._ws_lock:
|
|
|
|
|
|
self._ws_clients.discard(client)
|
|
|
|
|
|
|
|
|
|
|
|
def _broadcast_decision(self, decision: TradingDecision):
|
|
|
|
|
|
"""广播交易决策"""
|
|
|
|
|
|
self._broadcast({
|
|
|
|
|
|
"type": "trading_decision",
|
|
|
|
|
|
"data": decision.to_dict()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
def _broadcast_pending_order(self, order: PendingOrder):
|
|
|
|
|
|
"""广播待确认订单"""
|
|
|
|
|
|
self._broadcast({
|
|
|
|
|
|
"type": "pending_order",
|
|
|
|
|
|
"data": order.to_dict()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 价格处理与决策 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def process_price(self, symbol: str, current_price: float) -> Dict:
|
2026-03-10 17:38:13 +08:00
|
|
|
|
"""
|
2026-03-19 09:47:41 +08:00
|
|
|
|
处理价格变动,生成决策
|
|
|
|
|
|
|
|
|
|
|
|
这是核心入口:
|
|
|
|
|
|
1. 信号层生成信号
|
|
|
|
|
|
2. 策略层综合决策
|
|
|
|
|
|
3. 自动执行决策(生成PendingOrder)
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
symbol: 品种
|
|
|
|
|
|
current_price: 当前价格
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
处理结果
|
2026-03-10 17:38:13 +08:00
|
|
|
|
"""
|
2026-03-19 09:47:41 +08:00
|
|
|
|
result = {
|
|
|
|
|
|
"signals_generated": 0,
|
|
|
|
|
|
"decision": None,
|
|
|
|
|
|
"pending_order": None
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if not self.trade_config.enabled:
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 信号层生成信号
|
|
|
|
|
|
signals = self._signal_service.generate_signals(symbol, current_price)
|
|
|
|
|
|
result["signals_generated"] = len(signals)
|
|
|
|
|
|
|
|
|
|
|
|
if signals:
|
|
|
|
|
|
print(f"[TradingServer] {symbol} 生成了 {len(signals)} 个信号")
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 策略层做决策
|
|
|
|
|
|
decision = self.strategy_service.make_decision(symbol, current_price)
|
|
|
|
|
|
|
|
|
|
|
|
if decision:
|
|
|
|
|
|
# 记录决策历史
|
|
|
|
|
|
self._decision_history.append(decision)
|
|
|
|
|
|
|
|
|
|
|
|
result["decision"] = decision.to_dict()
|
|
|
|
|
|
|
|
|
|
|
|
# 广播决策
|
|
|
|
|
|
self._broadcast_decision(decision)
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 自动执行决策(如果允许)
|
|
|
|
|
|
if decision.action != "none" and decision.status != "rejected":
|
|
|
|
|
|
order_id = self.strategy_service.execute_decision(decision)
|
|
|
|
|
|
if order_id:
|
|
|
|
|
|
result["pending_order"] = {
|
|
|
|
|
|
"order_id": order_id,
|
|
|
|
|
|
"symbol": decision.symbol,
|
|
|
|
|
|
"action": decision.action,
|
|
|
|
|
|
"price": decision.entry_price,
|
|
|
|
|
|
"volume": decision.volume,
|
|
|
|
|
|
"sl": decision.sl,
|
|
|
|
|
|
"tp": decision.tp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 订单确认回调 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def _on_order_confirmed(self, order: PendingOrder):
|
|
|
|
|
|
"""订单确认回调"""
|
|
|
|
|
|
print(f"[TradingServer] 订单确认: {order.order_id}")
|
|
|
|
|
|
|
|
|
|
|
|
# 广播订单确认
|
|
|
|
|
|
self._broadcast_pending_order(order)
|
|
|
|
|
|
|
2026-03-10 17:38:13 +08:00
|
|
|
|
try:
|
|
|
|
|
|
# 创建交易指令
|
2026-03-19 09:47:41 +08:00
|
|
|
|
instruction_id = self.trading_instruction_service.create_from_pending_order(order)
|
|
|
|
|
|
print(f"[TradingServer] 交易指令已创建: {instruction_id}")
|
2026-03-10 17:38:13 +08:00
|
|
|
|
except Exception as e:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
print(f"[TradingServer] 创建交易指令失败: {e}")
|
2026-03-10 17:38:13 +08:00
|
|
|
|
import traceback
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# ==================== EA 接口 ====================
|
2026-03-04 23:14:41 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
def get_trades_by_symbol(self, symbol: str, price: Optional[float] = None) -> Dict:
|
|
|
|
|
|
"""
|
|
|
|
|
|
EA获取交易数据
|
2026-03-04 23:14:41 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
返回:
|
|
|
|
|
|
- trades: 待执行的交易指令
|
|
|
|
|
|
- pending_orders: 待确认的订单
|
|
|
|
|
|
- close_tickets: 平仓指令
|
2026-03-04 22:56:14 +08:00
|
|
|
|
"""
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 处理价格(生成信号和决策)
|
|
|
|
|
|
process_result = {}
|
|
|
|
|
|
if price is not None:
|
|
|
|
|
|
process_result = self.process_price(symbol, price)
|
2026-03-04 23:14:41 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 获取交易指令
|
|
|
|
|
|
trades = self.trading_instruction_service.fetch_instructions_for_ea(symbol, price)
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 获取待确认订单
|
|
|
|
|
|
pending_orders = self.pending_order_service.get_pending_orders_dict(symbol)
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# 获取平仓指令
|
|
|
|
|
|
close_tickets = self.get_close_position_instructions(symbol)
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
return {
|
|
|
|
|
|
"trades": trades,
|
|
|
|
|
|
"pending_orders": pending_orders,
|
|
|
|
|
|
"close_tickets": close_tickets,
|
|
|
|
|
|
"process_result": process_result
|
|
|
|
|
|
}
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
2026-03-19 09:47:41 +08:00
|
|
|
|
# ==================== 交易员接口 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def add_trade_instruction(self, instructions: List[TradeInstruction]) -> dict:
|
|
|
|
|
|
"""添加交易指令(交易员手动下单)"""
|
|
|
|
|
|
added = 0
|
|
|
|
|
|
rejected = 0
|
|
|
|
|
|
|
|
|
|
|
|
for instruction in instructions:
|
|
|
|
|
|
sl = instruction.sl if instruction.sl is not None else 0.0
|
|
|
|
|
|
tp = instruction.tp if instruction.tp is not None and instruction.tp > 0 else 0.005
|
|
|
|
|
|
|
|
|
|
|
|
# 验证止损止盈
|
|
|
|
|
|
if sl > 0 and tp > 0:
|
|
|
|
|
|
if instruction.action.lower() == 'b':
|
|
|
|
|
|
if not (instruction.price > sl and instruction.price < tp):
|
|
|
|
|
|
print(f"[警告] 忽略无效买入指令: {instruction}")
|
|
|
|
|
|
rejected += 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
elif instruction.action.lower() == 's':
|
|
|
|
|
|
if not (instruction.price < sl and instruction.price > tp):
|
|
|
|
|
|
print(f"[警告] 忽略无效卖出指令: {instruction}")
|
|
|
|
|
|
rejected += 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
self.trading_instruction_service.create_instruction(
|
|
|
|
|
|
symbol=instruction.symbol,
|
|
|
|
|
|
action=instruction.action,
|
|
|
|
|
|
price=instruction.price,
|
|
|
|
|
|
mount=instruction.mount,
|
|
|
|
|
|
sl=sl,
|
|
|
|
|
|
tp=tp,
|
|
|
|
|
|
description=instruction.description or "",
|
|
|
|
|
|
source="manual"
|
|
|
|
|
|
)
|
|
|
|
|
|
added += 1
|
|
|
|
|
|
|
|
|
|
|
|
print(f"[TradingServer] 已添加 {added} 条交易指令, 拒绝 {rejected} 条")
|
|
|
|
|
|
return {"added": added, "rejected": rejected}
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 统计数据 ====================
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
def save_statistics(self, stat_data: dict) -> None:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""保存统计数据"""
|
|
|
|
|
|
self.statistics_service.process_statistics(stat_data)
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
def get_latest_statistics(self, count: int = 10) -> List[Dict]:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""获取最新的统计数据"""
|
|
|
|
|
|
stats = self.statistics_store.get_all_recent(count)
|
|
|
|
|
|
return [s.to_dict() for s in stats]
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 指令管理 ====================
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
def get_all_pending_trades(self) -> Dict[str, List[Dict]]:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""获取所有待执行的交易指令"""
|
|
|
|
|
|
return self.trading_instruction_service.get_all_instructions_dict()
|
2026-03-04 22:56:14 +08:00
|
|
|
|
|
|
|
|
|
|
def clear_trades(self, symbol: Optional[str] = None) -> int:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""清空交易指令"""
|
|
|
|
|
|
if symbol is None:
|
|
|
|
|
|
count = self.trading_instruction_service.get_total_count()
|
|
|
|
|
|
self.trading_instruction_service.clear_all()
|
|
|
|
|
|
print(f"[TradingServer] 已清空所有交易指令,共 {count} 条")
|
|
|
|
|
|
return count
|
|
|
|
|
|
else:
|
|
|
|
|
|
return self.trading_instruction_service.clear_by_symbol(symbol)
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
|
|
|
|
|
def add_close_position_instruction(self, symbol: str, ticket: int) -> None:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""添加平仓指令"""
|
2026-03-10 17:38:13 +08:00
|
|
|
|
with self.lock:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
if not hasattr(self, '_close_position_instructions'):
|
|
|
|
|
|
self._close_position_instructions = defaultdict(list)
|
|
|
|
|
|
self._close_position_instructions[symbol].append(ticket)
|
|
|
|
|
|
print(f"[TradingServer] 添加平仓指令: {symbol} ticket={ticket}")
|
2026-03-10 17:38:13 +08:00
|
|
|
|
|
|
|
|
|
|
def get_close_position_instructions(self, symbol: str) -> List[int]:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
"""获取并清空平仓指令"""
|
2026-03-10 17:38:13 +08:00
|
|
|
|
with self.lock:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
if not hasattr(self, '_close_position_instructions'):
|
|
|
|
|
|
return []
|
|
|
|
|
|
tickets = self._close_position_instructions.get(symbol, [])
|
|
|
|
|
|
self._close_position_instructions[symbol] = []
|
2026-03-10 17:38:13 +08:00
|
|
|
|
if tickets:
|
2026-03-19 09:47:41 +08:00
|
|
|
|
print(f"[TradingServer] 返回平仓指令: {symbol} tickets={tickets}")
|
2026-03-10 17:38:13 +08:00
|
|
|
|
return tickets
|
2026-03-19 09:47:41 +08:00
|
|
|
|
|
|
|
|
|
|
# ==================== 决策历史 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def get_decision_history(self, symbol: str = None, count: int = 20) -> List[Dict]:
|
|
|
|
|
|
"""获取决策历史"""
|
|
|
|
|
|
decisions = list(self._decision_history)
|
|
|
|
|
|
if symbol:
|
|
|
|
|
|
decisions = [d for d in decisions if d.symbol == symbol]
|
|
|
|
|
|
return [d.to_dict() for d in decisions[-count:]]
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== LLM 分析接口(内部封装) ====================
|
|
|
|
|
|
|
|
|
|
|
|
def get_llm_analysis(self, symbol: str = None) -> Dict:
|
|
|
|
|
|
"""获取大模型分析结果"""
|
|
|
|
|
|
return self.llm_analyzer.get_analysis(symbol)
|
|
|
|
|
|
|
|
|
|
|
|
def get_llm_status(self) -> Dict:
|
|
|
|
|
|
"""获取大模型分析器状态"""
|
|
|
|
|
|
status = self.llm_analyzer.get_status()
|
|
|
|
|
|
status["interval_seconds"] = self.llm_analyzer.ANALYZE_INTERVAL
|
|
|
|
|
|
return status
|
|
|
|
|
|
|
|
|
|
|
|
def get_llm_config(self) -> Dict:
|
|
|
|
|
|
"""获取大模型配置"""
|
|
|
|
|
|
return self.llm_analyzer.get_config()
|
|
|
|
|
|
|
|
|
|
|
|
def trigger_llm_analysis(self) -> Dict:
|
|
|
|
|
|
"""手动触发大模型分析"""
|
|
|
|
|
|
return self.llm_analyzer.trigger_analysis()
|
|
|
|
|
|
|
|
|
|
|
|
def configure_llm(self, api_key: str = None, api_base: str = None, model: str = None) -> Dict:
|
|
|
|
|
|
"""配置大模型参数"""
|
|
|
|
|
|
return self.llm_analyzer.configure(api_key, api_base, model)
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 状态查询 ====================
|
|
|
|
|
|
|
|
|
|
|
|
def get_status(self) -> Dict:
|
|
|
|
|
|
"""获取服务状态"""
|
|
|
|
|
|
return {
|
|
|
|
|
|
"ws_clients": self.get_ws_client_count(),
|
|
|
|
|
|
"statistics": self.statistics_service.get_status(),
|
|
|
|
|
|
"positions": self.position_service.get_status(),
|
|
|
|
|
|
"trade_history": self.trade_history_service.get_status(),
|
|
|
|
|
|
"pending_orders": self.pending_order_service.get_status(),
|
|
|
|
|
|
"trading_instructions": self.trading_instruction_service.get_status(),
|
|
|
|
|
|
"strategy_service": self.strategy_service.get_status(),
|
|
|
|
|
|
}
|