量化交易多智能体系统,包含: - 分析师、投资组合经理、风险经理等智能体 - 股票分析、投资组合管理、风险控制工具 - React 前端界面 - FastAPI 后端服务 Co-Authored-By: Claude <noreply@anthropic.com>
141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from datetime import datetime, timezone
|
|
from typing import Callable, Optional
|
|
|
|
from rich.console import Console
|
|
from rich.live import Live
|
|
from rich.style import Style
|
|
from rich.table import Table
|
|
from rich.text import Text
|
|
|
|
console = Console()
|
|
|
|
|
|
class AgentProgress:
|
|
"""Manages progress tracking for multiple agents."""
|
|
|
|
def __init__(self):
|
|
self.agent_status = {}
|
|
self.table = Table(show_header=False, box=None, padding=(0, 1))
|
|
self.live = Live(self.table, console=console, refresh_per_second=4)
|
|
self.started = False
|
|
self.update_handlers = []
|
|
|
|
def register_handler(
|
|
self,
|
|
handler: Callable[[str, Optional[str], str], None],
|
|
):
|
|
"""Register a handler to be called when agent status updates."""
|
|
self.update_handlers.append(handler)
|
|
return handler # Return handler to support use as decorator
|
|
|
|
def unregister_handler(
|
|
self,
|
|
handler: Callable[[str, Optional[str], str], None],
|
|
):
|
|
"""Unregister a previously registered handler."""
|
|
if handler in self.update_handlers:
|
|
self.update_handlers.remove(handler)
|
|
|
|
def start(self):
|
|
"""Start the progress display."""
|
|
if not self.started:
|
|
self.live.start()
|
|
self.started = True
|
|
|
|
def stop(self):
|
|
"""Stop the progress display."""
|
|
if self.started:
|
|
self.live.stop()
|
|
self.started = False
|
|
|
|
def update_status(
|
|
self,
|
|
agent_name: str,
|
|
ticker: Optional[str] = None,
|
|
status: str = "",
|
|
analysis: Optional[str] = None,
|
|
):
|
|
"""Update the status of an agent."""
|
|
if agent_name not in self.agent_status:
|
|
self.agent_status[agent_name] = {"status": "", "ticker": None}
|
|
|
|
if ticker:
|
|
self.agent_status[agent_name]["ticker"] = ticker
|
|
if status:
|
|
self.agent_status[agent_name]["status"] = status
|
|
if analysis:
|
|
self.agent_status[agent_name]["analysis"] = analysis
|
|
|
|
# Set the timestamp as UTC datetime
|
|
timestamp = datetime.now(timezone.utc).isoformat()
|
|
self.agent_status[agent_name]["timestamp"] = timestamp
|
|
|
|
# Notify all registered handlers
|
|
for handler in self.update_handlers:
|
|
handler(agent_name, ticker, status, analysis, timestamp)
|
|
|
|
self._refresh_display()
|
|
|
|
def get_all_status(self):
|
|
"""Get the current status of all agents as a dictionary."""
|
|
return {
|
|
agent_name: {
|
|
"ticker": info["ticker"],
|
|
"status": info["status"],
|
|
"display_name": self._get_display_name(agent_name),
|
|
}
|
|
for agent_name, info in self.agent_status.items()
|
|
}
|
|
|
|
def _get_display_name(self, agent_name: str) -> str:
|
|
"""Convert agent_name to a display-friendly format."""
|
|
return agent_name.replace("_agent", "").replace("_", " ").title()
|
|
|
|
def _refresh_display(self):
|
|
"""Refresh the progress display."""
|
|
self.table.columns.clear()
|
|
self.table.add_column(width=100)
|
|
|
|
# Sort Risk Management and Portfolio Management at the bottom
|
|
def sort_key(item):
|
|
agent_name = item[0]
|
|
if "risk_manager" in agent_name:
|
|
return (2, agent_name)
|
|
elif "portfolio_manager" in agent_name:
|
|
return (3, agent_name)
|
|
else:
|
|
return (1, agent_name)
|
|
|
|
for agent_name, info in sorted(
|
|
self.agent_status.items(),
|
|
key=sort_key,
|
|
):
|
|
status = info["status"]
|
|
ticker = info["ticker"]
|
|
# Create the status text with appropriate styling
|
|
if status.lower() == "done":
|
|
style = Style(color="green", bold=True)
|
|
symbol = "✓"
|
|
elif status.lower() == "error":
|
|
style = Style(color="red", bold=True)
|
|
symbol = "✗"
|
|
else:
|
|
style = Style(color="yellow")
|
|
symbol = "⋯"
|
|
|
|
agent_display = self._get_display_name(agent_name)
|
|
status_text = Text()
|
|
status_text.append(f"{symbol} ", style=style)
|
|
status_text.append(f"{agent_display:<20}", style=Style(bold=True))
|
|
|
|
if ticker:
|
|
status_text.append(f"[{ticker}] ", style=Style(color="cyan"))
|
|
status_text.append(status, style=style)
|
|
|
|
self.table.add_row(status_text)
|
|
|
|
|
|
# Create a global instance
|
|
progress = AgentProgress()
|