Files
evotraders/backend/config/data_config.py
cillin 12de93aa30 feat: initial commit - EvoTraders project
量化交易多智能体系统,包含:
- 分析师、投资组合经理、风险经理等智能体
- 股票分析、投资组合管理、风险控制工具
- React 前端界面
- FastAPI 后端服务

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-13 04:34:06 +08:00

83 lines
2.1 KiB
Python

# -*- 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