fix(옵투나·백테웹): 휩쏘 키 통일 + 엔진 뱃지 + 잡 삭제 + race·후처리 시그니처
휩쏘 키 통일 (bt-form-postfilter-key-parity.mdc 신설) - 저장키 vs 조회키 불일치 해소: whipsaw_enabled(옛) → whipsaw_filter_enabled(표준) - backtest_web.py: params[..] 세팅, static/js/backtest.js: 폼 파라미터 - optuna_web_jobs·param_search_apply_snapshot·param_search_scalping: 옛 alias 제거 - bt_post_filters: 로컬 변수도 whipsaw_filter_enabled 로 통일 - scripts/scratch: 관련 스크립트 동기 반영 엔진 뱃지 (optuna-job-engine-label.mdc 신설) - optuna_web_jobs: use_rust 명시값만 신뢰, 미상은 ❔ (전략명 하드코딩 폴백 금지) - 스캘핑/모멘텀/돌파 Rust 포팅 확장에도 안전한 라벨링 Optuna 웹 잡 UX - save_job: tmp 파일 PID 접미 (멀티 프로세스 race 해소) - _spawn_job_reaper: mode_refine 완료 시 phase1/phase2 JSON 자동 등록 → 예전 UX 복원 (실행 잡ID 위에 결과 잡ID 노출) - delete_job / delete_jobs_bulk 신설 + API + UI 삭제 버튼 실행 중 잡 거부, 로그·원본 결과 JSON 보존 후처리 시그니처 수정 - bt_post_filters.orderbook_reject_for_entry 호출: price= → current_price=, 단일 대입 → 튜플 unpack (매 trial 마다 TypeError 삼켜지고 후처리 무효화되던 버그) 버그 조사·룰 강화 - verify-before-conclude-cross-strategy.mdc: 함수 추적 딥다이브 → 근본 대안 3개 - .cursorrules: 룰 27~29 추가 (해외 UI 정합·휩쏘 키·엔진 뱃지) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
58
.cursor/rules/bt-form-postfilter-key-parity.mdc
Normal file
58
.cursor/rules/bt-form-postfilter-key-parity.mdc
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
description: 웹백테 폼 → params → 후처리 필터 조회 키 정합 (whipsaw·호가 등)
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# 웹백테 폼 ↔ 후처리 필터 키 정합 (whipsaw / orderbook / program)
|
||||
|
||||
이 대화에서 실제로 난 사고: **웹 백테 폼 “휩쏘 ON” 토글이 후처리에서 항상 OFF로 판정**되어 옵투나↔웹백테 결과가 1원 단위로 안 맞음. 원인은 “저장 키 vs 조회 키” 이름 파편화 (`whipsaw_enabled` 저장 → `whipsaw_filter_enabled` 조회).
|
||||
|
||||
## 1. 절대 원칙 — 저장 키 = 조회 키
|
||||
|
||||
- **웹 백테 요청 처리에서 `params[...] = ...` 로 세팅한 키는 후처리/엔진이 실제로 조회하는 키와 100% 동일해야 한다.** 서로 다른 이름이면 “세팅한 값”이 조용히 사라져 옵투나(=파람서치 저장 키)와 다른 엔진이 된다.
|
||||
- 실제 소비자를 **grep으로 반드시 확인**한 뒤 세팅 키를 정한다. “예전 이름 습관”으로 세팅하지 말 것.
|
||||
- 소비자 여러 개가 서로 다른 alias를 볼 수 있으면 **하위호환 폴백은 소비자 쪽에만**. 새 코드/새 진입점에서는 **표준 키 하나만** 세팅.
|
||||
|
||||
## 2. 표준 키 (2026-09-06 통일 · 옛 alias 완전 폐기)
|
||||
|
||||
| 도메인 | 표준 키 | 폐기된 이름 (재도입 금지) |
|
||||
|---|---|---|
|
||||
| 휩쏘 활성 | `whipsaw_filter_enabled` | `whipsaw_enabled` ← 2026-09-06 완전 제거 |
|
||||
| 호가 활성 | `_orderbook_filter_enabled` | `orderbook_filter_enabled` |
|
||||
| 프로그램매매 활성 | `_program_filter_enabled` | — |
|
||||
| 휩쏘 서브바 초 | `whipsaw_subbar_sec` | — |
|
||||
| 휩쏘 룩백 초 | `whipsaw_lookback_sec` | — |
|
||||
|
||||
- 신규 키 추가 시 이 표에 함께 등록. 폐기된 이름으로 새로 만들지 말 것.
|
||||
- **DB env는 별도 계층**: `{SCALP|MOMENTUM|BREAKOUT|TAIL}_WHIPSAW_FILTER_ENABLED` + 글로벌 `WHIPSAW_FILTER_ENABLED`. apply 시점(`param_search_*.apply_params_to_db`·`tail_env_keys.py`·`optuna_whipsaw_recommend`)에서 소문자 파라미터에 prefix를 붙여 변환. 파이썬/JS 파라미터 계층은 전략 무관 단일 키 유지.
|
||||
|
||||
## 3. 필수 grep (수정·리뷰 시)
|
||||
|
||||
웹백테 폼 / Optuna / apply / 후처리 / 프론트 5개 축을 **한 세트로** 검사한다.
|
||||
|
||||
```bash
|
||||
rg -n 'whipsaw_filter_enabled|whipsaw_enabled' \
|
||||
backtest_web.py static/js/backtest.js templates/backtest.html \
|
||||
kis_trader/backtest kis_trader/engine
|
||||
```
|
||||
|
||||
- `backtest_web.py`의 `params["..."] = ...` (웹 폼 → params) — 저장 키
|
||||
- `kis_trader/backtest/bt_post_filters.py` — 후처리 조회 키
|
||||
- `kis_trader/backtest/param_search_*.py` — apply 맵 키
|
||||
- `kis_trader/backtest/optuna_*.py` — Optuna trial params 저장 키
|
||||
- `static/js/backtest.js` — 폼 파라미터 name (`out.whipsaw_filter=1|0`) 및 hidden 표시
|
||||
|
||||
**세팅 키 ↔ 조회 키가 다르면 완료 아님.**
|
||||
|
||||
## 4. 완료 전 스모크 (필수 1회)
|
||||
|
||||
1. 동일 기간·동일 파라미터로 웹 백테 실행 (휩쏘 ON) → 거래수·PnL 기록
|
||||
2. 같은 조건 Optuna best JSON 로드 → 웹 백테 재실행
|
||||
3. 두 결과가 **1원 단위 일치** 해야 정합. 안 맞으면 이 규칙 §3 grep 다시.
|
||||
4. 실매 코어를 만졌으면 `python3 -u scripts/test_live_execution_validation.py` (`live-execution-validation.mdc`).
|
||||
|
||||
## 5. 자주 나는 함정
|
||||
|
||||
- 프론트가 폼 파라미터를 `whipsaw_filter=1|0` 으로 보내는데, 백엔드가 이를 `params["whipsaw_enabled"]` 로 저장 → 후처리 조회 키(`whipsaw_filter_enabled`)와 불일치. **읽는 이름과 쓰는 이름을 분리해서 검사할 것.** (2026-09-06 통일로 이 경로는 해소됨)
|
||||
- 하위호환 폴백을 **양쪽에 다 넣으면** 어느 쪽이 실제 진리인지 흐려져 다음 사고 촉발. 신 alias 도입 시 폴백은 **소비자 1곳만·기한부**로 두고 다음 릴리즈에서 제거.
|
||||
- apply 맵(`param_search_*.py`)에 두 alias를 다 넣으면 apply는 무해히 동작해도, “통일” 계획을 반쯤 어긴 상태로 남는다. 계획 문서와 실 코드가 어긋나면 다음 리팩터에서 다시 사고.
|
||||
40
.cursor/rules/optuna-job-engine-label.mdc
Normal file
40
.cursor/rules/optuna-job-engine-label.mdc
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
description: Optuna job 엔진 뱃지(Rust⚡/Python🐢) — use_rust 명시 저장, 폴백 하드코딩 금지
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Optuna Job 엔진 뱃지 라벨링
|
||||
|
||||
이 대화에서 실제로 난 사고: 파이썬으로 돌린 스캘핑 job이 UI에서 `Rust⚡`로, 러스트 스캘핑 refine2 가 헷갈리게 표시. 원인은 `optuna_web_jobs.py`에서 `use_rust` 필드가 없는 옛 JSON에 **전략명 하드코딩 폴백**(“tail이면 Rust, 나머지는 Python”)을 붙였기 때문.
|
||||
|
||||
## 1. 원칙
|
||||
|
||||
- Optuna job(`logs/optuna_web_jobs/<id>.json`) 저장 시 **`use_rust: true|false` 를 항상 명시 저장**한다. 프론트 뱃지·필터·정렬이 이 필드를 진리로 사용한다.
|
||||
- 백엔드 job_list 렌더링은 `use_rust` 가 **없거나 None이면** `engine_label = "미상"` (예: `❔`) 로만 표기. **전략명에 따라 임의로 Rust/Python을 부여하지 말 것.**
|
||||
- 프론트도 `engine_label` 문자열을 신뢰. 하드코딩 매핑 금지.
|
||||
|
||||
## 2. 금지
|
||||
|
||||
- `if "tail" in strategy: label = "Rust⚡" else "Python🐢"` 류 폴백.
|
||||
- 신규 Rust 포팅 전략(스캘핑·모멘텀·돌파 등)이 늘어날 때 이 조건을 늘려 유지보수하는 방식.
|
||||
- 옛 JSON을 뒤늦게 스캔하며 라벨을 “추정”해 덮어쓰기.
|
||||
|
||||
## 3. 필수 저장 필드
|
||||
|
||||
`optuna_web_jobs` 저장 시 아래를 반드시 포함:
|
||||
|
||||
- `use_rust: bool` — 실제 실행 엔진
|
||||
- `strategy: str` — 전략 코드
|
||||
- `mode: str` — Optuna mode (tpe/fast/coarse/…)
|
||||
- `label: str` — UI 표시용(예: `1·2차TPE·스캘핑`). 초기화 실패 시 `_labels.get(strat, strat)` 폴백만 허용.
|
||||
|
||||
## 4. 완료 전 스모크
|
||||
|
||||
1. Rust로 스캘핑 mode 1회 실행 → UI에서 `Rust⚡` 로 뜨는지
|
||||
2. Python으로 스캘핑 mode 1회 실행 → `Python🐢` 로 뜨는지
|
||||
3. `use_rust` 누락 옛 JSON 하나 열어 → `❔` (미상) 으로 뜨는지
|
||||
4. 브라우저 검증 URL은 `http://192.168.0.149:5050/` (`backtest-web-restart.mdc`)
|
||||
|
||||
## 5. 참고
|
||||
|
||||
- `label`이 `None` 이면 UI가 `study_short`(`refine2` 등)로 폴백하며 사용자에게는 의미 없는 표기가 됨. 라벨은 항상 `_base_label = label if label else _labels.get(strat, strat)` 로 방어.
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
description: 가설은 검증 후에만 결론 · 한 전략 사고/수정 시 타전략 교차검증 필수
|
||||
description: 버그=딥다이브 후 근본원인·3안 제시 · 추측 금지 · 타전략 교차검증
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# 가설 검증 필수 · 전략 교차검증 (추측으로 답 금지)
|
||||
# 가설 검증 · 버그 딥다이브 · 전략 교차검증
|
||||
|
||||
이 대화에서 실제로 낭비된 패턴: **가설만 말하고 값 패치로 끝내기**, **한 전략만 보고 타전략 동일 이슈 미검사**.
|
||||
이 대화에서 실제로 낭비된 패턴: **가설만 말하고 값 패치로 끝내기**, **추측성 대안 나열**, **한 전략만 보고 타전략 동일 이슈 미검사**.
|
||||
|
||||
## 1. 추측·가설로 답변 금지
|
||||
|
||||
@@ -18,7 +18,32 @@ alwaysApply: true
|
||||
- 검증에 쓴 증거(테이블·파일·시각·수치)를 보고에 **짧게** 남긴다. 없으면 “미확인”이라고 쓰고 단정 금지.
|
||||
- CRITICAL §5(근본원인 먼저)와 동일 정신. 값만 고치고 “고쳤다”고 하지 말 것.
|
||||
|
||||
## 2. 한 전략 수정·사고 조사 시 → 타전략 교차검증 (필수)
|
||||
## 2. 버그 발견 시 — 함수 추적 딥다이브 → 근본 3안 (필수)
|
||||
|
||||
버그·이상 수치·정합 깨짐을 발견하면 **즉시 패치하지 말고** 아래를 끝낸 뒤 보고한다.
|
||||
**오래 걸려도 된다.** 짧은 추측 턴을 여러 번 돌리는 토큰 낭비를 금지하고, **한 번에 구석구석 분석**한다.
|
||||
|
||||
### 2-1. 분석 (코드 근거 없이 대안 금지)
|
||||
|
||||
1. 증상 진입점(로그 시그니처·함수명·콜사이트)을 확정한다.
|
||||
2. 해당 함수를 **호출 체인 따라** 읽는다 (호출자 → 피호출 → 공유 헬퍼/캐시/DB/WS).
|
||||
3. 분기·기본값·env·None/빈값·재시도·락·전략별 분기까지 **구석구석** 대조한다.
|
||||
4. 실측 증거(코드 라인·로그·DB/스키마)로 **근본원인 1개**를 확정한다. 미확정이면 “미확인” + 다음에 볼 경로만 적고 **대안·수정 금지**.
|
||||
|
||||
### 2-2. 보고 — 근본적인 대안 정확히 3개
|
||||
|
||||
근본원인 확정 **후에만**, 땜빵이 아닌 **근본 해결안 3개**를 제시한다.
|
||||
|
||||
| 안 | 내용 (필수) |
|
||||
|----|-------------|
|
||||
| 대안 A/B/C | 무엇을 어디서 고치는지 (파일·함수) |
|
||||
| 각 안 | 왜 근본원인에 닿는지 · 실매/백테/타전략 부작용 · 리스크 |
|
||||
| 추천 | 3안 중 1개를 고르고 이유 1~2문장 |
|
||||
|
||||
- **금지**: 코드 미추적 추측 대안, “일단 값만 바꾸기/재시도 늘리기/±1 보정” 류 증상 가리기, 근거 없는 4안 이상 나열.
|
||||
- **필수**: 선보고 → 사용자 승인 후 수정 (핵심 매매/인프라는 `.cursorrules` 선수정 원칙과 동일).
|
||||
|
||||
## 3. 한 전략 수정·사고 조사 시 → 타전략 교차검증 (필수)
|
||||
|
||||
전략 A(꼬리/모멘텀/돌파/스캘핑 등)에서 버그·잘못된 apply·단위·UI를 찾거나 고쳤으면, **보고 전에** 같은 종류의 위험이 B·C에도 있는지 검사한다.
|
||||
|
||||
@@ -33,7 +58,7 @@ alwaysApply: true
|
||||
- 타전략이 정상이면 **검사한 증거**(예: 마지막 apply=gated#1, live 값=trial params)를 한 줄씩 적는다.
|
||||
- 타전략도 동일/유사면 **잔여 위험**으로 명시하고, 사용자 승인 없이 일괄 값 패치하지 말 것.
|
||||
|
||||
## 3. Optuna 적용 추적 (감사)
|
||||
## 4. Optuna 적용 추적 (감사)
|
||||
|
||||
- HTTP access 로그만으로는 body(`source=mode`)가 안 남을 수 있음.
|
||||
- 1차 추적: `logs/optuna_web_jobs/<job_id>.json` → `applied_at` / `applied_source` / `applied_rank` / `applied_trial` / `applied_upto`
|
||||
|
||||
Reference in New Issue
Block a user