feat: initial commit - EvoTraders project
量化交易多智能体系统,包含: - 分析师、投资组合经理、风险经理等智能体 - 股票分析、投资组合管理、风险控制工具 - React 前端界面 - FastAPI 后端服务 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
0
backend/config/__init__.py
Normal file
0
backend/config/__init__.py
Normal file
76
backend/config/constants.py
Normal file
76
backend/config/constants.py
Normal 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
|
||||
# }
|
||||
}
|
||||
82
backend/config/data_config.py
Normal file
82
backend/config/data_config.py
Normal 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
|
||||
36
backend/config/env_config.py
Normal file
36
backend/config/env_config.py
Normal 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
|
||||
Reference in New Issue
Block a user