diff --git a/CLAUDE.md b/CLAUDE.md index 72c74c9..addfb0d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,6 +15,9 @@ pytest -v --cov=src # Run (paper trading) python -m src.main --mode=paper + +# Run with dashboard +python -m src.main --mode=paper --dashboard ``` ## Telegram Notifications (Optional) @@ -43,6 +46,10 @@ Get real-time alerts for trades, circuit breakers, and system events via Telegra - ℹ️ Market open/close notifications - πŸ“ System startup/shutdown status +### Interactive Commands + +With `TELEGRAM_COMMANDS_ENABLED=true` (default), the bot supports 9 bidirectional commands: `/help`, `/status`, `/positions`, `/report`, `/scenarios`, `/review`, `/dashboard`, `/stop`, `/resume`. + **Fail-safe**: Notifications never crash the trading system. Missing credentials or API errors are logged but trading continues normally. ## Smart Volatility Scanner (Optional) @@ -109,17 +116,23 @@ User requirements and feedback are tracked in [docs/requirements-log.md](docs/re ``` src/ β”œβ”€β”€ analysis/ # Technical analysis (RSI, volatility, smart scanner) +β”œβ”€β”€ backup/ # Disaster recovery (scheduler, cloud storage, health) +β”œβ”€β”€ brain/ # Gemini AI decision engine (prompt optimizer, context selector) β”œβ”€β”€ broker/ # KIS API client (domestic + overseas) -β”œβ”€β”€ brain/ # Gemini AI decision engine +β”œβ”€β”€ context/ # L1-L7 hierarchical memory system β”œβ”€β”€ core/ # Risk manager (READ-ONLY) -β”œβ”€β”€ evolution/ # Self-improvement optimizer +β”œβ”€β”€ dashboard/ # FastAPI read-only monitoring (8 API endpoints) +β”œβ”€β”€ data/ # External data integration (news, market data, calendar) +β”œβ”€β”€ evolution/ # Self-improvement (optimizer, daily review, scorecard) +β”œβ”€β”€ logging/ # Decision logger (audit trail) β”œβ”€β”€ markets/ # Market schedules and timezone handling -β”œβ”€β”€ notifications/ # Telegram real-time alerts +β”œβ”€β”€ notifications/ # Telegram alerts + bidirectional commands (9 commands) +β”œβ”€β”€ strategy/ # Pre-market planner, scenario engine, playbook store β”œβ”€β”€ db.py # SQLite trade logging β”œβ”€β”€ main.py # Trading loop orchestrator └── config.py # Settings (from .env) -tests/ # 343 tests across 14 files +tests/ # 551 tests across 25 files docs/ # Extended documentation ``` @@ -131,6 +144,7 @@ ruff check src/ tests/ # Lint mypy src/ --strict # Type check python -m src.main --mode=paper # Paper trading +python -m src.main --mode=paper --dashboard # With dashboard python -m src.main --mode=live # Live trading (⚠️ real money) # Gitea workflow (requires tea CLI) diff --git a/README.md b/README.md index 16a818e..eba289e 100644 --- a/README.md +++ b/README.md @@ -10,28 +10,41 @@ KIS(ν•œκ΅­νˆ¬μžμ¦κΆŒ) API둜 λ§€λ§€ν•˜κ³ , Google Gemini둜 νŒλ‹¨ν•˜λ©°, 자 β”‚ (λ§€λ§€ μ‹€ν–‰) β”‚ β”‚ (거래 루프) β”‚ β”‚ (μ˜μ‚¬κ²°μ •) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” - β”‚Risk Manager β”‚ - β”‚ (μ•ˆμ „μž₯치) β”‚ - β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” - β”‚ Evolution β”‚ - β”‚ (μ „λž΅ μ§„ν™”) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”΄β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” + β”‚Risk Manager β”‚ β”‚ DB β”‚ β”‚ Telegram β”‚ + β”‚ (μ•ˆμ „μž₯치) β”‚ β”‚ β”‚ β”‚ (μ•Œλ¦Ό+λͺ…λ Ή) β”‚ + β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ +β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”β”Œβ”€β”€β”΄β”€β”€β”β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β” +β”‚Strategy β”‚β”‚Ctx β”‚β”‚Evolution β”‚ +β”‚(ν”Œλ ˆμ΄λΆ)β”‚β”‚(λ©”λͺ¨λ¦¬)β”‚β”‚ (μ§„ν™”) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` +**v2 핡심**: "Plan Once, Execute Locally" β€” μž₯ μ‹œμž‘ μ „ AIκ°€ μ‹œλ‚˜λ¦¬μ˜€ ν”Œλ ˆμ΄λΆμ„ 1회 μƒμ„±ν•˜κ³ , 거래 μ‹œκ°„μ—λŠ” 둜컬 μ‹œλ‚˜λ¦¬μ˜€ 맀칭만 μˆ˜ν–‰ν•˜μ—¬ API λΉ„μš©κ³Ό μ§€μ—° μ‹œκ°„μ„ λŒ€ν­ 절감. + ## 핡심 λͺ¨λ“ˆ -| λͺ¨λ“ˆ | 파일 | μ„€λͺ… | +| λͺ¨λ“ˆ | μœ„μΉ˜ | μ„€λͺ… | |------|------|------| -| μ„€μ • | `src/config.py` | Pydantic 기반 ν™˜κ²½λ³€μˆ˜ λ‘œλ”© 및 νƒ€μž… 검증 | -| 브둜컀 | `src/broker/kis_api.py` | KIS API 비동기 래퍼 (토큰 κ°±μ‹ , 레이트 리미터, ν•΄μ‹œν‚€) | -| λ‘λ‡Œ | `src/brain/gemini_client.py` | Gemini ν”„λ‘¬ν”„νŠΈ ꡬ성 및 JSON 응닡 νŒŒμ‹± | -| 방패 | `src/core/risk_manager.py` | μ„œν‚· 브레이컀 + 팻 ν•‘κ±° 체크 | -| μ•Œλ¦Ό | `src/notifications/telegram_client.py` | ν…”λ ˆκ·Έλž¨ μ‹€μ‹œκ°„ 거래 μ•Œλ¦Ό (선택사항) | -| μ§„ν™” | `src/evolution/optimizer.py` | μ‹€νŒ¨ νŒ¨ν„΄ 뢄석 β†’ μƒˆ μ „λž΅ 생성 β†’ ν…ŒμŠ€νŠΈ β†’ PR | -| DB | `src/db.py` | SQLite 거래 둜그 기둝 | +| μ„€μ • | `src/config.py` | Pydantic 기반 ν™˜κ²½λ³€μˆ˜ λ‘œλ”© 및 νƒ€μž… 검증 (35+ λ³€μˆ˜) | +| 브둜컀 | `src/broker/` | KIS API 비동기 래퍼 (κ΅­λ‚΄ + ν•΄μ™Έ 9개 μ‹œμž₯) | +| λ‘λ‡Œ | `src/brain/` | Gemini ν”„λ‘¬ν”„νŠΈ ꡬ성, JSON νŒŒμ‹±, 토큰 μ΅œμ ν™” | +| 방패 | `src/core/risk_manager.py` | μ„œν‚· 브레이컀 + 팻 ν•‘κ±° 체크 (READ-ONLY) | +| μ „λž΅ | `src/strategy/` | Pre-Market Planner, Scenario Engine, Playbook Store | +| μ»¨ν…μŠ€νŠΈ | `src/context/` | L1-L7 κ³„μΈ΅ν˜• λ©”λͺ¨λ¦¬ μ‹œμŠ€ν…œ | +| 뢄석 | `src/analysis/` | RSI, ATR, Smart Volatility Scanner | +| μ•Œλ¦Ό | `src/notifications/` | ν…”λ ˆκ·Έλž¨ μ–‘λ°©ν–₯ (μ•Œλ¦Ό + 9개 λͺ…λ Ήμ–΄) | +| λŒ€μ‹œλ³΄λ“œ | `src/dashboard/` | FastAPI 읽기 μ „μš© λͺ¨λ‹ˆν„°λ§ (8개 API) | +| μ§„ν™” | `src/evolution/` | μ „λž΅ μ§„ν™” + Daily Review + Scorecard | +| μ˜μ‚¬κ²°μ • 둜그 | `src/logging/` | 전체 거래 κ²°μ • 감사 좔적 | +| 데이터 | `src/data/` | λ‰΄μŠ€, μ‹œμž₯ 데이터, 경제 μΊ˜λ¦°λ” 연동 | +| λ°±μ—… | `src/backup/` | μžλ™ λ°±μ—…, S3 ν΄λΌμš°λ“œ, 무결성 검증 | +| DB | `src/db.py` | SQLite 거래 둜그 (5개 ν…Œμ΄λΈ”) | ## μ•ˆμ „μž₯치 @@ -42,6 +55,7 @@ KIS(ν•œκ΅­νˆ¬μžμ¦κΆŒ) API둜 λ§€λ§€ν•˜κ³ , Google Gemini둜 νŒλ‹¨ν•˜λ©°, 자 | 신뒰도 μž„κ³„κ°’ | Gemini 신뒰도 80 미만이면 κ°•μ œ HOLD | | 레이트 리미터 | Leaky Bucket μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ API 호좜 μ œν•œ | | 토큰 μžλ™ κ°±μ‹  | 만료 1λΆ„ μ „ μžλ™μœΌλ‘œ Access Token μž¬λ°œκΈ‰ | +| μ†μ ˆ λͺ¨λ‹ˆν„°λ§ | ν”Œλ ˆμ΄λΆ μ‹œλ‚˜λ¦¬μ˜€ 기반 μ‹€μ‹œκ°„ ν¬μ§€μ…˜ 보호 | ## λΉ λ₯Έ μ‹œμž‘ @@ -67,7 +81,11 @@ pytest -v --cov=src --cov-report=term-missing ### 4. μ‹€ν–‰ (λͺ¨μ˜νˆ¬μž) ```bash +# κΈ°λ³Έ μ‹€ν–‰ python -m src.main --mode=paper + +# λŒ€μ‹œλ³΄λ“œ ν™œμ„±ν™” +python -m src.main --mode=paper --dashboard ``` ### 5. Docker μ‹€ν–‰ @@ -76,7 +94,20 @@ python -m src.main --mode=paper docker compose up -d ouroboros ``` -## ν…”λ ˆκ·Έλž¨ μ•Œλ¦Ό (선택사항) +## 지원 μ‹œμž₯ + +| κ΅­κ°€ | κ±°λž˜μ†Œ | μ½”λ“œ | +|------|--------|------| +| πŸ‡°πŸ‡· ν•œκ΅­ | KRX | KR | +| πŸ‡ΊπŸ‡Έ λ―Έκ΅­ | NASDAQ, NYSE, AMEX | US_NASDAQ, US_NYSE, US_AMEX | +| πŸ‡―πŸ‡΅ 일본 | TSE | JP | +| πŸ‡­πŸ‡° 홍콩 | SEHK | HK | +| πŸ‡¨πŸ‡³ 쀑ꡭ | μƒν•˜μ΄, μ„ μ „ | CN_SHA, CN_SZA | +| πŸ‡»πŸ‡³ λ² νŠΈλ‚¨ | ν•˜λ…Έμ΄, 호치민 | VN_HNX, VN_HSX | + +`ENABLED_MARKETS` ν™˜κ²½λ³€μˆ˜λ‘œ ν™œμ„± μ‹œμž₯ 선택 (κΈ°λ³Έ: `KR,US`). + +## ν…”λ ˆκ·Έλž¨ (선택사항) 거래 μ‹€ν–‰, μ„œν‚· 브레이컀 λ°œλ™, μ‹œμŠ€ν…œ μƒνƒœ 등을 ν…”λ ˆκ·Έλž¨μœΌλ‘œ μ‹€μ‹œκ°„ μ•Œλ¦Ό 받을 수 μžˆμŠ΅λ‹ˆλ‹€. @@ -102,25 +133,51 @@ docker compose up -d ouroboros - ℹ️ μž₯ μ‹œμž‘/μ’…λ£Œ μ•Œλ¦Ό - πŸ“ μ‹œμŠ€ν…œ μ‹œμž‘/μ’…λ£Œ μƒνƒœ -**μ•ˆμ „μž₯치**: μ•Œλ¦Ό μ‹€νŒ¨ν•΄λ„ κ±°λž˜λŠ” 계속 μ§„ν–‰λ©λ‹ˆλ‹€. ν…”λ ˆκ·Έλž¨ API 였λ₯˜λ‚˜ μ„€μ • λˆ„λ½μ΄ μžˆμ–΄λ„ 거래 μ‹œμŠ€ν…œμ€ 정상 μž‘λ™ν•©λ‹ˆλ‹€. +### μ–‘λ°©ν–₯ λͺ…λ Ήμ–΄ + +`TELEGRAM_COMMANDS_ENABLED=true` (κΈ°λ³Έκ°’) μ„€μ • μ‹œ 9개 λŒ€ν™”ν˜• λͺ…λ Ήμ–΄ 지원: + +| λͺ…λ Ήμ–΄ | μ„€λͺ… | +|--------|------| +| `/help` | μ‚¬μš© κ°€λŠ₯ν•œ λͺ…λ Ήμ–΄ λͺ©λ‘ | +| `/status` | 거래 μƒνƒœ (λͺ¨λ“œ, μ‹œμž₯, P&L) | +| `/positions` | κ³„μ’Œ μš”μ•½ (μž”κ³ , ν˜„κΈˆ, P&L) | +| `/report` | 일일 μš”μ•½ (거래 수, P&L, 승λ₯ ) | +| `/scenarios` | 였늘의 ν”Œλ ˆμ΄λΆ μ‹œλ‚˜λ¦¬μ˜€ | +| `/review` | 졜근 μŠ€μ½”μ–΄μΉ΄λ“œ (L6_DAILY) | +| `/dashboard` | λŒ€μ‹œλ³΄λ“œ URL ν‘œμ‹œ | +| `/stop` | 거래 μΌμ‹œ μ •μ§€ | +| `/resume` | 거래 재개 | + +**μ•ˆμ „μž₯치**: μ•Œλ¦Ό μ‹€νŒ¨ν•΄λ„ κ±°λž˜λŠ” 계속 μ§„ν–‰λ©λ‹ˆλ‹€. ## ν…ŒμŠ€νŠΈ -35개 ν…ŒμŠ€νŠΈκ°€ TDD λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ 전에 λ¨Όμ € μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. +551개 ν…ŒμŠ€νŠΈκ°€ 25개 νŒŒμΌμ— 걸쳐 κ΅¬ν˜„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ΅œμ†Œ 컀버리지 80%. ``` -tests/test_risk.py β€” μ„œν‚· 브레이컀, 팻 ν•‘κ±°, 톡합 검증 (11개) -tests/test_broker.py β€” 토큰 관리, νƒ€μž„μ•„μ›ƒ, HTTP μ—λŸ¬, ν•΄μ‹œν‚€ (6개) -tests/test_brain.py β€” JSON νŒŒμ‹±, 신뒰도 μž„κ³„κ°’, 비정상 응닡 처리 (15개) +tests/test_scenario_engine.py β€” μ‹œλ‚˜λ¦¬μ˜€ λ§€μΉ­ (44개) +tests/test_data_integration.py β€” μ™ΈλΆ€ 데이터 연동 (38개) +tests/test_pre_market_planner.py β€” ν”Œλ ˆμ΄λΆ 생성 (37개) +tests/test_main.py β€” 거래 루프 톡합 (37개) +tests/test_token_efficiency.py β€” 토큰 μ΅œμ ν™” (34개) +tests/test_strategy_models.py β€” μ „λž΅ λͺ¨λΈ 검증 (33개) +tests/test_telegram_commands.py β€” ν…”λ ˆκ·Έλž¨ λͺ…λ Ήμ–΄ (31개) +tests/test_latency_control.py β€” μ§€μ—°μ‹œκ°„ μ œμ–΄ (30개) +tests/test_telegram.py β€” ν…”λ ˆκ·Έλž¨ μ•Œλ¦Ό (25개) +... μ™Έ 16개 파일 ``` +**상세**: [docs/testing.md](docs/testing.md) + ## 기술 μŠ€νƒ - **μ–Έμ–΄**: Python 3.11+ (asyncio 기반) -- **브둜컀**: KIS Open API (REST) +- **브둜컀**: KIS Open API (REST, κ΅­λ‚΄+ν•΄μ™Έ) - **AI**: Google Gemini Pro -- **DB**: SQLite -- **검증**: pytest + coverage +- **DB**: SQLite (5개 ν…Œμ΄λΈ”: trades, contexts, decision_logs, playbooks, context_metadata) +- **λŒ€μ‹œλ³΄λ“œ**: FastAPI + uvicorn +- **검증**: pytest + coverage (551 tests) - **CI/CD**: GitHub Actions - **배포**: Docker + Docker Compose @@ -128,27 +185,50 @@ tests/test_brain.py β€” JSON νŒŒμ‹±, 신뒰도 μž„κ³„κ°’, 비정상 응닡 처 ``` The-Ouroboros/ -β”œβ”€β”€ .github/workflows/ci.yml # CI νŒŒμ΄ν”„λΌμΈ β”œβ”€β”€ docs/ -β”‚ β”œβ”€β”€ agents.md # AI μ—μ΄μ „νŠΈ 페λ₯΄μ†Œλ‚˜ μ •μ˜ -β”‚ └── skills.md # μ‚¬μš© κ°€λŠ₯ν•œ 도ꡬ λͺ©λ‘ +β”‚ β”œβ”€β”€ architecture.md # μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜ +β”‚ β”œβ”€β”€ testing.md # ν…ŒμŠ€νŠΈ κ°€μ΄λ“œ +β”‚ β”œβ”€β”€ commands.md # λͺ…λ Ήμ–΄ 레퍼런슀 +β”‚ β”œβ”€β”€ context-tree.md # L1-L7 λ©”λͺ¨λ¦¬ μ‹œμŠ€ν…œ +β”‚ β”œβ”€β”€ workflow.md # Git μ›Œν¬ν”Œλ‘œμš° +β”‚ β”œβ”€β”€ agents.md # μ—μ΄μ „νŠΈ μ •μ±… +β”‚ β”œβ”€β”€ skills.md # 도ꡬ λͺ©λ‘ +β”‚ β”œβ”€β”€ disaster_recovery.md # λ°±μ—…/볡ꡬ +β”‚ └── requirements-log.md # μš”κ΅¬μ‚¬ν•­ 기둝 β”œβ”€β”€ src/ -β”‚ β”œβ”€β”€ config.py # Pydantic μ„€μ • -β”‚ β”œβ”€β”€ logging_config.py # JSON ꡬ쑰화 λ‘œκΉ… -β”‚ β”œβ”€β”€ db.py # SQLite 거래 기둝 -β”‚ β”œβ”€β”€ main.py # 비동기 거래 루프 -β”‚ β”œβ”€β”€ broker/kis_api.py # KIS API ν΄λΌμ΄μ–ΈνŠΈ -β”‚ β”œβ”€β”€ brain/gemini_client.py # Gemini μ˜μ‚¬κ²°μ • μ—”μ§„ -β”‚ β”œβ”€β”€ core/risk_manager.py # 리슀크 관리 -β”‚ β”œβ”€β”€ notifications/telegram_client.py # ν…”λ ˆκ·Έλž¨ μ•Œλ¦Ό -β”‚ β”œβ”€β”€ evolution/optimizer.py # μ „λž΅ μ§„ν™” μ—”μ§„ -β”‚ └── strategies/base.py # μ „λž΅ 베이슀 클래슀 -β”œβ”€β”€ tests/ # TDD ν…ŒμŠ€νŠΈ μŠ€μœ„νŠΈ +β”‚ β”œβ”€β”€ analysis/ # 기술적 뢄석 (RSI, ATR, Smart Scanner) +β”‚ β”œβ”€β”€ backup/ # λ°±μ—… (μŠ€μΌ€μ€„λŸ¬, S3, 무결성 검증) +β”‚ β”œβ”€β”€ brain/ # Gemini μ˜μ‚¬κ²°μ • (ν”„λ‘¬ν”„νŠΈ μ΅œμ ν™”, μ»¨ν…μŠ€νŠΈ 선택) +β”‚ β”œβ”€β”€ broker/ # KIS API (κ΅­λ‚΄ + ν•΄μ™Έ) +β”‚ β”œβ”€β”€ context/ # L1-L7 계측 λ©”λͺ¨λ¦¬ +β”‚ β”œβ”€β”€ core/ # 리슀크 관리 (READ-ONLY) +β”‚ β”œβ”€β”€ dashboard/ # FastAPI λͺ¨λ‹ˆν„°λ§ λŒ€μ‹œλ³΄λ“œ +β”‚ β”œβ”€β”€ data/ # μ™ΈλΆ€ 데이터 연동 +β”‚ β”œβ”€β”€ evolution/ # μ „λž΅ μ§„ν™” + Daily Review +β”‚ β”œβ”€β”€ logging/ # μ˜μ‚¬κ²°μ • 감사 좔적 +β”‚ β”œβ”€β”€ markets/ # μ‹œμž₯ μŠ€μΌ€μ€„ + νƒ€μž„μ‘΄ +β”‚ β”œβ”€β”€ notifications/ # ν…”λ ˆκ·Έλž¨ μ•Œλ¦Ό + λͺ…λ Ήμ–΄ +β”‚ β”œβ”€β”€ strategy/ # ν”Œλ ˆμ΄λΆ (Planner, Scenario Engine) +β”‚ β”œβ”€β”€ config.py # Pydantic μ„€μ • +β”‚ β”œβ”€β”€ db.py # SQLite λ°μ΄ν„°λ² μ΄μŠ€ +β”‚ └── main.py # 비동기 거래 루프 +β”œβ”€β”€ tests/ # 551개 ν…ŒμŠ€νŠΈ (25개 파일) β”œβ”€β”€ Dockerfile # λ©€ν‹°μŠ€ν…Œμ΄μ§€ λΉŒλ“œ β”œβ”€β”€ docker-compose.yml # μ„œλΉ„μŠ€ μ˜€μΌ€μŠ€νŠΈλ ˆμ΄μ…˜ └── pyproject.toml # μ˜μ‘΄μ„± 및 도ꡬ μ„€μ • ``` +## λ¬Έμ„œ + +- **[μ•„ν‚€ν…μ²˜](docs/architecture.md)** β€” μ‹œμŠ€ν…œ 섀계, μ»΄ν¬λ„ŒνŠΈ, 데이터 흐름 +- **[ν…ŒμŠ€νŠΈ](docs/testing.md)** β€” ν…ŒμŠ€νŠΈ ꡬ쑰, 컀버리지, μž‘μ„± κ°€μ΄λ“œ +- **[λͺ…λ Ήμ–΄](docs/commands.md)** β€” CLI, Dashboard, Telegram λͺ…λ Ήμ–΄ +- **[μ»¨ν…μŠ€νŠΈ 트리](docs/context-tree.md)** β€” L1-L7 계측 λ©”λͺ¨λ¦¬ +- **[μ›Œν¬ν”Œλ‘œμš°](docs/workflow.md)** β€” Git μ›Œν¬ν”Œλ‘œμš° μ •μ±… +- **[μ—μ΄μ „νŠΈ μ •μ±…](docs/agents.md)** β€” μ•ˆμ „ μ œμ•½, κΈˆμ§€ ν–‰μœ„ +- **[λ°±μ—…/볡ꡬ](docs/disaster_recovery.md)** β€” μž¬ν•΄ 볡ꡬ 절차 +- **[μš”κ΅¬μ‚¬ν•­](docs/requirements-log.md)** β€” μ‚¬μš©μž μš”κ΅¬μ‚¬ν•­ 좔적 + ## λΌμ΄μ„ μŠ€ 이 ν”„λ‘œμ νŠΈμ˜ λΌμ΄μ„ μŠ€λŠ” [LICENSE](LICENSE) νŒŒμΌμ„ μ°Έμ‘°ν•˜μ„Έμš”. diff --git a/docs/architecture.md b/docs/architecture.md index e31ea9c..30d5d62 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -2,7 +2,9 @@ ## Overview -Self-evolving AI trading agent for global stock markets via KIS (Korea Investment & Securities) API. The main loop in `src/main.py` orchestrates four components across multiple markets with two trading modes: daily (batch API calls) or realtime (per-stock decisions). +Self-evolving AI trading agent for global stock markets via KIS (Korea Investment & Securities) API. The main loop in `src/main.py` orchestrates components across multiple markets with two trading modes: daily (batch API calls) or realtime (per-stock decisions). + +**v2 Proactive Playbook Architecture**: The system uses a "plan once, execute locally" approach. Pre-market, the AI generates a playbook of scenarios (one Gemini API call per market per day). During trading hours, a local scenario engine matches live market data against these pre-computed scenarios β€” no additional AI calls needed. This dramatically reduces API costs and latency. ## Trading Modes @@ -46,9 +48,11 @@ High-frequency trading with individual stock analysis: **KISBroker** (`kis_api.py`) β€” Async KIS API client for domestic Korean market - Automatic OAuth token refresh (valid for 24 hours) -- Leaky-bucket rate limiter (10 requests per second) +- Leaky-bucket rate limiter (configurable RPS, default 2.0) - POST body hash-key signing for order authentication - Custom SSL context with disabled hostname verification for VTS (virtual trading) endpoint due to known certificate mismatch +- `fetch_market_rankings()` β€” Fetch volume surge rankings from KIS API +- `get_daily_prices()` β€” Fetch OHLCV history for technical analysis **OverseasBroker** (`overseas.py`) β€” KIS overseas stock API wrapper @@ -63,10 +67,7 @@ High-frequency trading with individual stock analysis: - `is_market_open()` checks weekends, trading hours, lunch breaks - `get_open_markets()` returns currently active markets - `get_next_market_open()` finds next market to open and when - -**New API Methods** (added in v0.9.0): -- `fetch_market_rankings()` β€” Fetch volume surge rankings from KIS API -- `get_daily_prices()` β€” Fetch OHLCV history for technical analysis +- 10 global markets defined (KR, US_NASDAQ, US_NYSE, US_AMEX, JP, HK, CN_SHA, CN_SZA, VN_HNX, VN_HSX) ### 2. Analysis (`src/analysis/`) @@ -91,14 +92,9 @@ High-frequency trading with individual stock analysis: - **Fallback**: Uses static watchlist if ranking API unavailable - **Realtime mode only**: Daily mode uses batch processing for API efficiency -**Benefits:** -- Reduces Gemini API calls from 20-30 stocks to 1-3 qualified candidates -- Fast Python-based filtering before expensive AI judgment -- Logs selection context (RSI, volume_ratio, signal, score) for Evolution system +### 3. Brain (`src/brain/`) -### 3. Brain (`src/brain/gemini_client.py`) - -**GeminiClient** β€” AI decision engine powered by Google Gemini +**GeminiClient** (`gemini_client.py`) β€” AI decision engine powered by Google Gemini - Constructs structured prompts from market data - Parses JSON responses into `TradeDecision` objects (`action`, `confidence`, `rationale`) @@ -106,11 +102,20 @@ High-frequency trading with individual stock analysis: - Falls back to safe HOLD on any parse/API error - Handles markdown-wrapped JSON, malformed responses, invalid actions +**PromptOptimizer** (`prompt_optimizer.py`) β€” Token efficiency optimization + +- Reduces prompt size while preserving decision quality +- Caches optimized prompts + +**ContextSelector** (`context_selector.py`) β€” Relevant context selection for prompts + +- Selects appropriate context layers for current market conditions + ### 4. Risk Manager (`src/core/risk_manager.py`) **RiskManager** β€” Safety circuit breaker and order validation -⚠️ **READ-ONLY by policy** (see [`docs/agents.md`](./agents.md)) +> **READ-ONLY by policy** (see [`docs/agents.md`](./agents.md)) - **Circuit Breaker**: Halts all trading via `SystemExit` when daily P&L drops below -3.0% - Threshold may only be made stricter, never relaxed @@ -118,7 +123,79 @@ High-frequency trading with individual stock analysis: - **Fat-Finger Protection**: Rejects orders exceeding 30% of available cash - Must always be enforced, cannot be disabled -### 5. Notifications (`src/notifications/telegram_client.py`) +### 5. Strategy (`src/strategy/`) + +**Pre-Market Planner** (`pre_market_planner.py`) β€” AI playbook generation + +- Runs before market open (configurable `PRE_MARKET_MINUTES`, default 30) +- Generates scenario-based playbooks via single Gemini API call per market +- Handles timeout (`PLANNER_TIMEOUT_SECONDS`, default 60) with defensive playbook fallback +- Persists playbooks to database for audit trail + +**Scenario Engine** (`scenario_engine.py`) β€” Local scenario matching + +- Matches live market data against pre-computed playbook scenarios +- No AI calls during trading hours β€” pure Python matching logic +- Returns matched scenarios with confidence scores +- Configurable `MAX_SCENARIOS_PER_STOCK` (default 5) +- Periodic rescan at `RESCAN_INTERVAL_SECONDS` (default 300) + +**Playbook Store** (`playbook_store.py`) β€” Playbook persistence + +- SQLite-backed storage for daily playbooks +- Date and market-based retrieval +- Status tracking (generated, active, expired) + +**Models** (`models.py`) β€” Pydantic data models + +- Scenario, Playbook, MatchResult, and related type definitions + +### 6. Context System (`src/context/`) + +**Context Store** (`store.py`) β€” L1-L7 hierarchical memory + +- 7-layer context system (see [docs/context-tree.md](./context-tree.md)): + - L1: Tick-level (real-time price) + - L2: Intraday (session summary) + - L3: Daily (end-of-day) + - L4: Weekly (trend analysis) + - L5: Monthly (strategy review) + - L6: Daily Review (scorecard) + - L7: Evolution (long-term learning) +- Key-value storage with timeframe tagging +- SQLite persistence in `contexts` table + +**Context Scheduler** (`scheduler.py`) β€” Periodic aggregation + +- Scheduled summarization from lower to higher layers +- Configurable aggregation intervals + +**Context Summarizer** (`summarizer.py`) β€” Layer summarization + +- Aggregates lower-layer data into higher-layer summaries + +### 7. Dashboard (`src/dashboard/`) + +**FastAPI App** (`app.py`) β€” Read-only monitoring dashboard + +- Runs as daemon thread when enabled (`--dashboard` CLI flag or `DASHBOARD_ENABLED=true`) +- Configurable host/port (`DASHBOARD_HOST`, `DASHBOARD_PORT`, default `127.0.0.1:8080`) +- Serves static HTML frontend + +**8 API Endpoints:** + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/` | GET | Static HTML dashboard | +| `/api/status` | GET | Daily trading status by market | +| `/api/playbook/{date}` | GET | Playbook for specific date and market | +| `/api/scorecard/{date}` | GET | Daily scorecard from L6_DAILY context | +| `/api/performance` | GET | Trading performance metrics (by market + combined) | +| `/api/context/{layer}` | GET | Query context by layer (L1-L7) | +| `/api/decisions` | GET | Decision log entries with outcomes | +| `/api/scenarios/active` | GET | Today's matched scenarios | + +### 8. Notifications (`src/notifications/telegram_client.py`) **TelegramClient** β€” Real-time event notifications via Telegram Bot API @@ -126,7 +203,13 @@ High-frequency trading with individual stock analysis: - Non-blocking: failures are logged but never crash trading - Rate-limited: 1 message/second default to respect Telegram API limits - Auto-disabled when credentials missing -- Gracefully handles API errors, network timeouts, invalid tokens + +**TelegramCommandHandler** β€” Bidirectional command interface + +- Long polling from Telegram API (configurable `TELEGRAM_POLLING_INTERVAL`) +- 9 interactive commands: `/help`, `/status`, `/positions`, `/report`, `/scenarios`, `/review`, `/dashboard`, `/stop`, `/resume` +- Authorization filtering by `TELEGRAM_CHAT_ID` +- Enable/disable via `TELEGRAM_COMMANDS_ENABLED` (default: true) **Notification Types:** - Trade execution (BUY/SELL with confidence) @@ -134,12 +217,12 @@ High-frequency trading with individual stock analysis: - Fat-finger protection triggers (order rejection) - Market open/close events - System startup/shutdown status +- Playbook generation results +- Stop-loss monitoring alerts -**Setup:** See [src/notifications/README.md](../src/notifications/README.md) for bot creation and configuration. +### 9. Evolution (`src/evolution/`) -### 6. Evolution (`src/evolution/optimizer.py`) - -**StrategyOptimizer** β€” Self-improvement loop +**StrategyOptimizer** (`optimizer.py`) β€” Self-improvement loop - Analyzes high-confidence losing trades from SQLite - Asks Gemini to generate new `BaseStrategy` subclasses @@ -147,99 +230,196 @@ High-frequency trading with individual stock analysis: - Simulates PR creation for human review - Only activates strategies that pass all tests +**DailyReview** (`daily_review.py`) β€” End-of-day review + +- Generates comprehensive trade performance summary +- Stores results in L6_DAILY context layer +- Tracks win rate, P&L, confidence accuracy + +**DailyScorecard** (`scorecard.py`) β€” Performance scoring + +- Calculates daily metrics (trades, P&L, win rate, avg confidence) +- Enables trend tracking across days + +**Stop-Loss Monitoring** β€” Real-time position protection + +- Monitors positions against stop-loss levels from playbook scenarios +- Sends Telegram alerts when thresholds approached or breached + +### 10. Decision Logger (`src/logging/decision_logger.py`) + +**DecisionLogger** β€” Comprehensive audit trail + +- Logs every trading decision with full context snapshot +- Captures input data, rationale, confidence, and outcomes +- Supports outcome tracking (P&L, accuracy) for post-analysis +- Stored in `decision_logs` table with indexed queries +- Review workflow support (reviewed flag, review notes) + +### 11. Data Integration (`src/data/`) + +**External Data Sources** (optional): + +- `news_api.py` β€” News sentiment data +- `market_data.py` β€” Extended market data +- `economic_calendar.py` β€” Economic event calendar + +### 12. Backup (`src/backup/`) + +**Disaster Recovery** (see [docs/disaster_recovery.md](./disaster_recovery.md)): + +- `scheduler.py` β€” Automated backup scheduling +- `exporter.py` β€” Data export to various formats +- `cloud_storage.py` β€” S3-compatible cloud backup +- `health_monitor.py` β€” Backup integrity verification + ## Data Flow +### Playbook Mode (Daily β€” Primary v2 Flow) + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Pre-Market Phase (before market open) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Pre-Market Planner β”‚ + β”‚ - 1 Gemini API call per market β”‚ + β”‚ - Generate scenario playbook β”‚ + β”‚ - Store in playbooks table β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Trading Hours (market open β†’ close) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Market Schedule Check β”‚ + β”‚ - Get open markets β”‚ + β”‚ - Filter by enabled markets β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Scenario Engine (local) β”‚ + β”‚ - Match live data vs playbook β”‚ + β”‚ - No AI calls needed β”‚ + β”‚ - Return matched scenarios β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Risk Manager: Validate Order β”‚ + β”‚ - Check circuit breaker β”‚ + β”‚ - Check fat-finger limit β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Broker: Execute Order β”‚ + β”‚ - Domestic: send_order() β”‚ + β”‚ - Overseas: send_overseas_order()β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Decision Logger + DB β”‚ + β”‚ - Full audit trail β”‚ + β”‚ - Context snapshot β”‚ + β”‚ - Telegram notification β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Post-Market Phase β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Daily Review + Scorecard β”‚ + β”‚ - Performance summary β”‚ + β”‚ - Store in L6_DAILY context β”‚ + β”‚ - Evolution learning β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + ### Realtime Mode (with Smart Scanner) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Main Loop (60s cycle per market) β”‚ +β”‚ Main Loop (60s cycle per market) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Market Schedule Check β”‚ - β”‚ - Get open markets β”‚ - β”‚ - Filter by enabled markets β”‚ - β”‚ - Wait if all closed β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Market Schedule Check β”‚ + β”‚ - Get open markets β”‚ + β”‚ - Filter by enabled markets β”‚ + β”‚ - Wait if all closed β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Smart Scanner (Python-first) β”‚ + β”‚ Smart Scanner (Python-first) β”‚ β”‚ - Fetch volume rankings (KIS) β”‚ β”‚ - Get 20d price history per stockβ”‚ β”‚ - Calculate RSI(14) + vol ratio β”‚ β”‚ - Filter: vol>2x AND RSI extreme β”‚ β”‚ - Return top 3 qualified stocks β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ For Each Qualified Candidate β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ For Each Qualified Candidate β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Broker: Fetch Market Data β”‚ β”‚ - Domestic: orderbook + balance β”‚ β”‚ - Overseas: price + balance β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Calculate P&L β”‚ - β”‚ pnl_pct = (eval - cost) / cost β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Brain: Get Decision (AI) β”‚ + β”‚ - Build prompt with market data β”‚ + β”‚ - Call Gemini API β”‚ + β”‚ - Parse JSON response β”‚ + β”‚ - Return TradeDecision β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Brain: Get Decision (AI) β”‚ - β”‚ - Build prompt with market data β”‚ - β”‚ - Call Gemini API β”‚ - β”‚ - Parse JSON response β”‚ - β”‚ - Return TradeDecision β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Risk Manager: Validate Order β”‚ + β”‚ - Check circuit breaker β”‚ + β”‚ - Check fat-finger limit β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Risk Manager: Validate Order β”‚ - β”‚ - Check circuit breaker β”‚ - β”‚ - Check fat-finger limit β”‚ - β”‚ - Raise if validation fails β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Broker: Execute Order β”‚ + β”‚ - Domestic: send_order() β”‚ + β”‚ - Overseas: send_overseas_order()β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Broker: Execute Order β”‚ - β”‚ - Domestic: send_order() β”‚ - β”‚ - Overseas: send_overseas_order() β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Notifications: Send Alert β”‚ - β”‚ - Trade execution notification β”‚ - β”‚ - Non-blocking (errors logged) β”‚ - β”‚ - Rate-limited to 1/sec β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Database: Log Trade β”‚ - β”‚ - SQLite (data/trades.db) β”‚ - β”‚ - Track: action, confidence, β”‚ - β”‚ rationale, market, exchange β”‚ - β”‚ - NEW: selection_context (JSON) β”‚ - β”‚ - RSI, volume_ratio, signal β”‚ - β”‚ - For Evolution optimization β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Decision Logger + Notifications β”‚ + β”‚ - Log trade to SQLite β”‚ + β”‚ - selection_context (JSON) β”‚ + β”‚ - Telegram notification β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## Database Schema -**SQLite** (`src/db.py`) +**SQLite** (`src/db.py`) β€” Database: `data/trades.db` +### trades ```sql CREATE TABLE trades ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -251,25 +431,73 @@ CREATE TABLE trades ( quantity INTEGER, price REAL, pnl REAL DEFAULT 0.0, - market TEXT DEFAULT 'KR', -- KR | US_NASDAQ | JP | etc. - exchange_code TEXT DEFAULT 'KRX', -- KRX | NASD | NYSE | etc. - selection_context TEXT -- JSON: {rsi, volume_ratio, signal, score} + market TEXT DEFAULT 'KR', + exchange_code TEXT DEFAULT 'KRX', + selection_context TEXT, -- JSON: {rsi, volume_ratio, signal, score} + decision_id TEXT -- Links to decision_logs ); ``` -**Selection Context** (new in v0.9.0): Stores scanner selection criteria as JSON: -```json -{ - "rsi": 28.5, - "volume_ratio": 2.7, - "signal": "oversold", - "score": 85.2 -} +### contexts +```sql +CREATE TABLE contexts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + layer TEXT NOT NULL, -- L1 through L7 + timeframe TEXT, + key TEXT NOT NULL, + value TEXT NOT NULL, -- JSON data + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); +-- Indices: idx_contexts_layer, idx_contexts_timeframe, idx_contexts_updated ``` -Enables Evolution system to analyze correlation between selection criteria and trade outcomes. +### decision_logs +```sql +CREATE TABLE decision_logs ( + decision_id TEXT PRIMARY KEY, + timestamp TEXT NOT NULL, + stock_code TEXT, + market TEXT, + exchange_code TEXT, + action TEXT, + confidence INTEGER, + rationale TEXT, + context_snapshot TEXT, -- JSON: full context at decision time + input_data TEXT, -- JSON: market data used + outcome_pnl REAL, + outcome_accuracy REAL, + reviewed INTEGER DEFAULT 0, + review_notes TEXT +); +-- Indices: idx_decision_logs_timestamp, idx_decision_logs_reviewed, idx_decision_logs_confidence +``` -Auto-migration: Adds `market`, `exchange_code`, and `selection_context` columns if missing for backward compatibility. +### playbooks +```sql +CREATE TABLE playbooks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + date TEXT NOT NULL, + market TEXT NOT NULL, + status TEXT DEFAULT 'generated', + playbook_json TEXT NOT NULL, -- Full playbook with scenarios + generated_at TEXT NOT NULL, + token_count INTEGER, + scenario_count INTEGER, + match_count INTEGER DEFAULT 0 +); +-- Indices: idx_playbooks_date, idx_playbooks_market +``` + +### context_metadata +```sql +CREATE TABLE context_metadata ( + layer TEXT PRIMARY KEY, + description TEXT, + retention_days INTEGER, + aggregation_source TEXT +); +``` ## Configuration @@ -284,29 +512,62 @@ KIS_APP_SECRET=your_app_secret KIS_ACCOUNT_NO=XXXXXXXX-XX GEMINI_API_KEY=your_gemini_key -# Optional +# Optional β€” Trading Mode MODE=paper # paper | live -DB_PATH=data/trades.db -CONFIDENCE_THRESHOLD=80 -MAX_LOSS_PCT=3.0 -MAX_ORDER_PCT=30.0 -ENABLED_MARKETS=KR,US_NASDAQ # Comma-separated market codes - -# Trading Mode (API efficiency) TRADE_MODE=daily # daily | realtime DAILY_SESSIONS=4 # Sessions per day (daily mode only) SESSION_INTERVAL_HOURS=6 # Hours between sessions (daily mode only) -# Telegram Notifications (optional) +# Optional β€” Database +DB_PATH=data/trades.db + +# Optional β€” Risk +CONFIDENCE_THRESHOLD=80 +MAX_LOSS_PCT=3.0 +MAX_ORDER_PCT=30.0 + +# Optional β€” Markets +ENABLED_MARKETS=KR,US # Comma-separated market codes +RATE_LIMIT_RPS=2.0 # KIS API requests per second + +# Optional β€” Pre-Market Planner (v2) +PRE_MARKET_MINUTES=30 # Minutes before market open to generate playbook +MAX_SCENARIOS_PER_STOCK=5 # Max scenarios per stock in playbook +PLANNER_TIMEOUT_SECONDS=60 # Timeout for playbook generation +DEFENSIVE_PLAYBOOK_ON_FAILURE=true # Fallback on AI failure +RESCAN_INTERVAL_SECONDS=300 # Scenario rescan interval during trading + +# Optional β€” Smart Scanner (realtime mode only) +RSI_OVERSOLD_THRESHOLD=30 # 0-50, oversold threshold +RSI_MOMENTUM_THRESHOLD=70 # 50-100, momentum threshold +VOL_MULTIPLIER=2.0 # Minimum volume ratio (2.0 = 200%) +SCANNER_TOP_N=3 # Max qualified candidates per scan + +# Optional β€” Dashboard +DASHBOARD_ENABLED=false # Enable FastAPI dashboard +DASHBOARD_HOST=127.0.0.1 # Dashboard bind address +DASHBOARD_PORT=8080 # Dashboard port (1-65535) + +# Optional β€” Telegram TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz TELEGRAM_CHAT_ID=123456789 TELEGRAM_ENABLED=true +TELEGRAM_COMMANDS_ENABLED=true # Enable bidirectional commands +TELEGRAM_POLLING_INTERVAL=1.0 # Command polling interval (seconds) -# Smart Scanner (optional, realtime mode only) -RSI_OVERSOLD_THRESHOLD=30 # 0-50, oversold threshold -RSI_MOMENTUM_THRESHOLD=70 # 50-100, momentum threshold -VOL_MULTIPLIER=2.0 # Minimum volume ratio (2.0 = 200%) -SCANNER_TOP_N=3 # Max qualified candidates per scan +# Optional β€” Backup +BACKUP_ENABLED=false +BACKUP_DIR=data/backups +S3_ENDPOINT_URL=... +S3_ACCESS_KEY=... +S3_SECRET_KEY=... +S3_BUCKET_NAME=... +S3_REGION=... + +# Optional β€” External Data +NEWS_API_KEY=... +NEWS_API_PROVIDER=... +MARKET_DATA_API_KEY=... ``` Tests use in-memory SQLite (`DB_PATH=":memory:"`) and dummy credentials via `tests/conftest.py`. @@ -340,4 +601,9 @@ Tests use in-memory SQLite (`DB_PATH=":memory:"`) and dummy credentials via `tes - Invalid token β†’ log error, trading unaffected - Rate limit exceeded β†’ queued via rate limiter -**Guarantee**: Notification failures never interrupt trading operations. +### Playbook Generation Failure +- Timeout β†’ fall back to defensive playbook (`DEFENSIVE_PLAYBOOK_ON_FAILURE`) +- API error β†’ use previous day's playbook if available +- No playbook β†’ skip pre-market phase, fall back to direct AI calls + +**Guarantee**: Notification and dashboard failures never interrupt trading operations. diff --git a/docs/commands.md b/docs/commands.md index 1053ac5..6f00b17 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -119,7 +119,7 @@ No decorator needed for async tests. # Install all dependencies (production + dev) pip install -e ".[dev]" -# Run full test suite with coverage +# Run full test suite with coverage (551 tests across 25 files) pytest -v --cov=src --cov-report=term-missing # Run a single test file @@ -137,11 +137,61 @@ mypy src/ --strict # Run the trading agent python -m src.main --mode=paper +# Run with dashboard enabled +python -m src.main --mode=paper --dashboard + # Docker docker compose up -d ouroboros # Run agent docker compose --profile test up test # Run tests in container ``` +## Dashboard + +The FastAPI dashboard provides read-only monitoring of the trading system. + +### Starting the Dashboard + +```bash +# Via CLI flag +python -m src.main --mode=paper --dashboard + +# Via environment variable +DASHBOARD_ENABLED=true python -m src.main --mode=paper +``` + +Dashboard runs as a daemon thread on `DASHBOARD_HOST:DASHBOARD_PORT` (default: `127.0.0.1:8080`). + +### API Endpoints + +| Endpoint | Description | +|----------|-------------| +| `GET /` | HTML dashboard UI | +| `GET /api/status` | Daily trading status by market | +| `GET /api/playbook/{date}` | Playbook for specific date (query: `market`) | +| `GET /api/scorecard/{date}` | Daily scorecard from L6_DAILY context | +| `GET /api/performance` | Performance metrics by market and combined | +| `GET /api/context/{layer}` | Context data by layer L1-L7 (query: `timeframe`) | +| `GET /api/decisions` | Decision log entries (query: `limit`, `market`) | +| `GET /api/scenarios/active` | Today's matched scenarios | + +## Telegram Commands + +When `TELEGRAM_COMMANDS_ENABLED=true` (default), the bot accepts these interactive commands: + +| Command | Description | +|---------|-------------| +| `/help` | List available commands | +| `/status` | Show trading status (mode, markets, P&L) | +| `/positions` | Display account summary (balance, cash, P&L) | +| `/report` | Daily summary metrics (trades, P&L, win rate) | +| `/scenarios` | Show today's playbook scenarios | +| `/review` | Display recent scorecards (L6_DAILY layer) | +| `/dashboard` | Show dashboard URL if enabled | +| `/stop` | Pause trading | +| `/resume` | Resume trading | + +Commands are only processed from the authorized `TELEGRAM_CHAT_ID`. + ## Environment Setup ```bash diff --git a/docs/requirements-log.md b/docs/requirements-log.md index 59a0eae..8522657 100644 --- a/docs/requirements-log.md +++ b/docs/requirements-log.md @@ -86,3 +86,28 @@ - Plan Consistency (ν•„μˆ˜), Safety & Constraints, Quality, Workflow 4개 μΉ΄ν…Œκ³ λ¦¬ **이슈/PR:** #114 + +--- + +## 2026-02-16 + +### λ¬Έμ„œ v2 동기화 (전체 λ¬Έμ„œ ν˜„ν–‰ν™”) + +**λ°°κ²½:** +- v2 κΈ°λŠ₯ κ΅¬ν˜„ μ™„λ£Œ ν›„ λ¬Έμ„œκ°€ μ‹€μ œ μ½”λ“œ μƒνƒœμ™€ 크게 괴리 +- λ¬Έμ„œμ—λŠ” 54 tests / 4 files둜 κΈ°λ‘λ˜μ—ˆμœΌλ‚˜ μ‹€μ œλ‘œλŠ” 551 tests / 25 files +- v2 핡심 κΈ°λŠ₯(Playbook, Scenario Engine, Dashboard, Telegram Commands, Daily Review, Context System, Backup) λ¬Έμ„œν™” λˆ„λ½ + +**μš”κ΅¬μ‚¬ν•­:** +1. `docs/testing.md` β€” 551 tests / 25 files 반영, 전체 ν…ŒμŠ€νŠΈ 파일 μ„€λͺ… +2. `docs/architecture.md` β€” v2 μ»΄ν¬λ„ŒνŠΈ(Strategy, Context, Dashboard, Decision Logger λ“±) μΆ”κ°€, Playbook Mode 데이터 ν”Œλ‘œμš°, DB μŠ€ν‚€λ§ˆ 5개 ν…Œμ΄λΈ”, v2 ν™˜κ²½λ³€μˆ˜ +3. `docs/commands.md` β€” Dashboard μ‹€ν–‰ λͺ…λ Ήμ–΄, Telegram λͺ…λ Ήμ–΄ 9μ’… 레퍼런슀 +4. `CLAUDE.md` β€” Project Structure 트리 ν™•μž₯, ν…ŒμŠ€νŠΈ 수 μ—…λ°μ΄νŠΈ, `--dashboard` ν”Œλž˜κ·Έ +5. `docs/skills.md` β€” DB 파일λͺ… `trades.db`둜 톡일, Dashboard λͺ…λ Ήμ–΄ μΆ”κ°€ +6. 기쑴에 μœ νš¨ν•œ νŠΈλŸ¬λΈ”μŠˆνŒ…, μ½”λ“œ 예제 등은 μœ μ§€ + +**κ΅¬ν˜„ κ²°κ³Ό:** +- 6개 λ¬Έμ„œ 파일 μ—…λ°μ΄νŠΈ +- 이전 μ‹œλ„(2개 컀밋)λŠ” κΈ°μ‘΄ λ‚΄μš©μ„ κ³Όλ„ν•˜κ²Œ μ‚­μ œν•˜μ—¬ 폐기, main κΈ°μ€€μœΌλ‘œ μž¬μž‘μ—… + +**이슈/PR:** #131, PR #134 diff --git a/docs/skills.md b/docs/skills.md index dc75ba4..96ea254 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -34,6 +34,12 @@ python -m src.main --mode=paper ``` Runs the agent in paper-trading mode (no real orders). +### Start Trading Agent with Dashboard +```bash +python -m src.main --mode=paper --dashboard +``` +Runs the agent with FastAPI dashboard on `127.0.0.1:8080` (configurable via `DASHBOARD_HOST`/`DASHBOARD_PORT`). + ### Start Trading Agent (Production) ```bash docker compose up -d ouroboros @@ -59,7 +65,7 @@ Analyze the last 30 days of trade logs and generate performance metrics. python -m src.evolution.optimizer --evolve ``` Triggers the evolution engine to: -1. Analyze `trade_logs.db` for failing patterns +1. Analyze `trades.db` for failing patterns 2. Ask Gemini to generate a new strategy 3. Run tests on the new strategy 4. Create a PR if tests pass @@ -91,12 +97,12 @@ curl http://localhost:8080/health ### View Trade Logs ```bash -sqlite3 data/trade_logs.db "SELECT * FROM trades ORDER BY timestamp DESC LIMIT 20;" +sqlite3 data/trades.db "SELECT * FROM trades ORDER BY timestamp DESC LIMIT 20;" ``` ### Export Trade History ```bash -sqlite3 -header -csv data/trade_logs.db "SELECT * FROM trades;" > trades_export.csv +sqlite3 -header -csv data/trades.db "SELECT * FROM trades;" > trades_export.csv ``` ## Safety Checklist (Pre-Deploy) diff --git a/docs/testing.md b/docs/testing.md index b65d35e..3ab75a5 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -2,51 +2,29 @@ ## Test Structure -**54 tests** across four files. `asyncio_mode = "auto"` in pyproject.toml β€” async tests need no special decorator. +**551 tests** across **25 files**. `asyncio_mode = "auto"` in pyproject.toml β€” async tests need no special decorator. The `settings` fixture in `conftest.py` provides safe defaults with test credentials and in-memory DB. ### Test Files -#### `tests/test_risk.py` (11 tests) -- Circuit breaker boundaries -- Fat-finger edge cases +#### Core Components + +##### `tests/test_risk.py` (14 tests) +- Circuit breaker boundaries and exact threshold triggers +- Fat-finger edge cases and percentage validation - P&L calculation edge cases - Order validation logic -**Example:** -```python -def test_circuit_breaker_exact_threshold(risk_manager): - """Circuit breaker should trip at exactly -3.0%.""" - with pytest.raises(CircuitBreakerTripped): - risk_manager.validate_order( - current_pnl_pct=-3.0, - order_amount=1000, - total_cash=10000 - ) -``` - -#### `tests/test_broker.py` (6 tests) +##### `tests/test_broker.py` (11 tests) - OAuth token lifecycle - Rate limiting enforcement - Hash key generation - Network error handling - SSL context configuration -**Example:** -```python -async def test_rate_limiter(broker): - """Rate limiter should delay requests to stay under 10 RPS.""" - start = time.monotonic() - for _ in range(15): # 15 requests - await broker._rate_limiter.acquire() - elapsed = time.monotonic() - start - assert elapsed >= 1.0 # Should take at least 1 second -``` - -#### `tests/test_brain.py` (18 tests) -- Valid JSON parsing -- Markdown-wrapped JSON handling +##### `tests/test_brain.py` (24 tests) +- Valid JSON parsing and markdown-wrapped JSON handling - Malformed JSON fallback - Missing fields handling - Invalid action validation @@ -54,33 +32,143 @@ async def test_rate_limiter(broker): - Empty response handling - Prompt construction for different markets -**Example:** -```python -async def test_confidence_below_threshold_forces_hold(brain): - """Decisions below confidence threshold should force HOLD.""" - decision = brain.parse_response('{"action":"BUY","confidence":70,"rationale":"test"}') - assert decision.action == "HOLD" - assert decision.confidence == 70 -``` - -#### `tests/test_market_schedule.py` (19 tests) +##### `tests/test_market_schedule.py` (24 tests) - Market open/close logic - Timezone handling (UTC, Asia/Seoul, America/New_York, etc.) - DST (Daylight Saving Time) transitions -- Weekend handling -- Lunch break logic +- Weekend handling and lunch break logic - Multiple market filtering - Next market open calculation -**Example:** -```python -def test_is_market_open_during_trading_hours(): - """Market should be open during regular trading hours.""" - # KRX: 9:00-15:30 KST, no lunch break - market = MARKETS["KR"] - trading_time = datetime(2026, 2, 3, 10, 0, tzinfo=ZoneInfo("Asia/Seoul")) # Monday 10:00 - assert is_market_open(market, trading_time) is True -``` +##### `tests/test_db.py` (3 tests) +- Database initialization and table creation +- Trade logging with all fields (market, exchange_code, decision_id) +- Query and retrieval operations + +##### `tests/test_main.py` (37 tests) +- Trading loop orchestration +- Market iteration and stock processing +- Dashboard integration (`--dashboard` flag) +- Telegram command handler wiring +- Error handling and graceful shutdown + +#### Strategy & Playbook (v2) + +##### `tests/test_pre_market_planner.py` (37 tests) +- Pre-market playbook generation +- Gemini API integration for scenario creation +- Timeout handling and defensive playbook fallback +- Multi-market playbook generation + +##### `tests/test_scenario_engine.py` (44 tests) +- Scenario matching against live market data +- Confidence scoring and threshold filtering +- Multiple scenario type handling +- Edge cases (no match, partial match, expired scenarios) + +##### `tests/test_playbook_store.py` (23 tests) +- Playbook persistence to SQLite +- Date-based retrieval and market filtering +- Playbook status management (generated, active, expired) +- JSON serialization/deserialization + +##### `tests/test_strategy_models.py` (33 tests) +- Pydantic model validation for scenarios, playbooks, decisions +- Field constraints and default values +- Serialization round-trips + +#### Analysis & Scanning + +##### `tests/test_volatility.py` (24 tests) +- ATR and RSI calculation accuracy +- Volume surge ratio computation +- Momentum scoring +- Breakout/breakdown pattern detection +- Market scanner watchlist management + +##### `tests/test_smart_scanner.py` (13 tests) +- Python-first filtering pipeline +- RSI and volume ratio filter logic +- Candidate scoring and ranking +- Fallback to static watchlist + +#### Context & Memory + +##### `tests/test_context.py` (18 tests) +- L1-L7 layer storage and retrieval +- Context key-value CRUD operations +- Timeframe-based queries +- Layer metadata management + +##### `tests/test_context_scheduler.py` (5 tests) +- Periodic context aggregation scheduling +- Layer summarization triggers + +#### Evolution & Review + +##### `tests/test_evolution.py` (24 tests) +- Strategy optimization loop +- High-confidence losing trade analysis +- Generated strategy validation + +##### `tests/test_daily_review.py` (10 tests) +- End-of-day review generation +- Trade performance summarization +- Context layer (L6_DAILY) integration + +##### `tests/test_scorecard.py` (3 tests) +- Daily scorecard metrics calculation +- Win rate, P&L, confidence tracking + +#### Notifications & Commands + +##### `tests/test_telegram.py` (25 tests) +- Message sending and formatting +- Rate limiting (leaky bucket) +- Error handling (network timeout, invalid token) +- Auto-disable on missing credentials +- Notification types (trade, circuit breaker, fat-finger, market events) + +##### `tests/test_telegram_commands.py` (31 tests) +- 9 command handlers (/help, /status, /positions, /report, /scenarios, /review, /dashboard, /stop, /resume) +- Long polling and command dispatch +- Authorization filtering by chat_id +- Command response formatting + +#### Dashboard + +##### `tests/test_dashboard.py` (14 tests) +- FastAPI endpoint responses (8 API routes) +- Status, playbook, scorecard, performance, context, decisions, scenarios +- Query parameter handling (market, date, limit) + +#### Performance & Quality + +##### `tests/test_token_efficiency.py` (34 tests) +- Gemini token usage optimization +- Prompt size reduction verification +- Cache effectiveness + +##### `tests/test_latency_control.py` (30 tests) +- API call latency measurement +- Rate limiter timing accuracy +- Async operation overhead + +##### `tests/test_decision_logger.py` (9 tests) +- Decision audit trail completeness +- Context snapshot capture +- Outcome tracking (P&L, accuracy) + +##### `tests/test_data_integration.py` (38 tests) +- External data source integration +- News API, market data, economic calendar +- Error handling for API failures + +##### `tests/test_backup.py` (23 tests) +- Backup scheduler and execution +- Cloud storage (S3) upload +- Health monitoring +- Data export functionality ## Coverage Requirements @@ -91,20 +179,6 @@ Check coverage: pytest -v --cov=src --cov-report=term-missing ``` -Expected output: -``` -Name Stmts Miss Cover Missing ------------------------------------------------------------ -src/brain/gemini_client.py 85 5 94% 165-169 -src/broker/kis_api.py 120 12 90% ... -src/core/risk_manager.py 35 2 94% ... -src/db.py 25 1 96% ... -src/main.py 150 80 47% (excluded from CI) -src/markets/schedule.py 95 3 97% ... ------------------------------------------------------------ -TOTAL 510 103 80% -``` - **Note:** `main.py` has lower coverage as it contains the main loop which is tested via integration/manual testing. ## Test Configuration