주식분석

HTFC v4 Transformer 학습 및 실거래 준비 과정

파동분석가 2026. 4. 30. 13:06

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번호>