Refactor: restructure market module with services, stores, and utils
This commit is contained in:
@@ -2,256 +2,476 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
交易服务核心类
|
||||
内部聚合信号层,对外暴露策略层
|
||||
"""
|
||||
|
||||
from collections import deque, defaultdict
|
||||
from typing import List, Dict, Optional
|
||||
from typing import List, Dict, Optional, Set
|
||||
from datetime import datetime
|
||||
import threading
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from models import TradeInstruction
|
||||
from market.store import MarketStore
|
||||
from market.pivot_detector import PivotDetector
|
||||
from market.monitor import PivotMonitor, TradeConfig
|
||||
from market.trend_analyzer import TrendAnalyzer
|
||||
from market.pending_orders import PendingOrderManager
|
||||
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
|
||||
from market.llm_analyzer import LLMAnalyzer
|
||||
|
||||
|
||||
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)
|
||||
# 大模型分析器(需要在 PivotMonitor 之前初始化)
|
||||
self.llm_analyzer = LLMAnalyzer(self.market_store)
|
||||
# 转折点监控器
|
||||
self.pivot_monitor = PivotMonitor(self.market_store, self.pivot_detector, self.pending_orders, self.llm_analyzer)
|
||||
# 设置统计数据历史引用(用于获取价差)
|
||||
self.pivot_monitor.set_statistics_history(self.statistics_history)
|
||||
# 趋势分析器
|
||||
self.trend_analyzer = TrendAnalyzer()
|
||||
self.trend_analyzer.set_statistics_history(self.statistics_history)
|
||||
# 交易配置
|
||||
# ==================== 行情模块(内部) ====================
|
||||
# 存储层
|
||||
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()
|
||||
|
||||
print("[信息] 交易服务已初始化")
|
||||
# 注册信号生成器
|
||||
self._setup_signal_generators()
|
||||
|
||||
def _on_order_confirmed(self, order: Dict):
|
||||
# ==================== 订单/指令模块 ====================
|
||||
# 存储层
|
||||
self.pending_order_store = PendingOrderStore()
|
||||
self.trading_instruction_store = TradingInstructionStore()
|
||||
|
||||
# 服务层
|
||||
self.pending_order_service = PendingOrderService(self.pending_order_store)
|
||||
self.trading_instruction_service = TradingInstructionService(self.trading_instruction_store)
|
||||
|
||||
# 设置订单确认回调
|
||||
self.pending_order_service.set_confirm_callback(self._on_order_confirmed)
|
||||
|
||||
# 更新策略服务的订单服务引用
|
||||
self.strategy_service.set_pending_order_service(self.pending_order_service)
|
||||
|
||||
# 策略服务使用持仓服务进行风险管理
|
||||
self.strategy_service.set_position_service(self.position_service)
|
||||
|
||||
# 风险管理器使用统计服务获取账户信息
|
||||
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:
|
||||
"""
|
||||
订单确认回调 - 将确认的订单加入交易队列
|
||||
处理价格变动,生成决策
|
||||
|
||||
这是核心入口:
|
||||
1. 信号层生成信号
|
||||
2. 策略层综合决策
|
||||
3. 自动执行决策(生成PendingOrder)
|
||||
|
||||
Args:
|
||||
symbol: 品种
|
||||
current_price: 当前价格
|
||||
|
||||
Returns:
|
||||
处理结果
|
||||
"""
|
||||
print(f"[TradingServer] _on_order_confirmed 被调用,订单: {order}")
|
||||
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)
|
||||
|
||||
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),
|
||||
description=order.get('description', '')
|
||||
)
|
||||
print(f"[TradingServer] 创建交易指令: symbol={instruction.symbol}, action={instruction.action}, mount={instruction.mount}, price={instruction.price}, sl={instruction.sl}, tp={instruction.tp}, description={instruction.description}")
|
||||
# 添加到交易队列
|
||||
result = self.add_trade_instruction([instruction])
|
||||
print(f"[TradingServer] 订单已加入交易队列: {result}")
|
||||
instruction_id = self.trading_instruction_service.create_from_pending_order(order)
|
||||
print(f"[TradingServer] 交易指令已创建: {instruction_id}")
|
||||
except Exception as e:
|
||||
print(f"[TradingServer] 加入交易队列失败: {e}")
|
||||
print(f"[TradingServer] 创建交易指令失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def add_trade_instruction(self, instructions: List[TradeInstruction]) -> dict:
|
||||
"""
|
||||
添加交易指令
|
||||
返回一个字典,包含添加和拒绝的数量。
|
||||
|
||||
在此处对缺失的 sl/tp 值进行补全:
|
||||
- sl 若未设置保持0.0
|
||||
- tp 若未设置则默认 0.005
|
||||
|
||||
同时按照规则进行价格检查:
|
||||
* 买入指令: price 需大于 sl 且小于 tp
|
||||
* 卖出指令: price 需小于 sl 且大于 tp
|
||||
若 sl 或 tp 未设置(<=0),则忽略检查。
|
||||
"""
|
||||
with self.lock:
|
||||
added = 0
|
||||
rejected = 0
|
||||
for instruction in instructions:
|
||||
# 填充默认值
|
||||
if instruction.sl is None:
|
||||
instruction.sl = 0.0
|
||||
if instruction.tp is None or instruction.tp <= 0.0:
|
||||
instruction.tp = 0.005
|
||||
|
||||
# 验证价格与 SL/TP 关系
|
||||
if instruction.sl > 0 and instruction.tp > 0:
|
||||
if instruction.action.lower() == 'b':
|
||||
if not (instruction.price > instruction.sl and instruction.price < instruction.tp):
|
||||
print(f"[警告] 忽略无效买入指令: {instruction}")
|
||||
rejected += 1
|
||||
continue
|
||||
elif instruction.action.lower() == 's':
|
||||
if not (instruction.price < instruction.sl and instruction.price > instruction.tp):
|
||||
print(f"[警告] 忽略无效卖出指令: {instruction}")
|
||||
rejected += 1
|
||||
continue
|
||||
|
||||
# 直接使用原始symbol,不做转换
|
||||
symbol = instruction.symbol
|
||||
self.trade_instructions[symbol].append(instruction)
|
||||
added += 1
|
||||
|
||||
print(f"[信息] 已添加 {added} 条交易指令, 拒绝 {rejected} 条")
|
||||
for symbol, trades in self.trade_instructions.items():
|
||||
print(f" {symbol}: {len(trades)} 条待执行")
|
||||
|
||||
return {"added": added, "rejected": rejected}
|
||||
|
||||
# ==================== EA 接口 ====================
|
||||
|
||||
def get_trades_by_symbol(self, symbol: str, price: Optional[float] = None) -> Dict:
|
||||
"""
|
||||
获取指定SYMBOL的交易指令并删除
|
||||
EA获取交易数据
|
||||
|
||||
同时调用策略检查(在 PivotMonitor 中执行)
|
||||
|
||||
返回: {"trades": [...], "pivot_alerts": [...]}
|
||||
返回:
|
||||
- trades: 待执行的交易指令
|
||||
- pending_orders: 待确认的订单
|
||||
- close_tickets: 平仓指令
|
||||
"""
|
||||
# 检查所有策略(关键点位、支撑压力、AI趋势)
|
||||
pivot_alerts = []
|
||||
# 处理价格(生成信号和决策)
|
||||
process_result = {}
|
||||
if price is not None:
|
||||
pivot_alerts = self.pivot_monitor.check_and_alert(symbol, price)
|
||||
if pivot_alerts:
|
||||
print(f"[信息] {symbol} 当前价格 {price} 接近转折点")
|
||||
process_result = self.process_price(symbol, price)
|
||||
|
||||
with self.lock:
|
||||
# 调试:打印当前所有待执行指令
|
||||
if len(self.trade_instructions) > 0:
|
||||
print(f"[调试] get_trades_by_symbol 查询symbol={symbol}")
|
||||
print(f"[调试] 当前trade_instructions keys: {list(self.trade_instructions.keys())}")
|
||||
for k, v in self.trade_instructions.items():
|
||||
print(f"[调试] {k}: {len(v)} 条")
|
||||
# 获取交易指令
|
||||
trades = self.trading_instruction_service.fetch_instructions_for_ea(symbol, price)
|
||||
|
||||
if symbol not in self.trade_instructions or len(self.trade_instructions[symbol]) == 0:
|
||||
return {"trades": [], "pivot_alerts": pivot_alerts}
|
||||
# 获取待确认订单
|
||||
pending_orders = self.pending_order_service.get_pending_orders_dict(symbol)
|
||||
|
||||
# 获取所有指令并直接返回
|
||||
trades = self.trade_instructions[symbol]
|
||||
result = [{
|
||||
"symbol": t.symbol,
|
||||
"action": t.action.lower(),
|
||||
"mount": t.mount,
|
||||
"price": t.price,
|
||||
"sl": t.sl,
|
||||
"tp": t.tp,
|
||||
"description": t.description or ""
|
||||
} for t in trades]
|
||||
# 获取平仓指令
|
||||
close_tickets = self.get_close_position_instructions(symbol)
|
||||
|
||||
# 清空指令队列
|
||||
self.trade_instructions[symbol] = []
|
||||
return {
|
||||
"trades": trades,
|
||||
"pending_orders": pending_orders,
|
||||
"close_tickets": close_tickets,
|
||||
"process_result": process_result
|
||||
}
|
||||
|
||||
if len(result) > 0:
|
||||
print(f"[信息] 推送了 {len(result)} 条 {symbol} 指令给EA")
|
||||
# ==================== 交易员接口 ====================
|
||||
|
||||
return {"trades": result, "pivot_alerts": pivot_alerts}
|
||||
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}
|
||||
|
||||
# ==================== 统计数据 ====================
|
||||
|
||||
def save_statistics(self, stat_data: dict) -> None:
|
||||
"""
|
||||
保存统计数据
|
||||
自动保留最新10条
|
||||
"""
|
||||
with self.lock:
|
||||
self.statistics_history.append(stat_data)
|
||||
print(f"[信息] 统计数据已记录 - {stat_data.get('timestamp', 'unknown')}")
|
||||
print(f" 当前保存数据条数: {len(self.statistics_history)}")
|
||||
"""保存统计数据"""
|
||||
self.statistics_service.process_statistics(stat_data)
|
||||
|
||||
def get_latest_statistics(self, count: int = 10) -> List[Dict]:
|
||||
"""
|
||||
获取最新的统计数据
|
||||
"""
|
||||
with self.lock:
|
||||
return list(self.statistics_history)[-count:]
|
||||
"""获取最新的统计数据"""
|
||||
stats = self.statistics_store.get_all_recent(count)
|
||||
return [s.to_dict() for s in stats]
|
||||
|
||||
# ==================== 指令管理 ====================
|
||||
|
||||
def get_all_pending_trades(self) -> Dict[str, List[Dict]]:
|
||||
"""
|
||||
获取所有待执行的交易指令(不删除)
|
||||
用于查询接口
|
||||
"""
|
||||
with self.lock:
|
||||
result = {}
|
||||
for symbol, trades in self.trade_instructions.items():
|
||||
result[symbol] = [
|
||||
{
|
||||
"symbol": t.symbol,
|
||||
"action": t.action.lower(),
|
||||
"mount": t.mount,
|
||||
"price": t.price,
|
||||
"sl": t.sl,
|
||||
"tp": t.tp,
|
||||
"description": t.description or ""
|
||||
}
|
||||
for t in trades
|
||||
]
|
||||
return result
|
||||
"""获取所有待执行的交易指令"""
|
||||
return self.trading_instruction_service.get_all_instructions_dict()
|
||||
|
||||
def clear_trades(self, symbol: Optional[str] = None) -> int:
|
||||
"""
|
||||
清空交易指令
|
||||
如果指定symbol则只清空该symbol
|
||||
返回清空的指令数量
|
||||
"""
|
||||
with self.lock:
|
||||
if symbol is None:
|
||||
total = sum(len(trades) for trades in self.trade_instructions.values())
|
||||
self.trade_instructions.clear()
|
||||
print(f"[信息] 已清空所有交易指令,共 {total} 条")
|
||||
return total
|
||||
else:
|
||||
count = len(self.trade_instructions.get(symbol, []))
|
||||
if symbol in self.trade_instructions:
|
||||
del self.trade_instructions[symbol]
|
||||
print(f"[信息] 已清空 {symbol} 的交易指令,共 {count} 条")
|
||||
return count
|
||||
"""清空交易指令"""
|
||||
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)
|
||||
|
||||
def add_close_position_instruction(self, symbol: str, ticket: int) -> None:
|
||||
"""
|
||||
添加平仓指令
|
||||
"""
|
||||
"""添加平仓指令"""
|
||||
with self.lock:
|
||||
self.close_position_instructions[symbol].append(ticket)
|
||||
print(f"[信息] 添加平仓指令: {symbol} ticket={ticket}")
|
||||
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}")
|
||||
|
||||
def get_close_position_instructions(self, symbol: str) -> List[int]:
|
||||
"""
|
||||
获取并清空平仓指令
|
||||
"""
|
||||
"""获取并清空平仓指令"""
|
||||
with self.lock:
|
||||
tickets = self.close_position_instructions.get(symbol, [])
|
||||
self.close_position_instructions[symbol] = []
|
||||
if not hasattr(self, '_close_position_instructions'):
|
||||
return []
|
||||
tickets = self._close_position_instructions.get(symbol, [])
|
||||
self._close_position_instructions[symbol] = []
|
||||
if tickets:
|
||||
print(f"[信息] 返回平仓指令: {symbol} tickets={tickets}")
|
||||
print(f"[TradingServer] 返回平仓指令: {symbol} tickets={tickets}")
|
||||
return tickets
|
||||
|
||||
# ==================== 决策历史 ====================
|
||||
|
||||
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(),
|
||||
}
|
||||
Reference in New Issue
Block a user