Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@
실전 주문과 잔고 조회는 KIS API를 사용합니다.
데이터 수집, 리스크 관리, 알림, 대시보드, 리밸런싱 기능도 함께 붙여가며 확장하고 있습니다.

> **현재 상태 (2026-06-01)**:
> **현재 상태 (2026-06-10)**:
> - **바스켓 paper 운영 개시**: `kr_diversified_hold`(분산 대형주 buy&hold, 주식 80%/현금 20%) enabled — 일일 자동 사이클(리밸런싱 → NAV 스냅샷 → DB 백업 → 승격 진행률 보고)로 60영업일 트랙레코드 축적 중. `--mode health`가 사이클 끊김(스냅샷 4일+)을 자동 경고
> - **paper→live 승격 기준 정의**(`docs/BASKET_PAPER_EVALUATION.md`): 60영업일·스냅샷 커버리지 ≥95%·dead-letter 0건·비용 드래그 ≤1%/년. 베타 전략이므로 "시장 초과수익"은 기준이 아님. `tools/basket_paper_evaluation.py`로 자동 판정(WAIT/PASS_CANDIDATE/FAIL_REVIEW)
> - **바스켓 전용 live gate 분기**: 기존 게이트가 바스켓에 신호 전략용 canonical promotion(벤치마크 초과수익 포함)을 요구해 영구 통과 불가였던 함정 해소 — paper 평가 PASS_CANDIDATE 기반으로 실제로 열리는 경로 확립. 전환 절차는 `docs/BASKET_LIVE_RUNBOOK.md`(모의서버 리허설 → 실계좌 소액 → 목표 자본)
> - live 바스켓 리밸런싱 실행 가능화: BUY가 "paper-only" 차단으로 항상 실패해 SELL-only 현금화가 되던 버그 수정(일반 매수와 동일한 집행 안전장치 + live gate 검사 승계), 회전율 예산 SELL 우선·부분 실행, KIS 잔고 미확인 시 사이징 fail-closed
> - 주문 응답 유실 시 재시도 래퍼가 재전송하던 잔여 구멍 폐쇄(`KISOrderResponseUnknown` → reconcile 대기), 손절가 하한 클램프, 히스터리시스 SELL 해제 부호 수정, 내장 지표 폴백 pandas-ta 패리티(RSI ~12pt 오차 정정)
> - 트랙레코드 도구가 현금 배분(`target_stock_weight`·`min_cash_ratio`)을 무시해 수익·MDD를 과대 보고하던 문제 정정 — 배포 바스켓 정직 수치(2021-12~2026-06): **CAGR +26.9%, Sharpe 1.09, MDD −21.4%**
> - 인자 없이 실행 시 백테스트 자동실행 대신 사용 가이드 출력(`--mode guide`), 운영 문서 v6.1 갱신
>
> **이전 상태 (2026-06-01)**:
> - 적대적 코드 감사로 실거래 안전 버그 정리: KIS 주문이 응답 유실 시 재전송돼 이중 체결되던 경로를 `idempotent=False`로 차단(최대 1회 제출), 서킷 브레이커 재시도 루프 내 재확인, 429 Retry-After HTTP-date 크래시 가드
> - 부분 익절이 매 모니터링 사이클마다 재발동되던 버그 수정(`Position.partial_tp_done` 영속화), 스케줄러 진입 예외 시 손절/익절 스킵 방지, 일일 손실 한도 기준값에 당일 스냅샷 사용 차단
> - 라이브 게이트 fail-closed 보강: NaN/Inf 지표가 임계값 비교를 통과하던 구멍을 막아(`_as_float` 비유한값 → None) 손상된 지표로 라이브 승격되는 것을 차단
Expand Down
75 changes: 75 additions & 0 deletions docs/BASKET_LIVE_RUNBOOK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# 바스켓 live 전환 런북 (kr_diversified_hold)

> 작성: 2026-06-10. paper 운영 평가가 `PASS_CANDIDATE`에 도달한 뒤, 임기응변 없이
> 단계적으로 live 전환하기 위한 절차서. 승격 기준은 `docs/BASKET_PAPER_EVALUATION.md`,
> 게이트 구현은 `core/live_readiness.py`(바스켓 전용 분기) 참고.

## 전제 (모두 충족해야 시작)

