1. 배경
v3 MDN 모델 실패 원인
- 아키텍처: Regime-Routed MDN (3개 전문 에이전트), 96K 파라미터
- 문제점: 모델이 거의 상수에 가까운 출력만 생성 (prob_profit 범위 0.51~0.54)
- 진단 결과:
- mu_bias가 고정값으로 수렴 → 시장 데이터를 무시하고 상수 편향만 출력
- Return centering으로 편향 제거 후에도 패턴 학습 불가
- 96K 파라미터 MDN이 34개 feature에서 유의미한 패턴을 찾기에 용량 부족
- 백테스트 결과: 승률 39.5%, PF 0.91 (손실)
- 실거래 결과 (v2): 15연패 후 중단
v4 Transformer 선택 이유
- 직접 분류 (buy/sell/hold) → MDN 밀도 추정의 복잡성 제거
- Self-attention으로 시계열 패턴 직접 학습 가능
- 576K 파라미터 (v3 대비 6배) → 더 높은 표현력
- Patch embedding으로 M5 바 그룹을 효율적으로 인코딩
2. v4 모델 아키텍처
TransformerTrader
입력: M5 feature window [96 bars, 34 features]
↓
Patch Embedding: 4 bars → 128-dim (96 bars → 24 patches)
↓
CLS Token + Positional Embedding (learnable)
↓
4-Layer Pre-Norm Transformer Encoder
- 4 attention heads
- d_model=128, d_ff=256
- GELU activation
- Dropout 0.1
↓
CLS Token Output → 3개 헤드:
1. Direction: 3-class (buy=0, sell=1, hold=2)
2. Confidence: sigmoid → [0, 1]
3. Magnitude: 예상 변동 크기
- 파라미터: 576,389 (0.58M)
- 입력: 96개 M5 바 × 34개 feature (rolling z-score 정규화)
- 출력: 방향 확률 [buy, sell, hold] + 신뢰도 + 크기
Feature 목록 (34개)
- 가격 기반: returns, log_returns, hlc3_ret, typical_price_ret
- 변동성: atr_14, natr_14, bbw_20, keltner_width, hist_vol_20
- 추세: sma_cross, ema_cross, macd_signal, adx_14, aroon_osc
- 모멘텀: rsi_14, stoch_k, stoch_d, cci_20, williams_r, roc_10, mfi_14
- 시장구조: hurst_20, frac_dim, squeeze, obv_slope
- 기타: vwap_dist, spread_norm, hour_sin, hour_cos, dow_sin, dow_cos, usdx_ret, usdx_corr
3. 학습 과정
Phase 1: Directional Classification (60 epochs)
데이터: 200K M5 bars × 4 symbols (EURUSD, GBPUSD, AUDUSD, NZDUSD)
샘플: 199,892개 (buy 47.5%, sell 46.6%, hold 5.9%)
Train/Val: 159,913 / 39,979 (80/20 random split)
클래스 가중치: buy=0.70, sell=0.72, hold=5.61
손실함수: CrossEntropyLoss (label_smoothing=0.05) + SmoothL1Loss(magnitude) × 0.1
옵티마이저: AdamW (lr=3e-4, weight_decay=1e-4)
스케줄러: CosineAnnealingLR (eta_min=3e-6)
Gradient clipping: max_norm=1.0
라벨 생성:
- 12-bar forward return (centered, scale=10000)
- buy: return > 0.5 pips
- sell: return < -0.5 pips
- hold: ±0.5 pips 이내
결과:
EpochLossTrain AccVal AccVal Dir AccLR
| 1 | 1.6057 | 20.4% | 20.7% | 17.1% | 3.0e-4 |
| 10 | 1.5615 | 31.3% | 31.4% | 29.6% | 2.8e-4 |
| 20 | 1.5206 | 38.5% | 38.2% | 37.8% | 2.3e-4 |
| 30 | 1.4659 | 44.3% | 40.1% | 40.2% | 1.5e-4 |
| 40 | 1.4094 | 49.3% | 44.7% | 45.6% | 7.7e-5 |
| 50 | 1.3714 | 52.3% | 46.2% | 47.4% | 2.3e-5 |
| 60 | 1.3554 | 53.3% | 46.6% | 47.7% | 3.0e-6 |
Best val_acc = 46.7% → saved_models/htfc_v4_phase1.pt
Phase 2: Sharpe Optimization (30 epochs) — 폐기
목적: 미분가능 시뮬레이터로 Sharpe ratio 직접 최적화
결과: 모델이 "거래 안 하기"를 학습 (confidence → 0)
loss는 줄었지만 position이 0에 수렴
원인: Sharpe 최적화에서 가장 안전한 전략 = 거래 안 하기
→ Phase 2 결과 폐기, Phase 1 모델 사용
4. 백테스트 결과 (Walk-Forward 6-Fold)
설정
모델: htfc_v4_phase1.pt (Phase 1 only)
신뢰도 임계값: 0.65
SL: 2.0 ATR, TP: 3.0 ATR
최대 보유: 36 bars (3시간)
쿨다운: 6 bars (30분)
시작 자본: $10,000
결과
구간기간(일)거래승률수익샤프PFMDD
| 1 | ~35 | 487 | 66.1% | $16,311 | 24.81 | 2.77 | 5.14% |
| 2 | ~35 | 496 | 59.3% | $8,815 | 16.95 | 1.99 | 5.49% |
| 3 | ~35 | 485 | 59.0% | $10,507 | 18.40 | 2.09 | 4.13% |
| 4 | ~35 | 506 | 57.3% | $13,509 | 13.28 | 1.78 | 6.45% |
| 5 | ~35 | 506 | 62.5% | $12,736 | 21.59 | 2.39 | 2.91% |
| 6 | ~35 | 503 | 64.0% | $19,536 | 21.02 | 2.46 | 5.00% |
| 평균 | 2,983 | 61.4% | $81,413 | 19.34 | 2.25 | 4.85% |
- 6/6 구간 수익 (전 구간 수익)
- v3 대비: 승률 39.5% → 61.4%, PF 0.91 → 2.25
주의사항
- 인샘플 결과: 모델이 학습한 데이터로 테스트한 것이므로 실전보다 높은 수치
- 샤프비율 19는 비현실적 — 실전에서 1~3이면 우수
- 진짜 성과는 실거래에서 확인
5. 신호 생성 로직
# 1. M5 feature 96개 바 추출
window = m5_features[bar - 96 : bar] # [96, 34]
# 2. Transformer 추론
out = model(window)
probs = softmax(out["logits"]) # [buy_prob, sell_prob, hold_prob]
# 3. 방향 결정 (최대 확률 클래스)
if buy_prob > sell_prob and buy_prob > hold_prob:
direction = "buy"
elif sell_prob > buy_prob and sell_prob > hold_prob:
direction = "sell"
else:
direction = "hold" (진입 안 함)
# 4. 신뢰도 = max(buy_prob, sell_prob)
confidence = max(buy_prob, sell_prob)
# 5. 진입 조건: confidence > 0.70
# 6. SL = 현재가 ± 2.0 × ATR(14)
# 7. TP = 현재가 ± 3.0 × ATR(14)
6. 리스크 관리
항목설정값설명
| 랏 사이즈 | 1.0 | 고정 (변경 금지) |
| SL | 2.0 ATR | 14-bar ATR 기준 |
| TP | 3.0 ATR | SL의 1.5배 (비대칭 보상) |
| 최대 보유 | 36 bars | 3시간 초과 시 강제 청산 |
| 쿨다운 | 12 bars | SL 후 1시간 재진입 금지 |
| 최대 포지션 | 4개 | 심볼당 1개 |
| 연속 손실 제한 | 5회 | 5연패 시 12 bar 거래 중단 |
| 일일 손실 한도 | 5% | 일일 최대 낙폭 |
7. 파일 구조
HTFC_wave_323/wave/
├── scripts/
│ ├── train_v4.py # v4 Transformer 학습 스크립트
│ ├── backtest_v4.py # v4 백테스트 + Walk-Forward 검증
│ ├── live_v4.py # v4 실거래 진입점
│ ├── train.py # v3 학습 (참고용)
│ ├── backtest.py # v3 백테스트 (참고용)
│ └── live.py # v3 실거래 (참고용)
├── saved_models/
│ ├── htfc_v4_phase1.pt # ★ 현재 사용 중인 모델
│ ├── htfc_v4_final.pt # Phase 2 포함 (폐기됨)
│ └── htfc_v3_*.pt # v3 모델들 (참고용)
├── src/
│ ├── live/
│ │ ├── runner.py # LiveRunner (v3 기반, v4에서 상속)
│ │ ├── executor.py # MT5 주문 실행기
│ │ ├── state.py # 포지션/계좌 상태 관리
│ │ └── monitor.py # 성과 모니터링
│ ├── data/
│ │ ├── features.py # 34개 feature 계산
│ │ └── collector.py # parquet 데이터 로더
│ └── simulator/
│ └── differentiable_sim.py # 미분가능 시뮬레이터
├── config/
│ └── base.yaml # 기본 설정
├── data/ # parquet 데이터 (16 symbols × 6 TF)
├── logs/ # 로그 파일
└── live_state/ # 실거래 상태 (positions, account)
8. 실거래 실행 스크립트
실거래 시작 (LIVE)
cd /c/a_prj/HTFC_wave_323/wave
python scripts/live_v4.py \
--device cuda \
--model saved_models/htfc_v4_phase1.pt \
--confidence-threshold 0.70 \
--lot-size 1.0 \
--sl-atr 2.0 \
--tp-atr 3.0 \
--max-holding 36 \
--cooldown-bars 12 \
--max-positions 4 \
--max-consecutive-losses 5 \
--poll-interval 30
python scripts/live_v4.py --device cuda --model saved_models/htfc_v4_phase1.pt --confidence-threshold 0.70 --lot-size 1.0 --sl-atr 2.0 --tp-atr 3.0 --max-holding 36 --cooldown-bars 12 --max-positions 4 --max-consecutive-losses 5 --poll-interval 30
페이퍼 트레이딩 (DRY-RUN)
cd /c/a_prj/HTFC_wave_323/wave
python scripts/live_v4.py \
--device cuda \
--dry-run \
--model saved_models/htfc_v4_phase1.pt \
--confidence-threshold 0.70 \
--lot-size 1.0 \
--sl-atr 2.0 \
--tp-atr 3.0
오프라인 페이퍼 (parquet 데이터 사용)
cd /c/a_prj/HTFC_wave_323/wave
python scripts/live_v4.py \
--device cuda \
--dry-run \
--use-parquet \
--model saved_models/htfc_v4_phase1.pt \
--confidence-threshold 0.70
백테스트 재실행
# 단일 백테스트
python scripts/backtest_v4.py \
--device cuda \
--use-parquet \
--data-dir data \
--model saved_models/htfc_v4_phase1.pt \
--confidence-threshold 0.65
# Walk-Forward 6-Fold 검증
python scripts/backtest_v4.py \
--device cuda \
--use-parquet \
--data-dir data \
--model saved_models/htfc_v4_phase1.pt \
--walk-forward \
--n-folds 6 \
--confidence-threshold 0.65
학습 재실행
# Phase 1만 (권장)
python scripts/train_v4.py \
--device cuda \
--use-parquet \
--data-dir data \
--phases 1 \
--phase1-epochs 60
# Phase 1 + Phase 2
python scripts/train_v4.py \
--device cuda \
--use-parquet \
--data-dir data \
--phases all
# Phase 2만 (Phase 1 체크포인트에서 이어서)
python scripts/train_v4.py \
--device cuda \
--use-parquet \
--data-dir data \
--phases 2 \
--resume saved_models/htfc_v4_phase1.pt
프로세스 확인 / 종료
# 실행 중인지 확인
tasklist | grep python
# 종료
taskkill //F //PID <PID번호>'주식분석' 카테고리의 다른 글
| B-05. 피크와 밸리 — 고점과 저점을 수학적으로 찾는 방법 (0) | 2026.05.13 |
|---|---|
| B-04. 푸리에 변환과 주기 분석 — 시장의 박자를 찾아라 (0) | 2026.05.12 |
| HTFC v2: Hierarchical Temporal Fusion Chain with Shared Encoder (0) | 2026.04.30 |
| A-05. WaveRader 회원가입부터 첫 분석까지 — 완전 초보 가이드 (0) | 2026.04.28 |
| A-04. WaveRader vs 기존 HTS/MTS — 무엇이 다른가 (0) | 2026.04.27 |