Files
Stock-trading-programming/CLAUDE.md
T

339 lines
16 KiB
Markdown
Raw Normal View History

2026-06-04 10:39:01 +09:00
# StockBot v3.0 - Claude Code 운영 가이드
2026-06-04 10:39:01 +09:00
> 최종 수정: 2026-06-04
> 인프라: 로컬 Windows → Synology NAS Docker 이전 예정
> 현재 모드: 모의투자 (KIS_MOCK=true, DRY_RUN=true)
## Current safety policy
- AI is for market review and proposals only; code decides entries and exits.
- Evening Claude must not edit `app/config.py` or execution/strategy/risk code directly.
- Parameter changes must be written to `reports/proposals/YYYY-MM-DD_strategy_proposal.md` with evidence and manual approval required.
- `FORCE_EXIT = "14:50"` remains immutable.
2026-06-04 10:39:01 +09:00
## Current implementation status - 2026-06-04
- Mode: paper trading / dry-run focused. Real-cash trading is not approved yet.
2026-05-28 20:39:37 +09:00
- Approved strategy change applied: `ENTRY_START = "09:20"`.
2026-06-04 10:39:01 +09:00
- Applied runtime parameter: `MAX_HOLD_MIN = 90`.
2026-05-28 20:39:37 +09:00
- `FORCE_EXIT = "14:50"` remains unchanged.
- `avoid_sectors` runtime bug fixed: `main.py` now passes sector context into `check_entry()`.
- Sector handling now keeps a `ticker_sectors` cache when available and uses name-based hints for known avoid-sector cases.
2026-06-04 10:39:01 +09:00
- Re-entry controls are active:
- `TIME`/`FORCE` cooldown is based on final exit time, not original entry time.
- `TP1`/`TP2` final exits block same-day re-entry for that ticker.
- Re-entry control state is restored from today's DB rows after bot restart.
- Duplicate execution guards are active:
- `app/main.py` uses `SingleInstanceLock` on `logs/stockbot.lock`.
- `scripts/start_bot.py` stops the PID-file process and scans for existing `app/main.py` processes before starting one new bot.
- `scripts/run_morning.ps1` is the only owner of post-morning bot startup.
- `.claude/commands/morning.md` must not call `/start-bot` or `scripts/start_bot.py`; it only creates and sends morning context.
- KIS stability hardening is active:
- Mode-specific request spacing in `KISClient` (`mock` more conservative than `real`).
- Price lookups retry transient KIS timeout/rate-limit errors.
- DRY_RUN buy/sell paths can reuse the already-read quote as the simulated fill price to reduce extra API calls.
- Daily summary duplicate guard is active; summary Discord failures are logged without crashing settlement.
- Data layer: `entry_snapshots` and `post_entry_snapshots` are active for training data.
- Post-entry sampling: 60s, 180s, 300s, and 600s after successful entry.
- Training data export: `scripts/export_training_dataset.py`.
- External data collection:
2026-05-28 20:39:37 +09:00
- Daily market features: `scripts/collect_daily_features.py` with KIS fallback when pykrx fails.
- KIS minute bars: `scripts/collect_minute_data.py`, default ETF/ETN exclusion, multi-window collection from 09:30 to 14:00.
- External dataset builder: `scripts/build_external_training_dataset.py`, using prior daily OHLCV for breakout targets.
- ML engine:
- Training: `scripts/train_ai_model.py`.
- Model output: `models/scalping_model.joblib`.
- Metrics output: `models/scalping_model.metrics.json`.
- Runtime loader: `app/ml/predictor.py`.
2026-06-04 10:39:01 +09:00
- Latest successful training run: 2026-06-02 18:36, 5,773 rows total (`external_training_dataset.csv` 5,720 + bot dataset 53).
- Latest metrics: `label_stop_loss` ROC-AUC 0.896, `label_win` ROC-AUC 0.715.
2026-05-28 20:39:37 +09:00
- Training features exclude future/outcome leakage columns such as `ret_*`, `mfe_*`, `mae_*`, `price_*`, `pnl`, and `exit_price`.
- AI runtime mode: observation only. If a model exists, entry-time scores are logged and saved to `entry_snapshots`; they do not block or resize trades.
2026-06-04 10:39:01 +09:00
- Training schedule: `StockBot_Training` runs at 16:00 on trading days via `scripts/run_training_pipeline.ps1`; latest successful full run was 2026-06-02 18:36.
- Latest daily review/proposal files exist through 2026-06-02. 2026-06-03 was skipped as a market holiday.
- Dependency install:
- `requirements.txt` includes `app/requirements.txt`.
- `scripts/install_dependencies.ps1` installs from `vendor/wheels` when available.
- `scripts/download_dependencies.ps1` builds the local wheelhouse.
2026-06-04 10:39:01 +09:00
## Current operational risks - 2026-06-04
2026-06-04 10:39:01 +09:00
- Model is still observation-only and is dominated by external pretraining rows; bot-trade labels are 53 rows.
2026-05-28 20:39:37 +09:00
- KIS minute-bar collection is verified for same-day windows, but historical depth and ticker coverage remain limited.
- External minute data is pretraining data, not actual bot-trade data.
2026-05-28 20:39:37 +09:00
- pykrx daily feature collection can fail for same-day data; KIS fallback is active.
2026-06-04 10:39:01 +09:00
- KIS rate limits can still happen if multiple scripts/processes call KIS concurrently; runtime retries reduce but do not eliminate this.
- 2026-06-03 holiday training run logged a failure at the holiday-check step instead of a clean skip; inspect before relying on holiday automation noise level.
- 2026-06-04 morning duplicate execution happened before the `/morning` instruction fix; next scheduled morning run should be checked for exactly one context run and one `start_bot.py` startup.
- Real-cash mode still needs stronger fill, partial-fill, unfilled-order, cancel/replace, and recovery logic.
2026-06-04 10:39:01 +09:00
- Security cleanup is still needed: keep secrets out of tracked files and remote URLs; prefer environment variables for webhooks and credentials.
- Existing logs and older docs contain encoding damage; new operational notes should stay ASCII unless the file encoding is intentionally cleaned.
---
## 프로젝트 개요
| 항목 | 내용 |
|------|------|
| 목표 | KIS API 기반 한국 주식 단타 자동매매 |
| 전략 | 변동성 돌파 (K=0.5) |
| 언어 | Python 3.11 |
| DB | SQLite (data/stockbot.db) |
| 알림 | Discord Webhook (거래 알림 + 코드 변경 알림 채널 분리) |
| AI | Claude Code headless (`claude -p "/커맨드" --dangerously-skip-permissions`) |
| 코드 관리 | Gitea (NAS) — 파일 수정 후 확인 없이 자동 commit + push |
---
## Claude Code 권한 및 자동화 설정
2026-06-04 10:39:01 +09:00
- Claude 권한은 `.claude/settings.json`에서 관리한다.
- Codex 연동 환경변수/훅은 `.codex/config.toml`, `.codex/hooks.json`에서 관리한다.
- 파일 수정 완료 후 확인 없이 커밋 + `git push origin master`까지 수행한다.
- 단, `.env`, 실행 중 생성 파일, 사용자 작업 중 파일은 커밋하지 않는다.
- 인코딩: `PYTHONUTF8=1`, `PYTHONIOENCODING=utf-8` 환경변수 설정
---
## 핵심 설계 원칙 (절대 불변)
1. **14:50 강제 청산** — 하드코딩, 예외 없음
2. **손절 우선** — AI 판단과 무관하게 손절 룰 항상 우선순위 1위
3. **AI 역할 분리** — Claude Code는 장 전 분석 + 장 후 피드백만, 실시간 매매 개입 불가
4. **검증 순서** — 모의투자 3개월 → 조건 충족 → 실거래
---
## 하루 자동화 흐름
```
2026-06-04 10:39:01 +09:00
08:15 StockBot_Morning → run_morning.ps1 → claude /morning
RSS+네이버 뉴스+KIS 수급 분석 → daily_context.json
2026-06-04 10:39:01 +09:00
/morning 종료 후 run_morning.ps1이 python scripts/start_bot.py 호출
08:30 봇이 daily_context.json 로드 → Discord 전송 → 유니버스 30종목 확정
08:50 목표가 계산
09:00 아침 세션 시작 (변동성 돌파 신호 + AI 필터)
B안: 연속 손절 시 포지션 크기 자동 축소 (0회→1.0× / 1회→0.7× / 2회→0.5× / 3+→0.3×)
11:00 midday_context.json 미로드 시 신규 진입 일시 중단
11:20 StockBot_Midday → run_midday.ps1 → claude /midday
오전 결과+시장 스냅샷 수집 → midday_context.json 저장
파일 생성 즉시 봇이 감지 → 점심 세션 자동 시작
14:00 신규 진입 마감
14:50 강제 전량 청산 (절대 불변)
15:10 일일 결산 → Discord 전송
15:30 StockBot_Evening → run_evening.ps1 → claude /evening
2026-06-04 10:39:01 +09:00
결과 분석 + 리포트/제안서 저장
```
### 스케줄러 스크립트 주의사항 (scripts/run_*.ps1)
- 경로: `$PROJECT = Split-Path -Parent $PSScriptRoot` (한글 경로 인코딩 문제 방지)
2026-06-04 10:39:01 +09:00
- CLI 실행: `scripts/stockbot_env.ps1``Resolve-StockBotClaude``claude.cmd`를 우선 찾고 없으면 `codex.cmd`를 사용
- 인코딩: `New-Object System.Text.UTF8Encoding $false` + UTF-8 BOM으로 저장
2026-06-04 10:39:01 +09:00
- 봇 시작: `scripts/run_morning.ps1``/morning` 완료 후 `python scripts/start_bot.py`를 직접 실행
- 로그: `logs/morning.log`, `logs/midday.log`, `logs/evening.log`, `logs/training.log`, `logs/bot_stderr.log`, `logs/stockbot.log`
---
## Claude Code 역할 상세
### 장 전 분석 — `/morning` 슬래시 커맨드
```
1. python app/ai/morning.py --print (뉴스 크롤링 + KIS 수급 수집)
2. Claude가 데이터 분석 → 시장 분위기/섹터/boosted_tickers 판단
3. data/daily_context.json 저장
4. Discord로 분석 요약 전송
2026-06-04 10:39:01 +09:00
5. 여기서는 봇을 시작하지 않음. 봇 시작은 run_morning.ps1만 담당.
```
### 장중 분석 — `/midday` 슬래시 커맨드
```
1. python app/ai/midday.py --print (오전 거래 결과 + 현재 시장 스냅샷 수집)
2. 오전 daily_context 예측 vs 실제 결과 비교 분석
3. 점심 세션 파라미터 결정 (진입 허용 여부, 포지션 배율, 섹터 업데이트)
4. data/midday_context.json 저장 → 봇이 즉시 감지해 점심 세션 시작
5. Discord로 장중 분석 전송
```
### 장 후 피드백 — `/evening` 슬래시 커맨드
```
1. python app/ai/evening.py --print (오늘 매매 내역 조회)
2. 승률/손익/이상패턴 분석
3. app/config.py 파라미터 조정 (문제 명확할 때만)
4. reports/daily/날짜.md 저장
5. 실전 전환 조건 5가지 체크
6. Discord로 요약 전송
```
### 봇 시작 — `/start-bot` 슬래시 커맨드
```
2026-06-04 10:39:01 +09:00
1. python scripts/start_bot.py 실행
2. PID 파일 + 프로세스 스캔으로 기존 app/main.py 종료
3. app/main.py를 DETACHED_PROCESS로 백그라운드 시작
4. logs/bot.pid 저장 + Discord "[모의투자] 자동매매 봇 시작" 알림
```
---
## Discord 알림 구조
| 채널 | 내용 | 발신 |
|------|------|------|
| 거래 알림 | 매수/매도/손절/결산 | `app/monitor/notifier.py` |
2026-06-04 10:39:01 +09:00
| 코드 변경 | 커밋 내용 + Push 완료 여부 | `.claude/discord_notify.py` (Stop 훅, `.codex/hooks.json`에서도 호출) |
- 코드 변경 알림: **커밋이 있을 때만** 발송 (스케줄러 태스크 등 노이즈 없음)
- Discord 요청 시 반드시 `User-Agent: DiscordBot (stockbot, 1.0)` 헤더 포함 (Cloudflare 차단 방지)
---
## 파일 구조
```
stockbot_v3/
├── CLAUDE.md
2026-06-04 10:39:01 +09:00
├── AGENTS.md
├── .env ← API 키 (Git 절대 제외)
2026-06-04 10:39:01 +09:00
├── .codex/
│ ├── config.toml ← Codex 환경변수 설정
│ └── hooks.json ← Stop 훅에서 .claude/discord_notify.py 호출
├── .claude/
2026-06-04 10:39:01 +09:00
│ ├── commands/ ← /morning, /midday, /evening, /start-bot 명령
│ ├── settings.json ← Claude 권한 설정
│ └── discord_notify.py ← 코드 변경 Discord 전송
├── app/
│ ├── main.py ← 메인 매매 루프 (승인 필요)
│ ├── config.py ← 전략 파라미터 (수정 가능)
│ ├── ai/
│ │ ├── morning.py ← 장 전 데이터 수집
│ │ ├── midday.py ← 장중 데이터 수집
│ │ └── evening.py ← 장 후 데이터 수집
│ ├── strategy/
│ │ └── volatility_breakout.py ← 전략 로직 (수정 가능)
│ ├── execution/
│ │ ├── kis_client.py ← KIS API 래퍼 (승인 필요)
│ │ └── order_executor.py ← 주문 실행 (승인 필요)
│ ├── risk/
│ │ └── manager.py ← 리스크 관리 (수정 가능)
│ ├── monitor/
│ │ └── notifier.py ← Discord Webhook
│ └── db/
│ ├── models.py ← SQLite 스키마 (승인 필요)
│ └── repository.py ← DB 접근 (승인 필요)
├── scripts/
│ ├── run_bot.ps1 ← 스케줄러용 봇 시작
│ ├── run_morning.ps1 ← 스케줄러용 morning
│ ├── run_midday.ps1 ← 스케줄러용 midday (11:20)
│ ├── run_evening.ps1 ← 스케줄러용 evening
2026-06-04 10:39:01 +09:00
│ ├── run_training_pipeline.ps1
│ ├── start_bot.py ← 단일 봇 시작/기존 프로세스 종료
│ └── setup_scheduler.ps1 ← 스케줄러 전체 재등록
├── reports/
│ ├── daily/ ← 매일 자동 생성
│ └── live_ready/ ← 실전 전환 조건 충족 시 생성
├── data/
│ ├── stockbot.db
│ ├── daily_context.json ← 매일 /morning이 갱신, 봇이 08:30에 로드
│ ├── midday_context.json ← 매일 /midday가 갱신, 봇이 파일 감지 즉시 로드
│ ├── news/
│ └── market/
└── logs/
├── stockbot.log ← 봇 메인 로그 (UTF-8)
2026-06-04 10:39:01 +09:00
├── bot_stderr.log ← start_bot.py가 연결한 봇 stdout/stderr
├── bot.pid ← 현재 봇 PID
├── stockbot.lock ← 단일 실행 lock (실행 중 생성)
├── morning.log ← /morning 실행 로그
2026-06-04 10:39:01 +09:00
├── midday.log ← /midday 실행 로그
├── evening.log ← /evening 실행 로그
└── training.log ← 학습 파이프라인 로그
```
---
## 수정 범위
### 자유롭게 수정 가능
- `app/config.py` — 전략 파라미터 (TP1_PCT, TP2_PCT, SL_PCT, STRATEGY_K 등)
- `app/strategy/volatility_breakout.py` — 전략 로직
- `app/risk/manager.py` — 리스크 기준값 (L1~L5)
- `app/ai/daily_context.json` — 매일 장 전 생성
- `reports/` — 리포트 생성/저장
2026-06-04 10:39:01 +09:00
주의: 장후 자동 리뷰(`/evening`)에서는 파라미터를 직접 수정하지 않고 `reports/proposals/YYYY-MM-DD_strategy_proposal.md`에 제안서로 남긴다.
### 승인 필요 (사용자 확인 후 수정)
- `app/main.py` — 구조 변경, 스케줄 변경
- `app/execution/` — 주문 로직 변경
- `app/db/` — 스키마 변경
### 절대 금지
- `FORCE_EXIT = "14:50"` 변경
- 손절을 익절보다 후순위로 변경
- `.env` 파일 직접 수정 (KIS_MOCK, DRY_RUN 포함)
- `.env` Git 커밋
---
## Git 규칙
- branch: `master` / remote: `origin` (Gitea NAS)
2026-06-04 10:39:01 +09:00
- 파일 수정 후 **자동으로** 커밋 + `git push origin master`
- 단, `.env`, 실행 중 생성 파일(`logs/stockbot.lock`, `logs/bot.pid`), 사용자가 수정 중인 데이터 파일은 커밋하지 않는다.
- 커밋 메시지: `[날짜] 변경내용 요약`
- `.env`는 절대 커밋 금지
---
## 리스크 관리 (L1~L5)
| 레벨 | 조건 | 동작 | Discord |
|------|------|------|---------|
| L1 | 1회 -1.5% | 즉시 손절 | [손절] |
| L2 | 일일 -3% | 당일 신규 진입 중단 | [경고] |
| L3-B | 연속 손절 | 포지션 크기 단계 축소 (전면 중단 없음) | [경고] |
| L4 | 주간 -7% | 주말까지 중단 | [경고] |
| L5 | 월간 -15% | 전략 폐기 + 재검토 | [긴급] |
**L3-B 포지션 배율** (익절 시 한 단계 회복):
| 연속 손절 | 포지션 크기 |
|-----------|------------|
| 0회 | 1.0× (정상) |
| 1회 | 0.7× |
| 2회 | 0.5× |
| 3회+ | 0.3× (최소) |
---
## 실전 전환 조건 (claude_evening 자동 체크)
| 조건 | 기준 |
|------|------|
| 누적 운영 | 30거래일 이상 |
| 승률 | 최근 30일 > 48% |
| MDD | 최근 30일 < -10% |
| 샤프지수 | 최근 30일 > 1.0 |
| L3-B 최소배율(0.3×) 도달 | 월 2회 이하 |
전부 충족 시 → `reports/live_ready/날짜_READY.md` 생성 + Discord 🚀 알림
전환 방법: `.env`에서 `KIS_MOCK=false`, `DRY_RUN=false` 로 변경
---
## 운영 모드
| KIS_MOCK | DRY_RUN | 동작 |
|----------|---------|------|
| true | true | 신호 확인만 ← **현재** |
| true | false | 모의투자 실주문 |
| false | false | 실거래 |
---
## 다음 단계
- [ ] WebSocket 전환 — REST 폴링 → KIS WebSocket 실시간 시세
2026-06-04 10:39:01 +09:00
- [ ] `/morning` 중복 시작 수정 후 다음 장전 자동 실행에서 단일 실행 여부 확인
- [ ] 휴장일 training pipeline이 실패 로그 대신 정상 skip으로 끝나는지 확인/수정
- [ ] Discord webhook/remote credential 환경변수화 및 노출 이력 회수 검토
- [ ] NAS Docker 이전 (개발 완료 후 `git push` → NAS `git pull``docker-compose up -d`)