Skip to content

Latest commit

 

History

History
974 lines (842 loc) · 162 KB

File metadata and controls

974 lines (842 loc) · 162 KB

QUANT TRADER — 프로젝트 가이드

목적: 코드를 볼 때 파일별 역할, 프로그램 흐름, 알고리즘·설정을 세세히 알 수 있도록 정리한 문서. 문서 버전: v6.2 최종 수정: 2026-07-06 (weekly_report 모드, 사이클 관측성·집계 배치율 감시·성과 귀속 분해 반영 — 한 달 운영 리뷰 후속. 이전: 2026-06-10 guide/health/deploy_check) 참고: 전체 아키텍처·지표 공식·전략 상세·시스템 진단은 루트의 quant_trader_design.md 참고.


목차

  1. 프로그램이 어떻게 돌아가는지
  2. 실제 디렉터리·파일 구조
  3. 파일별 상세 역할
  4. 설정 파일(YAML) 요약
  5. 실행 모드별 데이터 흐름
  6. 알고리즘·지표 요약
  7. 전략 유효성 검증 및 실전 체크리스트
  8. watchlist 모드
  9. 의존성 및 환경
  10. 저장소(Git) 관리

1. 프로그램이 어떻게 돌아가는지

1.1 전체 흐름 요약

  1. 시작
    main.py 실행 → --mode에 따라 backtest / backtest_momentum_top / portfolio_backtest / validate / paper / schedule / live / liquidate / compare / optimize / dashboard / check_correlation / check_ensemble_correlation / rebalance / health / deploy_check / guide (17종) 중 하나로 분기. 인자 없이 실행하면 백테스트가 돌지 않고 사용 가이드만 출력된다(--mode guide와 동일 — 로거·DB 초기화 없이 종료).

  2. 백테스트 (backtest)
    DataCollector로 과거 주가 수집 → Backtester가 전략으로 시뮬레이션(수수료·세금·슬리피지·손절/익절/트레일링 스탑, gap/어닝/BlackSwan guard 반영, strict-lookahead 기본) → ReportGenerator가 txt/html 리포트 생성.

  3. 모의투자 (paper)
    워치리스트 1회 순회 후 프로세스 종료. WatchlistManager로 관심 종목 확정 → 종목마다 DataCollector.fetch_stock 수집 → 전략 generate_signal(df, symbol=symbol) → BUY 시 시장 국면 필터 적용 후 OrderExecutorDB에만 기록 + 알림. 실제 주문 없음. BUY/SELL 체결가는 모델 슬리피지를 반영한 실행가로 저장하고, DB 현금 흐름은 체결가 기준 수수료·세금만 별도 차감해 슬리피지를 중복 비용으로 처리하지 않는다.

  4. 스케줄 루프 (schedule)
    모의 전용 무한 루프. config.trading.modelive이면 거부(실전은 --mode live --confirm-live). core/runtime_lock.pydata/.scheduler.lock 파일 락을 잡은 뒤 Scheduler.run() — 장전/장중/장마감 루프가 paper와 동일하게 동작하며 프로세스를 유지(systemd 상시 구동용). 기본은 signal-only이며, full paper는 QUANT_AUTO_ENTRY=true로만 켠다.

  5. 실전 (live)
    ENABLE_LIVE_TRADING=true + --confirm-live + 전략 상태 레지스트리의 live 허용 + canonical live gate 통과 필수. KIS API 인증 → PortfolioManager.sync_with_broker()Scheduler 무한 루프.

    • 장전(08:50) 데이터 수집·전략 분석·시장 국면 필터 확인 후 매수 후보 선정(auto_entry: true 시 장중 매수).
    • 장중(09:00~15:30) 10분 간격으로 최대 보유 기간 초과 정리·신호·손절/익절 확인 → 시장 국면 필터 통과 시에만 진입 후보 실행 → OrderExecutor가 KIS API로 실제 주문. live에서는 장중 모니터링 루프에서 설정 주기(sync_broker_interval_minutes)에 따라 KIS↔DB 잔고를 먼저 크로스체크하며, 실패하거나 불일치하면 신규 진입 후보 실행·재스캔은 보류하고 exit 계열 점검은 유지한다. 주문 전 OrderGuard·KIS 미체결 조회로 중복 방지하며, 조회 실패는 “미체결 없음”이 아니라 주문 보류로 처리한다. live 주문 ACK 후 체결가·수량이 확인되지 않거나 부분체결이면 order_pending=True, requires_reconcile=True로 장부 반영을 보류하고 같은 장중 루프의 남은 신규 진입도 중단한다.
    • 장마감(15:35) 일일 리포트·스냅샷·KIS 크로스체크·DB 백업(설정 시)·디스코드.
  6. 공통
    설정: config/ YAML + .env. 데이터·포지션·거래 기록: SQLite(또는 설정 DB).

1.2 모드별 진입점

모드 main.py 호출 함수 핵심 모듈
backtest run_backtest(args) DataCollector → Backtester → ReportGenerator
backtest_momentum_top run_backtest_momentum_top(args) momentum_top_portfolio.run_momentum_top_portfolio_backtest() — 다종목 동일비중 모멘텀 포트폴리오, 리밸런싱·시장 국면·포트폴리오 스탑
validate run_strategy_validation(args) backtest.strategy_validator (3~5년, 샤프·MDD·벤치마크 KS11·코스피 상위 50 동일비중, in/out-of-sample, 손익비 자동 경고+디스코드). --no-benchmark-top50 으로 Top50 비활성화
paper run_paper_trading(args) WatchlistManager, DataCollector, 전략, OrderExecutor(paper), Notifier
schedule run_scheduler_loop(args) runtime_lock.scheduler_lock, Scheduler (무한 루프, paper 전용). 기본 signal-only, QUANT_AUTO_ENTRY=true 시 full paper. runtime state가 entry만 차단해도 exit/finalize/evidence는 유지
live run_live_trading(args) 4중 보안(전략 상태 live 허용·환경변수·CLI 플래그·hard gate 5조건) → KISApi, PortfolioManager(sync), Scheduler
liquidate run_emergency_liquidate(args) live에서는 KIS↔DB 잔고 동기화로 KIS-only 보유를 먼저 DB에 반영 → DB 포지션 조회 → 종목별 매도(KIS 현재가 주문). 결과 summary는 통합 알림으로 전파한다. trading.mode=live에서는 ENABLE_LIVE_TRADING=true + --confirm-live 필수
compare run_compare_paper_backtest(args) backtest.paper_compare (run_compare + check_live_readiness), divergence 경고 + 실전 전환 준비 자동 평가·디스코드 알림
optimize run_param_optimize(args) backtest.param_optimizer (Grid/Bayesian), Backtester.run(param_overrides=)
dashboard run_dashboard(args) monitoring.web_dashboard (aiohttp), PortfolioManager, get_portfolio_snapshots
check_correlation run_check_indicator_correlation(args) DataCollector, IndicatorEngine, SignalGenerator → core.indicator_correlation (스코어 상관계수·고상관 쌍 권고)
check_ensemble_correlation run_check_ensemble_correlation(args) DataCollector, StrategyEnsemble.analyze → core.ensemble_correlation (신호 상관 + BUY 동시 발생률 + 대안 전략 권고). validate --strategy ensemble 시 자동 실행
rebalance run_rebalance(args) BasketRebalancer (baskets.yaml 기반 목표 비중 vs 실제 비중 드리프트 체크 → 주문 생성·실행). --basket, --dry-run 옵션 지원. live 실행은 바스켓별 basket_rebalance:<basket> 승인 단위로 live gate/account/order tag가 일치해야 한다. 종료 시(비 dry-run) paper 일일 NAV 스냅샷 저장 + DB 일일 백업(database.backup_path 설정 시) — 상시 스케줄러 없이 일일 CLI만으로 트랙레코드 시계열·백업이 쌓인다
health run_health_check() core.operator_health — 전 전략 runtime state + current_blockers + **바스켓 paper 운영(스냅샷 끊김 감시)**을 단일 verdict(OK/ATTENTION/BLOCKED)로 요약. 반환 코드 0/1/2
deploy_check run_deploy_check(args) 바스켓 배포 점검 — 계획 주문·예상 비용·회전율·활성화 절차 출력. --as-of, --json 지원
weekly_report run_weekly_report() core.weekly_report — 주간 다이제스트 디스코드 발송(주간/누적 성과 · vs KS11 · 귀속 분해(실행/구성 격차) · 진행률/커버리지 · 주간 이벤트[결측 고유일수·사이클 오류]). 금요일 크론용
guide (인자 없이 실행과 동일) 사용 가이드 치트시트 출력 후 종료. 시스템 초기화 없음

2. 실제 디렉터리·파일 구조

quant_trader/
├── main.py                      # CLI 진입점, --mode 분기 (18개 모드; 무인자 실행 시 가이드 출력)
├── test_integration.py          # 통합 검증 스크립트 (단일 실행, pytest 아님)
├── pyproject.toml               # 프로젝트 메타데이터 (Python >=3.11,<3.13, 패키지, pytest 설정)
├── requirements.txt             # pip 의존성 목록
├── .env.example                 # 환경변수 템플릿 (KIS API, 디스코드, 텔레그램, 이메일, 긴급청산)
├── .gitignore                   # 제외 규칙 (.env, settings.yaml, data/, logs/, reports/* 등)
├── README.md                    # 프로젝트 소개·빠른 시작·실행 예시
├── quant_trader_design.md       # 전체 아키텍처·전략·리스크 설계서
├── config/
│   ├── __init__.py
│   ├── config_loader.py         # YAML 통합 로더, .env 덮어쓰기, QUANT_AUTO_ENTRY 해석, YAML/resolved hash, Config.get() 싱글톤
│   ├── settings.yaml.example    # 설정 예시 (settings.yaml은 .gitignore)
│   ├── settings.yaml            # KIS API, database, data_source, trading, discord, telegram, dashboard, watchlist
│   ├── strategies.yaml          # indicators, scoring, mean_reversion, trend_following, fundamental_factor, momentum_factor, volatility_condition, ensemble(components)
│   ├── risk_params.yaml         # backtest_universe, liquidity_filter, 포지션/손절/익절/트레일링/분산/MDD/성과열화/거래비용
│   ├── baskets.yaml             # 바스켓 포트폴리오 & 리밸런싱 설정 (종목별 목표 비중, drift/weekly/monthly 트리거, 신호 가중). kr_diversified_hold는 2026-06-10부터 paper 운영 중(enabled: true)
│   ├── holidays.yaml.example    # 한국 휴장일 예시
│   ├── holidays.yaml            # --update-holidays 로 자동 갱신
│   └── us_holidays.yaml         # 미국 휴장일(선택, NYSE 판별 보조)
├── core/
│   ├── __init__.py
│   ├── data_collector.py        # fetch_stock(통합): 미국 티커 yfinance, 한국 FDR→yfinance→KIS 폴백. 소스 추적·is_us_ticker(), get_krx_stock_list(), get_sector_map()
│   ├── watchlist_manager.py     # 관심 종목: manual/top_market_cap/kospi200/momentum_top/low_vol_top/momentum_lowvol + 유동성 필터 + 리밸런싱 캐시 + as_of_date
│   ├── indicator_engine.py      # pandas-ta: RSI, MACD, 볼린저, MA(SMA/EMA), 스토캐스틱, ADX, ATR, OBV, volume_ratio
│   ├── signal_generator.py      # 멀티 지표 스코어링 → BUY/SELL/HOLD, collinearity_mode(representative_only 권장)
│   ├── risk_manager.py          # 포지션 사이징(1% 룰), 분산(업종 비중 포함), 성과 열화, 손절/익절/트레일링, MDD/일일 손실, 거래 비용
│   ├── order_executor.py        # 매수/매도 (paper: DB만, live: KIS), paper BUY/SELL 모델 슬리피지 체결가 반영, 운영 손실 한도 신규 BUY 차단, PositionLock, OrderGuard, 유동성·어닝 필터, 매수 직전 재검증, Dead-letter 큐(재시도 실패 시 FailedOrder 저장)
│   ├── portfolio_manager.py     # 포지션·잔고·수익률, 체결가 기준 현금 요약, sync_with_broker(KIS↔DB 크로스체크), save_daily_snapshot()
│   ├── basket_rebalancer.py     # 바스켓 리밸런싱: 목표 비중 vs 실제 비중 드리프트 감지, 주문 생성·실행, 신호 가중 모드, 스케줄러 장전 자동 통합
│   ├── scheduler.py             # 무한 루프: 장전/장중(10분)/장마감, 시장 국면 필터, 블랙스완 recovery, 바스켓 리밸런싱, paper 실전전환 자동 평가
│   ├── runtime_lock.py          # schedule 모드 단일 인스턴스 락 (`data/.scheduler.lock`)
│   ├── trading_hours.py         # 한국 장·휴장일 + 미국(NYSE 정규장, us_holidays.yaml)
│   ├── holidays_updater.py      # 휴장일 YAML 자동 갱신 (pykrx 또는 fallback)
│   ├── blackswan_detector.py    # 급락 감지 → 전량 매도·쿨다운·recovery(점진적 재진입, recovery_scale)
│   ├── market_regime.py         # 시장 국면 필터: 3중 신호(200일선 + 단기모멘텀 + MA크로스) → bearish/caution/bullish
│   ├── fundamental_loader.py    # 펀더멘털(PER·부채비율) — pykrx(우선) → yfinance(폴백)
│   ├── dart_loader.py           # DART Open API (corp_code, 정기공시 기반 실적 시점 추정)
│   ├── earnings_filter.py       # 실적일 필터: yfinance → (선택) DART. `trading.skip_earnings_days`
│   ├── indicator_correlation.py # 스코어링 지표 상관계수 분석·고상관 쌍 제거 권고
│   ├── ensemble_correlation.py  # 앙상블 전략 신호 상관계수 + BUY 동시 발생률 + 대안 전략 권고 + auto_downgrade
│   ├── strategy_ensemble.py     # 앙상블: ensemble.components (technical·momentum_factor·volatility_condition·fundamental_factor 선택), auto_downgrade
│   ├── data_validator.py        # OHLCV 정합성 검사 (Null, NaN, 음수 주가, 타임스탬프 역전, lookahead 방지 정제)
│   ├── notifier.py              # 통합 알림 이중화 (1차 디스코드 → 2차 이메일 SMTP, critical 동시 발송; 웹훅 미설정 시에도 이메일 폴백. 텔레그램은 미구현)
│   ├── strategy_diagnostics.py  # 전략 진단 보조: DiagnosticLine — 전략별 신호·점수 진단 라인 생성
│   ├── paper_evidence.py        # Paper Evidence 수집 (일별 22개 지표, benchmark excess, anomaly detection)
│   ├── paper_runtime.py         # Paper Runtime State Machine (5개 상태, schema quarantine, allowed_actions)
│   ├── paper_pilot.py           # Paper Pilot Authorization (launch readiness + pilot auth + 리스크 캡)
│   ├── paper_preflight.py       # Paper Preflight Check (운영 준비 상태 점검)
│   ├── strategy_universe.py     # Paper 대상 전략 canonical 목록
│   ├── target_weight_rotation.py # Portfolio-level target-weight plan 생성/검증, 가격 최신성 진단
│   ├── evidence_collector.py    # Deprecated v1 collector no-op shim (v2 paper_evidence 사용)
│   ├── promotion_engine.py      # metrics 기반 전략 승격 판정 (research→paper→live)
│   ├── operator_health.py       # 운영 통합 헬스 요약 (전략 runtime + blockers + 바스켓 운영·집계 배치율 → OK/ATTENTION/BLOCKED)
│   ├── basket_evaluation.py     # 바스켓 paper→live 승격 판정 (60영업일·커버리지·dead-letter·비용 드래그 → WAIT/PASS_CANDIDATE/FAIL_REVIEW) + 리포트 v2 부가필드 + 성과 귀속 분해(실행/구성 격차)
│   ├── cycle_observability.py   # 일일 사이클 관측성 (CYCLE_START/END/ERROR·SNAPSHOT_* 이벤트 기록, 스냅샷 결측 감지·당일 경보)
│   ├── weekly_report.py         # 주간 요약 다이제스트 포맷터 (성과·귀속·진행률·주간 이벤트 — --mode weekly_report)
│   ├── position_lock.py         # threading.RLock (포지션/주문 동시 접근 제어)
│   └── order_guard.py           # 동일 종목 TTL(기본 600초) 동안 중복 주문 차단
├── tools/
│   ├── run_paper_evidence_pipeline.py  # Paper Evidence 파이프라인 (backfill/finalize/package/quality-report)
│   ├── paper_pilot_control.py          # Paper Pilot 활성화/비활성화/상태 확인 CLI (액션 옵션 동시 지정 차단)
│   ├── paper_bootstrap.py              # Paper 초기화 (runtime state 셋업)
│   ├── paper_preflight.py              # Paper 세션 전 체크리스트 CLI
│   ├── paper_launch_readiness.py       # Paper 진입 준비 상태 확인 CLI
│   ├── paper_runtime_status.py         # Paper 실행 상태 모니터링 CLI (액션 옵션 동시 지정 차단)
│   ├── paper_trade_quality_report.py   # Paper 체결 예상가/갭/슬리피지 품질 리포트
│   ├── evaluate_and_promote.py         # Canonical 평가 → artifact → 승격 판정 + blocker summary(--blocker-summary/--blocker-summary-check)
│   ├── research_candidate_sweep.py     # Research-only 후보 sweep → benchmark-aware ranking artifact + 벤치마크 결측 guard
│   ├── target_weight_rotation_pilot.py # target-weight 후보 전용 paper/pilot adapter + shadow proof
│   ├── rebuild_paper_runtime.py        # Paper 런타임 재구성
│   ├── basket_paper_evaluation.py      # 바스켓 paper 운영 평가 CLI (DB 수집 → 승격 판정·진행률 출력, --out 마크다운)
│   └── quarantine_test_artifacts.py    # 테스트 artifact 격리(paper_evidence/runtime/promotion)
├── strategies/
│   ├── __init__.py              # 전략 레지스트리(플러그인형): create_strategy(name), get_strategy_names(), register_strategy()
│   ├── base_strategy.py         # 추상 클래스: analyze(df), generate_signal(df, **kwargs)
│   ├── scoring_strategy.py      # IndicatorEngine + SignalGenerator, 멀티 지표 스코어링
│   ├── mean_reversion.py        # Z-Score·ADX·52주 이중 필터·코스피200 제한·펀더멘털 필터
│   ├── trend_following.py       # ADX·200일선·MACD·ATR 추세 추종
│   ├── fundamental_factor.py    # 펀더멘털 팩터 (--strategy fundamental_factor, 앙상블 구성 가능)
│   ├── momentum_factor.py       # 모멘텀 (N일 수익률, CLI `--strategy momentum_factor` 등록 + 앙상블 구성용)
│   └── volatility_condition.py  # 변동성 조건 (앙상블 내부 전용)
├── api/
│   ├── __init__.py
│   ├── kis_api.py               # KIS REST API: 토큰·시세·주문·잔고·일봉. 이중 Rate Limiter(초당+분당) + 지수 백오프+지터 + SSL/커넥션 에러 핸들러 + 토큰 쿨다운 + 사용량 모니터링 + Circuit Breaker(HALF_OPEN 단일 probe)
│   ├── websocket_handler.py     # KIS 웹소켓 실시간 체결/호가 (asyncio, Heartbeat 45초, 자동 재연결, 갭 보충/대시보드 노출)
│   └── circuit_breaker.py       # CLOSED → OPEN → HALF_OPEN, API 연속 5회 실패 시 60초 차단
├── backtest/
│   ├── __init__.py
│   ├── backtester.py            # 시뮬레이션: strict_lookahead 기본, 수수료·세금·동적 슬리피지·손절/익절/트레일링, gap/어닝/BlackSwan guard, 과매매 분석
│   ├── cost_impact.py           # 거래비용 전/후 성과 비교 공통 계산기
│   ├── portfolio_backtester.py  # 다종목 포트폴리오 시뮬레이션: 분산·투자비중 한도, gap/어닝/BlackSwan guard, 진단 카운터, 비용 드래그
│   ├── report_generator.py      # txt·html 리포트 (거래 내역, 성과 지표, 자본 곡선, 과매매/비용 영향 분석)
│   ├── strategy_validator.py    # validate: KS11·코스피 상위 50 동일비중 벤치마크, 손익비 자동 경고+디스코드
│   ├── momentum_top_portfolio.py # 다종목 동일비중 모멘텀 포트폴리오 백테스트 (리밸런싱·시장 국면·포트폴리오 스탑)
│   ├── paper_compare.py         # 모의투자 vs 백테스트 비교, 실전 전환 준비 자동 평가(check_live_readiness)
│   └── param_optimizer.py       # Grid / Bayesian(scikit-optimize) 최적화, 가중치 대칭 Grid Search + OOS 게이트
├── database/
│   ├── __init__.py
│   ├── models.py                # ORM 모델 6종(StockPrice, TradeHistory, Position, PortfolioSnapshot, DailyReport, FailedOrder), SQLite WAL/PostgreSQL, scoped_session, @with_retry, db_session()
│   ├── repositories.py          # CRUD — 읽기·쓰기 전체 @with_retry, 체결가 기준 get_trade_cash_summary, get_paper_performance_metrics, save_failed_order/get_pending_failed_orders/resolve_failed_order (Dead-letter)
│   └── backup.py                # SQLite Online Backup API로 WAL 안전 백업 (실패 시 -wal/-shm 포함 폴백), 보관 일수 자동 삭제
├── monitoring/
│   ├── __init__.py
│   ├── logger.py                # loguru 초기화 (파일 로테이션·콘솔 출력), log_trade(), log_signal()
│   ├── discord_bot.py           # 디스코드 웹훅 전송 (Notifier를 통해 호출 권장)
│   ├── liquidate_trigger.py     # HTTP POST /liquidate 긴급 청산 (X-Token 인증)
│   ├── dashboard.py             # 콘솔 대시보드 (선택, show_summary_line)
│   ├── dashboard_runtime_state.py # 대시보드 런타임 상태 관리 (스케줄러·전략 실행 현황 실시간 상태 전달)
│   ├── web_dashboard.py         # aiohttp 웹 대시보드 (포트폴리오·스냅샷 JSON/HTML, 10초 폴링)
│   └── paper_monitor.py         # Paper 운영 모니터링: log_event(), WeeklyReportGenerator, GoLiveChecker
├── tests/                       # pytest tests/ -q
│   ├── __init__.py
│   ├── test_backtester_strategies.py    # 백테스터 전략별 시뮬레이션 검증
│   ├── test_backtester_trailing_stop.py # 트레일링 스탑 로직 검증
│   ├── test_backtest_cost_impact.py     # 거래비용 전/후 성과 비교 리포트 검증
│   ├── test_portfolio_regime_filter.py  # 포트폴리오 시장국면·gap/어닝/BlackSwan guard 검증
│   ├── test_blackswan_detector.py       # 블랙스완 감지·쿨다운 검증
│   ├── test_discord_bot.py              # 디스코드 알림 모킹·콘솔 fallback
│   ├── test_integration_smoke.py        # 설정·DB·지표·신호 등 연동 스모크 테스트
│   ├── test_kis_websocket_e2e.py        # KIS API·웹소켓 모의 E2E 테스트
│   ├── test_order_executor_paper.py     # OrderExecutor paper 모드 검증
│   ├── test_portfolio_manager.py        # 포트폴리오·sync 검증
│   ├── test_risk_manager.py             # 리스크 매니저 (포지션·손절·동적 슬리피지)
│   ├── test_scheduler.py                # 스케줄러 구간·동작 검증
│   ├── test_signal_generator.py         # 신호 생성·스코어링 검증
│   ├── test_strategy_validator.py       # 전략 검증(validate) 로직 검증
│   ├── test_trading_hours.py            # 장 시간·휴장일 검증
│   ├── test_watchlist_manager.py        # watchlist 모드별 resolve 검증
│   ├── test_basket_rebalancer.py       # 바스켓 리밸런서 (설정·비중·드리프트·트리거·주문·실행)
│   ├── test_us_market_support.py      # 미국 티커·TradingHours NYSE 등
│   └── test_paper_lifecycle.py        # Full paper lifecycle 테스트 (BUY/SELL/snapshot, 격리 DB)
├── scripts/                     # 검증·분석 스크립트 (C-4 OOS, C-5 sleeve/필터/TP sweep/rolling WF/paper 리포트)
├── deploy/                      # (선택) Oracle Cloud ARM 서버 상시 구동
│   ├── README.md               # Oracle Cloud Free Tier ARM 배포 가이드
│   ├── setup.sh                # 시스템 셋업 (Python 3.11, venv, pip install)
│   ├── install_service.sh      # systemd 서비스 등록 스크립트
│   ├── quant_trader.service    # systemd 유닛 파일 (schedule 모드, auto-restart)
│   └── logrotate.conf          # 로그 로테이션 정책 (copytruncate)
├── docs/
│   ├── PROJECT_GUIDE.md         # 본 문서
│   ├── BASKET_PAPER_EVALUATION.md # 바스켓 paper→live 승격 기준 정의·근거 (60영업일 평가)
│   └── BACKTEST_IMPROVEMENT.md  # 백테스트 손익 개선 포인트
└── reports/                     # 백테스트 txt/html + Paper 운영 산출물
    ├── paper_evidence/          # Paper Evidence JSONL (append-only) + promotion package
    │   ├── daily_evidence_{strategy}.jsonl  # 일별 22개 지표
    │   ├── anomalies.jsonl                  # 이상 탐지 로그
    │   └── promotion_evidence_{strategy}.json
    ├── promotion/               # Canonical promotion bundle + promotion_blocker_summary.json/md
    ├── paper_runtime/           # Paper Runtime 상태
    │   ├── {strategy}_pilot_launch_readiness.json/md
    │   ├── pilot_authorizations.jsonl
    │   └── notifier_health.json
    ├── experiment_freeze_pack.md        # 60영업일 실험 동결 기준, hash, 실행 모드
    ├── daily_ops_checklist.md           # 일일 운영 체크리스트
    ├── weekly_ops_checklist.md          # 주간 운영 체크리스트
    ├── experiment_stop_conditions.md    # 중단/동결/재개 기준
    ├── paper_modes_explained.md         # signal-only/full paper 모드 차이
    ├── paper_runbook.md                 # Paper 운영 기본 명령
    └── promotion/               # Promotion 판정 결과

