On 2026-05-08 19:45 UTC a transient Oracle FRED-proxy 5xx storm caused
paper_engine_vix_fred_unavailable to fire (3 sequential 500s; the 4th
attempt returned 200 OK with VIX=17.08). The pre-fix engine just left
VIXCLS missing from the macro dict, which the selector at
libs/backtest/selector.py:1171-1173 already treats strict-conservatively
(None → veto). So the 5/8 incident vetoed v7.356 PEAD candidates for
~1 minute with no money-loss exposure. But:
- Log severity was thin (info-level "unavailable", no escalation).
- No tolerance for short outages — every 500 cost the gate's signal.
- EventDetector PostgreSQL rows do not pre-populate macro_vix per
engine.py:2810-2812 comment, so live trading depends entirely on
the FRED fetch path.
Fix: in-memory session-scoped cache + 3-tier fallback in
PaperTradingEngine._fetch_macro:
Tier 1 fetch ok → cache (value, now_utc), log ..._ok (info)
Tier 2 fail, cache <24h → return cached value, log ..._stale_fallback
(warning) with staleness_sec
Tier 3 fail, cache stale → None, log ..._unavailable_blocking (error)
with reason={no_cache,cache_too_stale}
The None-veto path through the selector is preserved exactly, so no
silent-pass on unknown VIX. Empty/0 observations now treated as outage
to defend against an upstream regression flipping "missing→veto" into
"0→always-pass".
The thin libs/oracle_client/fred.py is intentionally untouched — fallback
policy belongs in the engine, not the generic client.
6 new tests in tests/unit/paper_trader/test_vix_fred_fallback.py
(success/cache-write, 500+stale-<24h, 500+stale->24h-blocks,
no-cache+500-blocks, empty-observations-blocks, recovery-refresh).
All 18 tests in -k "vix or fred" pass; full paper_trader suite 45/45.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
3 months ago | |
|---|---|---|
| .claude | 4 months ago | |
| .playwright-mcp | 4 months ago | |
| apps | 3 months ago | |
| configs | 3 months ago | |
| dev | 5 months ago | |
| docker | 5 months ago | |
| docs | 4 months ago | |
| journal | 4 months ago | |
| libs | 3 months ago | |
| models/ranking | 5 months ago | |
| scripts | 4 months ago | |
| tests | 3 months ago | |
| .env.example | 5 months ago | |
| .gitignore | 5 months ago | |
| .paper_auto_state.json | 4 months ago | |
| .python-version | 5 months ago | |
| Makefile | 5 months ago | |
| README.md | 4 months ago | |
| alembic.ini | 5 months ago | |
| docker-compose.yml | 5 months ago | |
| justfile | 4 months ago | |
| pyproject.toml | 5 months ago | |
| uv.lock | 5 months ago | |
README.md
ACE-F v1 — AI Catalyst Event Engine (Free Data)
미국 주식 이벤트 기반 중단기 자동매매 시스템. SEC 공시 + 무료 시장 데이터를 활용하여 1~5일 continuation 종목을 자동 선별하고, 다음 세션에 기계적으로 진입·청산하는 AI 이벤트 트레이딩 엔진.
관련 문서:
목차
- 프로젝트 목적
- 핵심 철학
- 시스템 아키텍처
- 디렉토리 구조
- 데이터 파이프라인
- 전략 엔진
- 백테스트 시스템
- 전략 개선 시스템 (SQS / Journal / Leaderboard)
- 현재 개발 현황
- 현재 최고 전략 성과
- 설치 및 실행
- 사용법
- 기술 스택
- 데이터 소스
1. 프로젝트 목적
"공식 문서와 무료 attention 데이터를 이용해, 1~5일짜리 중단기 continuation 종목을 자동으로 선별하고, 다음 세션에 기계적으로 진입·청산하는 AI 이벤트 트레이딩 시스템"
핵심 목표:
- 무료 데이터만 사용하여 미국 주식의 1~5거래일 이벤트 드리프트를 자동 탐지
- LLM/AI는 가격 예측기가 아니라 공시·문서 해석기로 사용
- 전략 중심: 공식 이벤트 + 가격 반응 확인 + 리스크 통제
- 초기 버전은 수익률 최대화보다 재현성, 운영 안정성, 확장 가능성 우선
2. 핵심 철학
AI/LLM = 문서 해석기, ≠ 가격 예측기
- 공식 이벤트가 중심 — SEC 8-K, 10-Q, 6-K 등 기업이 직접 배포한 공시가 신호의 원천
- 가격이 반드시 1차 검증 — 이벤트 발생 후 첫 정규장 반응(reaction day)이 강하게 확인된 종목만 후보
- 재현성 최우선 — 무료 데이터 환경에서 가장 재현성 높은 데이터(SEC)를 중심에 배치
3. 시스템 아키텍처
전체 파이프라인
[SEC EDGAR / Stock Oracle / FRED / FINRA]
↓
Source Adapters
↓
Raw Storage (원문 보관)
↓
Normalizer / Document Parser
(규칙 기반 + LLM 보강)
↓
Feature Store (Parquet 스냅샷)
↓
Signal Ranker
(PEAD / Composite 스코어링)
↓
Portfolio & Risk Engine
(포지션 사이징, 섹터 제한, 진입 게이트)
↓
Backtest Engine / Execution
(이벤트 드리븐 시뮬레이션, 슬리피지)
↓
Strategy Improvement Tracker
(SQS, Journal, Leaderboard)
3대 핵심 엔진
| 엔진 | 역할 | 입력 | 출력 |
|---|---|---|---|
| Event Engine | 공식 문서에서 이벤트 후보 생성 | SEC 8-K, 10-Q, 6-K | event_type, direction, confidence |
| Document Understanding | 규칙+LLM으로 문서 질 해석 | exhibit text, XBRL | guidance_direction, demand_strength, margin_quality, oneoff_flags |
| Market Confirmation | 시장의 실제 반응 확인 | OHLCV bars | reaction_return, volume_ratio, close_location, gap_size |
4. 디렉토리 구조
fithia2/
├── apps/ # 애플리케이션 엔트리포인트
│ ├── backtester/ # 이벤트 드리븐 백테스트 시뮬레이션 & CLI
│ │ ├── run.py # 메인 백테스트 실행기 (BacktestRunner)
│ │ └── replay.py # 결정론 검증 (replay test)
│ ├── pipeline/ # 멀티스테이지 데이터 처리 파이프라인
│ │ ├── filing_poller/ # SEC EDGAR 신규 공시 폴링
│ │ ├── filing_fetcher/ # 공시 문서 다운로드
│ │ ├── event_parser/ # 이벤트 파싱 (규칙 + LLM)
│ │ ├── feature_builder/ # 스코어링 피처 생성
│ │ ├── label_generator/ # forward-return 라벨 생성
│ │ └── dataset_export/ # Parquet 스냅샷 내보내기
│ ├── sync/ # 데이터 동기화
│ │ ├── issuer_sync/ # 기업 메타데이터 (Stock Oracle)
│ │ ├── macro_sync/ # FRED 거시 지표
│ │ └── short_volume_sync/ # FINRA 공매도 잔량
│ ├── tracker/ # 전략 개선 추적 CLI (SQS, Journal, Leaderboard)
│ ├── tools/ # 분석·유틸리티 스크립트 (10개)
│ ├── review/ # 수동 리뷰 큐
│ └── qa/ # 데이터 품질 체크
│
├── libs/ # 핵심 라이브러리
│ ├── backtest/ # 백테스트 엔진 (3,600+ lines)
│ │ ├── domain.py # Pydantic 도메인 모델 30개+
│ │ ├── scoring.py # 후보 스코어링 (PEAD, composite)
│ │ ├── execution.py # 진입/청산 시뮬레이션
│ │ ├── allocator.py # 포지션 사이징 & 7개 진입 게이트
│ │ ├── selector.py # 후보 필터링 & 랭킹
│ │ ├── metrics.py # 21개 성과 지표 + 부트스트랩 CI
│ │ ├── tracker.py # SQS 계산, Journal I/O, Leaderboard
│ │ ├── snapshot_store.py # Parquet 데이터 로더
│ │ ├── splits.py # Walk-forward 윈도우 생성
│ │ ├── manifests.py # 실험 config 해석
│ │ ├── artifacts.py # 실행 결과 출력 (Parquet, JSON, CSV)
│ │ └── calendar.py # 거래일 유틸리티
│ ├── oracle_client/ # Stock Oracle API 클라이언트
│ │ ├── client.py # 비동기 httpx 클라이언트 (retry 로직)
│ │ ├── price.py # OHLCV bars, ATR-14
│ │ ├── financial.py # 재무제표 (BS, IS)
│ │ ├── filings.py # SEC 공시 검색/다운로드
│ │ ├── company.py # 기업 메타데이터
│ │ ├── screener.py # 유니버스 스크리닝
│ │ ├── fred.py # 거시 데이터
│ │ └── finra.py # 공매도 잔량
│ ├── parser/ # 공시 문서 파서
│ │ ├── rule_parser.py # 규칙 기반 8-K/6-K 파서
│ │ ├── merger.py # 규칙+LLM 결과 병합
│ │ └── text_normalizer.py # 텍스트 정규화
│ ├── features/ # 피처 엔지니어링
│ │ ├── builder.py # 오케스트레이터 (market+event+financial)
│ │ ├── market_features.py # 가격/거래량 피처
│ │ ├── event_features.py # 이벤트 품질 피처
│ │ ├── financial_features.py # 재무 피처 (EPS, 마진, 레버리지)
│ │ └── text_features.py # LLM 기반 텍스트 피처
│ ├── db/ # PostgreSQL 모델 (async SQLAlchemy)
│ │ ├── models.py # 7개 테이블 (Issuer, Symbol, Event, Document, ...)
│ │ └── migrations/ # Alembic 마이그레이션
│ ├── labeler/ # 라벨 생성 (1/3/5/7/15일 forward return, MFE/MAE)
│ ├── common/ # 로깅, config, 시간 유틸리티
│ ├── schemas/ # 공유 Pydantic 스키마
│ ├── export/ # 스냅샷 내보내기 (DB → Parquet)
│ ├── review/ # 리뷰 로직
│ └── llm/ # LLM 통합 (Claude/OpenAI, 캐시, 프롬프트)
│
├── configs/
│ ├── backtest/
│ │ └── defaults.json # 기본 전략 파라미터 (21개 설정)
│ ├── experiments/ # 실험 매니페스트 66개 (pead_midcap_step*, ...)
│ ├── app.yaml # 애플리케이션 설정
│ ├── symbols.yaml # 활성 유니버스
│ ├── symbols_midcap.yaml # 미드캡 유니버스 ($2B-10B)
│ ├── symbols_largecap.yaml # 라지캡 유니버스 ($10B+)
│ ├── symbols_smallmid.yaml # 스몰미드 유니버스
│ └── fred_series.yaml # FRED 거시 지표 정의
│
├── data/
│ ├── datasets/snapshots/ # Parquet 스냅샷 (후보, bars, macro)
│ ├── cache/ # LLM/API 응답 캐시
│ ├── analysis/ # 분석 결과 (플롯, CSV)
│ └── parquet/ # 원시 Parquet 내보내기
│
├── runs/ # 백테스트 실행 결과
│ └── midcap_steps/ # 65+ 실행 기록 (metrics.json, trade_blotter.csv, equity_curve.parquet)
│
├── journal/ # 전략 개선 저널
│ ├── improvement_journal.jsonl # append-only 개선 사이클 로그 (21개+ 엔트리)
│ ├── experiment_registry.json # 리더보드 데이터 (자동 생성)
│ └── LEADERBOARD.md # 사람이 읽을 수 있는 리더보드 (자동 생성)
│
├── tests/
│ ├── unit/ # 단위 테스트 270개+ (외부 의존성 없음)
│ ├── integration/ # 통합 테스트 (PostgreSQL 필요)
│ └── replay/ # 결정론/재현성 테스트
│
├── dev/ # 개발 문서
│ ├── overview.md # 전체 아키텍처 비전
│ ├── finished/ # 완료된 Phase 문서 (0, 1, 2, 3, 4)
│ └── phase5~8_deliverables/ # 진행 중인 Phase 문서
│
├── docker/ # Docker 관련 파일
├── docker-compose.yml # PostgreSQL 16 + Adminer
├── pyproject.toml # 의존성 & 빌드 설정
├── Makefile # 빌드 & 테스트 자동화
└── alembic.ini # DB 마이그레이션 설정
5. 데이터 파이프라인
5.1 데이터 흐름
단계 1: 원시 데이터 수집 (Phase 2)
┌──────────────────────────────────────────────────────┐
│ SEC EDGAR → 공시 JSON → 문서 (HTML/TXT) → raw zone │
│ Stock Oracle → 일봉 OHLCV → market_bars │
│ FRED → 거시 지표 (금리, 스프레드) → macro_features │
│ FINRA → 일별 공매도 잔량 → short_volume │
└──────────────────────────────────────────────────────┘
↓
단계 2: 파싱 & 피처 엔지니어링 (Phase 3)
┌──────────────────────────────────────────────────────┐
│ Rule Parser → event_type, guidance, confidence │
│ LLM Parser → 문서 이해 보강 (비활성화) │
│ Feature Builder → XBRL, reaction, text 스코어 │
│ Label Generator → 1/3/5/7/15일 forward return, │
│ MFE/MAE, time-to-target │
└──────────────────────────────────────────────────────┘
↓
단계 3: 스냅샷 내보내기
┌──────────────────────────────────────────────────────┐
│ PostgreSQL → Parquet 스냅샷 (point-in-time) │
│ 후보 (symbol, score, features) │
│ Bars (symbol, date, OHLCV) │
│ Macro (date, 거시 지표) │
└──────────────────────────────────────────────────────┘
↓
단계 4: 백테스트 & 평가 (Phase 4)
┌──────────────────────────────────────────────────────┐
│ SnapshotStore.load() → 메모리 로드 │
│ Signal Ranker → Candidate Selection → Position Sizing │
│ Entry/Exit Simulation → 21개 성과 지표 계산 │
│ SQS Score → Journal 기록 → Leaderboard 갱신 │
└──────────────────────────────────────────────────────┘
5.2 실행 명령어
# 기업 메타데이터 동기화
python -m apps.sync.issuer_sync.main
# 공시 폴링 → 다운로드 → 파싱
python -m apps.pipeline.filing_poller.main
python -m apps.pipeline.filing_fetcher.main
python -m apps.pipeline.event_parser.main
# 피처 빌드 → 라벨 생성
python -m apps.pipeline.feature_builder.main
python -m apps.pipeline.label_generator.main
# Parquet 스냅샷 내보내기
python -m apps.pipeline.dataset_export.main
6. 전략 엔진
6.1 현재 구현된 전략: PEAD (Post-Earnings Announcement Drift)
가설: 시장은 어닝 발표에 과소반응하며, 발표 후 3~5일간 드리프트(continuation)가 발생한다.
| 구성 요소 | 설정 |
|---|---|
| 신호 | 어닝 발표 + reaction day return ≥ 10% + PEAD score ≥ 0.65 |
| 진입 | reaction day 다음 세션 시초가 (next-open) |
| 보유 | 최대 7 거래일 |
| 청산 | Target (ATR 기반) 또는 Stop loss (ATR 기반) 또는 시간 만기 |
| 방향 | 롱 + 숏 (양방향) |
| 유니버스 | 미드캡 ($2B~$10B), NYSE/Nasdaq 보통주 |
6.2 PEAD 스코어링
3개 컴포넌트의 가중 합산:
| 컴포넌트 | 비중 | 피처 |
|---|---|---|
| Event Quality | 65% | parser confidence + signal strength + guidance |
| Reaction Direction | 20% | positive/flat/negative 방향성 |
| Volume Conviction | 15% | 평균 대비 거래량 확인 |
6.3 진입 게이트 (7개 Veto)
포지션이 열리기 전 모든 게이트를 통과해야 함:
- 유니버스 필터 — 최소 가격 $5, 최소 ADV $1M, ETF 제외
- 최대 포지션 수 — 포트폴리오 전체 동시 보유 제한 (기본 8)
- 섹터 집중 제한 — 동일 섹터 최대 포지션 수
- 포지션 크기 제한 — 포트폴리오 대비 최대 비중
- ADV 비율 제한 — 일평균 거래대금의 1% 이내
- 연패 쿨다운 — 연속 손실 후 대기 (설정 가능)
- 파싱 신뢰도 게이트 — 최소 confidence 40%
6.4 Exit 로직
매 거래일 포지션 상태 체크:
1) Target 도달? → target_1_fraction만큼 청산 (기본 50%)
2) Stop loss 도달? → 전량 청산
3) 보유 기한 초과? → 전량 시가 청산
4) Trailing stop? → 최고점 대비 하락 시 청산
| 파라미터 | 기본값 | 설명 |
|---|---|---|
stop_atr_multiplier |
3.0 | ATR-14 × 3.0 stop |
target_atr_multiplier |
1.5 | ATR-14 × 1.5 target |
target_1_fraction |
0.5 | target 도달 시 50% 청산 |
trailing_stop_pct |
0.05 | 5% trailing stop |
max_holding_days |
15 | 최대 보유일 |
slippage_bps |
10 | 10bps 슬리피지 |
7. 백테스트 시스템
7.1 이벤트 드리븐 시뮬레이션
- 이벤트 귀속: reaction day (공시 후 첫 거래일) 기준
- 신호 계산: reaction day 종가 기준
- 진입: 다음 세션 시초가 (look-ahead bias 방지)
- 일별 포트폴리오 상태: 매일 equity, exposure, drawdown 추적
- Kill switch: 최대 낙폭 25% 초과 시 전략 중단
7.2 Walk-Forward 검증
현재 평가는 단일 3-split만으로 끝내지 않는다. 시간축이 다른 여러 검증 층을 같이 본다.
| Split | 역할 | 용도 |
|---|---|---|
| Train | 파라미터 탐색 | 최적화용 |
| Valid | 검증 | 과적합 체크 |
| Test | 최종 평가 | 고정 OOS 성과 |
추가 검증:
- WFV: rolling train/test fold 분포 확인
- Robustness Matrix: 여러 horizon과 start-date에서 분포 확인
- Repaired OOT Robustness:
2020~2021별도 snapshot에서 추가 확인
즉 public SQS는 더 이상 고정 test 숫자 하나가 아니라,
3-split + WFV + robustness + repaired OOT를 함께 반영한다.
7.3 21개 성과 지표
거래 지표 (7개)
- win_rate, avg_win%, avg_loss%, profit_factor, expectancy_r, avg_r, trade_count
포트폴리오 지표 (8개)
- total_return, monthly_returns, sharpe_ratio, max_drawdown, equity_curve_r², VaR, CVaR, consecutive_losses
부트스트랩 95% 신뢰구간
- 리샘플링을 통한 통계적 유의성 확인
7.4 실행 예시
# 단일 split 백테스트
python -m apps.backtester.run \
--manifest configs/experiments/return_max_long_v1.51.json \
--split test \
--snapshot-dir data/datasets/snapshots \
--output-root runs/return_max_long_v1.51
# 3-split 전체 백테스트
for split in train valid test; do
python -m apps.backtester.run \
--manifest configs/experiments/return_max_long_v1.51.json \
--split $split \
--snapshot-dir data/datasets/snapshots \
--output-root runs/return_max_long_v1.51
done
# Walk-forward CV
python -m apps.backtester.run \
--manifest configs/experiments/return_max_long_v1.51.json \
--walk-forward --wf-train-days 252 --wf-test-days 63
출력 예시:
Run complete: bt_baseline_swing_v1_midcap-filte_20260316...
Trades: 72
Total return: +0.73%
SQS: 64.2 (profitability=68.4, risk=61.2, consistency=58.7, robustness=65.3)
8. 전략 개선 시스템
전략 개선을 체계적으로 관리하기 위한 3계층 시스템. 중복 실험 방지, 데이터 기반 의사결정, 리더보드를 통한 최고 전략 추적.
운영 기준과 handoff 규칙은 별도 문서로 관리한다: docs/research_workflow_and_handoff.md
clean-lineage 버전 체계는 v1.1부터 시작한다.
historical return_max_long_v326 같은 전략은 의미상 v0.326으로 취급한다.
다만 현재 active clean baseline은 return_max_long_v1.51.json 이다.
중요한 운영 규칙:
- manifest에 named micro engine이 남아 있으면
enabled: false여도 contaminated로 본다. - default leaderboard에는 truly clean manifest만 남긴다.
- 현재 상세 운영 기준은 docs/research_workflow_and_handoff.md 를 따른다.
8.1 Strategy Quality Score (SQS)
현재 public SQS는 단일 test split 점수가 아니다.
고정 split 성과, WFV, robustness, repaired OOT, 그리고 자본 효율 지표를 함께 반영하는 종합 점수다.
대표적으로 아래를 같이 본다.
- train / valid / test 수익률
- test annualized return
- test max drawdown
- test average gross exposure
- test days in market
- test return on gross exposure
- WFV fold quality와 최근 1년 fold 품질
- robustness matrix
- repaired OOT robustness
점수 체계는 연구 중 계속 보정될 수 있지만, 방향은 항상 "고정 구간 headline return"보다 "시간축 분포와 자본 효율"에 더 무게를 둔다.
SQS 해석 기준:
| SQS 범위 | 해석 |
|---|---|
| 0–20 | 손실 전략 |
| 20–40 | 손익분기 근처 |
| 40–55 | 유망, 개선 필요 |
| 55–70 | 좋음, OOS 엣지 있음 |
| 70–85 | 강함, 실전 후보 |
| 85–100 | 예외적 (데이터 오류 확인 필요) |
8.2 Journal (개선 저널)
모든 실험 결과를 기록하는 append-only 로그.
journal/
├── improvement_journal.jsonl ← append-only 개선 사이클 로그
├── experiment_registry.json ← 리더보드 데이터 (자동 생성)
└── LEADERBOARD.md ← 사람이 읽는 리더보드 (자동 생성)
Journal 엔트리 구조:
{
"entry_id": "IMP-0015",
"timestamp": "2026-03-17T01:45:00+00:00",
"experiment_name": "pead_midcap_step14_score65",
"hypothesis": "Score threshold 0.60→0.65로 높여 약한 신호 필터링",
"config_delta": {
"base_experiment": "pead_midcap_step13_best",
"changes": { "signal.score_threshold": "0.60 → 0.65" }
},
"results": {
"train": { "run_id": "bt_...", "trade_count": 312, "profit_factor": 1.15, "..." : "..." },
"valid": { "run_id": "bt_...", "trade_count": 145, "profit_factor": 1.28, "..." : "..." },
"test": { "run_id": "bt_...", "trade_count": 72, "profit_factor": 1.22, "..." : "..." }
},
"sqs_score": 64.2,
"sqs_breakdown": {
"profitability": 68.4,
"risk": 61.2,
"consistency": 58.7,
"robustness": 65.3
},
"verdict": "better",
"verdict_reasoning": "Test SQS 64.2 > 57.7. Return +0.73% > +0.43%. Trade count 72 sufficient.",
"next_direction": "Test exit tuning (target, fraction, hold) on top of score 0.65"
}
8.3 실험 매니페스트
실험은 JSON 매니페스트로 정의. base_config에 overrides를 적용하는 구조:
{
"experiment_name": "pead_midcap_step14_score65",
"dataset_snapshot_id": "midcap-filtered",
"description": "Step 14: Score threshold 0.60→0.65",
"base_config": "configs/backtest/defaults.json",
"overrides": {
"event_type_profiles": {
"earnings_release": { "enabled": true, "direction_filter": "any" }
},
"signal": {
"scoring_model": "pead",
"pead_reaction_threshold": 0.10,
"pead_volume_threshold": 2.0,
"score_threshold": 0.65,
"max_candidates_per_day": 3
},
"execution": { "max_holding_days": 7 },
"risk": { "max_positions": 8 }
},
"tags": ["pead", "midcap", "step14", "score65"]
}
8.4 개선 워크플로우
1. 실험 config 생성 configs/experiments/my_experiment.json
2. 3-split 백테스트 실행 for split in train valid test; do ... done
3. Journal에 기록 fithia2 rec -e my_experiment ...
4. Leaderboard 확인 fithia2 lb
5. 다음 실험 계획 verdict + SQS breakdown 기반
6. 중복 실험 확인 fithia2 dup -e my_experiment
7. 1번부터 반복
8.5 Tracker CLI
pip install -e . 후 fithia2 명령어로 실행. --journal-dir / --runs-dir 생략 시 기본값(journal/, runs/) 사용.
# 도움말
fithia2
# 리더보드 출력 (top 10)
fithia2 lb
# 리더보드 — 상위 N개
fithia2 lb -n 20
# 실험 결과 기록
fithia2 rec \
-e pead_midcap_step14_score65 \
-H "Score threshold 0.60→0.65" \
-b pead_midcap_step13_best \
-v better \
-r "Test SQS 64.2 > 57.7, Return +0.73% > +0.43%" \
-n "Test exit tuning on top of score 0.65"
# 엔트리 상세 조회
fithia2 s IMP-0015
# 중복 실험 확인
fithia2 dup -e my_experiment_name
| 명령 | alias | 설명 |
|---|---|---|
leaderboard |
lb |
SQS 순위표 출력 및 LEADERBOARD.md 재생성 |
record |
rec |
실험 결과를 저널에 기록 |
show |
s |
특정 저널 항목 상세 조회 |
check-duplicate |
dup |
동일 실험명 중복 여부 확인 |
8.6 핵심 발견사항
21개 실험을 통해 얻은 인사이트:
| 발견 | 설명 |
|---|---|
| Score threshold가 가장 강력한 레버 | 0.60→0.65로 올리면 SQS 50.2→64.2 (+28%) |
| 넓은 funnel은 OOS에서 실패 | reaction 0.10→0.07로 낮추면 거래 수는 늘지만 품질 하락 |
| Exit 튜닝은 한계적 | target/fraction/hold 변경은 noise 범위 내 |
| 조합이 개별보다 나쁨 | 한계적 개선들을 합치면 과적합 리스크로 오히려 하락 |
| 단순함이 최고 | Step14(score 0.65만 변경)가 모든 복합 변형보다 우수 |
| 라지캡 확장 실패 | $10B+ 대형주에서는 OOS 성과 없음, 미드캡이 최적 |
| 보유기간 5~7일 최적 | PEAD 드리프트의 평균 보유는 3.28일 |
9. 현재 개발 현황
Phase별 진행 상태
| Phase | 이름 | 상태 | 설명 |
|---|---|---|---|
| Phase 0 | 전략/운용 명세 동결 | 완료 | strategy_spec.md, risk_policy.md, data_source_policy.md, event_taxonomy.md |
| Phase 1 | 개발 기반 & DB 스키마 | 완료 | Docker, PostgreSQL, Alembic, adapter contracts, 공통 인프라 |
| Phase 2 | 핵심 데이터 수집 | 완료 | SEC, Alpaca(→Stock Oracle), FRED, FINRA 어댑터 구축 |
| Phase 3 | 문서 파서 & 피처 빌더 | 완료 | 규칙 기반 파서 + LLM 보강, 피처 엔지니어링, 라벨 생성 |
| Phase 4 | 백테스트 엔진 | 완료 | 이벤트 드리븐 시뮬레이터, walk-forward CV, SQS 스코어링, 21개 지표 |
현재 작동 중인 것
- 백테스트 엔진 (이벤트 드리븐, 재현 가능, 21개 지표)
- Walk-forward cross-validation (train/valid/test 분할)
- 실험 추적 (Journal, Leaderboard, SQS 스코어링)
- PEAD 전략 (주력 신호, SQS 64.2, +0.73% OOS)
- 단위/통합 테스트 (270개+ 자동화)
- 포트폴리오 리스크 엔진 (포지션 사이징, 섹터 제한, stop/target)
- 데이터 파이프라인 (filing_poller → event_parser → feature_builder → dataset_export)
10. 현재 최고 전략 성과
Leaderboard (Top 10, 2026-03-17 기준)
| # | Experiment | SQS | PF | Ret% | WR | Sharpe | DD% | Trades |
|---|---|---|---|---|---|---|---|---|
| 1 | pead_midcap_step14_score65 | 64.2 | 1.22 | +0.7 | 57% | 1.3 | 0.9 | 72 |
| 2 | pead_midcap_step18_nofrac | 63.2 | 1.23 | +0.8 | 52% | 1.4 | 0.9 | 64 |
| 3 | pead_midcap_step19_hold5 | 62.9 | 1.20 | +0.7 | 57% | 1.2 | 0.9 | 72 |
| 4 | pead_midcap_step20_best3 | 62.0 | 1.22 | +0.7 | 52% | 1.3 | 0.9 | 64 |
| 5 | pead_midcap_step17_target2 | 59.4 | 1.18 | +0.6 | 53% | 1.1 | 0.8 | 66 |
| 6 | pead_midcap_step13_best | 57.7 | 1.12 | +0.4 | 55% | 0.8 | 0.9 | 75 |
| 7 | pead_midcap_step16_react7_score65 | 53.2 | 0.97 | -0.1 | 56% | -0.2 | 1.6 | 89 |
| 8 | pead_midcap_step5_maxcand3 | 52.5 | 0.95 | -0.2 | 54% | -0.4 | 1.4 | 96 |
| 9 | pead_midcap_step15_react7 | 51.7 | 0.94 | -0.3 | 55% | -0.5 | 1.6 | 91 |
| 10 | pead_midcap_step11_score60 | 50.2 | 1.02 | +0.1 | 52% | 0.2 | 0.9 | 77 |
최고 전략: pead_midcap_step14_score65
SQS: 64.2 (Good — OOS edge 확인)
수익률: +0.73% (OOS test)
PF: 1.22
승률: 56.9%
Sharpe: 1.3
최대낙폭: 0.9%
거래 수: 72
보유기간: 평균 3.28일
핵심 설정:
- reaction threshold: 10% (어닝 발표 후 첫날 10% 이상 반응한 종목만)
- score threshold: 0.65 (PEAD 스코어 0.65 이상만 진입)
- volume threshold: 2.0x (평균 대비 2배 이상 거래량)
- max candidates/day: 3 (하루 최대 3개 후보)
- max holding: 7일
- earnings_release만 활성화 (다른 이벤트 타입 비활성화)
11. 설치 및 실행
요구사항
- Python 3.11+
- PostgreSQL 16 (Docker 제공)
- Stock Oracle API (Docker, localhost:18001)
설치
# 의존성 설치
pip install -e ".[dev]"
# PostgreSQL 시작
docker compose up -d
# DB 마이그레이션
alembic upgrade head
# 환경 변수 설정
cp .env.example .env
환경 변수
| 변수 | 기본값 | 설명 |
|---|---|---|
STOCK_ORACLE_URL |
http://localhost:18001 |
Stock Oracle API 엔드포인트 |
POSTGRES_DSN |
postgresql+asyncpg://acef:acef@localhost:5432/acef |
DB 연결 |
DATA_ROOT |
./data |
데이터 저장 루트 |
LOG_LEVEL |
INFO |
로그 레벨 |
LLM_ENABLED |
false |
LLM 문서 파싱 활성화 |
Makefile 타겟
make bootstrap # 의존성 설치
make db-upgrade # 마이그레이션 실행
make db-reset # DB 전체 리셋
make test-unit # 단위 테스트만
make test-integration # 통합 테스트 (PostgreSQL 필요)
make test-replay # 결정론 테스트
make lint # Ruff 린트
make typecheck # MyPy 엄격 모드
make ci # 전체 CI (lint + typecheck + test)
12. 사용법
데이터 파이프라인 실행
# 1) 기업 메타데이터 동기화
python -m apps.sync.issuer_sync.main
# 2) 공시 수집 → 파싱 → 피처 빌드 → 라벨 생성
python -m apps.pipeline.filing_poller.main
python -m apps.pipeline.filing_fetcher.main
python -m apps.pipeline.event_parser.main
python -m apps.pipeline.feature_builder.main
python -m apps.pipeline.label_generator.main
# 3) 백테스트용 Parquet 스냅샷 내보내기
python -m apps.pipeline.dataset_export.main
백테스트 실행
# 3-split 백테스트 (train/valid/test)
for split in train valid test; do
python -m apps.backtester.run \
--manifest configs/experiments/return_max_long_v1.51.json \
--split $split \
--snapshot-dir data/datasets/snapshots \
--output-root runs/return_max_long_v1.51
done
주의: Stock Oracle API는 단일 스레드이므로 백테스트를 순차적으로 실행해야 합니다. 병렬 실행 시 API가 과부하되어 연결이 끊깁니다.
Paper Backtest (과거 기간 시뮬레이션)
# 단일 전략 backtest (연도 지정 — 1월 1일~12월 31일, 올해는 어제까지)
fithia2 paper backtest \
--config configs/experiments/return_max_long_v6new.9.json --year 2025
# 리더보드 top 5 전략 비교
fithia2 paper backtest --top 5 --year 2025
# 리더보드 rank 범위 지정 (20~40위)
fithia2 paper backtest --rank 20-40 --year 2025
# 날짜 범위 직접 지정 (YYYY-MM-DD 또는 YYYY)
fithia2 paper backtest --top 3 --start 2025-06-01 --end 2026-03-23
# 복수 전략 비교 + trade log 숨김 + CSV 저장
fithia2 paper backtest \
--config configs/experiments/return_max_long_v6new.9.json \
--config configs/experiments/return_max_long_v6.92.json \
--capital 10000 --year 2025 \
--no-trades --output ./bt_results/
# Overlay 전략 backtest (명시적 지정 필요)
fithia2 paper backtest \
--overlay configs/overlays/return_book_overlay_v3.json \
--year 2025 --no-trades
| 옵션 | 설명 |
|---|---|
--config, -c |
전략 config 경로 (반복 가능) |
--overlay |
Overlay config 경로 (반복 가능) |
--top, -t N |
리더보드 SQS 상위 N개 자동 선택 |
--rank START-END |
리더보드 rank 범위 선택 (예: 20-40, 5) |
--capital, -k |
전략별 초기 자본 (기본: $10,000) |
--year, -y |
연도 지정 (= --start YYYY --end YYYY) |
--start |
시작일 (YYYY-MM-DD, YYYY-MM, YYYY) |
--end |
종료일 (YYYY-MM-DD, YYYY-MM, YYYY; 올해면 어제까지) |
--no-trades |
Trade log 출력 생략 (Summary만) |
--output, -o |
CSV 저장 디렉토리 |
Paper Trading (실시간 운영)
Alpaca Paper Trading 계좌를 통한 실시간 전략 실행. 환경변수 ALPACA_API_KEY / ALPACA_SECRET_KEY 필요.
# 세션 생성 (전략 config + 초기 자본 지정)
fithia2 paper create \
--name my_session \
--config configs/experiments/return_max_long_v6new.9.json \
--capital 10000
# 세션 목록 및 상태 확인
fithia2 paper list
fithia2 paper status # 전체 세션 요약
fithia2 paper status --session my_session
# 당일 처리 실행 (종일 단일 실행 방식)
fithia2 paper run --session my_session
# 분리 실행 방식 (3:40 PM, 9:30 AM 두 번 실행)
fithia2 paper run-close --session my_session # 장 마감 전: same-day MOC 진입
fithia2 paper run-open --session my_session # 장 시작 후: 전날 exit + after-close 진입
# 포지션 및 거래 내역 확인
fithia2 paper positions # 전체 세션 오픈 포지션
fithia2 paper trades # 최근 거래 내역
fithia2 paper equity # 세션별 수익 곡선
# 세션 종료
fithia2 paper close --session my_session
Reconciliation (자동 불일치 감지)
run / run-open 실행 시 매일 자동으로 Alpaca ↔ 로컬 DB 정합성 검증:
| 상황 | 감지 방식 | 처리 |
|---|---|---|
| Orphaned position | Alpaca에 있지만 로컬 DB에 없음 (주문 체결 후 DB 저장 실패 등) | WARNING 로그, 수동 확인 필요 |
| Ghost position | 로컬 DB에 있지만 Alpaca에 없음 (수동 청산, 주문 미체결 등) | 자동으로 로컬 상태 닫고 RECONCILED 거래 기록 |
| Stale orders | 전일 미체결 주문 | 자동 취소 |
| Order fill verify | 시장가 주문 체결 여부 확인 (2초 polling) | 미체결 시 로컬 상태 저장 skip |
Kill Switch
drawdown이 초기 자본 대비 25% 이상 떨어지면 자동 발동:
- 당일 부터 모든 신규 진입 차단
fithia2 paper status에서Kill Switch: ON표시- 수동으로만 해제 가능
실험 결과 기록
# Journal에 기록
fithia2 rec \
-e pead_midcap_step14_score65 \
-H "Score threshold 0.60→0.65" \
-b pead_midcap_step13_best \
-v better \
-r "Test SQS 64.2 > 57.7" \
-n "Exit tuning on top of score 0.65"
# 리더보드 확인
fithia2 lb
테스트
# 단위 테스트 (빠름, 외부 의존성 없음)
pytest tests/unit/ -v
# 백테스트 모듈 테스트
pytest tests/unit/backtest/ -v
# 통합 테스트 (PostgreSQL 필요)
pytest tests/integration/ -v
# 전체 CI
make ci
13. 기술 스택
| 구성 요소 | 기술 |
|---|---|
| 언어 | Python 3.11+ |
| 도메인 모델 | Pydantic v2 |
| 운영 DB | PostgreSQL 16 + async SQLAlchemy + asyncpg |
| 연구 데이터 | DuckDB + Apache Parquet |
| 마이그레이션 | Alembic |
| HTTP 클라이언트 | httpx (비동기) |
| 컨테이너 | Docker Compose |
| 린트 | Ruff (line 100, Python 3.11+) |
| 타입 체크 | MyPy (strict mode) |
| 테스트 | Pytest + pytest-asyncio (270+ 테스트) |
| 로깅 | structlog (JSON) |
| LLM | Ollama (인프라 구현, 파서 비활성화) |
| 문서 파싱 | BeautifulSoup4 + 규칙 기반 + LLM |
| 거래일 캘린더 | exchange-calendars |
14. 데이터 소스
| 소스 | 역할 | 계층 | 비용 |
|---|---|---|---|
| SEC EDGAR | 이벤트 원천 (8-K, 10-Q, 6-K 공시) | Core | 무료 |
| Stock Oracle API | 시장 데이터 (OHLCV, 기업정보, 재무) | Core | 내부 |
| FRED | 거시 레짐 (금리, 스프레드, 경기 지표) | Core | 무료 |
| FINRA | 공매도 잔량 (crowding 신호) | 보조 | 무료 |
데이터 정책
- 모든 시장 데이터는 Stock Oracle API를 통해서만 접근 — 직접 외부 API 호출 금지
- API 부재 기능은 구현 대신 보고
- 유료 데이터 소스 사용 금지
- LLM은 문서 해석기로만 사용, 가격 예측 금지
License
Private project. All rights reserved.