feat: initial commit - EvoTraders project

量化交易多智能体系统,包含:
- 分析师、投资组合经理、风险经理等智能体
- 股票分析、投资组合管理、风险控制工具
- React 前端界面
- FastAPI 后端服务

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-03-13 04:34:06 +08:00
commit 12de93aa30
115 changed files with 29304 additions and 0 deletions

View File

View File

@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
# flake8: noqa: E501
# pylint: disable=C0301
# Agent configuration for dashboard display
AGENT_CONFIG = {
"portfolio_manager": {
"name": "Portfolio Manager",
"role": "Portfolio Manager",
"avatar": "pm",
"is_team_role": True,
},
"risk_manager": {
"name": "Risk Manager",
"role": "Risk Manager",
"avatar": "risk",
"is_team_role": True,
},
"sentiment_analyst": {
"name": "Sentiment Analyst",
"role": "Sentiment Analyst",
"avatar": "sentiment",
"is_team_role": False,
},
"technical_analyst": {
"name": "Technical Analyst",
"role": "Technical Analyst",
"avatar": "technical",
"is_team_role": False,
},
"fundamentals_analyst": {
"name": "Fundamentals Analyst",
"role": "Fundamentals Analyst",
"avatar": "fundamentals",
"is_team_role": False,
},
"valuation_analyst": {
"name": "Valuation Analyst",
"role": "Valuation Analyst",
"avatar": "valuation",
"is_team_role": False,
},
}
ANALYST_TYPES = {
"fundamentals_analyst": {
"display_name": "Fundamentals Analyst",
"agent_id": "fundamentals_analyst",
"description": "Uses LLM to intelligently select analysis tools, focuses on financial data and company fundamental analysis",
"order": 12,
},
"technical_analyst": {
"display_name": "Technical Analyst",
"agent_id": "technical_analyst",
"description": "Uses LLM to intelligently select analysis tools, focuses on technical indicators and chart analysis",
"order": 11,
},
"sentiment_analyst": {
"display_name": "Sentiment Analyst",
"agent_id": "sentiment_analyst",
"description": "Uses LLM to intelligently select analysis tools, analyzes market sentiment and news sentiment",
"order": 13,
},
"valuation_analyst": {
"display_name": "Valuation Analyst",
"agent_id": "valuation_analyst",
"description": "Uses LLM to intelligently select analysis tools, focuses on company valuation and value assessment",
"order": 14,
},
# "comprehensive_analyst": {
# "display_name": "Comprehensive Analyst",
# "agent_id": "comprehensive_analyst",
# "description": "Uses LLM to intelligently select analysis tools, performs comprehensive analysis",
# "order": 15
# }
}

View File

@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"""
Centralized Data Source Configuration
Auto-detects and manages data source based on available API keys.
Priority: FINNHUB_API_KEY > FINANCIAL_DATASETS_API_KEY
"""
import os
from dataclasses import dataclass
from typing import Literal, Optional
DataSource = Literal["finnhub", "financial_datasets"]
@dataclass
class DataSourceConfig:
"""Immutable data source configuration"""
source: DataSource
api_key: str
# Module-level cache for the resolved configuration
_config_cache: Optional[DataSourceConfig] = None
def _resolve_config() -> DataSourceConfig:
"""
Resolve data source configuration based on available API keys.
Priority:
1. FINNHUB_API_KEY (if set)
2. FINANCIAL_DATASETS_API_KEY (if set)
3. Raises error if neither is available
"""
# Check for Finnhub API key first (higher priority)
finnhub_key = os.getenv("FINNHUB_API_KEY")
if finnhub_key:
return DataSourceConfig(source="finnhub", api_key=finnhub_key)
# Fallback to Financial Datasets API
fd_key = os.getenv("FINANCIAL_DATASETS_API_KEY")
if fd_key:
return DataSourceConfig(source="financial_datasets", api_key=fd_key)
# No API key available
raise ValueError(
"No API key found. Please set either FINNHUB_API_KEY or "
"FINANCIAL_DATASETS_API_KEY in your .env file.",
)
def get_config() -> DataSourceConfig:
"""
Get the resolved data source configuration (cached).
Returns:
DataSourceConfig with source and api_key
Raises:
ValueError: If no API key is configured
"""
global _config_cache
if _config_cache is None:
_config_cache = _resolve_config()
return _config_cache
def get_data_source() -> DataSource:
"""Get the configured data source name."""
return get_config().source
def get_api_key() -> str:
"""Get the API key for the configured data source."""
return get_config().api_key
def reset_config() -> None:
"""Reset the cached configuration (useful for testing)."""
global _config_cache
_config_cache = None

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Simple environment config helpers
"""
import os
def get_env_list(key: str, default: list = None) -> list:
"""Get comma-separated list from env"""
value = os.getenv(key, "")
if not value:
return default or []
return [item.strip() for item in value.split(",") if item.strip()]
def get_env_float(key: str, default: float = 0.0) -> float:
"""Get float from env"""
value = os.getenv(key)
if value is None:
return default
try:
return float(value)
except ValueError:
return default
def get_env_int(key: str, default: int = 0) -> int:
"""Get int from env"""
value = os.getenv(key)
if value is None:
return default
try:
return int(value)
except ValueError:
return default