import os from pathlib import Path from pydantic_settings import BaseSettings from functools import lru_cache # 프로젝트 루트 디렉토리 (backend의 상위 디렉토리) BASE_DIR = Path(__file__).resolve().parent.parent.parent BACKEND_ENV_FILE = BASE_DIR / ".env" class Settings(BaseSettings): # Application APP_NAME: str = "Auto Stock Trading System" ENVIRONMENT: str = "development" DEBUG: bool = True SECRET_KEY: str = "change-this-secret-key" # Server BACKEND_HOST: str = "0.0.0.0" BACKEND_PORT: int = 8000 # Database DATABASE_URL: str = "postgresql://autostock:autostock_password@localhost:5432/autostock_db" # Redis REDIS_URL: str = "redis://localhost:6379/0" # RabbitMQ RABBITMQ_URL: str = "amqp://autostock:autostock_password@localhost:5672/" # Korea Investment API KOREA_INVESTMENT_APP_KEY: str = "" KOREA_INVESTMENT_APP_SECRET: str = "" KOREA_INVESTMENT_ACCOUNT_NUMBER: str = "" KOREA_INVESTMENT_API_BASE_URL: str = "https://openapi.koreainvestment.com:9443" # Alias for backward compatibility with .env file KIS_APP_KEY: str = "" KIS_APP_SECRET: str = "" KIS_ACCOUNT_NO: str = "" KIS_BASE_URL: str = "" def __init__(self, **kwargs): super().__init__(**kwargs) # Use KIS_* values if KOREA_INVESTMENT_* are empty if not self.KOREA_INVESTMENT_APP_KEY and self.KIS_APP_KEY: self.KOREA_INVESTMENT_APP_KEY = self.KIS_APP_KEY if not self.KOREA_INVESTMENT_APP_SECRET and self.KIS_APP_SECRET: self.KOREA_INVESTMENT_APP_SECRET = self.KIS_APP_SECRET if not self.KOREA_INVESTMENT_ACCOUNT_NUMBER and self.KIS_ACCOUNT_NO: self.KOREA_INVESTMENT_ACCOUNT_NUMBER = self.KIS_ACCOUNT_NO if self.KIS_BASE_URL: self.KOREA_INVESTMENT_API_BASE_URL = self.KIS_BASE_URL # Claude AI ANTHROPIC_API_KEY: str = "" # MCP Server MCP_SERVER_URL: str = "http://localhost:8001" # News API NEWS_API_KEY: str = "" # Logging LOG_LEVEL: str = "INFO" # Trading Settings MAX_POSITION_SIZE: float = 0.1 # 10% of portfolio MAX_DAILY_TRADES: int = 10 STOP_LOSS_PERCENT: float = -5.0 TAKE_PROFIT_PERCENT: float = 15.0 # API Rate Limiting & Retry Settings (모의투자 API 안전 운영) API_MAX_RETRIES: int = 3 # 최대 재시도 횟수 API_RETRY_DELAY: float = 1.5 # 초기 재시도 대기 시간 (초) API_RETRY_BACKOFF: float = 2.0 # 지수 백오프 배율 API_MIN_REQUEST_INTERVAL: float = 0.5 # 최소 요청 간격 (초) - 초당 2회 권장 API_MAX_CONCURRENT_REQUESTS: int = 2 # 동시 최대 요청 수 API_TIMEOUT: float = 30.0 # API 타임아웃 (초) # Monitoring & Alerting API_ERROR_THRESHOLD: float = 0.3 # 오류율 임계값 (30%) API_MONITORING_WINDOW: int = 100 # 모니터링 윈도우 (최근 N개 요청) class Config: env_file = str(BACKEND_ENV_FILE) if BACKEND_ENV_FILE.exists() else ".env" case_sensitive = True extra = "ignore" # .env 파일의 추가 필드 무시 env_file_encoding = "utf-8" @lru_cache() def get_settings() -> Settings: return Settings() settings = get_settings()