47 일 데이터로 새 봇을 검증하려 했다. 신호가 0 번 나왔다.
INCONCLUSIVE
V5.0-SHORT 본격 코드를 박은 직후 47 일 long-bot 거래 로그를 fixture 로 써서 signal_short 백테스트를 돌렸다. 결과 한 줄.
Strict signal_short 가 47 일 동안 0 번 발화.
처음 본 순간 = 신호가 망가진 줄 알았다. 7 개 필터 중 어디서 막혔나, vol_ratio 인가 RSI 인가, 임계 잘못 박았나, 부터 의심. 코드 한 시간 더 봤다.
진짜 이유는 다른 데 있었다.
두 universe 가 mutex
long V3.7.1 봇의 47 일 거래 데이터 = long 봇이 진입한 순간들만 박힘. 그 순간의 시장 = 무엇인가:
| 항목 | long 봇 데이터 | V5.0-SHORT 요구 | 겹침 |
|---|---|---|---|
| trend | UP 6701 / FLAT 2531 / DOWN 0 | DOWN 만 | 0% |
| RSI | 8.6 ~ 55.0 (cap) | 60 ~ 75 | 0% |
| vol_ratio | 1.20 ~ 35.48 | 1.5 ~ 4.0 | 52.6% |
| bounce/drop | 다양 | 0.3% ~ 0.8% | 42.7% |
long 봇이 본 시장의 trend = DOWN 이 0 개. 한 번도 없음. 이유는 단순. long 봇은 trend 가 DOWN 일 때 진입을 거부하니까. 거부한 데이터는 trade_log 에 안 박힌다. trade_log 가 long 봇 진입의 biased sample.
RSI 도 같은 식이다. long 봇이 RSI > 55 에서는 진입 안 함. 그래서 trade_log 의 RSI 최댓값 = 55.0. short 봇은 RSI 60-75 에서 진입. 겹치는 RSI 값 = 단 한 줄도 없음.
trend 와 RSI 두 축에서 동시에 mutex. 다른 5 개 필터가 아무리 잘 동작해도 = 진입 자체가 일어날 수 없는 universe.
더 흥미로운 발견 = mirror 효과 0
기대했던 검증 한 가지 = "long 봇이 손실 본 시간대에 short 봇이 신호 잡았나". 즉 거울 confirmation. long 봇이 47 일 동안 305 번 loss 봤다. short 봇이 그 시간대에 진입 신호를 catch 한 비율 = 0/305 (0.0%).
처음에는 "이건 결함이다" 싶었다. 같은 시장 같은 시간대에 한 봇은 long 진입하고 다른 봇은 short 진입해야 mirror confirmation 이지. 0 이면 신호가 잘못 짠 것 같다.
다시 보니 아니다. 두 봇이 서로 다른 시장 regime 을 targeting 한다.
V3.7.1 long 봇 = "추세 따라가는 스캘퍼". 작은 swing 잡기. UP 추세에서 잠깐 pullback 했다가 다시 올라갈 때 진입. 짧게 잡고 짧게 나옴.
V5.0-SHORT 봇 = "DOWN 추세 반전 noise 잡기". 큰 음봉 자르기. 시장이 강하게 떨어진 후 잠깐 반등할 때 진입. 그 반등이 죽을 거라 예상.
두 봇이 한 번도 동시에 진입 안 함 = architectural separation 이 의도된 것. 한 봇은 UP 추세 라이더, 다른 봇은 DOWN 추세 반전 sniper. 같은 시장의 다른 phase 를 targeting.
무엇이 검증된 건가
strict 패스에서 0 번 발화 = 검증 실패가 아님. fixture 가 검증할 자격이 없다는 검증.
다른 검증 한 가지는 일어났다. trend 와 RSI 필터 둘 다 꺼봤다 (= Pass C). 그러면 47 일 동안 46 번 발화. 단:
- Win rate = 47.5%
- Max DD = 43%
- Train 25 신호 win rate 28% / Test 21 신호 win rate 47.6%
- OOS drift > 15pt
= trend + RSI 필터가 빠지면 = MDD 폭발 + train/test drift 큼. 즉 이 두 필터는 노이즈 차단의 핵심. 빠질 수 없다.
이게 negative validation 이다. 두 필터를 풀어보고 "안 풀어도 된다" 가 확인된 것.
다음 단계 = 새 데이터
47 일 long fixture 로는 더 검증 못 한다. 새 데이터가 필요하다.
- Binance USDM 의
/fapi/v1/klinesREST 호출 (= ccxt 안 거쳐 직접) - 5 심볼 (BTC / ETH / SOL / BNB / XRP) × 6 개월 1 분 OHLCV
/fapi/v1/fundingRate동기간- 위 데이터로
backtest_signal_short.py재실행 - 100 개 이상 OOS fired signals 모이면 → paper_runner 2 주 → testnet → 소액 라이브
본 데이터 가져오는 게 다음 주 작업. D-day 가 정확히 D3 (= 5/27 D5 리뷰) 박힌 후 진입 결정 시점에 = 진짜 OOS 데이터 위에서 검증된 결과 박혀 있어야 함.
sniper 자산 라인의 8 번째 사용
V3.7.1 봇 자체 = 5/12 셧다운 후 안 돌아간다. 그러나 그 봇이 47 일 동안 박은 데이터 + 그 봇 짜면서 박은 코드 패턴이 = dev.to 4 편 → 5 편 → 6 편 → 7 편 + 5/22 셋업 일지 + 본 글 = 자산의 8 번째 사용.
8 번째 사용이 = fixture-mismatch 발견의 honest writeup. 이건 win 도 loss 도 아닌 결과를 "왜 안 됐는지" 깊이 박는 라인. 다른 builder 가 같은 길 안 가게 하는 자산.
V3.7.1 의 47 일 거래 로그 = long bot 의 자산. 동시에 = long bot 진입 universe 의 sample. 그 sample 로 short bot 검증 시도 = 자연스러운 다음 단계. 단 = 그 sample 이 biased 라는 것을 발견하는 것 자체가 결과.
failed 봇 ≠ 실패. inconclusive 백테스트 ≠ 실패. 빠진 부분을 정확히 명시하는 것 = 가장 큰 진척.
검증 도구
본 작업 자료:
C:\Users\user\.openclaw\workspace\v5_short_design\BACKTEST_RESULTS.md(= 1 페이지 결과)C:\Users\user\.openclaw\workspace\v5_short_design\backtest_signal_short.py(= 재실행 가능 스크립트)C:\Users\user\.openclaw\workspace\v5_short_design\backtest_raw.json(= raw 숫자)
다음 글 = OHLCV 6 개월 데이터 가져온 후 재실행 결과 발표 예정. 이 글 publish 시점 = D3-D4 사이 (= 5/24-5/26 KST 추정).
47 일 fixture 위에서 0 번 발화하는 새 봇. 결과는 inconclusive 다. 단 inconclusive 자체가 가장 단단한 builder feedback.