# Backtest Architecture ## 1. 목적 Phase 4의 백테스터는 **Phase 3에서 생성된 canonical feature dataset**을 입력으로 받아, **event-driven continuation 전략**을 시뮬레이션하고, 포트폴리오/리스크 규칙을 반영한 뒤, 정량 결과와 리포트를 산출하는 엔진입니다. 이 엔진은 “가격만 넣고 대충 수익률 계산”하는 수준이 아니라, 다음을 반드시 만족해야 합니다. - point-in-time only - session-aware event alignment - deterministic execution - reproducible experiment runs - 동일 전략을 다른 horizon / regime split에 재사용 가능 ## 2. 입력 계층 백테스터 입력은 아래 5개 레이어로 나뉩니다. ### 2.1 Event snapshot Phase 3의 `canonical_event_record` + feature snapshot. 필수 필드: - `event_id` - `symbol` - `issuer_cik` - `event_type` - `event_timestamp_et` - `availability_timestamp_et` - `reaction_session_date` - `entry_eligibility_date` - `event_score_components` - `attention_score_components` - `final_candidate_score` ### 2.2 Market bars 일봉은 필수, 분봉은 선택입니다. 무료 데이터 제약상 v1의 기준 execution은 **next open / next close / stop-on-daily-bar approximation**입니다. 필수 필드: - `trade_date` - `symbol` - `open` - `high` - `low` - `close` - `volume` - `vwap_optional` - `adjustment_factor` ### 2.3 Instrument master 필수 필드: - `symbol` - `asset_type` - `listing_exchange` - `sector` - `industry` - `is_tradable` - `first_seen_date` - `last_seen_date` ### 2.4 Regime data 필수 필드: - `trade_date` - `spy_trend_state` - `qqq_trend_state` - `vix_level` - `macro_regime` ### 2.5 Experiment config 전략, risk model, sizing model, slippage model, universe filter를 정의하는 manifest. ## 3. 출력 계층 ### 3.1 Trade blotter 모든 체결/부분청산/최종청산을 row-level로 저장합니다. 필수 필드: - `run_id` - `trade_id` - `position_id` - `symbol` - `entry_date` - `entry_price` - `exit_date` - `exit_price` - `shares` - `gross_pnl` - `net_pnl` - `exit_reason` - `holding_days` ### 3.2 Position timeline 일자별 포지션 평가, 노출, MFE/MAE, stop distance. ### 3.3 Daily equity curve 일자별 자산곡선과 drawdown. ### 3.4 Metrics report - CAGR-like annualized return - average trade return - expectancy - hit rate - payoff ratio - max drawdown - profit factor - turnover - avg holding period - exposure - sector concentration - regime-by-regime performance ### 3.5 Attribution report - by event type - by guidance direction - by sector - by score bucket - by attention overlay bucket ## 4. 서비스 경계 ### 4.1 Snapshot reader 입력 데이터셋에서 **시점상 이용 가능한 feature만** 읽어옵니다. 이 계층은 절대 미래 row를 읽으면 안 됩니다. ### 4.2 Candidate selector 특정 날짜의 후보 종목을 정렬하고 상위 N개를 선택합니다. ### 4.3 Portfolio allocator 동시보유 수, 섹터 제한, 현금 제한, per-trade risk budget을 반영합니다. ### 4.4 Execution simulator 진입/청산 주문을 체결 가격으로 변환합니다. ### 4.5 Report writer 실험 결과를 표준 포맷으로 저장합니다. ## 5. 실행 흐름 ```text experiment manifest → dataset snapshot resolve → calendar iteration by trade date → candidate selection for date D → eligibility filter → ranking / tie-break → portfolio allocation → entry fill simulation → open position management → exit checks → pnl / exposure update → end-of-day ledger snapshot → final metrics / artifacts write ``` ## 6. 날짜/시간 처리 원칙 ### 6.1 세션 경계 - 미국 동부시간(ET) 기준으로 판단합니다. - premarket / regular / after-hours를 구분합니다. - event timestamp가 장후면 reaction session은 다음 거래일입니다. - event timestamp가 장중이면 reaction session은 당일이지만, feature availability timestamp를 반드시 확인합니다. ### 6.2 entry eligibility 기본 전략은 **reaction day 종료 후 점수 확정 → 다음 거래일 진입**입니다. 따라서 entry date는 최소한 reaction day + 1 trading session입니다. ### 6.3 split/dividend adjustment 가격계열은 조정값을 명시적으로 사용합니다. 단, 체결 시뮬레이션과 리포트는 같은 조정 기준을 사용해야 합니다. ## 7. bias 방지 원칙 - future-adjusted universe 금지 - delisted symbol 제거 금지 - 나중에 정리된 event timestamp 사용 금지 - later corrected filing 내용으로 과거 시점 feature overwrite 금지 - final labels가 feature generation 단계에 들어가는 것 금지 ## 8. backtest engine의 최소 클래스 경계 추천 Python 경계: - `BacktestRunner` - `MarketCalendar` - `SnapshotStore` - `CandidateSelector` - `PortfolioAllocator` - `ExecutionSimulator` - `PositionManager` - `MetricsEngine` - `ArtifactWriter` 각 클래스는 side-effect를 최소화하고 deterministic 해야 합니다.