fix: ML 게이트 스케일 불일치 + 운영 실측 반영 (문서 정정 3건)
## ML 게이트 이중 블렌딩 (플래그 OFF 로 출고) market_analyzer.py:603-608 이 이미 rule30/ML70 으로 블렌딩한 뒤 0~15 로 축소 저장하는데, trade_executor 가 그 값을 정규화 없이 **또** 블렌딩했다. weighted_score = score_val(0~15) * 0.3 + ml_score(0~100) * 0.7 ≥ 60 룰 기여가 최대 4.5 로 임계 60 의 7.5% — 문서상 "룰 30%" 가 지켜지지 않았다. _ml_gate_score_v2() 신설 + ML_SCORE_NORMALIZE_ENABLED(기본 False). OFF 시 7,373 조합 비트 동일 검증. RULE_SCORE_MAX=15 신설(하드코딩 제거). 운영 실측으로 확인된 것: ML-BUY 분기는 어느 설정으로도 발화 불가. OFF: ml_score ≥ 85.7 필요 / 실측 ml_score 최대 50 ON : score ≥ 9 필요 / 실측 score 역대 최대 6 (801건) 즉 ML 게이트는 HOLD 차단(브레이크)으로만 기능해 왔다. 임계값 재보정이 필요하며 §8.1-5 에 따라 백테스트가 선행돼야 한다. ## 문서 정정 (잘못된 전제 제거) 1. "NAS 다운 → 백테스트 불가" 는 사실이 아니다. NAS 는 가동 중이고 autostock-postgres 도 떠 있다. DB 가 127.0.0.1:15433 바인딩이라 외부 직결만 안 되는 것이며, NAS 내부에서 접근 가능하다. **백테스트 재실행 가능.** 2. docs/BATCH_GUIDE.md 의 cron 서술 정정 — 운영 NAS 에 crontab 이 없고 앱 내부 스케줄러(main.py:269 → schedulers.py:74, 10분 간격)가 배치를 돌린다. setup-cron.sh 를 쓰면 오히려 중복 실행된다. 3. market_schedule.py 에 휴장일 판정이 없다 — 2026-09-24~25 거래·분석 0건은 추석 연휴이며 장애가 아니다. ## §8.4.1 운영 실측 신설 - daytrading 257건 vs swing 53건 (DT 가 거래 건수 주력). DT 포지션 0 은 15:20 EOD 전량 청산이 설계대로 동작한 결과 - strategy_configs 가 옛 값으로 운영되던 상태(RSI 30 / SL -6%)를 2026-09-28 배포(alembic 0011→0012)로 해소 - 룰 점수는 0~15 스케일(market_analyzer.py:608 에서 축소 저장), 실측 -1~6 - 9/23 에 active_trades 유령 행 129개(day_trade 120 + swing 9)를 수동 정리한 백업이 남아 있다 — 전략명 없이 close 해 엉뚱한 행이 닫히던 문제의 증거 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
CLAUDE.md
16
CLAUDE.md
@@ -295,14 +295,26 @@ DX(0~100)에 합산형 평활을 적용한 버그. 측정: `up 1361 vs 97 / flat
|
||||
6. 몬테카를로(거래 순서 셔플 10,000회) — MDD 95th pctile, §5.3 트리거 빈도 변화
|
||||
7. 미국은 수정 전/후 A-B 로 1봉 정렬 효과를 분리 측정한 뒤 walk-forward
|
||||
|
||||
### 8.4.1 운영 실측 (2026-09-28)
|
||||
|
||||
운영 DB 를 직접 조회한 결과. 배포 전/후를 구분해 기록한다.
|
||||
|
||||
- **거래 이력**: `daytrading` 257건(BUY 127/SELL 130, 2026-04-06~09-23) vs `swing` 53건(BUY 15/SELL 38). **DT 가 거래 건수로는 주력**이었다. DT 포지션이 항상 0인 것은 15:20 EOD 전량 청산이 설계대로 동작한 결과이며 결함이 아니다.
|
||||
- **2026-09-24~25 거래·분석 0건은 추석 연휴**다. `market_schedule.py` 에 휴장일 판정이 없어 로그만으로는 장애와 구분되지 않는다.
|
||||
- **`strategy_configs` 가 옛 값으로 운영되고 있었다** (alembic 0012 배포 전): BULL 진입 RSI **30**(config 46), 손절 **-6%**(-7%), DT 3종목·종목당 10%. RSI<46 후보는 95종목인데 RSI<30 은 **32종목** — 후보가 3분의 1 이었다. **2026-09-28 배포(alembic 0011→0012)로 해소됨.**
|
||||
- **룰 점수는 0~15 스케일**이다(`market_analyzer.py:608` 이 `combined_score/100*15` 로 축소 저장). 실측 분포는 최소 -1 / 최대 6 / 평균 1.4 (199종목). 따라서 `score >= 60` 형태의 비교는 **구조적으로 충족 불가**다.
|
||||
- **배치는 cron 이 아니라 앱 내부 스케줄러**가 돌린다(`main.py:269` → `schedulers.py:74`, 10분 간격). NAS 에 crontab 은 등록되어 있지 않다.
|
||||
- **9/23 에 `active_trades` 유령 행 129개**(`day_trade` 120 + `swing` 9)를 수동 정리한 백업이 배포 디렉터리에 남아 있다(`active_trades_backup_20260923_1036.sql`). 전략명 없이 close 해 엉뚱한 행이 닫히던 문제의 증거이며, 이번 세션에서 수정했다.
|
||||
|
||||
### 8.5 미해결 항목 (알려진 문제, 임의로 "고쳤다"고 판단하지 말 것)
|
||||
|
||||
> 2026-09-27 작업으로 이전 목록 11건 + 추가 발견 결함 다수가 해소되었다. 아래는 **그 과정에서 새로 드러난 것과 의도적으로 남긴 것**이다.
|
||||
> 전체 유닛 스위트는 `559 passed / 0 failed`(11.8초, 소켓 차단 하) 상태다.
|
||||
|
||||
**백테스트 (최우선)**
|
||||
1. **기존 백테스트 산출물 전부 폐기 상태 — 재실행 필요.** §8.4 의 최소 요건 7개를 갖춘 새 산출물이 나오기 전까지 **어떤 파라미터도 "검증됐다"고 말할 수 없다.** NAS(DB) 복구가 선행 조건.
|
||||
2. `RANGE_TRADE_ENABLED` / `MEAN_REVERSION_BEAR_V2_ENABLED` 는 **백테스트 통과 전 True 금지**. 각 파일 docstring 에 통과 조건이 기재되어 있다. BEAR v2 는 "반전캔들 없이 %B+거래량으로 통과"가 발화의 53% 이므로 그 버킷만 분리 집계해 PF < 1.0 이면 `_W_REVERSAL` 을 필수화하거나 `_MIN_SCORE` 를 0.75 로 올려야 한다.
|
||||
1. **기존 백테스트 산출물 전부 폐기 상태 — 재실행 필요.** §8.4 의 최소 요건 7개를 갖춘 새 산출물이 나오기 전까지 **어떤 파라미터도 "검증됐다"고 말할 수 없다.**
|
||||
✅ **2026-09-28 정정: 재실행이 가능하다.** 이전 판이 "NAS 다운으로 백테스트 불가"라고 적은 것은 오류였다 — NAS(`nas.shium.net`, DNS 정상)는 가동 중이고 `autostock-postgres` 도 떠 있다. DB 포트가 `127.0.0.1:15433` 로 바인딩돼 **외부에서 직접 붙을 수 없을 뿐**이며, NAS 안에서(`docker exec autostock-postgres psql`) 또는 SSH 터널로 접근한다.
|
||||
2. `RANGE_TRADE_ENABLED` / `MEAN_REVERSION_BEAR_V2_ENABLED` 는 **백테스트 통과 전 True 금지**. 각 파일 docstring 에 통과 조건이 기재되어 있다. (DB 가 살아 있으므로 실제로 검증할 수 있다.) BEAR v2 는 "반전캔들 없이 %B+거래량으로 통과"가 발화의 53% 이므로 그 버킷만 분리 집계해 PF < 1.0 이면 `_W_REVERSAL` 을 필수화하거나 `_MIN_SCORE` 를 0.75 로 올려야 한다.
|
||||
3. 박스권 전략이 **스케줄러에 배선되어 있지 않다.** 배선 위치는 `swing/scheduler.py` 의 MDD/`AUTO_TRADE_ENABLED` 게이트 직후(기존 step 7 은 추천 데이터 존재를 전제하므로 SIDEWAYS 에서 도달하지 못한다). `swing/exit_service.py` 에 `RANGE_TRADE` 전용 청산 분기도 없어 현재는 평균회귀 청산으로 처리된다 — 박스 상단 익절·박스 이탈 즉시 손절이 적용되지 않는다.
|
||||
|
||||
**미국 전략 (`US_TRADING_ENABLED=False` 라 당장 위험은 없으나 켜기 전 필수)**
|
||||
|
||||
Reference in New Issue
Block a user