diff --git a/orchestrator/backtest_mode.py b/orchestrator/backtest_mode.py index a0e2488e..604b81d2 100644 --- a/orchestrator/backtest_mode.py +++ b/orchestrator/backtest_mode.py @@ -1,9 +1,8 @@ import logging from dataclasses import dataclass, field from datetime import datetime, timedelta -from typing import List, Optional +from typing import List -from orchestrator.config import OrchestratorConfig from orchestrator.signals import FinalSignal logger = logging.getLogger(__name__) diff --git a/orchestrator/live_mode.py b/orchestrator/live_mode.py index b96b5e04..76c04c51 100644 --- a/orchestrator/live_mode.py +++ b/orchestrator/live_mode.py @@ -1,5 +1,4 @@ import asyncio -import json import logging from datetime import datetime, timezone from typing import List, Optional @@ -27,7 +26,9 @@ class LiveMode: results = [] for ticker in tickers: try: - sig = self._orchestrator.get_combined_signal(ticker, date) + sig = await asyncio.to_thread( + self._orchestrator.get_combined_signal, ticker, date + ) results.append({ "ticker": ticker, "date": date, diff --git a/orchestrator/signals.py b/orchestrator/signals.py index 1ccecaa3..0715409d 100644 --- a/orchestrator/signals.py +++ b/orchestrator/signals.py @@ -52,8 +52,6 @@ class SignalMerger: # 只有 LLM(quant 失败) if quant is None: - if llm is None: - raise ValueError("llm signal is None when quant is None") return FinalSignal( ticker=ticker, direction=llm.direction, diff --git a/web_dashboard/backend/main.py b/web_dashboard/backend/main.py index 229b2852..e27d2671 100644 --- a/web_dashboard/backend/main.py +++ b/web_dashboard/backend/main.py @@ -363,7 +363,7 @@ async def start_analysis(request: AnalysisRequest, api_key: Optional[str] = Head # Use clean environment - don't inherit parent env clean_env = {k: v for k, v in os.environ.items() if not k.startswith(("PYTHON", "CONDA", "VIRTUAL"))} - clean_env["ANTHROPIC_API_KEY"] = api_key + clean_env["ANTHROPIC_API_KEY"] = anthropic_key clean_env["ANTHROPIC_BASE_URL"] = "https://api.minimaxi.com/anthropic" proc = await asyncio.create_subprocess_exec( @@ -1103,6 +1103,18 @@ async def root(): @app.websocket("/ws/orchestrator") async def ws_orchestrator(websocket: WebSocket): """WebSocket endpoint for orchestrator live signals.""" + import sys + sys.path.insert(0, str(REPO_ROOT)) + from orchestrator.config import OrchestratorConfig + from orchestrator.orchestrator import TradingOrchestrator + from orchestrator.live_mode import LiveMode + + config = OrchestratorConfig( + quant_backtest_path=os.environ.get("QUANT_BACKTEST_PATH", ""), + ) + orchestrator = TradingOrchestrator(config) + live = LiveMode(orchestrator) + await websocket.accept() try: while True: @@ -1111,18 +1123,6 @@ async def ws_orchestrator(websocket: WebSocket): tickers = payload.get("tickers", []) date = payload.get("date") - # Lazy import to avoid loading heavy deps at startup - import sys - sys.path.insert(0, str(REPO_ROOT)) - from orchestrator.config import OrchestratorConfig - from orchestrator.orchestrator import TradingOrchestrator - from orchestrator.live_mode import LiveMode - - config = OrchestratorConfig( - quant_backtest_path=os.environ.get("QUANT_BACKTEST_PATH", ""), - ) - orchestrator = TradingOrchestrator(config) - live = LiveMode(orchestrator) results = await live.run_once(tickers, date) await websocket.send_text(json.dumps({"signals": results})) except WebSocketDisconnect: