Files
kis_bot/docs/BREAKOUT_LIVE_BT_QA.md
Your Name 61bec4bd1d feat: Add DART strategy and related configurations
ㅇ
Changes:
- Introduced the DART strategy to the trading system, including its configuration and integration into the existing framework.
- Updated the database schema to include DART-specific tables for disclosures and watchlists.
- Enhanced the backtesting and parameter search functionalities to support the DART strategy.
- Implemented new rules for browser verification and API interactions to ensure compliance with the updated DART strategy.

Impact:
- These additions expand the trading capabilities of the system, allowing for more comprehensive analysis and execution of DART-related strategies, while maintaining system integrity and performance.
2026-07-21 07:50:24 +09:00

178 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 돌파 실매↔백테 괴리 Q&A (2026-07-16 기준)
> **패치 적용 완료 (2026-07-17).** 실매 봇은 재시작하지 않음. 백테 웹만 재시작.
---
## 1번 — 웜업 넣으면 되나?
**네 → 적용됨.**
- env: `BREAKOUT_BACKTEST_CANDLE_WARMUP_BARS` (기본 **50**, DB 시드)
- `prepend_breakout_candle_warmup` — 기간 시작 전 1분봉 prepend
- 포트폴리오 `all_times``_backtest_period_start_key` 이후만 (전일 시계 오염 방지)
- 모멘텀 `MOMENTUM_BACKTEST_CANDLE_WARMUP_BARS`와 동일 계열
---
## 2번 — 유니버스 sticky/grace
**실매 따라가기 → 적용됨.**
### 동작
- 공통 `resolve_universe_exit_debounce_sec()` → 기본값 = `CONDITION_EXIT_GRACE_SEC`(운영 **60**, 기존 120→2026-07-17 축소)
- 돌파/꼬리/모멘텀 타임라인 `debounce_sec`에 연결
- 전략별 오버라이드: `BREAKOUT_UNIVERSE_EXIT_DEBOUNCE_SEC` / `TAIL_*` / `MOMENTUM_*` (있으면 우선, `0`=OFF)
### 09:07 1종 스냅샷 점검 결과
| event_time | n |
|---|---|
| 03:16 | 22 |
| 09:07 | **1** (248170만) |
| 09:11 | 2 |
- history는 **effective 유니버스 저장** 설계 → 09:07에 1종이면 그 tick의 live effective도 1종으로 보는 게 맞음 (저장이 grace를 빼먹은 버그로 단정하지 않음). 새벽 스냅샷 후 장초 첫 변동·콜드스타트 가능성이 큼.
- 디바운스 ON 시: 09:07 스냅샷에서도 overnight 종목을 **60초** 유지 → 이후 신규 스냅샷 기준으로 정리. 실매 EXIT grace와 같은 전환 규칙.
### 영향 범위
- **백테 유니버스 재생** (돌파·꼬리·모멘텀 등 타임라인 사용 전략). 실매 주문 로직 자체는 변경 없음.
- 망가뜨리는 패치가 아니라 **실매 grace 정합** 쪽. 백테 거래수/PnL은 실매에 가까워지도록 **바뀔 수 있음**.
---
## 3번 — 슬롯 늘려서 테스트
**사용자 검증용 (코드 변경 없음).** 총한도/동시보유↑로 슬롯 경쟁 효과 확인.
---
## 4번 — 미청산 flatten / EOD
**적용됨 (돌파·모멘텀·RANGE_BREAK).**
- 공통 `flatten_remaining_portfolio_trades` — 루프 끝 미청산을 **마지막 확정봉 종가**로 장부 기록
- `eod_enabled``sell_reason=eod`, 아니면 `bt_flatten`
- skip_stats: `bt_flatten_count`
- 모멘텀: 웜업은 기존, **flatten은 이번에 추가** (이전 “미완” 해소)
---
## (부수) invest_cap 이중 % 스케일
**적용됨 (돌파·RANGE_BREAK).**
- `_resolve_breakout_sl_pct_ui`: `stop_loss_pct`(비율) → UI% ; `sl_pct`만 있으면 UI%/비율 자동 판별
- `breakout_invest_amount_krw`**UI% 한 번만** 전달 (×100 이중 제거)
---
## 패치 상태
| 순위 | 항목 | 상태 |
|------|------|------|
| 1 | 돌파 백테 **전일 봉 웜업** | **완료** |
| 2 | 유니버스 **sticky/grace 디바운스** + 09:07 점검 | **완료** |
| 3 | 슬롯/한도 검증용 백테 | 사용자 |
| 4 | 백테 종료 **미청산 flatten** | **완료** (돌파·모멘텀·레인지) |
| 부수 | `invest_cap` `%` 이중 스케일 | **완료** |
---
## 관련 파일
- 웜업·디바운스: `kis_trader/backtest/breakout_backtest_common.py`
- 공통 디바운스: `kis_trader/backtest/universe_timeline.py` (`resolve_universe_exit_debounce_sec`)
- flatten: `kis_trader/backtest/backtest_portfolio_common.py`
- 포트폴리오: `breakout_portfolio_backtest.py`, `momentum_portfolio_backtest.py`, `range_break_portfolio_backtest.py`
- 꼬리 디바운스: `tail_backtest_common.py`
- env 키: `database.py` (`BREAKOUT_BACKTEST_CANDLE_WARMUP_BARS` 등)
---
## 검증
- `py_compile` OK
- 스모크: debounce(03:16→09:07 유지→09:11 정리) / invest_cap(30만) / flatten(`eod`) → `SMOKE_OK`
- DB: `BREAKOUT_BACKTEST_CANDLE_WARMUP_BARS=50` 시드, config 컬럼 추가
- `kis_backtest_web.service` 재시작 (`active` + HTTP 200)
- 브라우저: `http://192.168.0.149:5050/`**돌파매매 백테스트** 탭 클릭, 폼·「백테스트 실행」버튼 정상 표시
### 잔여 / 다음 확인
| 순위 | 항목 | 상태 |
|------|------|------|
| 다음 | **2번 검증** — 장초 이노테나·한울 `직전봉약세` | **근본원인 확정 + 갭보정 진행분 제외 적용** (봇 재시작 시 반영) |
| 후보 | 1번 A — 마지막 봉 경과 시 포트폴리오 루프에서 **즉시** 슬롯 해제 (전 전략 공통) | 대기 — 저유동은 C로도 분 생성 불가 시 필요 |
| 진행 | **1번 C — 판 뒤 1회 REST 백필** | **적용** (아래) |
| — | 3번 슬롯 경쟁 | 패스 |
### 1번 C 적용 (2026-07-17)
- 모듈: `kis_trader/engine/post_sell_candle_backfill.py`
- 실매 훅: `order_manager._finalize_sell_fill` → 매도 후 **비동기 1회** (시세=키움 **실키**)
- env: `POST_SELL_CANDLE_BACKFILL` (기본 true), `POST_SELL_CANDLE_ROLLUP_3M`, sleep 1~3초
- 즉시 백필 CLI: `scripts/backfill_trade_candles.py --like '2026-07-16%'`
- 로그: `/tmp/backfill_trade_candles_0716c.log` (및 선행 0716b)
- 한계: 거래 자체가 없는 분(저유동)은 REST에도 없음 → **C만으로는 완전 메꿈 불가**, A 보완 여지
- 웹 돌파 **2026-07-16** 재백테 ↔ 실매 비교는 C 반영 후 / 장초 직전봉 수정과 병행
- 실매 봇: post-sell 훅 반영하려면 **재시작 필요** (백필 CLI는 봇 없이 완료 가능)
---
## 장초 직전봉 (이노테나·한울) — 2번 검증 결과 (2026-07-17)
### 현상
| | 이노테나 `333050` | 한울 `320000` |
|--|--|--|
| 실매 매수 | 09:01:09 @5350 | 09:01:42 @11590 |
| 실매 로그 `prevChg` | **1.34%** | **0.61%** |
| BT (DB+웜업) | `탈락-직전봉약세` **0.19%** | `탈락-직전봉약세` **-2.37%** |
| `PREV_CHG_MIN` | 0.3 (실매=BT 동일) | 동일 |
### 숫자 재현 (스펙: 전전봉 종가 → 직전봉 종가 %)
- 이노테나 09:00: O=5220 C=5290 / 전일 15:30 C=5280
- **전일대비 C2C** `(5290-5280)/5280` = **0.19%** ← BT 탈락
- **당일 몸통** `(5290-5220)/5220` = **1.34%** ← 실매 `prevChg`**일치**
- 한울: 전일 15:58 C=11810 → 09:00 C=11530 → C2C **-2.37%**; 몸통 ≈ **0.70%** ≈ 실매 0.61%(RAM OHLC 미세차)
### 실매 journal 타임라인 (결정적)
1. `09:00:25` 333050 갭보정 REST 빈응답 → `09:00:34` **500봉 RAM 적재** (진행 중 **당일 09:00** 포함)
2. `09:00:34~09:01:01` 내내 `탈락-직전봉약세 prev=-1.14%`
- `(5220-5280)/5280 = -1.14%` → 갭보정이 넣은 **미완성 09:00(종가≈시가 5220)** 이 확정봉으로 잡힌 상태
3. `09:01:01` `봉강제확정` 09:00 C=5290
4. `09:01:02~` `탈락-저항미돌파` (직전봉 게이트 **통과**) → `09:01:06` `BREAKOUT-B ... prevChg=1.34%` 매수
한울도 동일 패턴: 장중 `prev=-2.96%`(갭/전일) → 09:00 확정 후 저항 대기 → `prevChg=0.61%`로 매수.
### 근본원인
**갭보정(REST ka10080)이 장중에 “아직 진행 중인 당일 1분봉”을 `is_confirmed`로 RAM에 넣음.**
- 실매 `check_buy` = `get_candles`(확정) + `get_current_candle`(진행) → **같은 09:00이 확정·진행 양쪽에** 있거나, 확정 체인이 **전일 종가 대신 시가(불완전봉 종가)**`prev_prev`로 물음.
- 그 결과 직전봉 필터가 문서/코드 스펙(전전봉→직전봉 **종가대비**)이 아니라 **당일 첫 봉 몸통%** 에 가깝게 통과.
- BT는 DB 확정봉(+웜업 전일 종가)만 쓰므로 **0.19%/-2.37%로 올바르게 거름** → 장초 실매만 사는 괴리.
코드 위치: `kis_ws.merge_confirmed_bars` / `fill_gap_from_rest` (현재 분 제외 없음) + `breakout.check_buy` (`virtual = confirmed + forming`).
### 수정 방향 (승인 후 — 아직 미적용)
1. **갭보정 시 `candle_time >= 현재 진행 분` 봉은 confirmed merge 제외** (또는 `_current`만 갱신). 실매·BT 모두 전일 종가 C2C로 통일.
2. (선택) 매수 성공 로그에 `confirmed[-2/-1] candle_time/close` 남겨 재발 추적.
3. 스펙을 “직전봉 몸통%”로 바꾸려면 실매·웹·Optuna를 **한 세트**로 바꿔야 함 — 비권장(HTS/주석과 불일치).
**권장: 1번(진행분 REST 제외).** 핵심 매매 임계값 변경이 아니라 인프라 정합.
### 수정 적용 (2026-07-17)
- env: `WS_GAP_FILL_SKIP_INCOMPLETE_BUCKET` (기본 **true**, DB 시드)
- `fill_gap_from_rest` / `merge_confirmed_bars`: 진행 중 버킷(`>=` 현재 봉시작) **insert 금지 + RAM purge**
- 스모크: `scripts/smoke_candle_upsert_rollup.py` (진행분 skip/purge)
- **실매 반영: `kis_trader_main` 재시작 필요** (미재시작 시 기존 프로세스 구코드)