```
.venv\Scripts\python.exe tools/basket_paper_evaluation.py
```
- 판정 **PASS_CANDIDATE** (60영업일·스냅샷 커버리지 ≥95%·dead-letter 0건·비용 드래그 ≤1%/년)
- `--mode health` 가 바스켓 운영 이슈 없음
- `--mode deploy_check --basket kr_diversified_hold` 로 계획 주문·예상 비용·회전율 확인

## 안전장치 요약 (live 리밸런싱이 통과해야 하는 것들)

`python main.py --mode rebalance` 가 live에서 주문에 도달하려면 **전부** 통과해야 한다:
1. `config.trading.mode: "live"` (settings.yaml)
2. 환경변수 `ENABLE_LIVE_TRADING=true`
3. CLI 플래그 `--confirm-live`
4. 바스켓별 live gate `basket_rebalance:kr_diversified_hold`
(= paper 평가 PASS_CANDIDATE + 바스켓 enabled + 비중 합 1.0 + 데이터 소스 health)
5. KIS↔DB 포지션 동기화 성공 (실패 시 즉시 중단)
6. KIS 잔고 확인 (미확인 시 사이징 fail-closed — 계획 자체를 중단)
7. 주문 단계: OrderGuard·미체결 조회 fail-closed·체결 확인·reconcile 보류·응답 유실 재전송 금지

하나라도 빠지면 주문이 나가지 않는다. 이 차단이 정상 동작이다.

## 단계적 전환

### Phase 0 — paper (현재)
- 일일 자동 사이클(스케줄 작업)이 트랙레코드를 축적 중. 개입 불필요.

### Phase 1 — KIS 모의투자 서버로 live 경로 리허설 (권장)
실계좌 없이 **live 코드 경로 전체**(KIS 인증·주문·체결조회·sync)를 리허설한다.
1. `.env`: KIS 모의투자 앱키/시크릿/계좌 설정
2. `settings.yaml`: `kis_api.use_mock: true` (모의투자 도메인), `trading.mode: "live"`
3. 실행:
```
set ENABLE_LIVE_TRADING=true
.venv\Scripts\python.exe main.py --mode rebalance --basket kr_diversified_hold --dry-run
.venv\Scripts\python.exe main.py --mode rebalance --basket kr_diversified_hold --confirm-live
```
4. 검증: 주문 체결 확인 로그(`✅ 매수 완료`), KIS 모의계좌 잔고 = DB 포지션,
`requires_reconcile` 발생 시 다음 사이클에서 자동 대조되는지
5. 며칠 반복 후 이상 없으면 Phase 2

### Phase 2 — 실계좌 소액
1. **소액만 입금한 실계좌** 사용 (live 자본은 KIS 잔고 기준으로 사이징되므로
계좌 잔고 자체가 리스크 상한이다)
2. `settings.yaml`: `kis_api.use_mock: false`, 실계좌 번호
3. Phase 1과 동일 명령. `--dry-run`으로 계획 먼저 확인 후 실행
4. 1~2주 관찰: 체결가 품질(슬리피지), 일일 사이클 안정성, 알림 동작

### Phase 3 — 목표 자본
- Phase 2 이상 없을 때 증액. `max_turnover_ratio`(15%)가 사이클당 거래를 제한하므로
증액 직후에도 점진 매입된다(한 번에 시장가 폭탄 없음).

## 비상 절차

| 상황 | 명령 |
|---|---|
| 전 종목 긴급 청산 | `ENABLE_LIVE_TRADING=true` + `.venv\Scripts\python.exe main.py --mode liquidate --confirm-live` |
| live 즉시 중지(주문만 차단) | 환경변수 `ENABLE_LIVE_TRADING` 제거 — 이후 모든 live 주문 경로 차단 |
| paper로 복귀 | `settings.yaml` `trading.mode: "paper"` |

## 전환 후 일상 운영

- 일일: 자동 사이클 보고(리밸런싱 결과·NAV·평가 진행률) 확인
- `--mode health`: 전략·바스켓·blocker 통합 점검 (스냅샷 끊김 자동 경고)
- DB 백업: `data/backups/`에 일일 자동 (retention 14일)
- 주의: live 일일 NAV 스냅샷은 상시 스케줄러(장마감)가 담당 — 일일 CLI 운영을
유지한다면 rebalance 종료 시 저장되는 것은 paper 스냅샷 경로이므로, live 전환 후
상시 스케줄러(systemd, `deploy/`) 구동을 권장
Loading