Files
stockautomtion/app/core/config.py
gerd 182c2b38e6 feat: config.yaml 기반 설정 마이그레이션 및 대시보드/종목조회 기능 추가
- config.yaml에서 직접 KIS 설정 관리 (BaseSettings 제거)
- 대시보드 KIS 계좌 잔고 실시간 연동, 로컬 DB 폴백
- 종목 조회 페이지: 시세/호가/일봉차트 (canvas) 구현
- 호가 REST API 엔드포인트 (/api/stocks/{code}/orderbook) 추가
- 토큰 캐시(.auth_cache.json) 저장/복원, 1분 재시도 제한
- KIS WebSocket 자동 연결 + 재연결 로직
- httpx 타임아웃 10초→30초, 라우터 타임아웃 핸들링 (504)
- rate limit: requests_per_second 2.0 (모의투자 초당 2건)
- 사이드바 3메뉴: 실거래 / 과거기록 / 종목조회
2026-07-17 15:25:34 +09:00

121 lines
3.1 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import Any
import yaml
class KISConfig:
app_key: str = ""
app_secret: str = ""
account_no: str = ""
account_code: str = "01"
hts_id: str = ""
server_mode: str = "vps"
class AppConfig:
name: str = "StockAutomation"
version: str = "0.1.0"
host: str = "0.0.0.0"
port: int = 8000
debug: bool = False
db_path: str = "./data/stock.db"
log_level: str = "INFO"
class CollectorConfig:
interval_seconds: int = 5
market_open_hour: int = 9
market_close_hour: int = 15
market_close_minute: int = 30
class StrategyConfig:
check_interval_seconds: int = 3
max_daily_trades: int = 50
default_order_type: str = "00"
class TradingConfig:
max_order_amount: int = 10_000_000
min_order_amount: int = 100_000
slippage_percent: float = 0.1
class RateLimitConfig:
requests_per_second: float = 1.0
retry_delay: float = 1.5
class Settings:
def __init__(self) -> None:
self.kis = KISConfig()
self.app = AppConfig()
self.collector = CollectorConfig()
self.strategy = StrategyConfig()
self.trading = TradingConfig()
self.rate_limit = RateLimitConfig()
self._load_yaml()
def _load_yaml(self) -> None:
yaml_path = Path("config.yaml")
if not yaml_path.exists():
return
with open(yaml_path, encoding="utf-8") as f:
data: dict[str, Any] = yaml.safe_load(f) or {}
app = data.get("app", {})
for key, val in app.items():
if hasattr(self.app, key):
setattr(self.app, key, val)
kis = data.get("kis", {})
for key, val in kis.items():
if key == "rate_limit":
continue
if hasattr(self.kis, key):
setattr(self.kis, key, val)
rl = kis.get("rate_limit", {})
if "requests_per_second" in rl:
self.rate_limit.requests_per_second = rl["requests_per_second"]
if "retry_delay" in rl:
self.rate_limit.retry_delay = rl["retry_delay"]
collector = data.get("collector", {})
for key, val in collector.items():
if hasattr(self.collector, key):
setattr(self.collector, key, val)
strategy = data.get("strategies", {})
for key, val in strategy.items():
if hasattr(self.strategy, key):
setattr(self.strategy, key, val)
trading = data.get("trading", {})
for key, val in trading.items():
if hasattr(self.trading, key):
setattr(self.trading, key, val)
logging_cfg = data.get("logging", {})
if "level" in logging_cfg:
self.app.log_level = logging_cfg["level"]
settings = Settings()
def get_base_url() -> str:
if settings.kis.server_mode == "real":
return "https://openapi.koreainvestment.com:9443"
return "https://openapivts.koreainvestment.com:29443"
def get_ws_url() -> str:
if settings.kis.server_mode == "real":
return "ws://ops.koreainvestment.com:21000"
return "ws://ops.koreainvestment.com:31000"