# 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를 역추적할 수 있어야 합니다.
- 운영자가 특정 거래일의 데이터 누락 원인을 추적할 수 있어야 합니다.