3. 파일별 상세 역할

3.1 루트

파일 역할
main.py CLI 진입점. --mode: backtest / backtest_momentum_top / portfolio_backtest / validate / paper / schedule / live / liquidate / compare / optimize / dashboard / check_correlation / check_ensemble_correlation / rebalance / health / deploy_check / guide (17종). 인자 없이 실행하면 가이드만 출력(백테스트 자동실행 아님). strict-lookahead 기본 True, --allow-lookahead 시 해제(경고 출력). paper·schedule·live 시 스케줄러 경로에서 시장 국면 필터 등 동일 로직. rebalance 종료 시 paper 일일 NAV 스냅샷 + DB 백업(설정 시) 저장. 실전 live와 live 설정의 긴급 청산은 ENABLE_LIVE_TRADING=true + --confirm-live 필수.
test_integration.py 설정·DB·지표·신호·리스크·백테스트·리포트·디스코드 등 전체 파이프라인 일괄 검증(14단계). 단일 실행 스크립트 (pytest 아님).
pyproject.toml 프로젝트 메타데이터: name=quant_trader, version=0.1.0, Python >=3.11,<3.13, 패키지 구성, pytest 설정 (tests/ 대상, pandas 경고 필터).
requirements.txt pip 의존성 목록. pandas, numpy, scipy, pandas-ta, pykrx, finance-datareader, yfinance, requests, aiohttp, websockets, sqlalchemy, pyyaml, loguru, click, pytest 등.
.env.example 환경변수 템플릿. KIS API 키, 디스코드 웹훅, 텔레그램 봇, 이메일 SMTP, Rate Limit, 긴급 청산 토큰. 복사해 .env로 사용.
.gitignore .env, settings.yaml, data/, logs/, *.db, reports/*, fintics/, __pycache__/, .venv/ 등 제외.
README.md 프로젝트 소개, 주요 기능, 빠른 시작, 실행 예시(backtest/paper/live).
quant_trader_design.md 전체 아키텍처·지표 공식·전략·리스크 상세 설계서 (본 문서의 상위 참고 문서).

3.2 config/

파일 역할
config_loader.py load_settings(), load_strategies(), load_risk_params(), load_all_config(). .env로 KIS 키·계좌·디스코드·DART_API_KEY 등 덮어씀. QUANT_AUTO_ENTRY는 ENV > YAML > default(false) 순서로 해석하고 live 모드에서는 ENV override를 무시. Config.yaml_hash(YAML 원본)와 Config.resolved_hash(환경변수 반영 실행 설정)를 분리해 freeze-pack drift를 감지. 다중 계좌: kis_api.accounts, Config.get_account_no(strategy). Config.dart 속성. Config.get() 싱글톤.
settings.yaml.example 설정 예시. 복사해 settings.yaml로 사용. (settings.yaml은 .gitignore에 포함)
strategies.yaml active_strategy, indicators, scoring, mean_reversion, trend_following, fundamental_factor, momentum_factor, volatility_condition, ensemble(components로 technical·momentum_factor·volatility_condition·fundamental_factor on/off·가중치, mode, auto_downgrade, independence_threshold).
risk_params.yaml backtest_universe(mode: current/historical/kospi200, exclude_administrative), liquidity_filter(20일 평균 거래대금 하한, strict, check_on_entry), position_sizing(1% 룰, initial_capital), stop_loss, take_profit(부분 익절), trailing_stop, diversification(max_sector_ratio 포함), position_limits, drawdown, performance_degradation, paper_backtest_compare(live_readiness), transaction_costs(commission, tax, slippage, dynamic_slippage).
baskets.yaml 바스켓 포트폴리오 & 리밸런싱 설정. 바스켓별 종목·목표 비중·리밸런싱 트리거(drift/weekly/monthly)·신호 가중 모드 정의. --mode rebalance에서 사용.
holidays.yaml 한국 휴장일. python main.py --update-holidays로 pykrx+fallback 자동 갱신.
holidays.yaml.example 한국 휴장일 예시.
us_holidays.yaml 미국 휴장일(선택). 없으면 미국 거래일 판별 시 주말만 제외.

3.3 core/

파일 역할
data_collector.py fetch_stock: 미국 티커(is_us_ticker)는 yfinance(수정주가). 한국: FDR → yfinance → KIS 폴백. 소스 추적: _last_source, _source_history, check_source_consistency(). allow_kis_fallback: false로 KIS 일봉 폴백 차단 가능. fetch_korean_stock은 한국 전용 내부/레거시 호출에 사용. get_krx_stock_list, get_sector_map()(FDR Sector → KRX KIND 상장법인 업종 → pykrx → reports/sector_map_cache.json fallback).
watchlist_manager.py manual / top_market_cap / kospi200 / momentum_top / low_vol_top / momentum_lowvol. 유동성 필터(20일 거래대금 하한, strict 모드: 데이터 없는 종목도 제외)와 liquidity_filter_report() 진단 API. 리밸런싱 캐시: 팩터 모드는 rebalance_interval_days(기본 20)마다 재계산, 사이에는 data/watchlist_cache.json 사용. as_of_date 지원: 백테스트 시 과거 시점 유니버스 사용 가능.
indicator_engine.py pandas-ta로 RSI, MACD, 볼린저, MA, 스토캐스틱, ADX, ATR, OBV, volume_ratio. calculate_all(df)로 지표 컬럼 추가.
signal_generator.py strategies.yaml 스코어링 가중치로 점수 합산 → BUY/SELL/HOLD. generate(df), get_latest_signal(df). collinearity_mode: max_per_direction(방향별 최대 1개) 또는 representative_only(3그룹 대표 1개씩=MACD+볼린저+거래량만 사용, 권장). 초기화 시 가격 모멘텀 그룹 다중공선성 경고 자동 출력.
risk_manager.py 포지션 사이징(1% 룰), check_diversification(업종 비중 포함: max_sector_ratio, FDR/KRX KIND 업종 매핑), check_recent_performance, 손절/익절/트레일링, MDD·일일 손실 한도 계산. calculate_transaction_costs.
order_executor.py trading.mode: paper면 DB만, live면 KIS API. 거래 시간·블랙스완 쿨다운·실적 발표일 필터(skip_earnings_days) 검사, 재시도(지수 백오프+지터). PositionLock, OrderGuard·KIS 미체결 조회. max_monthly_roundtrips로 종목·모드·계좌별 월간 신규 BUY 횟수를 운영 주문에서도 제한하고, drawdown.max_portfolio_mdd/max_daily_loss에 닿으면 신규 BUY만 fail-closed 차단한다. MDD 한도 돌파 후에는 히스테리시스(RiskManager.check_mdd의 _is_halted)가 한도의 절반 아래로 회복할 때까지 신규 BUY 차단을 유지한다 — 한도 경계 깜빡 회복 시 재진입→재돌파 반복 방지(상시 스케줄러에서 누적 동작, 1회성 CLI는 정적 체크와 동일). live 손실 한도 확인에서 KIS 잔고가 확인되지 않으면 DB fallback 평가금액으로 신규 BUY를 판단하지 않고 차단한다. 시장 국면 필터가 allow_buys=false를 반환하면 직접 executor BUY 호출도 주문 전 중단한다. SELL/exit는 손실 축소 경로라 월간 cap·손실 한도와 무관하게 계속 허용한다. live 주문 전 미체결 조회 실패는 live_unfilled_check.checked=False로 fail-closed 차단한다. live 주문 ACK 뒤 체결가·체결수량 확인이 안 되거나 부분체결이면 ACKED/PARTIAL_FILLED pending으로 order_records에 저장하고 DB 거래·포지션 반영을 보류한다. SUBMITTED/ACKED/PARTIAL_FILLED 상태가 남아 있으면 OrderGuard TTL이 지나도 같은 종목 신규 주문을 차단한다. 이때 반환값의 success=False는 브로커 주문 없음이 아니라 reconcile 필요 상태다. Dead-letter 큐: 모든 재시도 실패 시 FailedOrder 테이블에 영구 저장.
portfolio_manager.py 보유 포지션·잔고·수익률. sync_with_broker()로 KIS 잔고↔DB 크로스체크. live get_portfolio_summary()는 조회용 DB fallback 여부를 broker_balance_ok/source/error로 표시하고, 주문 sizing에 쓰는 get_current_capital()/get_available_cash()는 KIS 잔고 미확인 시 예외로 fail-closed 처리한다. 자동보정 시 KIS 기준 수량을 절대값으로 반영하고, 복구 포지션에는 손절·익절·트레일링 스탑을 재생성한다.
basket_rebalancer.py 바스켓 리밸런싱 엔진. baskets.yaml에서 바스켓 로드. get_target_weights()(신호 가중 지원), get_current_weights(), calculate_drift(), should_rebalance()(drift/weekly/monthly 트리거), plan_rebalance()(SELL→BUY 순서, max_turnover 제한), execute()(dry_run 지원). paper BUY 실행은 PortfolioManager.get_current_capital()/get_available_cash()로 자본과 현금을 조회한 뒤 OrderExecutor.execute_buy_quantity()에 넘긴다. live 실행은 basket_rebalance:<basket> 승인 단위가 account_key와 주문 strategy에 동일하게 전달되고, KIS↔DB 포지션 동기화가 성공해야 주문 실행부에 도달한다. CLI와 스케줄러 자동 체크 모두 같은 승인 단위를 사용한다. get_status_report()로 현황 리포트 생성.
scheduler.py 실전 무한 루프. 장전/장중/장마감. 시장 국면 필터(단계적: bearish→매수 중단, caution→사이징 축소). 장중 10분 간격. 루프 10분 초과 시 다음 사이클 스킵. 장전 단계에서 바스켓 리밸런싱 자동 체크 (_run_basket_rebalance_check). live에서는 바스켓별 basket_rebalance:<basket> readiness gate와 KIS↔DB 동기화를 통과한 뒤에만 주문 계획과 실행으로 넘어간다. live 신규 진입 중 requires_reconcile 또는 order_pending 결과가 나오면 남은 BUY 후보와 같은 루프 재스캔을 중단하고, 다음 성공적인 KIS↔DB 동기화 전까지 미확정 체결분을 무시한 추가 진입을 막는다. 전략 레지스트리 기반 _get_strategy().
runtime_lock.py scheduler_lock(lock_file) 컨텍스트: 스케줄 프로세스 중복 실행 방지.
trading_hours.py 한국 장·휴장일(holidays.yaml → pykrx → fallback). 미국: us_holidays.yaml, 동부 09:30~16:00 (is_us_trading_day, is_us_market_open 등). 주문 가능 시간 검사.
holidays_updater.py pykrx(또는 fallback)로 휴장일 조회 → config/holidays.yaml 저장. update_holidays_yaml().
blackswan_detector.py 급락 감지 시 전량 매도·디스코드 경고·쿨다운. 쿨다운 해제 시 즉시 재스캔 트리거 + recovery 기간(기본 120분) 중 사이징 50% 축소. blackswan_recovery_minutes, blackswan_recovery_scale.
market_regime.py check_market_regime() → 3중 신호 단계적 국면 판별. 신호 A: 200일선 이탈, 신호 B: 20일 수익률 ≤ -5%, 신호 C: MA(20)<MA(60) 데드크로스(선택적). 2개↑ 충족 → bearish(매수 중단), 1개 → caution(사이징 50%), 0 → bullish. 신호 C는 200일선 이탈보다 2~3주 빠르게 추세 전환 포착. 운영 필터가 켜진 상태에서 지수 조회 실패, 빈 데이터, MA 계산 실패가 발생하면 unknown/allow_buys=false/position_scale=0.0으로 fail-closed 처리한다. resolve_market_regime_config()가 운영과 백테스트의 trading.market_regime_* 기준을 동기화하고, backtest_regime_filter는 명시 값만 실험용 override로 사용한다. 기본값은 검증 결과에 맞춰 OFF.
fundamental_loader.py get_fundamentals(symbol), check_fundamental_filter(). pykrx(우선) → yfinance(폴백) 순서로 PER·부채비율 조회. pykrx는 한국 종목 PER 정확도 높음. yfinance는 부채비율 등 보충.
dart_loader.py DartEarningsLoader: DART API로 corp_code 매핑·정기공시 기반 차기 실적 시점 추정. data/dart_corpCode.zip 캐시.
earnings_filter.py is_near_earnings(symbol, skip_days, config=...). 1순위 yfinance earningsDate, 2순위 DART(settings.dart.enabled·API 키). 둘 다 조회 불가이면 기본 earnings_filter_unknown_policy=block으로 신규 BUY를 차단한다. 운영자가 명시적으로 allow를 설정한 경우에만 조회 불가를 통과시킨다. trading.skip_earnings_days(기본 3).
indicator_correlation.py 스코어링 지표 점수 시리즈 상관계수·고상관 쌍 권고. --mode check_correlation 시 사용. 다중공선성 안내: 3그룹 각 대표 1개만 권장. suggest_disable_weights(): 고상관 쌍에서 자동 비활성화 키 추출. 리포트 하단에 다음 단계 CLI 명령어 자동 출력.
ensemble_correlation.py 앙상블 전략 신호 시리즈 상관계수 + BUY/SELL 동시 발생률 + 구체적 대안 전략 권고. quick_independence_check(): 런타임 경량 검사. should_force_conservative(): 고상관 시 conservative 전환 판단.
position_lock.py 포지션/주문 공유 자원용 threading.RLock.
order_guard.py 동일 종목에 대해 최근 주문 접수 후 TTL(기본 600초) 동안 추가 주문 차단.
strategy_ensemble.py strategies.yamlensemble.components에 정의된 구성(기본: technical·momentum_factor·volatility_condition·fundamental_factor 등) 신호 통합. majority_vote / weighted_sum / conservative. auto_downgrade. 설계서 §4.4.
data_validator.py OHLCV Null·NaN·음수 주가·거래량·타임스탬프 역전 등 검사. 결측 정제는 시간순 정렬 뒤 과거값 ffill만 사용하고, 선행 OHLC 결측은 제거해 미래 가격이 과거 신호·백테스트에 섞이지 않게 한다.
notifier.py 통합 알림 이중화. 1차 디스코드 → 2차 이메일(SMTP) 폴백, critical=True 시 동시 발송 (텔레그램은 미구현 — 문서만 앞서 있던 것 정정). 디스코드 웹훅 미설정(콘솔 폴백) 상태도 '전달 안 됨'으로 취급해 이메일 폴백을 트리거한다. Scheduler, CircuitBreaker, main.py 등 주요 모듈이 DiscordBot 대신 Notifier 사용. 알림 실패 5회 누적 시 점검 경고.
strategy_diagnostics.py DiagnosticLine — 전략별 신호·점수 진단 라인 생성. 스케줄러·대시보드에서 전략 실행 현황 요약 시 사용.
paper_evidence.py Paper Evidence 런타임 수집. DailyEvidence 데이터클래스, collect_daily_evidence(), append_shadow_plan_evidence(), finalize_daily_evidence(), generate_promotion_package(), 3종 benchmark excess (same_universe/exposure_matched/cash_adjusted), 6 anomaly rule (repeated_reject, phantom_position, stale_pending, duplicate_flood, reconcile, deep_drawdown), cash-only carry-forward (zero-return semantics). PortfolioSnapshot의 양수 MDD는 evidence 표준인 음수 drawdown(%)으로 정규화해 anomaly/promotion 차단에 반영한다. Canonical view는 같은 날짜의 뒤쪽 최신 record를 유지하되, 검증된 real_paper/pilot_paper 증거를 나중에 추가된 backfill/shadow/비승격 repair record가 덮지 못하게 보호한 뒤 날짜순으로 반환하고, promotion package에 earliest_evidence_date/latest_evidence_datetrade_quality를 남긴다. Shadow plan evidence는 execution_backed=False라 promotion에는 반영되지 않는다. package 생성 시 canonical strategy_specs가 target-weight 후보로 식별한 전략은 prefix가 없어도 verified pilot proof와 canonical params hash 일치를 요구한다.
paper_runtime.py Paper Runtime State Machine. 5개 상태 (research_disabled/normal/degraded/frozen/blocked_insufficient_evidence), schema quarantine (legacy record 제외), allowed_actions (모든 상태에서 exit/cancel/reconcile/finalize/evidence/reporting 허용). legacy approved_strategies.json가 깨지면 fail-closed로 entry/shadow를 닫고 exit/finalize만 유지한다. get_paper_runtime_state(), filter_runtime_eligible().
paper_pilot.py Paper Pilot Authorization. PilotAuthorization 데이터클래스, enable_pilot(), get_active_pilot(), check_pilot_prerequisites(), check_pilot_entry(), compute_launch_readiness(), generate_launch_readiness_artifact(). enable_pilot()은 날짜 형식/기간 순서와 max orders/positions/notional/exposure 양수 cap을 auth 기록 전에 검증하고, 날짜 또는 cap이 잘못된 enabled auth record는 active pilot으로 쓰지 않는다. launch readiness: clean_final_days ≥ 3 + evidence_fresh + benchmark_final_ratio ≥ 40% + 최근 24시간 내 Discord test-send 성공(notifier_ready). Pilot entry guard는 모든 allowed/blocked 결정을 audit하고 runtime/evidence/notifier/order/position/exposure guard 예외를 fail-closed로 차단하며, gross exposure cap은 현재 노출과 이번 주문 후 예상 노출을 함께 검사한다.
paper_preflight.py Paper 세션 전 운영 준비 상태 점검. runtime state, allowed_actions, evidence freshness, notifier health, test artifact 오염 여부 등을 확인. --send-test-notification 성공 시 notifier_health.jsondiscord_reachable, last_success_at을 남기며, test 없이 갱신해도 최근 성공 증거를 보존한다.
strategy_universe.py Paper 대상 전략 canonical 목록. 전략별 paper eligibility, 승격 상태, 활성화 여부 관리.
target_weight_rotation.py Target-weight 후보의 portfolio-level plan 생성. 직전 거래일 점수, KS11 risk overlay, 목표비중 수량 산출, pilot cap 검증, 종목별 가격 최신성, 벤치마크 최신성, 주문 종목별 최근 평균 거래대금/기존 평균매입가 diagnostics를 담당. 일반 generate_signal() 전략으로 위장하지 않는다. 전용 pilot 실행은 주문 실패, 실행일 불일치, 장 시간 외 실행, 가격 최신성 실패, 유동성 preflight 실패, 비용 반영 pre-trade risk 실패 시 주문 제출 전에 중단한다. 기존 pilot evidence 재사용 시에도 target/시작 수량/목표 수량/노출/최대 주문금액이 현재 plan과 일치해야 한다. tools/target_weight_rotation_pilot.py --record-shadow-evidence로 dry-run launch-readiness evidence, launch readiness JSON/MD, pilot runbook을 남기고, cap preview·실행일/장 시간·평균 거래대금 대비 주문 비율·비용 반영 현금/비중 한도로 pilot 승인 전 기본/제안 캡 및 실행 적합성을 확인한다.
evidence_collector.py Deprecated v1 collector no-op shim. 예전 import가 프로세스를 깨지 않도록 남겨두지만 evidence를 쓰지 않는다. scheduler 장마감 canonical 증거는 core.paper_evidence.collect_daily_evidence() v2 경로만 사용한다.
promotion_engine.py metrics 기반 전략 승격 판정. research_only → paper_only → provisional_paper_candidate → live_candidate. debiased WF + PF + Sharpe + EV/turnover + canonical benchmark excess + paper evidence 기준. artifact-driven 승격은 benchmark excess return/Sharpe가 모두 양수여야 하며, canonical data snapshot integrity 오류가 있으면 provisional/live를 fail-closed 차단한다. live_candidate는 promotion package의 최신 evidence date가 canonical run_metadata.generated_at 기준 14일 이내이고 same-universe/cash-adjusted paper excess가 모두 양수여야 하며, package 내부 strategy가 현재 전략명과 정확히 일치하고 package_integrity.payload_hash가 현재 payload와 일치해야 한다. live gate는 daily evidence JSONL에서 source_records를 재계산해 package의 시작일/종료일/승격 가능 일수가 원본 first/last/count와 같은지도 다시 확인한다. 전략명 누락/불일치, package 무결성 누락/불일치, source/headline 불일치, 미래일/초과 age/비양수 excess는 fail-closed 차단한다. target-weight 계열은 canonical strategy_specsbase_strategy=target_weight_rotation을 우선 기준으로 식별하며, execution_backed=True인 verified pilot_paper execution proof, invalid day 0건, evidence 내부 params hash 일관성, paper evidence hash와 canonical 후보 params hash 일치가 모두 필요해야 live_candidate가 된다. tools/evaluate_and_promote.py --canonical으로 실행하며, 현재 canonical bundle에는 기존 risk-overlay 후보와 손실방어 eligible 6개 후보가 canonicalized research candidate로 포함된다.

3.4 strategies/

파일 역할
__init__.py 전략 레지스트리. 등록명: scoring, mean_reversion, trend_following, trend_pullback, breakout_volume, relative_strength_rotation, fundamental_factor, momentum_factor, ensemble. volatility_condition은 레지스트리에 없음(앙상블 내부 전용). create_strategy, get_strategy_names, register_strategy.
base_strategy.py analyze(df) → 지표·신호 붙은 DataFrame, generate_signal(df, **kwargs) → 최신 BUY/SELL/HOLD·점수·상세.
scoring_strategy.py IndicatorEngine + SignalGenerator. 총점 ≥ buy_threshold 매수, ≤ sell_threshold 매도.
mean_reversion.py Z-Score·ADX 필터. 52주 이중 필터, restrict_to_kospi200, 펀더멘털 필터(pykrx→yfinance). 설계서 §4.2.
trend_following.py ADX·200일선·MACD·ATR 추세 추종. 손익비 ≥ 2.0 검증 필수(§4.3).
trend_pullback.py C-3A: SMA60 상승추세 + RSI 눌림목 + ADX 추세 확인. edge-trigger 진입. 설계서 §4.
breakout_volume.py C-4: 전고점 돌파 + 거래량 급증 + ADX 추세 확인. edge-trigger 진입. ATR 2.5 trailing stop 위임. frozen params(period=10, surge=1.5, adx=20). 설계서 §4.4b.
relative_strength_rotation.py C-5: 60d+120d 복합 모멘텀 상위 종목 월간 회전 보유. SMA60 추세 필터. max_positions=2. TS OFF(disable_trailing_stop), TP 7%(per-strategy override). KS11 SMA200 시장 필터·abs momentum 필터 코드 포함(비활성). 설계서 §4.4c.
fundamental_factor.py 재무(PER 상대·ROE·부채·영업이익 성장 등)만으로 신호. pykrx→yfinance. 백테스트 시 df.attrs['symbol'] 권장.
momentum_factor.py N일 수익률만. CLI 등록 완료--strategy momentum_factor로 단독 사용 가능 + 앙상블 구성용.
volatility_condition.py N일 실현변동성만. 앙상블 구성용 — 단독 CLI 전략 아님.

3.5 api/

파일 역할
kis_api.py OAuth 토큰 발급·갱신, 시세·주문·잔고·일봉 조회. 이중 Rate Limiter: Token Bucket(초당) + 슬라이딩 윈도우(분당). 지수 백오프+지터: _backoff_with_jitter()로 thundering-herd 방지. SSL/커넥션 에러 전용 핸들러: ConnectionError, SSLError 등 별도 처리 + _total_conn_errors 추적. 토큰 쿨다운: 인증 실패 시 60초간 요청 차단(_token_error_until). get_rate_limit_stats(): 사용량 모니터링(최근 60초 활용률, 429 누적, 커넥션 에러 누적, 쿨다운 상태). CircuitBreaker 연동.
websocket_handler.py KIS 웹소켓 실시간 체결/호가. asyncio 기반, Heartbeat 45초 타임아웃, 자동 재연결, 콜백으로 가격 전달. 재연결 갭은 대시보드 상태로 노출하고 1분↑ 분봉 보충·급변 보고, 2분↑ REST 현재가/일봉 캐시 갱신·BlackSwan 즉시 점검, 디스코드 경고를 수행한다.
circuit_breaker.py API 연속 5회 실패 시 CLOSED → OPEN(60초 차단) → HALF_OPEN. 요청 차단으로 계정 제재 방지. Notifier 알림.

3.6 backtest/

파일 역할
backtester.py OHLCV + 전략 시뮬레이션. 수수료·세금·슬리피지·1% 룰·손절/익절/트레일링 스탑, gap/어닝/BlackSwan 이벤트 guard. strict_lookahead 기본 True. 성과 지표 + 과매매 분석(평균 보유 기간, 총 수수료) + 비용 전/후 수익률 비교.
cost_impact.py 백테스트 거래비용 영향 공통 계산. summarize_cost_impact()가 비용 차감 전 추정 수익률, 비용 드래그(bp), 비용/순손익, cost impact status/pass-warn-fail을 표준화한다.
portfolio_backtester.py 다종목 동시 보유 시뮬레이션. 입력 universe를 평가 시작일 기준 20일 평균 거래대금으로 먼저 거르고, 분산·최대 포지션·총투자비중 한도와 종목별 OHLCV/event column 기반 gap-up 매수 차단, gap-down 청산, 어닝 윈도우 매수 차단, BlackSwan 청산·쿨다운·recovery 사이징을 반영한다. 매수/매도 비용 계산에는 종목별 20일 평균 거래량을 넘겨 동적 슬리피지를 반영하고, liquidity_filter, gap_*/earnings_*/blackswan_*, participation_rate, 비용 드래그 진단을 반환.
strategy_validator.py 최소 3~5년, 샤프·MDD·벤치마크(KS11 + 코스피 상위 50 동일비중). in/out-of-sample. run(), run_walk_forward(). --no-benchmark-top50 으로 Top50 비활성화. 손익비 자동 경고: 추세 추종 < 2.0, 기타 < 1.0 시 WARN + 디스코드 알림.
report_generator.py txt·html 리포트. 거래 내역, 성과 지표, 자본 곡선, 과매매 분석(평균 보유 기간, 총 수수료), 비용 전/후 성과 비교. --output-dir.
paper_compare.py 지정 기간 paper 성과 vs 동일 기간·전략 백테스트. divergence 시 경고·디스코드(설정 시). check_live_readiness(): 방향성 일치율 ≥70%, 수익률 차이 ≤5%, 최소 거래일·거래건 충족 시 "실전 전환 준비 완료" 신호 + 디스코드 알림. paper 모드 장마감 시 자동 평가.
momentum_top_portfolio.py 다종목 동일비중 모멘텀 포트폴리오 백테스트. run_momentum_top_portfolio_backtest(): WatchlistManager(momentum_top) → 종목별 데이터 수집 → 리밸런싱 주기(기본 20일)마다 포트폴리오 재구성 → 시장 국면 필터·포트폴리오 스탑 적용. print_momentum_top_portfolio_report(). --mode backtest_momentum_top에서 사용.
param_optimizer.py Grid Search / Bayesian(scikit-optimize). train_ratio·OOS 보고. --include-weights스코어링 가중치 대칭 Grid Search + OOS 샤프≥1.0 게이트. --auto-correlation: 최적화 전 상관 분석 자동 실행, 고상관 지표 자동 비활성화. --disable-weights w_rsi,w_ma 등으로 수동 지정도 가능. Backtester.run(..., param_overrides=).
tools/research_candidate_sweep.py promotion/live artifact와 분리된 research-only 후보 공장. 시작 시 universe를 20일 평균 거래대금 하한으로 사전 제외하고 입력/통과/제외 사유를 artifact에 남긴다. `--candidate-family rotation

3.7 database/

파일 역할
models.py ORM 모델 6종 (StockPrice, TradeHistory, Position, PortfolioSnapshot, DailyReport, FailedOrder). init_database() 시 WAL 활성화 검증 — WAL이 아니면 ERROR 로그. scoped_session: 스레드별 세션 격리. @with_retry: DB locked 시 3회 지수 백오프 재시도. db_session(): 컨텍스트 매니저(commit/rollback/close 자동). FailedOrder: 주문 실패 Dead-letter 큐 (status: pending/retried/cancelled).
repositories.py CRUD — 읽기·쓰기 전체 함수@with_retry 적용 (WAL 체크포인트 중 일시적 locked에도 안전). get_paper_performance_metrics(start, end) (compare 모드).
backup.py SQLite Online Backup API (sqlite3.Connection.backup())로 WAL 모드에서도 일관된 스냅샷 백업. 실패 시 -wal/-shm 파일 포함 shutil.copy2 폴백. 보관 일수 초과 분 삭제.

3.8 monitoring/

파일 역할
logger.py loguru 초기화. logging 설정에 따라 파일 로테이션·콘솔 출력.
discord_bot.py 디스코드 웹훅 전송 전용. 직접 사용보다는 Notifier를 통해 호출 권장 (이중화 보장).
liquidate_trigger.py LIQUIDATE_TRIGGER_TOKEN·LIQUIDATE_TRIGGER_HOST·LIQUIDATE_TRIGGER_PORT 설정 시 POST /liquidate (X-Token 또는 Authorization: Bearer)로 긴급 청산. 토큰은 기본 최소 16자 이상이어야 하고 흔한 placeholder 값은 거부한다. 기본 바인드는 127.0.0.1이며, 외부 호출이 꼭 필요할 때만 LIQUIDATE_TRIGGER_HOST=0.0.0.0처럼 명시한다. GET은 실행하지 않고 405로 거부하며, URL query token은 LIQUIDATE_TRIGGER_ALLOW_QUERY_TOKEN=true일 때만 허용한다. live 설정에서는 ENABLE_LIVE_TRADING=trueLIQUIDATE_TRIGGER_CONFIRM_LIVE=true가 함께 필요하며, 내부 guard 실패나 개별 매도 실패는 HTTP 실패 응답으로 반환한다.
dashboard.py 콘솔 대시보드(선택).
dashboard_runtime_state.py 대시보드 런타임 상태 관리. 스케줄러·전략 실행 현황 등 실시간 상태를 웹 대시보드에 전달하는 중간 계층.
web_dashboard.py aiohttp. 포트폴리오 요약·포지션·최근 30일 스냅샷. 10초 폴링. 기본 바인드는 127.0.0.1:8080이며 --mode dashboard [--dashboard-host HOST] [--dashboard-port PORT] 또는 python -m monitoring.web_dashboard [--host HOST] [--port PORT]로 조정한다.
paper_monitor.py Paper 운영 모니터링 (v2.8 추가). log_event(): OperationEvent DB 기록 (SIGNAL/API_FAILURE/BLACKSWAN 등). WeeklyReportGenerator: 주간 리포트 JSON/TXT 자동 생성. GoLiveChecker: 8개 기준 + 5개 blocker로 live 전환 판정.

3.9 tests/

파일 역할
test_backtester_strategies.py 백테스터 전략별 시뮬레이션 검증.
test_backtester_trailing_stop.py 트레일링 스탑 로직 검증.
test_backtest_cost_impact.py 거래비용 전/후 성과 비교: cost impact 계산, 포트폴리오 metrics 반영, txt 리포트 노출 검증.
test_portfolio_regime_filter.py 포트폴리오 시장국면 필터, 운영/백테스트 국면 설정 동기화, MA 크로스 신호, gap/어닝/BlackSwan 이벤트 guard 검증.
test_blackswan_detector.py 블랙스완 감지·쿨다운.
test_discord_bot.py 디스코드 알림(모킹).
test_integration_smoke.py 설정·DB·지표·신호 등 연동 스모크.
test_kis_websocket_e2e.py KIS 웹소켓 모의 E2E.
test_circuit_breaker.py KIS Circuit Breaker 상태 전환과 HALF_OPEN 단일 probe 제한.
test_order_executor_paper.py OrderExecutor paper 모드, 운영 월간 BUY cap, MDD/일일 손실 신규 BUY 차단, 청산 경로 허용 검증.
test_portfolio_manager.py 포트폴리오·sync.
test_risk_manager.py 리스크 매니저(포지션·손절·거래 비용 등).
test_scheduler.py 스케줄러 구간·동작.
test_signal_generator.py 신호 생성·스코어링.
test_strategy_validator.py 전략 검증(validate) 로직.
test_trading_hours.py 장 시간·휴장일.
test_paper_lifecycle.py Full paper lifecycle (BUY/SELL/Snapshot, 격리 DB truncate, 4/4 PASS).
test_evidence_e2e.py Paper Evidence v2 smoke/E2E: append-only JSONL → canonical records → weekly summary/promotion/quality report 파일 생성 검증.
test_paper_evidence.py Paper Evidence 수집/검증: JSONL I/O, canonical 날짜 정렬/idempotency, promotion period, anomaly detection, benchmark missing, E2E replay 7일, cash-only zero-return deadlock regression, shadow evidence 분리, target-weight shadow plan evidence, test artifact quarantine.
test_paper_runtime.py Paper Runtime State Machine (46건): 상태 전이, canonical latest date, schema quarantine, allowed_actions, auto-unfreeze.
test_paper_pilot.py Paper Pilot Authorization: pilot enable/disable, cap enforcement, launch readiness, preflight prerequisites, artifact-only target-weight 후보 eligibility, fail-closed/audited entry guard.
test_paper_preflight.py Paper Preflight Check: 운영 준비 상태 점검 시나리오.
test_promotion_engine.py Promotion 규칙: metrics 기반 자동 판정, threshold 경계.
test_order_state_machine.py 주문 상태기계: 9개 상태 전이, assert invariant.
test_order_lifecycle_integration.py E2E 주문 흐름 통합 테스트.
test_audit_safety.py 안전성 감시: live gate, 전략 레지스트리, 데이터 소스, WebSocket gap 임계값 검증.
test_critical_fixes.py live hard gate, 긴급 청산 확인 플래그, 브로커 동기화, 주문 상태·벤치마크 비용 회귀 검증.
test_live_status_sync.py live 시작 경계: registry live 허용, canonical gate, KIS 연결, 초기 브로커 동기화, Scheduler live 검증 플래그 정합성.
test_positive_path.py 성공 경로 (happy path) 검증.
test_watchlist_manager.py watchlist 모드별 resolve.
test_basket_rebalancer.py 바스켓 리밸런서 (설정 로딩, 비중 계산, 드리프트 감지, 트리거 판단, 주문 계획, dry-run 실행, paper BUY 자본 API 전달, live 승인 단위/account/order tag 정합성 회귀).
test_us_market_support.py fetch_stock 미국 라우팅, 미국 장/휴장일 관련 TradingHours 동작.

실행: pytest tests/ -q


4. 설정 파일(YAML) 요약

config/settings.yaml

섹션 주요 키 설명
kis_api app_key, app_secret, account_no, base_url, mock_url, use_mock, max_calls_per_sec(10), max_calls_per_min(300), max_retry(3) KIS API 인증·호출 제한. .env로 키 덮어씀
database type(sqlite), sqlite_path(data/quant_trader.db) DB 설정. type: postgresql 전환 가능
logging level(INFO), log_dir(logs), rotation(10MB), retention(30 days) loguru 로그 설정
data_source preferred(auto), allow_kis_fallback(false), warn_on_source_mismatch(true) 데이터 소스·수정주가 일치 제어. KIS 일봉 fallback은 비수정주가 혼입 위험 때문에 명시 허용 시에만 사용
trading market_open(09:00), market_close(15:30), mode(paper), auto_entry(false), skip_earnings_days(3), earnings_filter_unknown_policy(block), market_regime_filter(false), market_regime_index(KS11), blackswan_recovery_minutes(120), sync_broker_interval_minutes, position_mismatch_auto_correct, position_mismatch_allow_empty_broker_delete 등 매매 모드·시장 국면 필터·블랙스완·실적일 조회 실패 정책·KIS↔DB 보정
dart enabled, api_key(또는 DART_API_KEY 환경변수) 전자공시 기반 실적 시점 추정 → earnings_filter 폴백
discord enabled(false), webhook_url, username 디스코드 알림. target-weight capped paper pilot에서는 DISCORD_WEBHOOK_URL 필수
telegram enabled(false), bot_token, chat_id 텔레그램 알림 (이중화)
dashboard host(127.0.0.1), port(8080) 웹 대시보드. 외부 공개가 필요할 때만 인증/reverse proxy 구성 후 0.0.0.0 등으로 명시
watchlist mode(top_market_cap), market(KOSPI), top_n(20), rebalance_interval_days(20), symbols 관심 종목

config/strategies.yaml

섹션 주요 키 설명
active_strategy scoring 기본 전략
indicators rsi(period, oversold, overbought), macd, bollinger, moving_average, stochastic, adx, atr, volume 지표 파라미터
scoring buy_threshold(3), sell_threshold(-3), collinearity_mode(representative_only), weights 스코어링 가중치·임계값
mean_reversion z_score_buy(-2), z_score_sell(2), lookback_period(20), adx_filter, exclude_52w_low_near, fundamental_filter(PER·부채비율), restrict_to_kospi200 평균 회귀
trend_following adx_threshold, trend_ma_period, atr_stop_multiplier, trailing_atr_multiplier 추세 추종
momentum_factor lookback_days(20), buy_threshold_pct, sell_threshold_pct 모멘텀 팩터 (앙상블용)
volatility_condition lookback_days(60), low_vol_max_pct, high_vol_min_pct 변동성 조건 (앙상블용)
fundamental_factor per_sector_relative, roe_min, debt_ratio_max, earnings_growth_min, data_cache_hours 등 펀더멘털 단독 전략·앙상블 구성 공통 설정
ensemble components(name, enabled, weight), mode(majority_vote), auto_downgrade(true), independence_threshold(0.6), confidence_weight(레거시 폴백) 앙상블 통합

config/risk_params.yaml

섹션 주요 키 설명
backtest_universe mode(historical), exclude_administrative(true) 백테스트 유니버스·생존자 편향 완화
position_sizing max_risk_per_trade(0.01), initial_capital(10,000,000) 1% 룰 포지션 사이징
stop_loss type(atr), fixed_rate, atr_multiplier(2.0) 손절매
take_profit type(fixed), fixed_rate(0.08), partial_exit, partial_ratio(0.5), partial_target(0.04) 익절매 (부분 익절 포함)
trailing_stop enabled, type(fixed), fixed_rate(0.05), atr_multiplier 트레일링 스탑
liquidity_filter enabled(true), min_avg_trading_value_20d_krw(5e9), strict(true), check_on_entry(true) 유동성 필터 (20일 평균 거래대금)
diversification max_position_ratio(0.20), max_investment_ratio(0.70), max_positions(10), min_cash_ratio, max_sector_ratio(0.40) 분산 투자·업종 비중 제한
position_limits max_holding_days(30), min_holding_days(5) 최대/최소 보유 기간. 손절·갭다운·블랙스완·수동 긴급 청산은 최소 보유 기간 예외
drawdown max_portfolio_mdd(0.15), max_daily_loss(0.03), recovery_scale MDD 제한
performance_degradation enabled, recent_trades(20), min_win_rate(0.35) 성과 열화 감지
paper_backtest_compare live_readiness(min_direction_agreement_pct, max_return_diff_pct, min_trading_days, min_trades) 실전 전환 기준
transaction_costs commission_rate(0.00015), tax_rate(0.0020), slippage(0.0005), dynamic_slippage, capital_gains_tax 거래 비용

config/baskets.yaml

섹션 주요 키 설명
baskets.<name> name, enabled 바스켓 정의. enabled: true인 바스켓만 스케줄러/CLI에서 실행
rebalance trigger(drift/weekly/monthly), drift_threshold(0.05), min_trade_amount, max_turnover_ratio 리밸런싱 트리거·제약 조건
holdings symbol: weight 종목별 목표 비중 (합계 1.0)
signal_weighted signal_weighted, signal_strategy, signal_weight_range 전략 점수로 비중 동적 조정 (선택)

config/holidays.yaml

휴장일 목록. python main.py --update-holidays로 pykrx+fallback 자동 갱신.


5. 실행 모드별 데이터 흐름

백테스트 (단일 종목)

main.py (--mode backtest)
  → DataCollector.fetch_stock(symbol, start, end)   # 미국 티커는 yfinance 분기
  → Backtester.run(df, strategy_name)  # strict_lookahead 기본, 전략.analyze → _simulate
  → Backtester.print_report(result)
  → ReportGenerator.generate_all(result)  # txt, html

백테스트 (다종목 모멘텀 포트폴리오)

main.py (--mode backtest_momentum_top --top-n 20 --rebalance-days 20)
  → momentum_top_portfolio.run_momentum_top_portfolio_backtest()
      → WatchlistManager(momentum_top) → 모멘텀 상위 N종목 선정
      → 종목별 DataCollector.fetch_stock()
      → 리밸런싱 주기(기본 20일)마다 포트폴리오 재구성
      → 시장 국면 필터·포트폴리오 스탑 적용 (옵션)
  → print_momentum_top_portfolio_report()

모의투자(paper)

main.py (--mode paper)
  → WatchlistManager.resolve()
  → 종목마다: DataCollector.fetch_stock(symbol) → strategy.generate_signal(df)
  → BUY/SELL 시 Notifier, OrderExecutor.execute_buy/execute_sell (DB만)
  → PortfolioManager.get_portfolio_summary()

스케줄 루프(schedule)

main.py (--mode schedule --strategy scoring)
  → trading.mode == live 이면 거부
  → runtime_lock(data/.scheduler.lock) 획득 실패 시 종료
  → Scheduler.run()  # 장전/장중/장마감 무한 루프 (paper 설정 하에 동일 비즈니스 로직)

실전(live)

main.py (--mode live --confirm-live)
  → KISApi.authenticate(), verify_connection()
  → BlackSwanDetector, PortfolioManager.sync_with_broker()
  → Scheduler.run()
       장전: 데이터 수집, 전략 분석, 매수 후보
       장중: 10분마다 최대 보유 기간 정리·신호·손절/익절 → OrderExecutor (OrderGuard·미체결 확인 후 KIS 주문)
            루프 10분 초과 시 다음 사이클 1회 스킵
       장중: sync_broker_interval_minutes마다 KIS↔DB 크로스체크
       장마감: 일일 리포트, 스냅샷, 크로스체크, DB 백업(backup_path 설정 시), 디스코드

긴급 청산

방법 사용
CLI python main.py --mode liquidate — live에서는 KIS↔DB 잔고 동기화로 KIS-only 보유를 먼저 DB에 반영한 뒤 DB 포지션을 조회해 종목별 매도한다. 결과는 대상/성공/실패 summary로 반환하고 통합 알림으로 전파한다. trading.mode=live이면 ENABLE_LIVE_TRADING=true--confirm-live를 요구한 뒤 KIS 현재가를 사용한다.
HTTP LIQUIDATE_TRIGGER_TOKEN·LIQUIDATE_TRIGGER_PORT 설정 후 python -m monitoring.liquidate_trigger, POST /liquidate. 토큰은 최소 16자 이상의 임의 문자열을 사용한다. 기본 바인드는 127.0.0.1이고 외부 호출은 LIQUIDATE_TRIGGER_HOST를 명시할 때만 허용한다. 토큰은 기본적으로 X-Token 또는 Authorization: Bearer 헤더로 전달하고, GET은 실행하지 않는다. live 설정에서는 ENABLE_LIVE_TRADING=trueLIQUIDATE_TRIGGER_CONFIRM_LIVE=true를 함께 요구하며, 확인 실패나 개별 매도 실패는 서버 종료 대신 실패 응답으로 반환한다.

DB 백업·KIS 크로스체크

항목 설명
일일 백업 database.backup_path 설정 시 장마감 후 SQLite 날짜별 복사. backup_retention_days 초과 분 삭제.
KIS 크로스체크 live에서 장 시작 전·장중(sync_broker_interval_minutes)·장마감 시 KIS 잔고와 DB 포지션 대조. 잔고 API 응답은 rt_cd == 0일 때만 정상 잔고로 해석하며, 오류 응답은 빈 정상 잔고가 아니라 조회 실패로 처리한다. 장중 불일치·조회 실패는 신규 진입 후보 실행과 재스캔을 fail-closed 보류하고, 손절/익절·청산 점검은 계속 허용한다. 설정 시 자동 보정 후에도 다음 성공 동기화 전까지 신규 진입은 보류된다. 자동보정은 KIS 수량을 절대값으로 반영하고 복구 포지션에 손절·익절·트레일링 값을 채운다. 단, KIS 보유 목록이 비었는데 DB에는 포지션이 있으면 기본값으로 DB 전체 삭제 자동보정을 보류하며, 확실한 무보유 계좌일 때만 position_mismatch_allow_empty_broker_delete: true로 명시 허용한다.

자금 관리·성과 열화 감지

  • 자금 관리: diversification.max_investment_ratio(전체 주식 비중 상한), max_positions(동시 보유 종목 수), max_position_ratio(단일 종목 비중), max_sector_ratio(단일 업종 최대 비중, FDR Sector 또는 KRX KIND 업종 매핑 기준). RiskManager.check_diversification, Backtester._simulate에서 적용.
  • 성과 열화: performance_degradation.recent_trades, min_win_rate. 최근 N거래 승률이 임계값 미만이면 신규 매수만 중단. RiskManager.check_recent_performance → OrderExecutor에서 매수 전 호출.

분석·검증 모드

main.py (--mode check_correlation)
  → DataCollector.fetch_stock(symbol, ...)
  → IndicatorEngine.calculate_all(df)
  → SignalGenerator.generate(df)  # 각 지표별 스코어 시리즈 추출
  → indicator_correlation.run_indicator_correlation_check()  # Pearson 상관계수
  → 리포트 저장 (reports/indicator_correlation_*.txt)

main.py (--mode check_ensemble_correlation)
  → DataCollector.fetch_stock(symbol, ...)
  → StrategyEnsemble.analyze(df)  # 3개 전략 신호 시리즈
  → ensemble_correlation.run_ensemble_signal_correlation_check()  # 상관 + BUY 동시 발생률
  → 리포트 저장 + 대안 전략 권고

main.py (--mode optimize --include-weights --auto-correlation)
  → indicator_correlation (자동 실행) → 고상관 지표 비활성화
  → param_optimizer.grid_search_scoring_weights() → 대칭 Grid Search
  → OOS 샤프 ≥ 1.0 게이트 → 통과 시 YAML 스니펫 출력

main.py (--mode rebalance --basket kr_blue_chip --dry-run)
  → BasketRebalancer(basket_name) → baskets.yaml 로드
  → get_target_weights() (signal_weighted 시 전략 점수로 동적 조정)
  → get_current_weights() (PortfolioManager + 현재가 조회)
  → should_rebalance() → drift/weekly/monthly 트리거 판단
  → plan_rebalance() → SELL 주문 먼저 배치 → BUY 주문 (max_turnover 제한)
  → execute(orders, dry_run) → OrderExecutor로 실제 주문 또는 로그만 출력

6. 알고리즘·지표 요약

  • 지표: core/indicator_engine.py에서 pandas-ta로 RSI, MACD, 볼린저, MA, 스토캐스틱, ADX, ATR, OBV, volume_ratio 계산. 설정은 config/strategies.yamlindicators.
  • 스코어링: core/signal_generator.py가 가중치(weights)로 점수 합산 → buy_threshold/sell_threshold로 BUY/SELL 판단. ⚠️ 가중치는 미검증 직관값이며, 이 상태로 실전 투입하면 노이즈를 실행하는 것. collinearity_mode: representative_only(권장)로 설정하면 MACD+볼린저+거래량 3개만 합산하여 다중공선성을 근본적으로 차단. 반드시 check_correlation → optimize --include-weights --auto-correlation → validate --walk-forward 파이프라인으로 최적화 후 사용. 스코어링 전략 단독으로 안정적 수익을 낼 가능성은 낮음 — 설계서 §4.5.1 참고.
  • 전략 (CLI 등록): scoring, mean_reversion, trend_following, trend_pullback, breakout_volume, relative_strength_rotation, fundamental_factor, momentum_factor, ensemble. volatility_condition은 앙상블 내부 구성용. 앙상블은 ensemble.components로 구성·가중치 설정(기본 예시에 fundamental_factor 포함). breakout_volume(C-4)과 relative_strength_rotation(C-5)은 2-sleeve 멀티전략 포트폴리오 구조로 검증 완료 -- BV50/R50 paper 후보 확정(Rotation TS OFF, TP 7%). 각 전략의 시장 비효율성 가정은 설계서 §4 참고.

공식·파라미터·신호 조건 등 상세는 루트의 quant_trader_design.md §3(지표), §4(전략), §5(리스크) 참고.


7. 전략 유효성 검증 및 실전 체크리스트

중요: 현재 시스템의 신호 품질이 검증되지 않은 상태입니다. 아래 체크리스트를 모두 통과하기 전까지 실전 투입은 금지입니다. 상세 진단은 quant_trader_design.md §1.3 참고.

전략 상태 레지스트리 (v5.2 — core/promotion_engine.py 자동 판정)

전략 상태 허용 모드 Ret% PF WF P%/Sh+% Paper Status
relative_strength_rotation provisional_paper_candidate backtest, paper +18.09 1.62 100/83.3
scoring paper_only backtest, paper +11.22 1.07 83.3/50.0 risk-adjusted alpha 미달
breakout_volume disabled backtest only -13.31 0.79 0/0
mean_reversion disabled backtest only -8.36 0.85 33.3/0
trend_following disabled backtest only -6.94 0.67 16.7/0
ensemble disabled backtest only 0/0

승격 규칙: research_only → paper_only → provisional_paper_candidate → live_candidate
판정: python tools/evaluate_and_promote.py --canonical → artifact → engine → registry CI 검증 운영 점검: python tools/evaluate_and_promote.py --check-only는 promotion artifact 로드뿐 아니라 metrics_summary.json의 WF/benchmark 파생값 동기화, promotion_result.json 재계산, promotion_blocker_summary.json, reports/current_blockers.json 동기화까지 함께 검증한다. invalid promotion_evidence_{strategy}.json이 남아 있으면 python tools/evaluate_and_promote.py --paper-evidence-quarantine-invalid --dry-run으로 격리 대상을 먼저 확인한 뒤 실제 격리할 수 있다.

Live 진입 Hard Gate (우회 불가 — --force-live 제거됨)

  1. strategies/__init__.py:is_strategy_allowed(strategy, "live") — live_candidate만 허용
  2. 환경변수 ENABLE_LIVE_TRADING=true
  3. CLI 플래그 --confirm-live
  4. main.py:_check_live_readiness_gate()core/live_gate.py:validate_live_readiness()
  5. reports/promotion/ canonical bundle이 현재 git commit, Config.yaml_hash, Config.resolved_hash와 일치해야 함
  6. promotion_result.json의 해당 전략 status가 live_candidate이고 allowed_modeslive가 있어야 함
  7. live gate가 같은 canonical bundle과 paper evidence를 promotion_engine으로 재로딩해 승격 상태를 다시 계산하며, 재계산 결과도 live_candidate이고 live 허용이어야 함
  8. reports/current_blockers.json이 최신 promotion_blocker_summary.json source hash와 일치하고, go_live=true, live_candidates에 현재 전략 포함, hard_blockers 비어 있음 상태여야 함
  9. 운영자가 registry 상태를 live 미허용으로 낮춘 경우 canonical live gate가 통과해도 run_live_trading()Scheduler(live_gate_validated=True) 모두 실전 시작을 차단
  10. benchmark_comparison.json에 전략별 양의 excess return과 excess Sharpe가 있어야 하며, canonical promotion 계산 단계에서도 이 값이 양수가 아니면 provisional/live 승격이 차단됨
  11. reports/paper_evidence/promotion_evidence_{strategy}.json recommendation이 ELIGIBLE이어야 하며, 60영업일 execution-backed evidence, benchmark_final_ratio 80% 이상, 양의 same-universe/cash-adjusted excess와 cumulative return, 최소 sell 5건, win_rate 45% 이상, frozen day 0, 최신 evidence date 기준 14일 이내 freshness, expected_price 누락 없음, 불리한 체결 갭 50bp 이하를 만족해야 함
  12. canonical/evidence gate 통과 후 데이터 소스 health check를 수행

레거시 reports/approved_strategies.json와 오래된 validation_walkforward_*.json은 live 근거로 사용하지 않는다. 이 파일들이 남아 있어도 canonical bundle과 paper evidence가 현재 코드·설정과 맞지 않으면 live는 차단된다.

Paper 모드 2가지

모드 설정 동작
signal-only (기본) YAML trading.auto_entry=false, QUANT_AUTO_ENTRY 미설정 신호 분석·evidence/finalize만, 신규 주문 없음
full paper QUANT_AUTO_ENTRY=true 환경변수 BUY/SELL 자동 실행 (paper DB만 기록). YAML 원본은 유지하고 resolved hash만 달라짐

full paper 신규 BUY는 preflight status artifact와 runtime state가 모두 확인되어야 실행된다. preflight 누락/손상, runtime 조회 실패, critical fail은 OrderExecutor와 scheduler 양쪽에서 주문 생성 전 차단하며, 기존 포지션 청산을 위한 SELL/exit 경로는 계속 허용한다.

60영업일 실험은 reports/experiment_freeze_pack.mdreports/paper_experiment_manifest.json을 기준으로 동결한다. 실행 전 Config.yaml_hash, Config.resolved_hash, Config.auto_entry_source를 확인해 파일 변경과 환경변수 변경을 분리해서 기록한다.

현재 시스템의 핵심 한계

한계 설명
가중치 미검증 스코어링 가중치가 직관·예시용. 통계적 근거 없음
다중공선성 RSI, MACD, MA 등이 같은 가격 정보를 중복 반영
앙상블 독립성 부족 technical과 momentum_factor가 실질적으로 같은 정보 사용
한국 시장 미최적화 파라미터가 미국 시장 기준값 (200일선, ADX 25 등)
과매매 방어 ✅ 히스터리시스·최소 보유 기간 5일·월간 신규 BUY 8회 제한 구현 완료
운영 자동화 ✅ 헬스체크·포지션 보정·OperationEvent·주간 리포트·GoLive 체크 모두 구현 완료

검증 요구 사항

항목 요구
데이터 기간 최소 3~5년. --validation-years 기본 5.
샤프 비율 OOS 기준 1.0 이상. --min-sharpe 변경 가능.
벤치마크 코스피(KS11) + 코스피 상위 50종목 동일비중 대비 OOS 초과 수익 검증. --no-benchmark-top50 으로 Top50 비활성화.
오버피팅 in/out-of-sample 분리. --split-ratio 기본 0.7.
생존자 편향 backtest_universe.mode: historical 필수. current 사용 시 수익률 과대평가
과매매 점검 백테스트 리포트의 평균 보유 기간·총 수수료·연간 왕복 수 확인. 종목당 월 5회 초과 왕복 시 경고

검증 한계: 통과해도 실전 수익 보장 없음(국면 편향·OOS 과적합 가능). 여러 시장 국면(상승·하락·횡보)이 포함된 기간으로 검증 필수. 워크포워드: --mode validate --walk-forward 로 슬라이딩 윈도우 반복 검증 가능 (train 2년→test 1년, 1년 스텝). quant_trader_design.md §8.2.

실전 투입 전 체크리스트 (필수 — 순서대로)

# 항목 설명 완료
1 백테스트 유니버스 backtest_universe.mode: historical 설정 확인 후 백테스트 재실행 [ ]
2 데이터 소스 고정 data_source.preferred: fdr, allow_kis_fallback: false 설정. 실행 해시에도 data_source를 포함해 데이터 소스 정책 변경 시 promotion/live gate drift를 감지 [x]
3 지표 독립성 검증 --mode check_correlation 실행. 고상관( r
4 가중치 최적화 --mode optimize --include-weights --auto-correlation 실행. OOS 샤프 ≥ 1.0 통과 [ ]
5 워크포워드 검증 --mode validate --walk-forward 실행. 80% 이상 창 통과 [ ]
6 손익비 확인 추세 추종 전략: profit factor ≥ 2.0. 기타: ≥ 1.0 [ ]
7 Look-Ahead strict-lookahead 기본 유지. --allow-lookahead 미사용 [ ]
8 paper 모드 1개월 실시세 paper 운영 후 check_live_readiness 통과 (방향성 일치 ≥ 70%, 수익률 차이 ≤ 5%p) [ ]
9 KIS E2E 테스트 모의투자 환경에서 API·주문·잔고 전 과정 테스트 [ ]
10 첫 실전 규모 운용 예정 금액의 10% 이하로 시작 [ ]

실전 10분 루프 안전장치

안전장치 설명
주문 전 미체결 OrderGuard(TTL 600초) + KIS 미체결 조회. 미체결이 있거나 조회 실패/응답 이상이면 live 주문 보류.
루프 10분 초과 한 사이클 실행이 10분 초과 시 다음 사이클 1회 스킵. 종목 50개 이상 시 데이터 수집만으로 10분 가능 — 모니터링 필요

운영 안정성 — 구현 완료

항목 설명
✅ 신호 히스터리시스 BUY↔HOLD↔SELL 순차 전환 강제, 직접 전환 차단 (§5.13)
✅ 최소 보유 기간 매수 후 5일 미만 매도 차단, 손절·갭다운·블랙스완·수동 긴급 청산 예외 (§5.14)
✅ 포지션 불일치 자동 보정 KIS↔DB 크로스체크 → KIS 기준 DB 자동 동기화(미체결 조회 성공 시에만 자동 보정, 실패 시 대조/알림만 수행) (§9.1)
✅ 시스템 헬스체크 10분 주기 DB·API·디스크·메모리 자동 점검 (§9.1)
✅ 휴장일 자동 갱신 90일 경과 또는 연초 자동 호출 (§9.1)
✅ 10분 루프 모니터링 LoopMetrics 추적, 연속 스킵 경고, 장마감 리포트 포함
✅ KIS 호출 제어 강화 지수 백오프+지터, SSL/커넥션 에러 핸들러, 토큰 쿨다운 60초, Circuit Breaker HALF_OPEN 단일 probe
✅ 주문 실패 Dead-letter 큐 FailedOrder 테이블에 영구 저장, 재처리 API 지원
✅ 전략 레지스트리(플러그인형) create_strategy(name)으로 동적 로딩
✅ 바스켓 리밸런싱 목표 비중 관리, 드리프트/주기 트리거, 신호 가중, CLI+스케줄러 통합
✅ schedule 모드 + 런타임 락 모의 무한 루프, data/.scheduler.lock 중복 방지
✅ 미국 티커·휴장일 fetch_stock, us_holidays.yaml, NYSE 장세션 헬퍼
✅ DART(선택) DART_API_KEY / settings.dart 시 실적일 폴백
✅ momentum_factor CLI 등록 --strategy momentum_factor로 단독 사용 가능 (앙상블 구성도 유지)
✅ 다종목 모멘텀 포트폴리오 백테스트 --mode backtest_momentum_top — 리밸런싱·시장 국면·포트폴리오 스탑
✅ 전략 진단 보조 strategy_diagnostics.py DiagnosticLine — 전략별 신호·점수 진단
✅ 대시보드 런타임 상태 dashboard_runtime_state.py — 스케줄러·전략 실행 현황 실시간 전달
✅ C-4 breakout_volume 전고점 돌파+거래량 급증 전략. frozen params, 4종목 OOS 통과
✅ C-5 relative_strength_rotation 월간 상대강도 회전 전략. TS OFF + TP 7% 최적화, BV50/R50 paper 후보 확정
✅ 멀티전략 sleeve 비교 c5_sleeve_backtest.py, c5_weight_sweep.py — 독립 sleeve 결합 검증 인프라
✅ Rotation exit 최적화 trailing stop 제거(capture rate 71%->79%), TP 8%->7%(per-strategy override)
✅ Entry filter 탐색 KS11 SMA200, abs momentum, min_hold_days 테스트 — 모두 불채택
✅ Rolling walk-forward 10 windows x 12mo, 6mo step. BV50/R50 positive 60%, median +0.45%
✅ Paper 모니터링 c5_paper_monthly_report.py, signal/executed/skipped 카운터, guardrail 설정
Paper 실험 freeze pack scoring 2026-03-27~2026-06-19 60영업일 관측 기준 동결. BV50/R50 paper 운영 산출물은 legacy/비교 자료로 보존
주문 상태기계 core/order_state.py — OrderStatus 9개 상태, FILLED 전 position 없음 invariant. live 체결가·체결수량 미확인이나 부분체결은 requires_reconcile=True로 남겨 잔고 대조 전 장부 반영 차단
live 체결보류 신규진입 중단 live 주문이 접수됐지만 체결 확인 전이면 같은 장중 루프의 남은 신규 BUY 후보 실행을 멈추고, 다음 잔고 동기화 전까지 신규 진입 재개를 보류한다
live 미완료 주문 상태 영속화 live SUBMITTED/ACKED/PARTIAL_FILLED 주문 상태를 order_records에 저장하고, 재시작 또는 TTL 만료 뒤에도 DB 미완료 주문이 남아 있으면 같은 종목 주문을 fail-closed 차단한다
승격 규칙 v3 core/promotion_engine.py — metrics 기반 자동 판정 + artifact-driven
--force-live 제거 canonical bundle + paper evidence hard gate 우회 불가
벤치마크 거래비용 _buy_and_hold_metrics에 commission/tax/slippage 반영
debiased 전략 재평가 거래대금 기반 ex-ante proxy 20종목, portfolio WF 6 windows
Safety Regression CI 확대 live hard gate/긴급 청산/데이터 소스/WebSocket gap 안전 테스트를 포함한 paper/promotion/research sweep 회귀 묶음 기준
Paper Runtime State Machine core/paper_runtime.py — 5개 상태(normal/degraded/frozen/blocked/research_disabled), schema quarantine
Paper runtime registry 오류 차단 legacy reports/approved_strategies.json가 JSON 파싱 실패 또는 스키마 오류 상태면 명시 승인 파일을 신뢰하지 않고 research_disabled로 fail-closed 처리. 신규 entry/shadow는 닫고 exit/cancel/reconcile/finalize/evidence/reporting은 계속 허용
Paper Pilot Authorization core/paper_pilot.py — launch readiness + pilot auth + 리스크 캡
Paper Preflight core/paper_preflight.py — 세션 전 운영 준비 상태 점검
Strategy Universe core/strategy_universe.py — paper 대상 전략 canonical 목록
Paper 운영 도구 tools/ — evidence pipeline, pilot control, bootstrap, preflight, launch readiness CLI. tools/paper_pilot_control.pytools/paper_runtime_status.py는 액션 옵션을 한 번에 하나만 받으며, 상충되는 액션이 같이 들어오면 상태 조회·파일 기록 전에 fail-closed로 종료한다. tools/paper_pilot_control.py --status--strategy가 없을 때 reports/current_blockers.json의 primary strategy를 조회 전용 기본값으로 사용하지만, --enable/--disable/--check-prerequisites는 명시 전략 없이는 실패한다. tools/paper_bootstrap.py는 빈 watchlist, 빈/역전 날짜 범위, 요청일 evidence 미생성을 incomplete로 보고 non-zero 종료한다
Research candidate sweep tools/research_candidate_sweep.py — rotation/momentum/breakout/pullback/benchmark-relative/risk-budget/cash-switch/benchmark-aware rotation/target-weight top-N rotation 후보군을 benchmark-aware artifact로 랭킹하고 decision action 생성. raw EW B&H gate는 유지하면서 exposure-matched B&H 진단값도 기록. EW B&H 벤치마크 일부 종목 결측은 INSUFFICIENT_BENCHMARK_DATA로 fail-closed 차단하고 coverage ratio/결측 종목을 artifact에 기록. promotion/live gate와 분리
2026-04-29 all-family quick sweep 5종목, 후보 14개 비교 결과 NO_ALPHA_CANDIDATE. best=rotation_slow_momentum이나 excess=-165.22%p / excess Sharpe=-1.07
2026-04-30 top-20 all-family quick sweep canonical liquidity universe 20종목, 후보 14개 비교 결과 NO_ALPHA_CANDIDATE. best=momentum_factor_120d, return=+118.56%, excess=-30.83%p, MDD=-40.08%
pullback 후보군 추가 trend_pullback 기반 research-only 후보 4개 추가. 외부 재무 데이터 없이 SMA/RSI/ADX 눌림목 진입을 benchmark-aware sweep에서 검증
benchmark-relative momentum 추가 momentum_factor에 KS11 대비 초과 모멘텀/변동성 게이트 옵션 추가. research-only 후보 3개로 현재 실패 원인(benchmark underperformance)을 직접 검증
2026-04-30 신규 후보 smoke sweep 5종목 기준 benchmark_relative/pullback 모두 NO_ALPHA_CANDIDATE. best 신규 후보도 excess=-169%p 이하라 promotion 미진행
risk-budget 후보군 추가 CandidateSpec.diversification을 artifact에 기록하고 momentum/rotation 신호를 집중형·균형형·방어형 exposure budget으로 비교
2026-04-30 risk-budget smoke sweep 5종목 기준 NO_ALPHA_CANDIDATE. 방어형 rotation은 MDD=-6.41%로 개선됐지만 excess=-162.72%p라 promotion 미진행
cash-switch 후보군 추가 relative_strength_rotation.market_filter_exit로 KS11 이동평균 하회 시 보유 포지션을 현금화하는 research-only 후보 3개 추가
2026-04-30 cash-switch smoke sweep 5종목 기준 NO_ALPHA_CANDIDATE. best=cash_switch_rotation_slow_defensive, return=+1.87%, excess=-171.76%p, MDD=-11.78%라 promotion 미진행
exposure-matched benchmark 진단 추가 후보별 avg_exposure_pct, avg_cash_pct, exposure_matched_bh_return/sharpe/mdd, exposure_matched_excess_return/sharpe 기록. cash-switch 평균 노출 8.410.0%, exposure-matched excess=-7.87%p-0.36%p로 신호 edge도 미확인
benchmark-aware rotation 후보군 추가 relative_strength_rotation.score_mode=benchmark_excess, rank_entry_mode=dense_ranked, exit_rebalance_mode=score_floor를 추가해 KS11 대비 상대강도 랭킹과 노출 유지형 회전을 research-only로 검증
benchmark-aware rotation smoke sweep 5종목 기준 NO_ALPHA_CANDIDATE. best=benchmark_aware_rotation_60_120_balanced, return=+21.65%, Sharpe=0.50, avg exposure=24.1%였지만 raw excess=-151.98%p라 promotion 미진행. fast 40/100은 exposure-matched excess=+2.04%p로 다음 연구 힌트만 제공
target-weight top-N rotation 백테스터 추가 sparse BUY/SELL 신호 대신 매월 직전 거래일 기준 top-N을 목표비중으로 보유/교체하는 research-only 경로 추가. delta 리밸런싱, 거래비용, 일별 cash/value/n_positions 노출 진단 기록
target-weight top-N rotation smoke sweep 5종목 기준 NO_ALPHA_CANDIDATE. best=target_weight_rotation_top3_40_100_excess, return=+128.44%, Sharpe=1.13, avg exposure=85.3%로 노출은 개선됐지만 raw excess=-45.19%p라 promotion 미진행
canonical top-20 target-weight full sweep 20종목 기준 alpha 후보 확인. best 기존 후보=target_weight_rotation_top3_40_100_excess, return=+212.21%, raw excess=+62.82%p, exposure-matched excess=+83.66%p. 다만 promotion=paper_only, turnover/year=1412.1%라 KEEP_RESEARCH_ONLY
target-weight score-floor 후보 추가 min_score_floor_pct로 약한 KS11 초과 모멘텀 슬롯을 현금으로 남기는 후보 3개 추가. best=target_weight_rotation_top5_60_120_floor0, return=+210.21%, Sharpe=1.41, WF positive=100%, raw excess=+60.82%p였지만 turnover/year=1081.5%라 승격 금지
target-weight rank-hysteresis 후보 추가 hold_rank_buffer로 기존 보유 종목이 top-N 밖으로 소폭 밀려도 버퍼 안이면 유지. best=target_weight_rotation_top5_60_120_floor0_hold3, return=+278.57%, raw excess=+129.18%p, Sharpe=1.65, WF positive/Sh+ 100%, turnover/year=807.8%. turnover 병목은 해소했지만 MDD=-28.25%라 research-only
target-weight benchmark-risk overlay 후보 추가 KS11 SMA/낙폭/변동성 risk-off 구간에 부분 노출을 줄이는 후보 6개 추가. best=target_weight_rotation_top5_60_120_floor0_hold3_risk60_35는 초기 종가 체결 기준 return=+210.24%, PF=5.73였고, next-open/결측 진단 canonical 재검증 기준 return=+171.20%, PF=4.24, Sharpe=1.41, MDD=-19.90%, WF positive=100%, WF Sharpe+=83.3%로 provisional_paper_candidate 유지
target-weight canonical bridge 추가 tools/evaluate_and_promote.py --canonical이 target-weight canonical 후보군을 동일 후보 ID/params hash로 재평가하고 reports/promotion/* canonical bundle에 기록. 최신 기본 후보는 target_weight_rotation_top5_60_120_floor0_exp75_rankrisk90_tol5_sectorcap2_posloss8_frac50_pdd10_floor40_cd1이며, next-open/결측 진단 canonical 기준 return +198.15%, PF 5.58, MDD -17.18%, WF positive/Sh+ 100%로 provisional_paper_candidate 확인. promotion 계산은 canonical run_metadata.json이 없거나 형식이 깨지면 canonical_data_integrity_ok=false로 fail-closed 처리해 paper evidence만으로 provisional/live 승격이 열리지 않게 한다
target-weight paper/pilot adapter 추가 core/target_weight_rotation.py + tools/target_weight_rotation_pilot.py로 직전 거래일 점수 기반 목표비중 plan을 만들고 pilot cap을 plan-level로 검증. OrderExecutor.execute_buy_quantity()로 paper-only exact quantity 매수를 지원. 실행형 pilot_paper evidence는 같은 candidate/trade_day의 기존 pilot session artifact가 없고, run_pilot 점검과 execute_plan 주문 제출 직전 재확인에서 실제 paper position이 계획 입력 장부 position_quantities_before와 모두 일치하고, execution_trade_day_allowed=True, execution_market_session_allowed=True, pilot_authorization_snapshot_allowed=True, 유동성 preflight와 비용 반영 pre-trade risk 검증을 통과하고, 계획 주문 전부 성공(executed == planned, failed/skipped/halted 없음) 후 주문 결과 payload와 당일 TradeHistory fill 집계의 종목/방향/수량이 plan과 일치하며, 실제 paper position 전체가 리밸런싱 후 target_quantities_after 장부와 일치하고 계획 밖 양수 포지션이 없을 때만 수집한다. 같은 날짜 evidence가 이미 있으면 최신 canonical record가 pilot_paper, pilot_authorized=True, execution-backed, target-weight plan/params hash 일치, execution trade-day allowed, execution market-session allowed, 승인 snapshot allowed, pre-execution/liquidity/pre-trade-risk/order-count/order-result/order/fill/position complete와 order/fill/position reconciliation complete 조건을 만족할 때만 재사용한다. 중복 실행은 기본 차단하며 명시 재시도는 --allow-rerun으로만 허용한다. 실행 전 포지션 드리프트/실행일 불일치/장 시간 외 실행/승인 snapshot 불일치/유동성 preflight 실패/pre-trade risk 실패/부분 실행/중단/주문 결과 불일치/체결 기록 불일치/기존 evidence 검증 실패/포지션 불일치는 세션 artifact에 차단 사유를 남긴 뒤 승격 증거에서 제외한다. live 모드는 계속 거부
target-weight shadow proof 추가 dry-run에서 --record-shadow-evidence를 켜면 append_shadow_plan_evidence()가 non-promotable shadow_bootstrap record를 남김. execution_backed=False, excess=null이라 promotion은 오염하지 않고, launch readiness의 clean final day만 채운다. --shadow-days 3 또는 --shadow-start-date/--shadow-end-date로 여러 날짜 shadow bootstrap을 한 번에 누적할 수 있고, --shadow-days N은 휴장/데이터 공백으로 같은 거래일에 매핑되면 과거 평일을 추가 스캔해 N개 고유 resolved trade_day 충족을 목표로 한다. 목표 미달 또는 날짜별 실패가 있으면 CLI는 non-zero로 종료해 불완전한 증거가 자동화에서 성공으로 처리되지 않게 한다. 같은 실행에서 launch readiness JSON/MD와 pilot runbook을 생성하며 session/batch artifact에는 기본 cap preview, plan 기반 최소/추천 cap, enable 명령, launch artifact 경로를 기록
target-weight readiness audit 추가 tools/target_weight_rotation_pilot.py --readiness-audit로 주문 제출, shadow evidence 기록, pilot session 저장 없이 capped pilot 직전 상태를 JSON artifact와 Markdown 운영 리포트로 점검. clean shadow/launch readiness, active pilot auth와 cap validation, 추천 cap, 중복 session idempotency, 실행일 일치 여부, 장 시간 주문 가능 여부, 실행 전 position drift, 유동성 preflight, 비용 반영 pre-trade risk, 다음 조치(cap approval 또는 execute capped paper pilot)를 함께 판정한다. audit 시작 시 paper preflight를 먼저 갱신해 preflight_refresh를 남기며, Discord webhook 미설정 또는 notifier health 비정상은 주문 전 BLOCKED로 유지한다. 실행 준비/장 대기 상태는 실행일/장 시간 점검과 pilot authorization snapshot이 실제 checked=True로 통과한 경우에만 표시하고, 미점검 항목은 NOT CHECKED로 남겨 cap 승인 준비와 실행 준비를 분리한다. Markdown 리포트는 shadow 수집/audit 재실행/추천 cap 승인/capped paper 실행 명령을 함께 남기되, READY_TO_EXECUTE가 아닐 때 실행 명령은 # blocked: 주석으로 고정해 blocker 해소 전 paper 실행을 유도하지 않는다. 장 외 또는 cap 승인 준비가 안 된 blocker는 non-zero 종료로 자동화가 진행하지 못하게 한다
target-weight 60영업일 pilot manifest 추가 tools/target_weight_rotation_pilot.py --readiness-audit가 60영업일 pilot_paper 증거 누적 기준, 추천 cap, 차단 사유, 실행 명령을 담은 target_weight_paper_experiment_manifest_*.json을 함께 생성한다. reports/paper_experiment_manifest.json에도 기존 scoring 실험과 별도 target-weight capped paper pilot 기준을 기록해 운영 흐름을 분리한다
target-weight daily ops summary 추가 tools/target_weight_rotation_pilot.py --daily-ops-summary가 readiness audit, 60영업일 pilot evidence 진행률, 실행일 일치 여부, 장 시간 주문 가능 여부, 유동성/pre-trade risk 상태, 다음 운영 명령을 target_weight_daily_ops_summary_*.json/.md로 묶어 남긴다. 주문·증거·pilot session을 쓰지 않는 no-order summary라 장전/장마감 운영 확인에 안전하게 사용할 수 있다. daily ops 상태가 READY_TO_EXECUTE가 아니면 실행 명령은 # blocked:로 출력되어 추천 cap 승인, 장 시간, 승인 snapshot, 데이터 품질 blocker가 남은 상태에서 paper 실행 명령을 그대로 복사하지 못하게 한다. 당일 pilot 증거가 이미 기록된 PILOT_EVIDENCE_RECORDED 상태는 다음 KRX 영업일을 next_operator_trade_day/not_before_date로 남기고, 다음 --daily-ops-summary/--readiness-audit 명령을 날짜까지 고정해 reports/current_blockers.jsontools/paper_pilot_control.py --status에 함께 표시한다. current blockers/runbook은 not_before_date 전 다음 영업일 명령을 command에 직접 노출하지 않고 # blocked:로 고정하며, 원본 명령은 scheduled_command/scheduled_follow_up에만 보관해 너무 이른 복사 실행을 막는다. not_before_date 당일 이후에는 scheduled no-order 점검 명령을 다시 command/follow_up으로 승격해 운영자가 현재 해야 할 점검을 바로 실행할 수 있게 한다. target-weight status 화면의 pilot auth 판정은 Core Entry Check로 표시해 daily ops의 실효 실행 차단과 구분하고, current blockers에 있는 not_before_datepremature_run_guard를 함께 노출해 다음 영업일 명령을 너무 일찍 복사 실행하지 못하게 한다. --daily-ops-summary/--readiness-audit를 KST 오늘보다 미래인 --as-of-date로 너무 일찍 실행하면 plan 생성 전에 target_weight_future_as_of_date_blocked로 fail-closed 처리하고, current blockers에는 premature_run_guard로 같은 가드를 노출한다. --as-of-date가 오늘 이하라도 plan 생성 결과의 trade_day가 요청일과 다르면 target_weight_requested_trade_day_unavailable로 차단하고 failure artifact만 남겨, 다음 영업일 점검이 전일 daily ops summary를 덮어쓰거나 전일 증거를 invalid로 오염시키지 못하게 한다. 실수로 미래 영업일 summary artifact가 먼저 생성되거나 trade_day가 누락/손상돼도 current blockers와 status의 최신 상태로 채택하지 않는다. --daily-ops-summary--readiness-audit가 sector map, 가격 수집, stale benchmark 같은 plan 생성 blocker로 막히면 traceback 대신 target_weight_daily_ops_summary_failure_*.json/.md 또는 target_weight_readiness_audit_failure_*.json/.mdBLOCKED 원인, 재실행 명령, orders_submitted=false를 남긴다. reports/current_blockers.json schema v3도 operator_runbook과 next action별 command/order_safety를 남겨 daily ops summary, readiness audit, capped paper 실행 순서를 운영 파일 자체에서 확인하게 한다. 최신 daily ops summary가 없으면 current blockers는 daily ops summary 생성을 1순위로 두고, 최신 summary가 있으면 shadow 3일 수집, Discord test preflight, 추천 cap 승인, READY_TO_EXECUTE 당일 실행 중 현재 blocker에 맞게 자동 정렬한다. READY가 아닌 최신 summary에서 실행 명령이 노출되어도 current blockers는 이를 # blocked:로 정규화하고 order_safety=no_order로 표시한다
target-weight preflight/runbook 전용 안내 추가 core.paper_preflight.run_preflight()core.paper_pilot.generate_pilot_runbook()은 target-weight 후보에서 generic paper_bootstrap.py 또는 run_paper_evidence_pipeline.py를 pilot 증거 수집 경로처럼 안내하지 않는다. evidence 부족은 tools/target_weight_rotation_pilot.py --shadow-days 3 --shadow-end-date YYYY-MM-DD, 운영 재점검은 --daily-ops-summary, readiness/cap 승인은 --readiness-audit, Discord 도달성 검증은 tools/paper_preflight.py --send-test-notification으로 안내해 backfill/shadow/pilot evidence를 혼동하지 않게 한다
target-weight cash override 차단 --cash는 dry-run 계획 검토와 shadow bootstrap 보조 입력으로만 허용한다. --readiness-audit, --daily-ops-summary, --execute, --collect-evidence에서는 실제 paper 계좌 현금을 기준으로만 판단하며, cash override가 들어오면 CLI와 함수 호출 모두 target_weight_cash_override_blocked로 fail-closed 차단한다
target-weight 섹터맵 캐시 추가 DataCollector.get_sector_map()은 FDR/KRX KIND/pykrx 업종 매핑을 성공적으로 읽으면 reports/sector_map_cache.json schema v1 캐시를 저장하고, 실시간 소스가 모두 비어 있으면 캐시를 사용한다. KRX KIND가 우선주 섹터를 직접 주지 않는 경우 005935005930처럼 같은 5자리 stem의 보통주 섹터를 추론하고 sector_map_inferred_symbols에 남긴다. target-weight sector cap plan은 캐시가 있더라도 planning universe 전체 섹터 coverage가 없으면 target_weight_sector_map_incomplete로 fail-closed 차단해 부분 캐시로 섹터 cap이 느슨해지는 경로를 막는다
target-weight evidence 단독 수집 차단 --collect-evidence는 실행 완료 증거와 묶여야 하므로 --execute --collect-evidence 조합만 허용한다. 단독 --collect-evidence는 CLI와 함수 호출 모두 target_weight_collect_evidence_requires_execute로 차단해 dry-run 성공을 pilot evidence 수집 성공으로 오해하지 않게 한다
pilot freshness 영업일 기준 보정 check_pilot_entry()와 launch readiness가 evidence stale 여부를 달력일이 아니라 한국장 영업일 기준으로 계산한다. 긴 주말·휴장일 이후 정상적인 paper/pilot 흐름이 불필요하게 차단되지 않도록 evidence_stale_unit=business_days를 함께 남긴다
target-weight pilot enable guard 추가 tools/paper_pilot_control.py --enable이 canonical strategy_specs[].base_strategy=target_weight_rotation을 우선 기준으로 target-weight 후보를 식별하고, 기존 target_weight_* 접두어는 호환 fallback으로만 사용한다. pilot 제어 액션은 단일 명령에서 하나만 허용하므로 --enable과 다른 제어 액션을 함께 주는 운영 실수는 auth 기록 전에 차단된다. target-weight 후보 승인 때는 pilot auth 기록 전에 readiness audit을 재실행하고, 운영자가 요청한 cap이 현재 plan/launch readiness/유동성 preflight/비용 반영 pre-trade risk를 만족하며 readiness plan이 존재하고 plan candidate가 승인 대상 전략과 같고 audit/plan trade day가 --from과 정확히 같을 때만 승인한다. 요청 cap은 audit의 추천 cap과 정확히 같아야 하므로, 통과 가능한 더 큰 cap으로 승인 범위를 넓히는 경로도 차단된다. 승인 auth에는 현재 plan의 trade day/as-of date/params hash/targets/시작·목표 수량 snapshot을 저장해 cap 승인과 실행 계획을 직접 연결한다. stale plan이나 추천 cap 미충족 상태에서 auth만 먼저 열리는 경로를 차단한다
target-weight cap validation artifact 추가 --execute가 pilot cap validation에서 막혀도 예외로 조기 종료하지 않고 session JSON artifact에 차단 사유, skipped orders, evidence block reason을 남긴다. 주문/체결/증거 수집/runtime pilot session 저장은 하지 않아 cap 조정 후 재점검할 수 있다
target-weight promotion proof guard 추가 promotion package, evaluate_and_promote live_candidate 판정, live gate가 target-weight 계열 전략의 promotable day를 일반 execution_backed=True record로 인정하지 않는다. execution_backed=Truepilot_paper/authorized record가 target-weight plan/execution proof를 포함하고 pre-execution/liquidity/pre-trade/order-count/order-result/order/fill/position complete, order/fill/position reconciliation complete, plan/execution params hash 일치, 실행 execution_session_id와 fill별 execution_session_id/order_id 연결성을 만족한 날만 승격 카운트와 live 후보 판정에 포함한다
target-weight repair evidence 승격 제외 추가 --repair-pilot-evidence는 주문 없이 append-only로 성과/benchmark 필드를 복구할 수 있지만, benchmark_meta.performance_repair=True인 record는 기본 promotion proof에서 target_weight_repaired_performance_not_promotable로 제외한다. repair 구조 검증은 allow_repaired_performance=True 내부 경로에서만 통과시키고, 복구 record에는 promotion_eligible=false와 제외 사유를 남겨 projected 성과가 60영업일 승격 증거로 자동 산입되지 않게 한다
paper preflight/readiness 대상 옵션·실패 종료 보강 tools/paper_preflight.pytools/paper_launch_readiness.py의 운영 대상 범위를 --strategy 또는 --all 중 하나로 제한한다. 두 옵션이 함께 들어오면 DB 초기화, readiness 계산, artifact 기록 전에 argparse 단계에서 실패한다. preflight는 overall fail 또는 entry 차단이면 non-zero로 종료하고, launch readiness는 READY가 아니면 non-zero로 종료한다. 단순 리포트 생성은 --report-only로 명시한다
target-weight 실행 증거 E2E 회귀 추가 readiness audit, cap 승인 snapshot, capped paper 실행 증거, promotion package, promotion engine, live gate가 같은 params hash와 verified pilot proof를 공유하는지 단일 CI 테스트로 검증한다
target-weight 기존 증거 재사용 검증 강화 같은 candidate/date/params hash의 기존 pilot_paper evidence라도 target list, 시작 수량, 목표 수량, target exposure, gross exposure, 최대 주문금액이 현재 plan과 다르면 already_recorded 증거로 재사용하지 않는다. 수량 필드가 손상돼 정수로 해석되지 않는 경우도 예외로 중단하지 않고 mismatch 사유로 fail-closed 처리한다
target-weight proof consistency guard 추가 target-weight promotion evidence는 record date와 plan trade day가 일치해야 하며, 60영업일 verified pilot evidence 전체가 하나의 params hash로 고정되어야 한다. live gate는 paper evidence의 target-weight params hash와 canonical strategy_specs.params_hash가 다르면 실전 전환을 차단한다
target-weight liquidity preflight 추가 core.target_weight_rotation.build_target_weight_plan()이 주문 종목별 최근 20일 평균 거래대금을 plan diagnostics에 기록하고, tools/target_weight_rotation_pilot.py가 주문별 notional이 평균 거래대금의 기본 5%(--max-order-adv-pct)를 초과하거나 유동성 diagnostics가 누락되면 readiness audit과 --execute를 fail-closed 차단한다. 차단 결과는 session artifact, readiness JSON/MD, pilot session의 target_weight_execution.liquidity_check에 남기며 기존 pilot evidence 재사용도 liquidity-complete 조건을 요구한다
백테스트/research universe 유동성 필터 추가 포트폴리오 백테스트와 research candidate sweep이 평가 시작일 기준 20일 평균 거래대금 하한 미만 또는 strict 모드 데이터 누락 종목을 universe에서 사전 제외하고, 제외 사유를 결과/리서치 artifact에 기록
포트폴리오 백테스트 동적 슬리피지 보강 매수/매도 거래비용 계산에 종목별 20일 평균 거래량을 전달하고 거래 기록에 participation/slippage 진단값 기록
target-weight research 동적 슬리피지 보강 target-weight 리서치 백테스트가 종목별 20일 평균 거래량을 매수/매도 비용 계산에 전달하고 participation/slippage 진단값을 trade/metrics에 기록
target-weight research 다음 시가 체결 보강 직전 거래일 점수로 선정한 target-weight 리밸런싱을 당일 종가가 아니라 다음 거래일 원본 open으로 체결하고, 종가로 일말 평가한다. score day 종가 stale 종목은 후보에서 제외하고, 신규 top-N 후보 시가 누락은 target_weight_research_execution_price_missing으로 차단한다. 보유 종목 시가 누락은 없는 가격으로 매도했다고 가정하지 않고 해당 리밸런싱을 skip 진단으로 남긴다. 기존 종가 체결 기반 research artifact는 재생성 또는 execution_price_mode 확인 후 사용한다
Research benchmark coverage guard 추가 EW B&H 벤치마크 입력 universe 전체가 수집·기간 검증을 통과하지 못하면 후보의 benchmark excess를 신뢰하지 않고 INSUFFICIENT_BENCHMARK_DATA decision으로 canonical 평가 진행을 차단
live 체결 확인 guard 추가 KIS 주문 ACK 후 체결가·체결수량 조회 실패 또는 부분체결 확인 시 예상가 기준 전량 FILLED 처리 대신 주문을 ACKED/PARTIAL_FILLED pending으로 유지하고 DB 거래·포지션 기록을 보류
live 보류 주문 복구 대조 추가 재시작 복구에서 KIS 미체결 조회가 성공했고 DB ACKED/PARTIAL_FILLED 주문번호가 브로커 미체결 목록에서 사라졌으면 체결 조회 결과를 보강해 order_recordsRECONCILED로 닫고 종목별 OrderGuard를 해제한다. 잔고/포지션 정합성은 이어지는 KIS↔DB 동기화가 처리한다
live 미체결 조회 fail-closed 추가 KIS 미체결 조회 실패·비정상 응답을 “미체결 없음”으로 취급하지 않고 BUY/SELL 주문 전 차단. 재시작 복구의 전체 미체결 조회 실패도 critical 알림으로 노출
KIS 잔고 오류 응답 fail-closed 추가 잔고 조회 응답도 rt_cd == 0일 때만 정상 잔고로 해석한다. 오류 body는 빈 포지션/0원 잔고가 아니라 조회 실패로 반환해 연결 검증과 KIS↔DB 동기화가 실패 처리된다
live 잔고 동기화 신규 진입 guard 추가 장중 KIS↔DB 잔고 크로스체크를 신규 진입 후보 실행보다 먼저 수행한다. 불일치·조회 실패가 있으면 신규 BUY 후보 실행, 쿨다운 후 재진입 스캔, 신규 후보 재스캔을 보류하고 기존 포지션 exit 점검은 계속 수행한다
live 잔고 조회 실패 주문 판단 차단 추가 live 포트폴리오 summary가 KIS 잔고 실패로 DB fallback을 쓰면 broker_balance_ok=false를 남기고, 신규 BUY 손실 한도 확인과 주문 sizing용 현재자본/가용현금 조회는 DB fallback 값으로 진행하지 않고 fail-closed 차단한다
live 시작 전 연결·잔고 동기화 차단 추가 main.py --mode live는 canonical live gate를 통과해도 KIS 연결 검증 또는 초기 KIS↔DB 잔고 동기화가 실패하면 실전 스케줄러를 시작하지 않는다. live 루프 시작 전 브로커 연결과 장부 기준선을 fail-closed로 고정한다
live 긴급 청산 브로커 보유 반영 추가 live 설정의 --mode liquidate는 확인 플래그 통과 후 KIS↔DB 잔고 동기화를 먼저 실행한다. KIS-only 포지션은 DB에 보정한 뒤 청산 대상을 다시 읽고, 동기화 실패가 남으면 stale DB 포지션만으로 청산하지 않고 종료한다
HTTP 긴급 청산 live 확인 보강 추가 monitoring.liquidate_trigger는 live 긴급 청산을 ENABLE_LIVE_TRADING=true와 별도 LIQUIDATE_TRIGGER_CONFIRM_LIVE=true가 모두 있을 때만 확인 플래그로 전달한다. 내부 guard가 SystemExit을 내도 HTTP 서버를 종료하지 않고 실패 응답으로 변환한다
HTTP 긴급 청산 실패 결과 전파 추가 run_emergency_liquidate()가 대상/성공/실패 summary를 반환한다. HTTP 트리거는 개별 매도 실패가 있으면 성공 응답으로 포장하지 않고 실패 건수와 함께 실패 응답으로 반환한다
HTTP 긴급 청산 POST 전용화 추가 /liquidate는 POST 요청만 청산을 실행하고 GET은 405로 거부한다. 인증은 기본적으로 X-Token 또는 Authorization: Bearer 헤더만 허용하며, URL query token은 별도 환경변수를 켠 경우에만 허용한다
HTTP 긴급 청산 로컬 바인드 기본값 추가 HTTP 긴급 청산 서버는 기본적으로 127.0.0.1에만 바인드한다. 외부 호출이 꼭 필요할 때만 LIQUIDATE_TRIGGER_HOST=0.0.0.0처럼 명시해 노출 범위를 넓힌다
웹 대시보드 로컬 바인드 기본값 추가 웹 대시보드는 설정이 없거나 CLI host가 없으면 기본적으로 127.0.0.1:8080에만 바인드한다. 외부 공개가 필요할 때만 인증/reverse proxy 구성 후 --dashboard-host 0.0.0.0 또는 dashboard.host로 명시한다
HTTP 긴급 청산 토큰 강도 검증 추가 LIQUIDATE_TRIGGER_TOKEN은 기본 최소 16자 이상이어야 하며 흔한 placeholder 값은 서버 시작과 요청 처리 양쪽에서 거부한다
긴급 청산 결과 통합 알림 추가 run_emergency_liquidate()는 대상/성공/실패 summary를 통합 Notifier로 전파한다. 실패 상세는 최대 5건까지 포함하고, 알림 실패는 청산 결과를 뒤집지 않고 로그에 남긴다
재시작 복구 자동 보정 guard 추가 live 재시작 복구에서 KIS 미체결 조회가 실패하면 sync_with_broker(auto_correct=True)를 호출하지 않고 auto_correct=False 대조만 수행한다. 뒤늦은 미체결/부분체결 가능성이 남은 상태에서 DB 포지션이 자동 보정으로 오염되는 경로를 차단한다
빈 KIS 잔고 자동보정 보호 추가 KIS 보유 목록이 비었는데 DB 포지션이 남아 있으면 position_mismatch_auto_correct=true여도 DB 포지션 전체 삭제 자동보정을 기본 보류한다. 확실한 무보유 계좌 정리만 position_mismatch_allow_empty_broker_delete=true로 명시 허용한다
브로커 포지션 자동보정 방어값 복구 추가 KIS-only 포지션 추가와 수량 불일치 보정은 기존 DB 수량에 더하지 않고 KIS 수량 절대값으로 맞춘다. 복구 포지션에는 평균가 기준 손절·익절·트레일링 스탑을 재생성한다
target-weight pre-trade risk 추가 RiskManager.calculate_transaction_costs()의 수수료/세금/동적 슬리피지 예상 체결가를 재사용해 plan 전체 주문을 제출 전 시뮬레이션한다. 예상 현금 부족, 최소 현금비중, 최대 투자비중, 종목별 최대 비중, 최대 보유 종목 수 위반은 readiness audit과 --execute에서 fail-closed 차단하고, session/readiness/pilot evidence snapshot에 pre_trade_risk_check와 cost summary를 남긴다. 매도 주문은 plan diagnostics의 기존 평균매입가를 사용해 세금/양도세 옵션과도 연결된다
target-weight completed rerun block 추가 same-candidate/trade-day pilot session artifact가 이미 execution_complete=True이고 실제 주문 실행 수량이 있으면 --allow-rerun을 줘도 재실행을 차단한다. --allow-rerun은 부분 실행/중단 세션 복구에만 사용해 완료된 실행 증거가 중복 주문으로 오염되지 않게 한다
target-weight pilot 실행락 추가 --execute는 주문 제출 전 same-candidate/trade-day atomic .lock을 선점한다. 이미 lock이 있으면 주문 제출, 포지션 조회, session 저장, evidence 수집 전에 fail-closed 차단하고, 정상 종료 후 session artifact가 남은 뒤 lock을 해제한다. 이전 세션이 order_submission_reached=True, 실행 수량/실패 주문/중단 상태 중 하나라도 남기면 --allow-rerun도 차단한다
target-weight 실행일 guard 추가 --execute는 KST 오늘보다 미래인 --as-of-date를 plan 생성 전에 fail-closed 차단하고, plan.trade_day와 KST 기준 실제 실행일이 다르면 주문 제출, 실행 전 포지션 조회, 체결 대조, pilot evidence 수집 전에 차단한다. shadow bootstrap도 미래 end date를 plan 생성 전에 막아 다음 영업일 shadow/launch artifact가 조기 생성되지 않게 한다. --readiness-audit--daily-ops-summary도 같은 check를 blocker와 Markdown 리포트에 표시해 stale 또는 future --as-of-date 실행 명령이 READY 상태로 노출되지 않게 한다. 차단 사유와 execution_trade_day_check는 session/readiness artifact와 target-weight execution proof에 남겨 승격 증거 오염을 막는다
target-weight 승인 snapshot guard 추가 target-weight 전용 실행 어댑터는 후보명 접두어와 무관하게 활성 pilot auth의 승인 snapshot을 요구한다. --execute는 활성 pilot auth에 저장된 승인 snapshot의 schema_version/snapshot_type과 현재 plan의 trade_day, as_of_date, params_hash, risk_off, targets, 시작/목표 수량이 다르면 주문 제출, idempotency, 포지션 조회, 체결 대조, runtime pilot session 저장, pilot evidence 수집 전에 fail-closed로 차단한다. --readiness-audit--daily-ops-summary도 승인 snapshot mismatch를 blocker로 표시하고 실행 명령을 # blocked:로 바꿔 cap 승인 후 plan drift가 READY 상태로 보이지 않게 한다. promotion proof도 pilot_authorization_snapshot_allowed=True인 target-weight execution proof만 verified pilot day로 센다
target-weight 장 시간 guard 추가 --executeTradingHours.can_place_order() 기준으로 KRX 정규장 주문 가능 시간과 휴장/주말 여부를 확인한다. 같은 trade_day라도 장마감 후나 휴장일이면 idempotency, 포지션 조회, 주문 제출, 체결 대조, runtime pilot session 저장, pilot evidence 수집 전에 target_weight_execution_market_session_closed로 fail-closed 차단한다. readiness audit, daily ops summary, manifest, promotion proof도 execution_market_session_allowed=True를 요구해 장 외 paper 실행 증거가 승격 근거로 섞이지 않게 한다
target-weight 운영 리포트 상태 라벨 정리 readiness audit과 daily ops summary가 실행일·장 시간·승인 snapshot 검사 중 checked=false인 항목을 PASS 대신 NOT CHECKED로 표시한다. JSON risk snapshot에도 *_checked*_status를 남겨 미검사 상태를 통과로 오해하지 않게 한다
target-weight 가격 최신성 guard 추가 build_target_weight_plan()이 종목별 마지막 실제 종가 날짜(price_last_dates)와 벤치마크 최신 날짜(benchmark_last_date)를 diagnostics에 기록한다. ffill로 보정된 낡은 종목 가격이 최신 trade_day 가격처럼 쓰이면 target_weight_stale_price_data로 차단하고, benchmark_excess 점수 또는 benchmark risk overlay에 필요한 벤치마크 가격이 score day보다 오래되면 target_weight_benchmark_price_stale로 plan 생성 전에 중단한다
target-weight 데이터 품질 운영 리포트 추가 --readiness-audit--daily-ops-summary가 plan diagnostics의 price_last_dates, benchmark_last_date, missing_symbols, missing_position_symbolsdata_quality_check로 재검증한다. 가격 최신성 진단 누락, stale 종목 가격, 보유 종목 가격 누락, score day 이전 벤치마크는 readiness blocker로 표시하고 Markdown Data Quality 섹션에 남겨 daily ops에서 READY 상태로 숨기지 않는다
target-weight turnover-aware 리서치 추가 canonical risk-overlay 후보의 넓은 리밸런싱 tolerance 변형(target_tolerance_pct=3/5)을 research sweep 후보군에 추가하고, tolerance로 생략된 리밸런싱 거래 수·매수/매도 구분·notional을 target-weight metrics에 기록한다
target-weight 리스크 완화 top-200 검증 완료 target_weight_risk_relief --top-n 200 full sweep으로 risk-off/tolerance/exposure 축소 후보 10개를 비교했다. 최상위 tolerance 후보는 return +125.61%, raw excess +93.72%p, exposure-matched excess +104.53%p로 수익성은 개선됐지만 전 후보가 MDD -20%와 turnover/year 1000% 게이트를 넘지 못해 KEEP_RESEARCH_ONLY로 유지한다
target-weight 저회전 후보군 추가 rebalance_frequency를 target-weight research 날짜 계산에 연결하고 target_weight_turnover_relief family를 추가했다. 기존 risk overlay/tolerance 후보를 격월·분기 리밸런싱으로 재검증해 turnover/year 병목이 실제로 완화되는지 별도 sweep에서 확인할 수 있다
target-weight 저회전 top-200 검증 완료 target_weight_turnover_relief --top-n 200 full sweep에서 격월/분기 후보 6개를 비교했다. turnover/year는 456.1740.8%로 낮아졌지만 benchmark excess Sharpe가 모두 0 이하이고 MDD가 -25.35%-35.12%라 NO_ALPHA_CANDIDATE로 유지한다
target-weight 변동성 타깃 후보군 추가 benchmark_vol_target 노출 모드를 추가해 benchmark 실현 변동성이 목표치를 초과하면 base exposure를 비례 축소하고, benchmark drawdown trigger가 걸리면 지정 floor까지 낮춘다. target_weight_volatility_target family로 top-5 hold-buffer/risk-overlay/tolerance 후보의 변동성 타깃 변형을 따로 검증할 수 있게 했다
target-weight 변동성 타깃 top-200 검증 완료 target_weight_volatility_target --top-n 200 full sweep에서 후보 6개를 비교했다. best 후보는 return +105.18%, raw excess +73.29%p, exposure-matched excess +91.35%p, turnover/year 958.0%였지만 전 후보가 MDD -24.26%~-31.04%로 KEEP_RESEARCH_ONLY에 머문다
target-weight 리스크 페널티 랭킹 top-200 검증 완료 target_weight_downside_rank_relief --top-n 200 full sweep에서 후보 5개를 비교했다. best 후보는 return +132.51%, raw excess +100.62%p, exposure-matched excess +111.43%p였지만 전 후보가 MDD -25.20%~-33.07%, turnover/year 1143.8%~1366.0%로 KEEP_RESEARCH_ONLY에 머문다
target-weight churn control 후보군 추가 max_new_targets_per_rebalance로 리밸런싱당 신규 편입 종목 수를 제한하고, downside rank penalty 후보에 격월 리밸런싱·넓은 tolerance를 결합한 target_weight_churn_relief family를 추가했다
target-weight churn control top-200 검증 완료 target_weight_churn_relief --top-n 200 full sweep에서 후보 5개를 비교했다. best 후보는 return +118.89%, raw excess +87.00%p, exposure-matched excess +97.61%p, WF positive/Sh+ 100%였지만 MDD -26.95%, turnover/year 1034.2%로 KEEP_RESEARCH_ONLY에 머문다. maxnew1·격월 후보는 회전율을 낮췄지만 MDD와 benchmark excess Sharpe가 악화됐다
target-weight portfolio drawdown guard 후보군 추가 직전 평가 NAV 기준 포트폴리오 drawdown이 trigger를 넘으면 목표 노출을 floor까지 낮추고, 회복 직후에도 지정 리밸런싱 횟수만큼 cooldown을 유지하는 target_weight_drawdown_guard family를 추가했다
research empty-universe fail-closed 추가 canonical universe 목록 조회 실패, strict 유동성 필터, 데이터 수집 실패로 research universe가 0개가 되면 benchmark/candidate 평가를 건너뛰고 INSUFFICIENT_BENCHMARK_DATA, empty_universe_reason, selection_error, skipped_due_to_data를 artifact와 Markdown에 남겨 0% 성과 후보를 실제 검증 결과로 오해하지 않게 했다
target-weight 손실방어 top-200 검증 완료 target_weight_drawdown_guard --top-n 200 full sweep에서 후보 5개를 비교했다. best 후보는 return +99.53%, raw excess +67.64%p, exposure-matched excess +83.07%p, Sharpe 1.02, PF 4.88, MDD -19.56%, turnover/year 296.4%로 MDD와 회전율 병목을 동시에 완화했다. 2개 후보가 research sweep 기준 provisional 조건에 들어와 RUN_CANONICAL_EVALUATION으로 판정했고, 다음은 canonical promotion evaluation 재현성 확인이다
target-weight 손실방어 canonical 검증 완료 tools/evaluate_and_promote.py --canonical에 손실방어 eligible 2개 후보를 포함했다. pdd8/floor25 후보는 MDD -15.89%, turnover/year 530.8%로 방어력은 좋아졌지만 canonical benchmark excess -6.46%p라 paper_only. exp75/rankrisk90/pdd10/floor40 후보는 return +180.40%, benchmark excess +31.01%p, MDD -19.24%, WF positive/Sh+ 100%였지만 turnover/year 1026.3%로 paper_only. 기존 risk-overlay 후보만 provisional_paper_candidate를 유지한다
target-weight exp75 회전율 완화 검증 완료 exp75/rankrisk90/pdd10/floor40 후보에 tol3, tol4, tol5, maxnew2, tol3_maxnew2 변형을 추가했다. top-200 sweep에서는 tol4가 return +81.19%, raw excess +49.30%p, MDD -19.33%, turnover/year 886.7%, WF positive/Sh+ 100%로 canonical 평가 대상에 남았다. canonical에서는 return +183.02%, benchmark excess +33.63%p, Sharpe 1.50, PF 4.82, turnover/year 986.5%로 회전율 gate는 통과했지만 MDD -20.25%로 provisional gate를 0.25%p 초과해 paper_only다. tol3는 turnover/year 1009.0%로 회전율 미달이다
target-weight tol4 낙폭 완화 검증 완료 tol4 기반 pdd10_floor35, pdd8_floor40, pdd8_floor35, pdd10_floor40_cd2 변형을 추가해 target_weight_drawdown_guard --top-n 200 후보 14개를 재검증했다. 신규 변형은 canonical eligible에 추가되지 않았다. pdd10_floor35는 turnover/year 829.8%로 낮아졌지만 MDD -20.20%, pdd8_floor35도 MDD -20.20%로 실패했고, pdd8_floor40cooldown2는 MDD/turnover는 통과권이나 benchmark excess Sharpe<=0으로 제외됐다
target-weight rank-risk 보강 검증 완료 exp75 계열에 rankrisk90_dd75, rankrisk120을 추가하고 tol4+pdd10/floor40 guard와 결합했다. top-200 후보 16개 재검증에서는 rankrisk120_tol4가 return +84.41%, raw excess +52.52%p, MDD -19.30%, turnover/year 919.4%, rankrisk90_dd75_tol4가 return +82.56%, raw excess +50.67%p, MDD -19.54%, turnover/year 896.0%로 기존 tol4보다 개선됐다. canonical에서는 두 후보 모두 turnover는 통과했지만 benchmark excess -23.70%p/-23.40%p와 MDD -20.74%/-20.76%로 paper_only
포트폴리오 백테스트 이벤트 guard 추가 backtest/portfolio_backtester.py에 gap-up 신규 매수 차단, gap-down GAP_DOWN 청산, 어닝 윈도우 신규 매수 차단, BlackSwan 청산·쿨다운·recovery 사이징과 gap_*/earnings_*/blackswan_* 진단 카운터를 추가
비용 전/후 성과 비교 리포트 추가 backtest.cost_impact가 수수료·세금·슬리피지를 표준 집계해 비용 차감 전 추정 수익률, 비용 차감 후 수익률, 비용 드래그, 비용/순손익, cost impact status를 단일/포트폴리오 백테스트 metrics와 txt/html 리포트에 자동 노출한다
WebSocket 갭 상태/보충 처리 api/websocket_handler.py가 웹소켓 끊김·재연결 갭을 ring buffer와 대시보드 ws_gap에 기록한다. 재연결 시 REST 현재가/일봉 캐시 갱신, 분봉 보충 기반 급변 보고, BlackSwan 즉시 점검, 디스코드 경고를 수행하며, 연결 성공·명시 종료 상태도 대시보드 스냅샷에 즉시 반영한다
pilot entry fail-closed audit 추가 check_pilot_entry()의 모든 blocked/allowed 결과를 pilot_audit.jsonl에 기록하고, runtime/evidence/notifier/order-count/position-count/gross-exposure guard 예외는 pilot entry 차단으로 처리. 기존 pilot auth가 있더라도 entry 직전에 전략 상태와 artifact eligibility를 다시 확인해 승인 이후 강등된 전략은 차단한다. gross exposure cap은 현재 노출이 아직 한도 미만이어도 이번 주문 후 예상 노출이 한도를 넘으면 차단한다
generic paper entry guard 추가 main.py --mode paper, scheduler auto-entry, execute_buy_quantity() 모두 preflight/runtime 확인 실패 시 BUY를 fail-closed 차단. blocked runtime의 pilot override는 check_pilot_entry() 재검증을 통과해야 하며 SELL은 exit-safe 유지
canonical 평가 입력 snapshot 추가 tools/evaluate_and_promote.py --canonical이 선정 종목의 유동성 데이터 범위, 벤치마크 데이터 범위, 데이터 수집 오류, data_snapshot_hashrun_metadata.json에 기록한다. 평가 예외는 단순 0% 성과와 구분해 evaluation_status=failed로 남긴다
DataValidator lookahead 방지 정제 clean_dataframe()이 입력을 시간순 정렬·중복 제거한 뒤 과거값 ffill만 적용한다. 선행 OHLC 결측 행은 제거해 bfill로 미래 가격이 과거 지표·신호·백테스트에 섞이는 경로를 차단한다
live gate snapshot 검증 추가 core/live_gate.pycore/promotion_engine.py가 canonical run_metadata.jsondata_snapshot_hash, 재계산 hash, 종목군 데이터 범위, 수집 오류, 평가 오류 상태를 검증한다. 손상되거나 부분 실패한 승격 산출물은 live 진입과 산출물 기반 pilot eligibility 로드에서 fail-closed 처리한다
live gate 승격 재계산 검증 추가 core/live_gate.pypromotion_result.json의 status만 신뢰하지 않고 canonical metrics와 paper evidence를 promotion_engine에 다시 태워 promote() 결과를 재계산한다. core.promotion_engine.load_metrics_from_artifact()load_promotion_artifact()metrics_summary.json의 WF/benchmark 파생값이 walk_forward_summary.json, benchmark_comparison.json 원천값과 일치할 때만 결과를 반환한다. load_promotion_artifact()는 직접 조회되는 promotion_result.json의 status/allowed_modes/reason도 현재 metrics/evidence 재계산 결과와 비교해 stale 결과를 차단한다. MDD, PF, WF, turnover, benchmark, evidence 조건 중 하나라도 현재 규칙에서 live_candidate를 만들지 못하거나 원천 산출물 또는 저장된 승격 결과가 stale이면 실전 진입과 artifact 기반 pilot eligibility를 fail-closed 차단한다
current blockers live gate 연동 tools/evaluate_and_promote.py --canonicalreports/current_blockers.json을 함께 갱신하고, core/live_gate.py가 최신 promotion_blocker_summary.json source hash와 current_blockers의 hash/summary/go_live/live_candidates/hard_blockers/operator_runbook을 확인한다. 운영 요약이 NO-GO이거나 stale이면 promotion/evidence가 좋아 보여도 live 진입을 fail-closed 차단한다. --current-blockers--current-blockers-check는 current blockers를 다루기 전에 promotion blocker summary 자체의 동기화와 저장된 promotion_result.json의 metrics/evidence/metadata 재계산 일치 여부를 검증해, stale promotion_result에서 파생된 운영 파일이 통과하지 못하게 한다. schema v3 current blockers는 다음 액션에 실행 명령과 order_safety를 포함해 no-order 점검과 capped paper 주문 경로를 구분하고, 최신 target-weight daily ops summary가 없으면 daily ops 생성을 1순위로 올린다. 최신 summary가 있으면 shadow 수집, Discord 도달성 점검, 추천 cap 승인, READY_TO_EXECUTE 실행 중 현재 필요한 명령을 1순위로 올리고, webhook 미설정은 DISCORD_WEBHOOK_URL 설정 필요 액션으로 구분하며, READY 전 실행 명령은 # blocked:로 정규화한다. active target-weight pilot이 있으면 operator_runbook.core_entry_check에 핵심 진입 점검 상태를 함께 싣고, 알림 도달성 stale/unverified/missing은 core_entry_actionnext_actions의 no-order 사전점검 재실행 명령으로 노출한다. --check-only도 promotion artifact 로드 성공만 보지 않고 metrics/WF/benchmark 원천 동기화, blocker summary/current blockers 동기화, run_metadata.generated_at 7일 최신성까지 운영 기본 점검에서 확인한다. invalid paper evidence package는 승격 입력에서 제외하고, 운영자가 --paper-evidence-quarantine-invalid --dry-run으로 대상 확인 후 격리할 수 있도록 전략별 구조화된 WARN으로 한 번만 노출한다. live gate도 blocker summary/current blockers를 저장된 promotion_result가 아니라 전체 artifact의 현재 재계산 결과로 다시 만든 값과 비교해 next action, strategy summary, current blocker action, operator runbook, 다른 전략의 live/provisional 분류 같은 파생 필드가 오래되거나 수동 변경된 상태를 차단한다
snapshot DB 복구 후보 패키지 추가 tools/target_weight_rotation_pilot.py --diagnose-portfolio-snapshot이 DB trade_history/positions 증거 복구가 필요한 경우에만 artifact 기반 후보 CSV 2개와 manifest를 함께 생성한다. 이 패키지는 candidate_only=True, db_write_enabled=false, requires_authoritative_confirmation=true로 고정되어 자동 DB 반영이나 artifact-only snapshot 생성을 허용하지 않는다. 후보 trade_history의 가격·금액·수수료·세금·슬리피지는 같은 실행 artifact의 details[].resultpre_trade_risk_check.order_costs에서 보강하고 price_source로 출처를 남긴다. positions 후보 CSV는 0주 이하 수량을 제외하고 manifest/status에 제외 종목을 표시한다. --prepare-db-restore-review-bundle은 후보 CSV 사본과 빈 reviewed authoritative CSV 템플릿, 검토 checklist/verify 명령을 no-write로 생성해 candidate row를 원장 증거로 오인하지 않게 한다. reviewed authoritative 템플릿은 authoritative_source, authoritative_evidence_ref, reviewed_by, reviewed_at 메타데이터를 필수 컬럼으로 포함하고, verify는 모든 reviewed row의 원장 출처·증거 참조·검토자·검토 시각이 채워져 있어야 통과한다. current blockers/status는 review bundle 생성 전에는 bundle 명령을, 생성 후에는 authoritative 템플릿 경로와 verify 명령, 실제 reviewed CSV 파일에서 다시 읽은 행 수/빈 템플릿/누락 컬럼/검토 메타데이터 상태, 후보 대비 누락·예상 밖 행 수, 마지막 verify 이후 CSV 변경 여부를 1순위로 노출한다. review bundle이 참조한 manifest hash가 현재 manifest와 달라지면 target_weight_authoritative_db_restore_review_bundle_stale로 템플릿 작성 대신 bundle 재생성을 먼저 안내한다. 이어서 --verify-db-restore-package가 manifest 해시·CSV 행 수·현재 DB 상태·reviewed authoritative CSV 일치 여부를 no-write로 검증하며, 빈 reviewed 템플릿은 authoritative_*_csv_empty_template, 후보 CSV 파일을 authoritative 입력으로 직접 넘긴 경우는 authoritative_*_csv_candidate_source_rejected, 후보 전용 marker가 authoritative CSV 안에 남은 경우는 authoritative_*_csv_candidate_marker_rejected, 비교 컬럼 누락은 authoritative_*_csv_columns_missing, 행 수 불일치는 authoritative_*_csv_row_count_mismatch, 값 불일치는 authoritative_*_csv_content_mismatch blocker로 별도 차단한다. reviewed 메타데이터 컬럼 누락/미입력/후보 출처/후보 증거 참조/placeholder/잘못된 reviewed_at/미래 reviewed_at/체결·snapshot 이전 reviewed_at 표시는 authoritative_*_csv_review_metadata_* blocker로 차단하고 current blockers/status에도 metadata ok/누락 컬럼/미입력 행/후보 출처 행 수/후보 증거 참조 행 수/placeholder 행 수/시간 형식 오류 행 수/원천 이전 검토 시각 행 수를 표시한다. 메타데이터 없는 레거시 restore_ready=true 검증 artifact는 current blockers에서 effective ready로 보지 않고 재검증 대상으로 돌린다. 값 불일치는 authoritative_*_csv_identity_mismatchauthoritative_*_csv_economic_mismatch로 추가 분해해 주문 식별자 문제와 가격·금액 문제를 구분한다. 최신 검증 blocker를 함께 표시해 운영자가 원장 대조 후 authoritative 복구를 진행할 수 있게 한다
DB 복구 review progress inspect 추가 --inspect-db-restore-review-progress --restore-manifest ... --authoritative-*-csv ...가 DB 상태 조회나 DB write 없이 reviewed authoritative CSV의 작성 진행률을 점검한다. 후보 패키지 hash/행 수, reviewed row 수, 후보 대비 누락·예상 밖 행, 메타데이터 누락/placeholder/후보 증거 참조/검토 시각 오류를 JSON/Markdown/CLI 출력으로 보여주고, 완료 시 실행할 --verify-db-restore-package 명령을 함께 남긴다. inspect는 이미 채워진 reviewed row를 제외한 누락 후보만 target_weight_db_restore_review_worklist_*.csv 작업목록으로 생성하며, 이 파일에는 not_authoritative=true, 후보 row hash, 대상 authoritative CSV 경로, 원장 대조 후 채워야 할 메타데이터 입력 칸을 포함해 수동 대조 범위를 좁혀준다. 이어서 --validate-db-restore-review-worklist --restore-manifest ... --review-worklist-csv ...가 작업목록의 pending/rejected/unknown 상태, 원장 메타데이터 누락·placeholder·후보 출처 참조, 후보 row hash 손상, 대상 authoritative CSV 경로 누락을 DB 조회/쓰기 없이 검증하고, 아직 authoritative CSV를 쓰지 않았음을 no-write safety로 남긴다. 검증 상태가 ready가 되면 --write-db-restore-authoritative-csv-from-worklist --review-worklist-validation ...가 validation artifact와 worklist hash를 다시 확인한 뒤 reviewed authoritative CSV에만 append/dedup 병합하고, DB 초기화·조회·쓰기 없이 verify 명령으로 넘길 리포트를 남긴다. review bundle이 준비됐지만 verify가 아직 blocked이면 current blockers의 1순위 commandpaper_pilot_control.py --status의 Operator next action을 이 no-order inspect 명령으로 승격하고, 실제 verify는 scheduled_command로 남겨 원장 대조 중간 상태를 검증 명령 실패에 의존하지 않고 확인할 수 있다
DB 복구 수동 검토 체크리스트 추가 DB 복구 review bundle이 authoritative CSV를 자동 생성하지 않는 원칙은 유지하면서 manual_review_trade_history_checklist.csv, manual_review_positions_checklist.csv를 함께 만든다. 체크리스트는 각 후보 행의 review_item_id, 후보 행 hash, 검토 상태, 원장 출처·증거 참조·검토자·검토 시각 입력 칸을 포함하고 not_authoritative=true로 표시되어 후보 행과 원장 증거 대조 작업을 추적하되 DB 복구 입력으로 오인되지 않게 한다. review bundle 재실행 시 기존 authoritative 템플릿과 체크리스트가 있으면 덮어쓰지 않고 preserved 목록으로 보고해 수동 검토 내용을 보호한다. 단, 행이 없는 구버전 authoritative 템플릿이 필수 검토 메타데이터 컬럼 없이 남아 있으면 빈 파일만 최신 헤더로 upgrade 목록에 기록하고 보정하며, 한 줄이라도 작성된 수동 파일이나 낯선 헤더/메모는 그대로 보존한다. 체크리스트 CSV를 authoritative 입력으로 잘못 넘기면 checklist marker를 후보 marker로 감지해 authoritative_*_csv_candidate_marker_rejected로 차단한다. current blockers/status도 체크리스트 경로와 생성/보존/업그레이드 파일 목록을 노출한다
target-weight current blockers 실행 가드 추가 tools/target_weight_rotation_pilot.py --execute가 운영 reports/current_blockers.json 누락, stale freshness, 현재 전략·거래일 action 누락, DB persistence/review/snapshot recovery guard, # blocked: 명령을 감지하면 preflight/idempotency/position read/order submission 전에 skipped_current_blockers_guard로 중단한다. matched action이 daily_ops_status=READY_TO_EXECUTE, order_safety=paper_order_only, 실제 --execute 명령을 모두 만족할 때만 주문 경로를 열어 no-order 점검 액션이나 수동 복구 액션을 실행 허가로 오인하지 않는다. 운영 화면의 차단 명령을 우회해 직접 실행 CLI를 조립하거나 오래된 current blockers를 둔 상태에서도 DB 복구 proof 미완료 상태에서는 주문 경로로 넘어가지 않는다
DB 복구 검증 stale 차단 reviewed authoritative CSV가 restore_ready=true 검증 이후 다시 수정되면 current blockers가 수동 DB 복구 ready 액션으로 넘어가지 않고 target_weight_authoritative_db_restore_verification_stale_after_review_edit guard와 재검증 명령을 1순위로 노출한다
DB 복구 적용 계획 추가 --plan-db-restore-apply --restore-verification <verification_json>이 ready 검증 리포트의 authoritative CSV sha, 후보 hash, no-write safety, 현재 DB empty 상태를 다시 확인하고 trade_history 수동 insert와 positions 절대값 교체 계획을 JSON/Markdown으로 남긴다. CSV가 검증 이후 바뀌었거나 DB가 이미 채워져 있으면 blocked 처리하며, current blockers는 검증 완료 후 수동 write 대신 no-write 적용 계획 생성 명령을 우선 노출한다
DB 복구 guarded apply 추가 --backup-db-restore-state --restore-apply-plan <apply_plan_json>이 guarded apply 직전 대상 account/date의 현재 trade_history/positions 상태를 no-write 사전 백업 artifact로 남기고, 현재 DB가 비어 있을 때만 backup_ready=true로 통과한다. --apply-db-restore --restore-apply-plan <apply_plan_json> --restore-backup <backup_json>은 백업 artifact hash, candidate/snapshot date, empty DB precondition, 백업 확인과 명시 적용 확인 플래그가 모두 있어야 실제 DB write를 수행한다. 실행 직전 verification/CSV/current DB 상태를 다시 확인하고 기존 trade/position이 있으면 차단하며, 통과 시 trade_history와 positions를 단일 트랜잭션으로 반영하고 결과 artifact를 남긴다. ready apply plan이 있으면 current blockers/status가 먼저 사전 백업 명령을 안내하고, ready backup artifact가 있을 때만 guarded apply 명령을 다음 단계로 안내한다
paper excess 승격 기준 정합성 보강 promotion_engine의 live_candidate 판정도 live gate와 동일하게 same-universe excess와 cash-adjusted excess가 모두 양수인 paper evidence만 허용한다. promotion_result가 live_candidate로 보이다가 live gate에서 cash-adjusted excess로 다시 차단되는 기준 불일치를 줄인다
paper evidence 전략 식별 검증 강화 promotion_evidence_{strategy}.json 파일명이 맞아도 package 내부 strategy가 현재 전략명과 정확히 일치하지 않으면 promotion_engine, evaluate_and_promote, live_gate가 승격/라이브 증거로 쓰지 않는다. 전략명 누락 또는 다른 전략 패키지 재사용은 fail-closed로 차단한다
promotion evidence package 무결성 검증 promotion_enginepromotion_evidence_{strategy}.jsonpackage_integrity.schema_versionpayload_hash를 재계산해 검증한다. hash가 누락되거나 payload와 맞지 않으면 수동 편집·충돌 해결·부분 재생성된 package를 승격 입력으로 쓰지 않는다
target-weight metadata 식별 강화 target-weight 후보 여부를 이름 prefix만으로 판단하지 않고 canonical strategy_specs[].base_strategy=target_weight_rotation을 우선 사용한다. prefix 없는 canonical target-weight 후보도 paper evidence package 생성, promotion result, live gate에서 pilot proof와 params hash 검증을 요구해 일반 paper evidence만으로 live 후보가 되는 경로를 막는다
paper evidence 출처 검증 강화 60영업일 성과가 좋아도 execution_backed=Truereal_paper/pilot_paper 출처가 명시되지 않은 예전 형식·수작업 JSONL record는 승격 증거로 세지 않는다. 출처 없는 기록만 있으면 no_execution_backed_evidenceinsufficient_days=0/60으로 promotion package를 차단한다
paper evidence canonical 정렬 보강 append-only JSONL에서 같은 날짜는 뒤쪽 최신 record를 유지하되, canonical view는 날짜순으로 반환한다. 중복 확인도 마지막 10줄이 아니라 전체 파일의 해당 날짜 최신 record를 확인해 backfill/shadow 기록이 뒤섞여도 freshness, 최근 10일, promotion period가 append 순서에 흔들리지 않게 한다
paper evidence 최신성 승격 gate 추가 promotion package가 earliest_evidence_date/latest_evidence_date를 기록하고, promotion_engine은 canonical 평가 기준 최신 evidence age가 14일을 넘거나 날짜가 누락/미래이면 live_candidate를 fail-closed 차단한다. 오래된 60영업일 package가 현재 후보 승격 근거로 재사용되는 경로를 막는다
live gate paper evidence 최신성 검증 추가 core/live_gate.py도 live 진입 직전에 promotion_evidence_{strategy}.jsonlatest_evidence_date/period 종료일을 확인한다. 최신 증거가 14일을 넘었거나 날짜가 누락/미래이면 promotion_result가 live_candidate여도 실전 진입을 차단한다
live gate paper evidence source 정합성 추가 core/live_gate.py가 daily evidence JSONL에서 source_records를 재계산한 뒤 package의 earliest_evidence_date/latest_evidence_date/promotable_evidence_days와 first/last/count가 같은지 확인한다. package hash가 맞더라도 승격 가능 일수나 증거 기간 headline이 원본과 다르면 실전 진입을 fail-closed 차단한다
canonical benchmark coverage 승격 gate 추가 evaluate_and_promote가 promotion_result를 만들 때 canonical data_snapshot_manifest integrity와 전략별 benchmark excess return/Sharpe를 함께 요구한다. benchmark coverage 누락, material fetch error, 평가 오류, benchmark excess 누락/0 이하가 있으면 artifact상 provisional/live 승격도 fail-closed 차단한다
promotion blocker summary 추가 tools/evaluate_and_promote.py --canonicalpromotion_blocker_summary.json/md를 함께 생성하고, --blocker-summary로 기존 reports/promotion artifact만 읽어 요약을 재생성할 수 있다. 단, --blocker-summaryload_promotion_blocker_summary_from_artifacts()는 저장된 promotion_result.json이 metrics/evidence/metadata 재계산 결과와 일치할 때만 쓰기 또는 summary 생성을 허용한다. 내부 검증 비교처럼 원본 artifact 그대로의 요약이 필요한 경우는 validate=False를 명시한다. 요약에는 source artifact hash를 남기며 --blocker-summary-check--check-onlypromotion_result/metrics/run_metadata 동기화와 metrics/evidence/metadata 기준 promotion_result 재계산 일치 여부를 검증한다. 재계산 전에 metrics_summary.jsonbenchmark_excess_*wf_* 값이 benchmark_comparison.json, walk_forward_summary.json 원천값과 같은지도 확인해 오래된 metrics만으로 promotion을 갱신하지 못하게 한다. --promotion-artifacts-refresh는 기존 metrics/evidence/metadata에서 promotion_result.json, paper 필드가 반영된 metrics_summary.json, blocker summary, current blockers를 함께 갱신한다. 전략별 status, 주요 blocker, 핵심 metrics, 체결 품질 blocker, 다음 운영 조치를 한 화면에 정리해 긴 promotion_result.reason을 직접 파싱하지 않아도 된다. provisional 후보의 live 차단 원인이 paper evidence/target-weight pilot proof/체결 품질이면 benchmark 문구가 함께 있어도 해당 운영 조치를 먼저 안내한다
paper 체결 품질 리포트 추가 tools/paper_trade_quality_report.pyTradeHistoryexpected_price, price_gap, actual_slippage_pct, slippage, execution_session_id, order_id를 집계해 예상가 대비 불리한 체결 갭, expected_price 누락, 주문/실행 세션 연결 누락, 종목/일자별 체결 품질을 JSON/Markdown으로 남긴다. 기본 CLI는 reviewno_trades를 non-zero로 종료하며, 단순 리포트 목적의 체결 0건은 --allow-no-trades로만 성공 처리한다. generate_promotion_package()도 같은 기간의 trade_quality를 기록하고 no_trades, expected_price 누락, 주문/실행 세션 연결 누락, evidence total_trades 및 BUY/SELL 합계와 TradeHistory 체결 구성 불일치, BUY/SELL 외 action 또는 50bp 초과 불리한 체결 갭이 있으면 BLOCKED 처리한다. promotion_enginepaper_trade_quality_status=ok를 live 후보 조건으로 재확인해 paper evidence가 실제 체결 왜곡과 증거 연결성을 감당하는지 승격 전 확인할 수 있다
target-weight 변동성 예산 목표비중 추가 target_allocation_mode=inverse_volatility가 선택된 top-N 종목의 목표 금액을 동일가중 대신 rolling 실현 변동성의 역수로 배분한다. allocation_vol_lookback_days, allocation_vol_min_periods, allocation_vol_floor_pct, allocation_max_sleeve_weight_pct, 관측 sleeve weight와 volatility coverage 누락 종목을 metrics에 남기며, target_weight_volatility_budget family로 tol4/pdd10/floor40 및 sectorcap2 계열 후보를 실데이터 sweep에 올릴 수 있다. 아직 full sweep 전이므로 승격 대상은 아니다
test artifact quarantine 보강 tools/quarantine_test_artifacts.py를 정식 운영 도구로 두고 reports/paper_evidence, reports/paper_runtime, reports/promotion에서 test/demo 전략 artifact를 격리한다. promotion JSON 내부 top-level 전략명과 strategy/candidate_id payload도 검사하며, paper preflight가 발견 건수와 정리 명령을 WARN으로 남겨 테스트 산출물이 canonical promotion/operator view에 섞이는 경로를 줄인다
legacy evidence E2E 정리 v1 save_daily_evidence/load_all_evidence 기반 E2E를 v2 JSONL/canonical/weekly/promotion/quality report smoke로 교체했다. scheduler의 deprecated v1 collector 호출을 제거하고 core.evidence_collector는 import 호환용 no-op shim으로 축소해 전체 pytest collection을 깨지 않게 한다
Zero-return Semantics cash-only/no-position day deadlock 해소 — daily_return=0.0 추론
scoring paper_only 강등 Sharpe/PF/WF 안정성 미달. 관찰은 가능하지만 우선 pilot 후보 아님

다음 연구 방향 — 2026-05-13 기준

항목 결정
즉시 canonical promotion 완료. target_weight_rotation_top5_60_120_floor0_exp75_rankrisk90_tol5_sectorcap2_posloss8_frac50_pdd10_floor40_cd1가 next-open/결측 진단 기준 canonical promotion bundle에서 provisional_paper_candidate로 재현됨. 최신 재검증 기준 return=+198.15%, PF=5.58, Sharpe=1.57, MDD=-17.18%, WF positive/Sh+=100%
현재 후보군 target-weight 기본 capped pilot 후보는 tol5+sectorcap2+posloss8+pdd10 계열로 갱신. 전용 paper/pilot adapter는 rank penalty, sector cap, position loss reduction, portfolio drawdown guard 상태를 적용하며 일반 scheduler registry에는 아직 넣지 않음
다음 후보 탐색 신규 기본 후보는 research/canonical 기준만 통과했으므로 60영업일 verified pilot evidence와 target-weight execution proof 누적이 우선이다. 추가 후보 탐색은 paper pilot 증거가 쌓이는 동안 병행하되, research artifact만으로 paper/live 전환은 진행하지 않는다
운영 원칙 research artifact만으로 paper/live 전환 금지. full paper 신규 진입은 preflight status + runtime state + 필요 시 pilot authorization을 실행 직전에 통과해야 하며, canonical promotion + paper evidence + live gate 필요

운영 안정성 — 미구현 (중기 개선)

항목 설명 우선순위
DART·어닝 필터 고도화 기본 연동 완료(dart_loader+earnings_filter). 공시 키워드·커버리지·폴백 정책 확대 중기 (3~6개월)
펀더멘털 신호 고도화 fundamental_factor·앙상블 구성 반영됨. 지표·해외 종목·공시 연계 강화 중기
웹 대시보드 강화 전략별 신호, 주문 목록, API 사용량 표시 중기
WebSocket 갭 처리 고도화 기본 갭 보충·급변 감지는 완료. 향후 종목별 체결 공백 재구성, 브로커 체결 이벤트와의 교차 검증, 운영 알림 SLA를 확장 중기

다음 연구 방향 — 2026-04-29 기준

항목 결정
기존 rotation 변형 추가 승격 보류. quick sweep에서 NO_ALPHA_CANDIDATE
즉시 canonical promotion 진행하지 않음. benchmark excess gate 미달
다음 후보 탐색 유니버스 확장, 다른 후보군 설계, benchmark 대비 초과수익/초과 Sharpe 우선
운영 원칙 paper/live gate는 유지. research artifact만으로 실전 전환 금지

상세는 quant_trader_design.md §5.13, §5.14, §9.1, §10 참고.


8. watchlist 모드

config/settings.yamlwatchlist.

mode 설명
manual symbols 목록 직접 관리.
top_market_cap 시가총액 상위 N개. market(KOSPI/KOSDAQ), top_n. DataCollector.get_krx_stock_list() 기준.
kospi200 코스피200 유사 시총 상위 N개. kospi200_top_n.
momentum_top 12개월 수익률 상위 N개(모멘텀 팩터). 시총 풀에서 1년 수익률 계산 후 상위 top_n.
low_vol_top 60일 실현변동성 하위 = 저변동성 상위 N개.
momentum_lowvol 저변동성 필터 통과 종목 중 12개월 수익률 상위 N개.

리밸런싱 주기 (팩터 모드: momentum_top, low_vol_top, momentum_lowvol):

  • rebalance_interval_days(기본 20) 경과 시에만 재계산, 그 사이에는 data/watchlist_cache.json 캐시 사용.
  • 매일 재계산 → 종목 교체 잦아 거래비용 증가 / 너무 드물면 팩터 효과 희석. 월 1회(≈20일)가 학술 기준.
  • 캐시 강제 갱신: data/watchlist_cache.json 삭제 후 다음 resolve() 호출 시 즉시 재계산.

자동 모드 실패 시 symbols 또는 기본(005930) fallback.


9. 의존성 및 환경

Python 버전

pyproject.toml: >=3.11,<3.13. 3.11 또는 3.12 사용 권장.

주요 의존성 (requirements.txt)

카테고리 패키지 용도
데이터 처리 pandas>=2.0, numpy>=2.0, scipy>=1.14 OHLCV 시계열, 수치 계산, 통계
기술적 지표 pandas-ta>=0.4.67b0 RSI, MACD, 볼린저, ADX, ATR, OBV 등
데이터 수집 pykrx>=0.1, finance-datareader>=0.9.50, yfinance>=0.2.18 KRX 종목·시세, 한국/미국 주가, 수정주가
HTTP/비동기 requests>=2.32, aiohttp>=3.10, websockets>=14.0 KIS REST API, 웹 대시보드, 실시간 웹소켓
DB sqlalchemy>=2.0 ORM (SQLite WAL / PostgreSQL)
설정 pyyaml>=6.0 YAML 설정 파일 로드
로깅 loguru>=0.7 구조화 로그, 파일 로테이션
CLI click>=8.1 명령줄 인터페이스 (일부)
테스트 pytest>=8.0, pytest-asyncio>=0.24 단위·통합 테스트

환경변수 (.env)

변수 필수 설명
KIS_APP_KEY KIS API 앱 키
KIS_APP_SECRET KIS API 앱 시크릿
KIS_ACCOUNT_NO KIS 계좌번호
DART_API_KEY 선택 전자공시 API — 실적일 DART 폴백 (settings.dart.enabled와 함께)
DISCORD_WEBHOOK_URL target-weight capped pilot 필수 디스코드 알림 웹훅 URL. 비어 있으면 preflight/notifier guard가 readiness와 실행을 차단
QUANT_AUTO_ENTRY full paper 시 schedule 모드에서 DB 모의 주문을 켬. 허용값: true/false/1/0/on/off/yes/no. live 모드에서는 ENV override 무시
ENABLE_LIVE_TRADING live 시 true 설정 + --confirm-live 필수
MAX_CALLS_PER_SEC 선택 KIS API 초당 호출 제한 (기본 10)
MAX_CALLS_PER_MIN 선택 KIS API 분당 호출 제한 (기본 300)
TELEGRAM_BOT_TOKEN 선택 텔레그램 봇 토큰 (알림 이중화)
TELEGRAM_CHAT_ID 선택 텔레그램 채팅 ID
SMTP_SERVER / SMTP_PORT / SMTP_USER / SMTP_PASSWORD 선택 이메일 알림 (알림 삼중화)
ALERT_EMAIL_TO 선택 알림 수신 이메일
LIQUIDATE_TRIGGER_TOKEN 선택 HTTP 긴급 청산 인증 토큰. 기본 최소 16자 이상, placeholder 값 거부
LIQUIDATE_TRIGGER_MIN_TOKEN_LENGTH 선택 HTTP 긴급 청산 토큰 최소 길이. 기본 16이며 더 낮게 설정해도 16 미만으로 내려가지 않음
LIQUIDATE_TRIGGER_HOST 선택 HTTP 긴급 청산 바인드 주소 (기본 127.0.0.1). 외부 호출이 꼭 필요할 때만 0.0.0.0 등으로 명시
LIQUIDATE_TRIGGER_PORT 선택 HTTP 긴급 청산 포트 (기본 8765)
LIQUIDATE_TRIGGER_CONFIRM_LIVE live HTTP 긴급 청산 시 true 설정 시 HTTP 트리거가 --confirm-live에 해당하는 확인 플래그를 전달. ENABLE_LIVE_TRADING=true도 함께 필요
LIQUIDATE_TRIGGER_ALLOW_QUERY_TOKEN 선택 true 설정 시에만 /liquidate?token=... 인증 허용. 기본값은 비활성이고 헤더 인증 권장

10. 저장소(Git) 관리

커밋 대상:

항목 파일
Python 소스 main.py, test_integration.py, core/*.py, strategies/*.py, api/*.py, backtest/*.py, database/*.py, monitoring/*.py, tests/*.py, config/config_loader.py
설정 예시 config/settings.yaml.example, config/holidays.yaml.example, .env.example
메타데이터 pyproject.toml, requirements.txt
문서 README.md, quant_trader_design.md, docs/PROJECT_GUIDE.md, deploy/README.md(선택)
설정 (공개 가능) config/strategies.yaml, config/risk_params.yaml
기타 .gitignore

제외(.gitignore):

카테고리 대상
비밀/환경 .env, .env.local, .env.*.local, config/settings.yaml
Python 런타임 __pycache__/, .venv/, venv/, .pytest_cache/, *.py[cod], *.egg-info/
데이터/로그 data/, logs/, *.db, *.sqlite, *.log
백테스트 산출물 reports/backtest_*.html, reports/backtest_*.txt, reports/*.md
외부 프로젝트 fintics/ (본 저장소는 quant_trader 소스만 관리)
IDE/OS .idea/, .vscode/, Thumbs.db, .DS_Store

불필요한 소스·생성물·외부 프로젝트는 저장소에 포함하지 않습니다.


📌 상세 설계·지표 공식·전략 로직·시스템 진단: quant_trader_design.md 문서 버전: v5.3 최종 수정: 2026-05-08 (live unfilled check fail-closed 반영)