From 53cadcf7e34f05f77082e84f0696b56bcbcbae36 Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Thu, 2 Apr 2026 10:26:52 +0900 Subject: refactor: remove all crypto/Binance code, update to US stock symbols --- ...-01-operations-and-strategy-expansion-design.md | 458 --------------------- 1 file changed, 458 deletions(-) delete mode 100644 docs/superpowers/specs/2026-04-01-operations-and-strategy-expansion-design.md (limited to 'docs/superpowers/specs/2026-04-01-operations-and-strategy-expansion-design.md') diff --git a/docs/superpowers/specs/2026-04-01-operations-and-strategy-expansion-design.md b/docs/superpowers/specs/2026-04-01-operations-and-strategy-expansion-design.md deleted file mode 100644 index e1aea74..0000000 --- a/docs/superpowers/specs/2026-04-01-operations-and-strategy-expansion-design.md +++ /dev/null @@ -1,458 +0,0 @@ -# Operations Infrastructure & Strategy Expansion — Design Spec - -## Overview - -기존 Binance 현물 암호화폐 자동매매 플랫폼의 두 가지 영역을 강화한다: - -1. **운영 인프라** — DB 마이그레이션, 구조화된 로깅, Telegram 알림, 에러 복구, 메트릭 수집 -2. **전략 확장** — 추세 추종/스캘핑 전략 추가, 백테스트 고도화 - -접근 순서: 운영 인프라 먼저 완성 → 전략 추가. 안정적인 모니터링/알림 기반 위에서 새 전략을 검증할 수 있어야 한다. - ---- - -## Part 1: Operations Infrastructure - -### 1.1 DB Layer Migration (asyncpg → SQLAlchemy 2.0 Async + Alembic) - -**목표:** raw SQL과 asyncpg 직접 사용을 SQLAlchemy 2.0 async ORM으로 교체하고, Alembic으로 마이그레이션을 관리한다. - -**변경 사항:** - -- `shared/src/shared/db.py` — AsyncSession 기반으로 재작성 - - `create_async_engine()` + `async_sessionmaker()` 사용 - - asyncpg는 SQLAlchemy의 내부 드라이버로 유지 (`postgresql+asyncpg://`) - - 기존 raw SQL 함수들을 ORM 쿼리로 전환 - -- `shared/src/shared/sa_models.py` — SQLAlchemy ORM 모델 (신규) - - 기존 Pydantic 모델(models.py)과 1:1 매핑되는 SA 테이블 정의 - - `Candle`, `Signal`, `Order`, `Trade`, `Position`, `PortfolioSnapshot` 테이블 - - Pydantic 모델은 이벤트 직렬화/API 전용으로 유지 - -- `shared/alembic/` — Alembic 마이그레이션 환경 (신규) - - `alembic.ini` — 설정 파일 (DATABASE_URL 참조) - - `env.py` — async 엔진 설정, SA 모델 메타데이터 참조 - - `versions/` — 마이그레이션 파일들 - - 초기 마이그레이션: 기존 `db.py`의 CREATE TABLE 로직을 마이그레이션으로 이전 - -- `Makefile` 타겟 추가: - - `make migrate` — `alembic upgrade head` - - `make migrate-down` — `alembic downgrade -1` - - `make migrate-new MSG="description"` — `alembic revision --autogenerate -m "description"` - -- 각 서비스의 DB 접근 코드를 AsyncSession 기반으로 업데이트: - - `data-collector/storage.py` — bulk insert 쿼리를 SA ORM으로 - - `order-executor/executor.py` — order CRUD를 SA ORM으로 - - `portfolio-manager/portfolio.py` — position/snapshot 쿼리를 SA ORM으로 - - `backtester/engine.py` — candle 조회를 SA ORM으로 - -**의존성 추가:** `sqlalchemy[asyncio]>=2.0`, `alembic>=1.13` -**의존성 제거:** `asyncpg` (직접 의존 → SQLAlchemy 내부 의존으로 변경) - ---- - -### 1.2 Structured Logging (structlog) - -**목표:** 전 서비스에 JSON 구조화 로깅을 적용하고, 에러 로그를 Telegram 알림과 연결한다. - -**변경 사항:** - -- `shared/src/shared/logging.py` (신규) - - `setup_logging(service_name: str, log_level: str)` 함수 - - structlog 프로세서 체인: timestamp, log level, service_name 바인딩, JSON 렌더러 - - 개발 환경: 컬러 콘솔 출력 / 프로덕션: JSON stdout - - `LOG_FORMAT` 환경변수로 전환 (`console` | `json`, 기본값: `json`) - -- 각 서비스 `main.py`에서 `setup_logging()` 호출 -- 기존 `logging.getLogger()` 호출을 `structlog.get_logger()` 로 교체 -- 컨텍스트 바인딩 예시: - ```python - log = structlog.get_logger().bind(service="strategy-engine", symbol="BTCUSDT") - log.info("signal_generated", strategy="rsi", side="BUY", price=68500) - ``` - -- ERROR 이상 로그 → Telegram 알림 트리거 (1.3절 TelegramNotifier 연동) - - structlog 커스텀 프로세서로 구현 - - 알림 전송 실패 시 로그만 남기고 서비스 중단하지 않음 - -**의존성 추가:** `structlog>=24.0` - ---- - -### 1.3 Telegram Notification Service - -**목표:** 주요 이벤트(시그널, 주문, 에러, 일일 요약)를 Telegram으로 전송한다. - -**변경 사항:** - -- `shared/src/shared/notifier.py` (신규) - - `TelegramNotifier` 클래스 - - `__init__(bot_token: str, chat_id: str)` — aiohttp 세션 관리 - - `send(message: str, parse_mode: str = "HTML")` — 메시지 전송 - - `send_signal(signal: Signal)` — 시그널 포맷팅 후 전송 - - `send_order(order: Order)` — 주문 체결/실패 알림 - - `send_error(error: str, service: str)` — 에러 알림 - - `send_daily_summary(positions: list, pnl: Decimal)` — 일일 요약 - - Rate limiting: 초당 최대 1건 (asyncio.Semaphore + 큐) - - 연결 실패 시 최대 3회 재시도, 실패해도 서비스 중단하지 않음 - -- `shared/src/shared/config.py` — 설정 추가: - - `TELEGRAM_BOT_TOKEN: str = ""` - - `TELEGRAM_CHAT_ID: str = ""` - - `TELEGRAM_ENABLED: bool = False` (토큰 미설정 시 자동 비활성) - -- `.env.example` 업데이트: - ``` - TELEGRAM_BOT_TOKEN= - TELEGRAM_CHAT_ID= - TELEGRAM_ENABLED=false - ``` - -- 연동 포인트: - - `strategy-engine/engine.py` — 시그널 생성 시 `send_signal()` - - `order-executor/executor.py` — 주문 체결/실패 시 `send_order()` - - `shared/logging.py` — ERROR 로그 시 `send_error()` - - `portfolio-manager/main.py` — 매일 자정(UTC) `send_daily_summary()` - -**의존성:** aiohttp (이미 존재) - ---- - -### 1.4 Error Recovery & Health Checks - -**목표:** 서비스 장애 시 자동 복구하고, 헬스체크 엔드포인트로 상태를 모니터링한다. - -**변경 사항:** - -- `shared/src/shared/resilience.py` (신규) - - `retry_with_backoff(func, max_retries, base_delay)` — exponential backoff 데코레이터 - - 지터(jitter) 포함: `delay * (1 + random(0, 0.5))` - - 최대 지연: 60초 - - `CircuitBreaker` 클래스: - - 상태: CLOSED(정상) → OPEN(차단) → HALF_OPEN(시험) - - `failure_threshold`: 연속 실패 N회 시 OPEN (기본: 5) - - `recovery_timeout`: OPEN 후 N초 뒤 HALF_OPEN (기본: 60) - - OPEN 전환 시 Telegram 알림 전송 - -- `shared/src/shared/healthcheck.py` (신규) - - `HealthCheckServer` — aiohttp 기반 경량 HTTP 서버 - - `GET /health` → `{"status": "ok", "service": "...", "uptime": ..., "checks": {...}}` - - 체크 항목: Redis 연결, PostgreSQL 연결, Binance WS 연결(해당 서비스만) - - 포트: `HEALTH_PORT` 환경변수 (서비스별 다르게 설정) - -- 각 서비스에 적용: - - `data-collector` — Binance WS 재연결 (backoff), Redis/DB 재연결 - - `strategy-engine` — Redis 소비자 재연결 - - `order-executor` — 거래소 API 호출 재시도 (circuit breaker) - - `portfolio-manager` — Redis/DB 재연결 - -- `docker-compose.yml` — healthcheck를 `/health` 엔드포인트로 변경 - -- `shared/src/shared/config.py` — 설정 추가: - - `HEALTH_PORT: int = 8080` - - `CIRCUIT_BREAKER_THRESHOLD: int = 5` - - `CIRCUIT_BREAKER_TIMEOUT: int = 60` - ---- - -### 1.5 Prometheus Metrics - -**목표:** 각 서비스의 주요 지표를 Prometheus 포맷으로 노출한다. - -**변경 사항:** - -- `shared/src/shared/metrics.py` (신규) - - `MetricsServer` — prometheus_client 기반 - - `/metrics` 엔드포인트 (healthcheck 서버에 통합) - - 공통 메트릭: - - `service_up` (Gauge) — 서비스 상태 - - `errors_total` (Counter) — 에러 횟수 (label: service, error_type) - - `event_processing_seconds` (Histogram) — 이벤트 처리 시간 - -- 서비스별 메트릭: - - **data-collector:** - - `candles_received_total` (Counter) — 수신 캔들 수 - - `ws_reconnections_total` (Counter) — WS 재연결 횟수 - - **strategy-engine:** - - `signals_generated_total` (Counter, label: strategy, side) - - `strategy_execution_seconds` (Histogram, label: strategy) - - **order-executor:** - - `orders_total` (Counter, label: status, side) - - `risk_rejections_total` (Counter, label: reason) - - **portfolio-manager:** - - `portfolio_value` (Gauge) — 총 포트폴리오 가치 - - `unrealized_pnl` (Gauge, label: symbol) - -- `docker-compose.yml` — Prometheus + Grafana 서비스 추가 (선택적 프로필): - ```yaml - prometheus: - image: prom/prometheus:latest - profiles: ["monitoring"] - volumes: - - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - grafana: - image: grafana/grafana:latest - profiles: ["monitoring"] - ports: - - "3000:3000" - ``` - -- `monitoring/prometheus.yml` (신규) — 스크래핑 설정 -- `monitoring/grafana/` (신규) — 대시보드 프로비저닝 (선택적) - -**의존성 추가:** `prometheus-client>=0.20` - ---- - -## Part 2: Strategy Expansion - -### 2.1 Trend Following Strategies - -**MACD Strategy** (`strategies/macd_strategy.py`) -- MACD line = EMA(12) - EMA(26), Signal line = EMA(9) of MACD -- BUY: MACD가 Signal line 위로 교차 + 히스토그램 양전환 -- SELL: MACD가 Signal line 아래로 교차 + 히스토그램 음전환 -- 파라미터: `fast_period=12`, `slow_period=26`, `signal_period=9`, `quantity` -- warmup_period: `slow_period + signal_period` - -**Bollinger Bands Strategy** (`strategies/bollinger_strategy.py`) -- 중심선 = SMA(20), 상단 = 중심 + 2*std, 하단 = 중심 - 2*std -- BUY: 가격이 하단 밴드 아래로 이탈 후 복귀 -- SELL: 가격이 상단 밴드 위로 이탈 후 복귀 -- 변동성 필터: 밴드 폭이 임계값 미만이면 시그널 무시 (횡보장 필터) -- 파라미터: `period=20`, `num_std=2.0`, `min_bandwidth=0.02`, `quantity` -- warmup_period: `period` - -**EMA Crossover Strategy** (`strategies/ema_crossover_strategy.py`) -- 단기 EMA와 장기 EMA 교차 -- BUY: 단기 EMA가 장기 EMA 위로 교차 (Golden Cross) -- SELL: 단기 EMA가 장기 EMA 아래로 교차 (Death Cross) -- 파라미터: `short_period=9`, `long_period=21`, `quantity` -- warmup_period: `long_period` - ---- - -### 2.2 Scalping Strategies - -**VWAP Strategy** (`strategies/vwap_strategy.py`) -- VWAP = cumsum(price * volume) / cumsum(volume) -- BUY: 가격이 VWAP 아래에서 VWAP으로 복귀 (평균 회귀) -- SELL: 가격이 VWAP 위에서 VWAP으로 복귀 -- 일중 리셋: UTC 00:00에 VWAP 재계산 -- 파라미터: `deviation_threshold=0.002`, `quantity` -- warmup_period: 최소 30 캔들 - -**Volume Profile Strategy** (`strategies/volume_profile_strategy.py`) -- 최근 N개 캔들의 가격대별 거래량 분포 계산 -- POC (Point of Control): 가장 거래량이 많은 가격대 -- Value Area: 전체 거래량 70%가 집중된 구간 -- BUY: 가격이 Value Area 하단 지지선에서 반등 -- SELL: 가격이 Value Area 상단 저항선에서 거부 -- 파라미터: `lookback_period=100`, `num_bins=50`, `value_area_pct=0.7`, `quantity` -- warmup_period: `lookback_period` - ---- - -### 2.3 Strategy Common Improvements - -**BaseStrategy 확장:** -```python -class BaseStrategy(ABC): - @property - @abstractmethod - def warmup_period(self) -> int: - """지표 계산에 필요한 최소 캔들 수""" - pass - - @abstractmethod - def on_candle(self, candle: Candle) -> Signal | None: - pass - - @abstractmethod - def configure(self, params: dict) -> None: - pass - - def reset(self) -> None: - """전략 상태 초기화 (백테스트 간 재사용)""" - pass -``` - -**전략 파라미터 외부화:** -- `strategies/config/` 디렉토리에 YAML 설정 파일 -- 파일명: `{strategy_name}.yaml` (예: `rsi_strategy.yaml`) -- 구조: - ```yaml - # rsi_strategy.yaml - period: 14 - oversold: 30 - overbought: 70 - quantity: 0.001 - ``` -- `plugin_loader.py`가 전략 로드 시 자동으로 같은 이름의 YAML을 찾아 `configure()` 호출 -- CLI에서 `--param key=value`로 런타임 오버라이드 가능 - -**기존 전략 업데이트:** -- `RsiStrategy`, `GridStrategy`에 `warmup_period` 속성 추가 -- `reset()` 메서드 구현 - -**의존성 추가:** `pyyaml>=6.0` - ---- - -### 2.4 Backtest Enhancement - -**DetailedMetrics 데이터클래스** (`backtester/src/backtester/metrics.py`, 신규): -```python -@dataclass -class TradeRecord: - entry_time: datetime - exit_time: datetime - symbol: str - side: str - entry_price: Decimal - exit_price: Decimal - quantity: Decimal - pnl: Decimal - pnl_pct: float - holding_period: timedelta - -@dataclass -class DetailedMetrics: - # 기본 - total_return: float - total_trades: int - winning_trades: int - losing_trades: int - win_rate: float - profit_factor: float - - # 리스크 메트릭 - sharpe_ratio: float - sortino_ratio: float - calmar_ratio: float - max_drawdown: float - max_drawdown_duration: timedelta - - # 수익률 분석 - monthly_returns: dict[str, float] # "2025-01": 0.05 - avg_win: float - avg_loss: float - largest_win: float - largest_loss: float - avg_holding_period: timedelta - - # 개별 거래 - trades: list[TradeRecord] -``` - -**BacktestEngine 확장:** -- `engine.py`에 `DetailedMetrics` 계산 로직 추가 -- `simulator.py`에 `TradeRecord` 생성 로직 추가 (진입/청산 시점 기록) -- Sharpe ratio = `mean(daily_returns) / std(daily_returns) * sqrt(365)` (crypto는 365일) -- Sortino ratio = `mean(daily_returns) / downside_std * sqrt(365)` -- Calmar ratio = `annualized_return / max_drawdown` -- Max drawdown = `max(peak - trough) / peak` - -**Reporter 개선:** -- `reporter.py` — rich 라이브러리로 테이블 출력 - - 요약 테이블: 핵심 메트릭 - - 월별 수익률 테이블 - - 최고/최악 거래 Top 5 -- CSV/JSON 내보내기: `--output csv` / `--output json` 플래그 - -**CLI 확장:** -- `trading backtest run` — 기존 출력에 상세 메트릭 추가 -- `trading backtest run --output csv --file result.csv` — 결과 내보내기 - -**의존성 추가:** `rich>=13.0` - ---- - -## Updated Tech Stack - -| 용도 | 기존 | 변경 | -|------|------|------| -| DB ORM | asyncpg (raw SQL) | **SQLAlchemy 2.0 async** (asyncpg 드라이버) | -| 마이그레이션 | 없음 | **Alembic** | -| 로깅 | Python logging | **structlog** | -| 알림 | 없음 | **Telegram Bot API** (aiohttp) | -| 메트릭 | 없음 | **prometheus-client** | -| 전략 설정 | 하드코딩 | **YAML** (pyyaml) | -| 리포트 출력 | print | **rich** | - ---- - -## Updated .env.example - -```env -# Exchange -BINANCE_API_KEY= -BINANCE_API_SECRET= - -# Infrastructure -REDIS_URL=redis://localhost:6379 -DATABASE_URL=postgresql+asyncpg://trading:trading@localhost:5432/trading - -# Logging -LOG_LEVEL=INFO -LOG_FORMAT=json - -# Telegram -TELEGRAM_BOT_TOKEN= -TELEGRAM_CHAT_ID= -TELEGRAM_ENABLED=false - -# Risk Management -RISK_MAX_POSITION_SIZE=0.1 -RISK_STOP_LOSS_PCT=5 -RISK_DAILY_LOSS_LIMIT_PCT=10 -DRY_RUN=true - -# Health & Metrics -HEALTH_PORT=8080 -CIRCUIT_BREAKER_THRESHOLD=5 -CIRCUIT_BREAKER_TIMEOUT=60 -``` - ---- - -## New Files Summary - -| 파일 | 용도 | -|------|------| -| `shared/src/shared/sa_models.py` | SQLAlchemy ORM 모델 | -| `shared/src/shared/logging.py` | structlog 설정 | -| `shared/src/shared/notifier.py` | Telegram 알림 | -| `shared/src/shared/resilience.py` | retry, circuit breaker | -| `shared/src/shared/healthcheck.py` | 헬스체크 서버 | -| `shared/src/shared/metrics.py` | Prometheus 메트릭 | -| `shared/alembic/` | DB 마이그레이션 환경 | -| `strategies/config/*.yaml` | 전략 파라미터 설정 | -| `strategies/macd_strategy.py` | MACD 전략 | -| `strategies/bollinger_strategy.py` | Bollinger Bands 전략 | -| `strategies/ema_crossover_strategy.py` | EMA Crossover 전략 | -| `strategies/vwap_strategy.py` | VWAP 전략 | -| `strategies/volume_profile_strategy.py` | Volume Profile 전략 | -| `backtester/src/backtester/metrics.py` | 상세 백테스트 메트릭 | -| `monitoring/prometheus.yml` | Prometheus 설정 | - ---- - -## Scope Boundaries - -**포함:** -- SQLAlchemy 2.0 async 전환 + Alembic 마이그레이션 -- structlog JSON 로깅 -- Telegram 알림 (시그널, 주문, 에러, 일일 요약) -- 에러 복구 (retry, circuit breaker) + 헬스체크 -- Prometheus 메트릭 수집 -- 5개 신규 전략 (MACD, Bollinger, EMA Crossover, VWAP, Volume Profile) -- BaseStrategy에 warmup_period, reset() 추가 -- YAML 기반 전략 파라미터 -- 백테스트 상세 메트릭 + rich 리포트 - -**제외:** -- Grafana 대시보드 프로비저닝 (Prometheus만 설정, 대시보드는 수동) -- 멀티 거래소 지원 -- REST API / 웹 대시보드 -- 전략 조합 프레임워크 (향후 확장) -- cgit v1.2.3