출시된 잠긴 봇 스냅샷을 검증된 시장 데이터로 재현 가능하게 백테스트하기 위한 Python 저장소입니다.
이 문서는 현재 저장소에 실제로 존재하는 것만 기술합니다.
src/backtest_engine/
api.py # 인증·소유자 범위를 적용한 /api/v1 HTTP API
worker.py # SQS 소비, 재전달, 실행 키 CAS, DLQ, 취소 ack
contracts.py # 요청/결과 계약 검증
execution_policy.py # 실행 정책 카탈로그
lifecycle.py # 접수·큐 발행·결과 상태 전이
attempt_coordinator.py # 시도, 리스, 재시도, 취소 조정
event_clock.py # XNYS 정규장 세션 시계
data_availability.py # 입력 가용성 판정
basic_runtime.py # BASIC 컴파일 계획 평가
execution_model.py # 주문·체결·비용 모델
market_data.py # Parquet 시장데이터 리더
feature_outputs.py # 고정된 feature materialization 검증·로딩
orchestrator.py # 결정론적 이벤트 재생과 결과 발행
wiring.py # API/worker/오케스트레이터 조립
production.py # PostgreSQL, S3, HTTP 운영 어댑터
monthly_judgment.py # 월별 판정 요약
result_snapshot.py # 요약·상세 결과 스냅샷 빌더
object_store/ # 상세 Parquet와 매니페스트 경계
result_query.py # 소유자 범위 조회 프로젝션
persistence/ # SQLAlchemy Core 영속성 및 스키마 가드
표 데이터 처리는 PyArrow를 사용합니다.
- API 또는 요청 intake가 봇 스냅샷, 컴파일 계획, 시장 데이터/feature 해시를 고정합니다.
- worker가 SQS 메시지를 받고
worker_execution_keyCAS로 중복 실행을 차단합니다. - 오케스트레이터가 고정된 Parquet를 읽고 정규장 세션별
BAR_CLOSED이벤트를 만듭니다. - BASIC 런타임이 봉 종료 시점까지 알려진 값만 사용해 신호를 평가합니다.
- 실행 모델이 다음 체결 가능 시점부터 주문을 처리하고 슬리피지·수수료를 적용합니다.
- 성과, 월별 판정, 상세 Parquet를 만들고 DB와 오브젝트 결과를 발행합니다.
COMPLETED,FAILED,UNAVAILABLE,CANCELLED결과를 API로 전달하고 큐 메시지를 성공, 재시도, DLQ 또는 취소 ack로 마무리합니다.
재현성 경계는 스냅샷 해시, 입력 번들 fingerprint, 실행 정책 버전, 시장 데이터 및 feature materialization 결과 해시입니다. 같은 입력은 같은 이벤트 순서와 replay digest를 가져야 합니다.
| 입력 | ISO-8601 | 동작 |
|---|---|---|
30m |
PT30M |
30분 봉 |
1h |
PT1H |
1시간 봉 |
4h |
PT4H |
4시간 봉. 정규장 종료를 넘는 마지막 봉은 장 마감에서 잘립니다 |
1d |
PT24H |
거래일 정규장 1개를 한 봉으로 취급합니다 |
새로 발행되는 전략은 위 네 주기 중 하나만 사용할 수 있습니다. 1m, 5m, 15m는 활성
카탈로그에서 제거되었으며, 이미 릴리스된 bot을 동일하게 재현할 때만 구 catalog reader가
해석합니다. 모든 주기는 UTC timestamp를 쓰되, 거래 가능 여부와 거래일은 XNYS 정규장(ET)
기준입니다. 공급자가 일봉 시작을 자정으로
표시해도 session_date_et의 정규장 시가/종가로 정규화합니다.
4시간 봉처럼 세션 끝에서 짧아진 봉은 session_truncated=true인 경우에만 허용합니다.
봉 종료로 생성된 신호는 그 봉에 소급 체결하지 않습니다. 특히 일봉과 세션 마지막 봉의
신호는 다음 정규장 시가부터 주문 체결 대상이 됩니다.
- API는
/api/v1접수·목록·상세·시도·성과·월별 요약·상세 매니페스트·입력·결과 수신을 제공하고 인증 및 소유자 범위를 적용합니다. - worker는 SQS long poll, visibility heartbeat, 재전달, DLQ, 중복 실행 방지를 구현합니다.
취소는 실패가 아니므로 DLQ로 보내지 않고
CANCELLED로 저장한 뒤 메시지를 삭제합니다. - 소유자는
POST /api/v1/backtests/{runId}/cancellation으로 취소를 요청합니다.QUEUED는 즉시 취소되고RUNNING은 worker 안전 지점에서 협력 취소되며 요청·완료 시각이 보존됩니다. - 운영 어댑터는 PostgreSQL, S3 versioned object, 결과 수신 HTTP를 연결합니다.
- 런타임은 long-only 주문 모델입니다. 공매도와 정규장 외 체결은 지원하지 않습니다.
basic-elements:2026-08-08의 전체 14개 블록과 주문 비율·최대 실행·재진입 대기 의미는 live virtual trading runtime과 동일하게 구현됩니다. 두 서비스는 별도 배포 단위이므로 정확히 호환되는 root submodule pointer를 하나의 release candidate로 검증해야 합니다.
Python 3.12 (>=3.12,<3.13) 전용입니다.
python -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"
.venv\Scripts\python -m pytest # Docker 없는 빠른 단위 스위트
.venv\Scripts\python -m pytest -m docker # Testcontainers PostgreSQL 16 통합
.venv\Scripts\python -m ruff check src tests
.venv\Scripts\python -m mypy
.venv\Scripts\backtest-api # 환경변수 필요, 아래 참조
기본 pytest 실행은 -m 'not docker' 로 설정되어 있어 Docker를 건드리지 않습니다.
-m docker 를 주면 그 설정을 덮어써 통합 스위트만 실행합니다.
backtest_engine.wiring.API_REQUIRED_ENV 가 정본 목록입니다. 하나라도 없으면 프로세스는
누락된 이름을 전부 한 번에 알려주고 기동을 거부합니다. 기본값은 하나도 없습니다.
| 변수 | 값 |
|---|---|
BACKTEST_DATABASE_URL |
SQLAlchemy URL |
BACKTEST_QUEUE_URL |
작업 SQS 큐 URL |
BACKTEST_API_HOST / BACKTEST_API_PORT |
bind 주소 |
BACKTEST_AUTHENTICATOR |
package.module:factory → api.Authenticator |
BACKTEST_OBJECT_STORE |
package.module:factory → object_store.ObjectStore |
BACKTEST_OWNER_DIRECTORY |
package.module:factory → lifecycle.OwnerDirectory |
BACKTEST_COMPILED_PLAN_SOURCE |
package.module:factory → lifecycle.CompiledPlanSource |
BACKTEST_DATASET_MANIFEST_SOURCE |
package.module:factory → lifecycle.DatasetManifestSource |
BACKTEST_EXECUTION_POLICY_CATALOG |
package.module:factory → ExecutionPolicyCatalog |
BACKTEST_DEAD_LETTER_SINK |
package.module:factory → lifecycle.DeadLetterSink |
AWS_REGION/AWS_DEFAULT_REGION 과 AWS_ENDPOINT_URL 은 boto3 자체 설정입니다.
기동 순서는 구성 → 스키마 검증 → 서비스 입니다. 런타임은 DDL을 실행하지 않으므로 스키마 drift 는 복구 대상이 아니라 기동 실패 사유입니다.
backtest-worker 는 BACKTEST_QUEUE_URL, BACKTEST_DLQ_URL, BACKTEST_WORKER_ID,
BACKTEST_JOB_HANDLER, BACKTEST_EXECUTION_KEY_STORE 를 모두 요구합니다.
BACKTEST_EXECUTION_KEY_STORE 는 더 이상 선택 사항이 아닙니다. 비워 두면 프로세스 지역
딕셔너리(InMemoryExecutionKeyStore)로 조용히 대체되어, 이 모듈이 존재하는 이유인
프로세스 간 중복 실행 방지가 사라집니다.
자세한 경계는 DEVELOPMENT.md, 마이그레이션 기여 규약은 db/migration-contributions/README.md 를 확인합니다.