refactor(web-ai): rename signal_v2→ai_trade, deprecate signal_v1
박재오 결정 2026-05-19 — V2를 정식 명칭 ai_trade로 graduation, V1은 deprecated 마킹 (legacy 디렉토리 이동은 file lock 풀린 후 후속). 변경 사항: - signal_v2/ → ai_trade/ (git mv, import 일괄 sed: signal_v2.x → ai_trade.x) - root start.bat → legacy/start_v1.bat (V1 자동 시작 차단) - ai_trade/start.bat 내부 uvicorn target signal_v2.main → ai_trade.main - signal_v1/DEPRECATED.md 추가 (사용 금지 명시) - CLAUDE.md 디렉토리 표·서버 시작 방식 갱신 - services/ 디렉토리 미래 예정 (Plan-B-Insta 작업 시 신설) ai_trade tests 59/59 PASS 확인. signal_v1/ 디렉토리 자체 이동(legacy/signal_v1/)은 telegram_bot.log + data/news_snapshots.db file lock으로 보류. lock 해제 후 후속 커밋. 후속 작업: Plan-B-Insta (services/insta-render + NAS insta 분할) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
75
ai_trade/config.py
Normal file
75
ai_trade/config.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Signal V2 환경변수 로딩."""
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(Path(__file__).parent.parent / ".env")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Settings:
|
||||
stock_api_url: str = field(
|
||||
default_factory=lambda: os.getenv("STOCK_API_URL", "").rstrip("/")
|
||||
)
|
||||
webai_api_key: str = field(
|
||||
default_factory=lambda: os.getenv("WEBAI_API_KEY", "").strip()
|
||||
)
|
||||
port: int = field(default_factory=lambda: int(os.getenv("SIGNAL_V2_PORT", "8001")))
|
||||
db_path: Path = field(
|
||||
default_factory=lambda: Path(__file__).parent / "data" / "ai_trade.db"
|
||||
)
|
||||
# KIS — V1 호환 패턴 (KIS_ENV_TYPE virtual/real)
|
||||
kis_env_type: str = field(default_factory=lambda: os.getenv("KIS_ENV_TYPE", "virtual").lower())
|
||||
kis_real_app_key: str = field(default_factory=lambda: os.getenv("KIS_REAL_APP_KEY", "").strip())
|
||||
kis_real_app_secret: str = field(default_factory=lambda: os.getenv("KIS_REAL_APP_SECRET", "").strip())
|
||||
kis_real_account: str = field(default_factory=lambda: os.getenv("KIS_REAL_ACCOUNT", "").strip())
|
||||
kis_virtual_app_key: str = field(default_factory=lambda: os.getenv("KIS_VIRTUAL_APP_KEY", "").strip())
|
||||
kis_virtual_app_secret: str = field(default_factory=lambda: os.getenv("KIS_VIRTUAL_APP_SECRET", "").strip())
|
||||
kis_virtual_account: str = field(default_factory=lambda: os.getenv("KIS_VIRTUAL_ACCOUNT", "").strip())
|
||||
v1_token_path: Path = field(
|
||||
default_factory=lambda: Path(
|
||||
os.getenv("V1_TOKEN_PATH",
|
||||
str(Path(__file__).parent.parent / "signal_v1" / "data" / "kis_token.json"))
|
||||
)
|
||||
)
|
||||
chronos_model: str = field(default_factory=lambda: os.getenv("CHRONOS_MODEL", "amazon/chronos-2"))
|
||||
stop_loss_pct: float = field(
|
||||
default_factory=lambda: float(os.getenv("STOP_LOSS_PCT", "-0.07"))
|
||||
)
|
||||
take_profit_pct: float = field(
|
||||
default_factory=lambda: float(os.getenv("TAKE_PROFIT_PCT", "0.15"))
|
||||
)
|
||||
chronos_spread_threshold: float = field(
|
||||
default_factory=lambda: float(os.getenv("CHRONOS_SPREAD_THRESHOLD", "0.6"))
|
||||
)
|
||||
asking_bid_ratio_threshold: float = field(
|
||||
default_factory=lambda: float(os.getenv("ASKING_BID_RATIO_THRESHOLD", "0.6"))
|
||||
)
|
||||
confidence_threshold: float = field(
|
||||
default_factory=lambda: float(os.getenv("CONFIDENCE_THRESHOLD", "0.7"))
|
||||
)
|
||||
min_momentum_for_buy: str = field(
|
||||
default_factory=lambda: os.getenv("MIN_MOMENTUM_FOR_BUY", "strong_up")
|
||||
)
|
||||
|
||||
@property
|
||||
def kis_is_virtual(self) -> bool:
|
||||
return self.kis_env_type != "real"
|
||||
|
||||
@property
|
||||
def kis_app_key(self) -> str:
|
||||
return self.kis_real_app_key if self.kis_env_type == "real" else self.kis_virtual_app_key
|
||||
|
||||
@property
|
||||
def kis_app_secret(self) -> str:
|
||||
return self.kis_real_app_secret if self.kis_env_type == "real" else self.kis_virtual_app_secret
|
||||
|
||||
@property
|
||||
def kis_account(self) -> str:
|
||||
return self.kis_real_account if self.kis_env_type == "real" else self.kis_virtual_account
|
||||
|
||||
|
||||
def get_settings() -> Settings:
|
||||
return Settings()
|
||||
Reference in New Issue
Block a user