You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
6.1 KiB
Markdown
265 lines
6.1 KiB
Markdown
# Phase 2 데이터 수집 아키텍처
|
|
|
|
## 1. 목적
|
|
|
|
Phase 2의 목적은 **전략 판단 이전 단계의 데이터 공급 계층을 완성**하는 것입니다.
|
|
이 단계에서 만드는 시스템은 다음 성질을 만족해야 합니다.
|
|
|
|
1. **재실행 가능**해야 한다.
|
|
2. **부분 실패에 안전**해야 한다.
|
|
3. **원문(raw)을 보존**해야 한다.
|
|
4. **정규화와 적재가 분리**되어야 한다.
|
|
5. **체크포인트 기반 증분 수집**이 가능해야 한다.
|
|
6. **백필과 운영 실행이 동일한 코드 경로**를 사용해야 한다.
|
|
|
|
## 2. 상위 구조
|
|
|
|
```text
|
|
External Sources
|
|
├─ SEC EDGAR / data.sec.gov
|
|
├─ Alpaca Market Data
|
|
├─ FRED API
|
|
└─ FINRA Daily Short Sale Volume
|
|
|
|
↓
|
|
[Source Adapter Layer]
|
|
- source client
|
|
- fetch policy
|
|
- raw payload writer
|
|
- source checksum
|
|
|
|
↓
|
|
[Raw Zone]
|
|
- immutable payload files
|
|
- fetch metadata sidecar
|
|
|
|
↓
|
|
[Normalizer / Extractor Layer]
|
|
- canonical field mapping
|
|
- record decomposition
|
|
- validation
|
|
|
|
↓
|
|
[Staging Zone]
|
|
- parseable intermediate outputs
|
|
- extracted metadata
|
|
- entity identifiers
|
|
|
|
↓
|
|
[Structured Writer Layer]
|
|
- PostgreSQL upsert
|
|
- Parquet append/replace partition
|
|
- dedupe / idempotency guard
|
|
|
|
↓
|
|
[Operational State]
|
|
- job_runs
|
|
- checkpoints
|
|
- source_status
|
|
- write_manifest
|
|
```
|
|
|
|
## 3. 처리 단위
|
|
|
|
모든 수집 작업은 **job + run_id + source checkpoint** 단위로 동작합니다.
|
|
|
|
### 3.1 Job
|
|
|
|
예:
|
|
- `sec_submissions_poll`
|
|
- `sec_filing_fetch`
|
|
- `sec_xbrl_extract`
|
|
- `alpaca_daily_bars_backfill`
|
|
- `alpaca_intraday_bars_poll`
|
|
- `fred_series_sync`
|
|
- `finra_short_volume_fetch`
|
|
|
|
### 3.2 Run ID
|
|
|
|
모든 실행은 고유한 `run_id`를 가져야 하며,
|
|
raw sidecar / job_runs / structured manifest에 동일하게 남겨야 합니다.
|
|
|
|
예시:
|
|
- `2026-03-12T21:05:14Z_sec_submissions_poll_001`
|
|
|
|
### 3.3 Checkpoint
|
|
|
|
각 source/job 조합은 다음 형태의 체크포인트를 가져야 합니다.
|
|
|
|
- 시간 기반: 마지막 성공 시각
|
|
- 페이지 기반: 마지막 page token / cursor
|
|
- 파일 기반: 마지막 accession / filename / date
|
|
- 심볼 기반: 마지막 심볼/날짜 조합
|
|
|
|
## 4. 계층별 책임
|
|
|
|
### 4.1 Source Adapter
|
|
|
|
역할:
|
|
- 외부 API/file endpoint 요청
|
|
- response 수신
|
|
- raw payload 저장
|
|
- sidecar 메타데이터 기록
|
|
- 최소 검증(응답 비어 있음, 상태코드 오류, checksum 등)
|
|
|
|
금지:
|
|
- 전략 점수 계산
|
|
- event classification
|
|
- feature engineering
|
|
|
|
### 4.2 Normalizer / Extractor
|
|
|
|
역할:
|
|
- source-specific payload를 canonical schema로 변환
|
|
- 필요한 key field 추출
|
|
- 식별자 생성
|
|
- staging output 생성
|
|
|
|
예:
|
|
- SEC filing index에서 accession, filing_date, form_type, exhibit list 추출
|
|
- Alpaca bars 응답을 symbol/timestamp/ohlcv schema로 변환
|
|
- FRED series response를 series_id/date/value schema로 변환
|
|
- FINRA txt를 symbol/date/short_volume/total_volume schema로 변환
|
|
|
|
### 4.3 Structured Writer
|
|
|
|
역할:
|
|
- PostgreSQL upsert
|
|
- Parquet partition write
|
|
- write manifest 기록
|
|
- 중복 write 방지
|
|
|
|
### 4.4 Data Quality Validator
|
|
|
|
역할:
|
|
- null 비율 검사
|
|
- 날짜/시간 일관성 검사
|
|
- primary key uniqueness 검사
|
|
- partition completeness 검사
|
|
- source freshness 검사
|
|
|
|
## 5. 원칙
|
|
|
|
### 5.1 Raw First
|
|
|
|
원문 저장이 실패하면 downstream 단계는 진행하지 않습니다.
|
|
|
|
### 5.2 Deterministic Output
|
|
|
|
동일 input payload는 동일 normalized output을 만들어야 합니다.
|
|
|
|
### 5.3 Idempotent Writes
|
|
|
|
동일 raw payload를 다시 처리해도 structured 결과가 중복되면 안 됩니다.
|
|
|
|
### 5.4 Explicit Status Transition
|
|
|
|
작업 상태는 아래처럼 명시적으로 이동해야 합니다.
|
|
|
|
```text
|
|
created
|
|
→ running
|
|
→ raw_saved
|
|
→ staged
|
|
→ structured_written
|
|
→ validated
|
|
→ completed
|
|
```
|
|
|
|
실패 시:
|
|
|
|
```text
|
|
running
|
|
→ failed_retriable
|
|
or
|
|
running
|
|
→ failed_terminal
|
|
```
|
|
|
|
## 6. 체크포인트 전략
|
|
|
|
### 6.1 SEC
|
|
|
|
- `submissions poll`: 마지막 성공 시각 + 최근 처리 accession 목록
|
|
- `filing fetch`: accession 단위 완료 플래그
|
|
- `xbrl extract`: accession + taxonomy 버전 단위 완료 플래그
|
|
|
|
### 6.2 Alpaca
|
|
|
|
- 심볼 / timeframe / trading_date 단위 완료 플래그
|
|
- intraday poll은 마지막 bar timestamp 기록
|
|
|
|
### 6.3 FRED
|
|
|
|
- series_id / latest observation date
|
|
|
|
### 6.4 FINRA
|
|
|
|
- trading_date 파일 존재 여부 + checksum
|
|
|
|
## 7. 재시도 정책
|
|
|
|
### 7.1 공통
|
|
|
|
- 네트워크 오류: exponential backoff
|
|
- 응답 5xx: 재시도 가능
|
|
- 응답 4xx: 기본은 terminal, 단 rate-limit 계열은 retriable
|
|
- schema validation 실패: terminal
|
|
- raw write 실패: retriable
|
|
- structured deadlock/connection error: retriable
|
|
|
|
### 7.2 최대 재시도
|
|
|
|
기본값:
|
|
- 즉시 재시도 3회
|
|
- 이후 다음 scheduler tick에 다시 시도
|
|
- 같은 payload가 3번 연속 schema validation 실패 시 quarantine
|
|
|
|
## 8. Quarantine
|
|
|
|
아래 경우 quarantine 디렉터리와 quarantine 테이블에 기록합니다.
|
|
|
|
- parsing 불가 raw
|
|
- schema violation raw
|
|
- 필수 식별자 누락
|
|
- 비정상적으로 큰 payload
|
|
- source format drift 의심
|
|
|
|
경로 예시:
|
|
|
|
```text
|
|
data/quarantine/sec/2026-03-12/{run_id}/...
|
|
```
|
|
|
|
## 9. 운영 상태 저장
|
|
|
|
PostgreSQL에는 최소 아래가 필요합니다.
|
|
|
|
- `job_runs`
|
|
- `source_checkpoints`
|
|
- `raw_objects`
|
|
- `write_manifests`
|
|
- `data_quality_results`
|
|
- `quarantine_records`
|
|
|
|
세부 컬럼은 Phase 1의 `db_schema.md`를 따르되, Phase 2에서 필요한 상태 컬럼을 추가합니다.
|
|
|
|
## 10. 구성 요소별 구현 우선순위
|
|
|
|
1. SEC submissions / filing fetch
|
|
2. Alpaca daily bars
|
|
3. FRED series sync
|
|
4. FINRA short volume
|
|
5. Alpaca intraday bars
|
|
6. SEC XBRL extract
|
|
|
|
이 순서가 중요한 이유는,
|
|
전략 연구의 최소 요건이 **이벤트 원문 + 일봉 가격 + 거시 레짐 + crowding 보조지표**이기 때문입니다.
|
|
|
|
## 11. Phase 2 성공 기준
|
|
|
|
- 하루치 수집이 아니라, **기간 백필**이 안전하게 가능해야 합니다.
|
|
- 새 실행과 재실행이 동일한 코드 경로를 타야 합니다.
|
|
- raw/staging/structured 간 lineage를 역추적할 수 있어야 합니다.
|
|
- 운영자가 특정 거래일의 데이터 누락 원인을 추적할 수 있어야 합니다.
|