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.

6.8 KiB

Phase 2 저장 구조 및 데이터 계약

1. 목적

이 문서는 Phase 2 수집 파이프라인이 쓰는 파일 경로 규칙, raw sidecar 형식, staging canonical schema, structured write 규칙을 정의합니다.

핵심 목표는 아래와 같습니다.

  1. 모든 raw 파일의 출처와 실행(run)을 추적할 수 있어야 한다.
  2. 모든 staging/structured 레코드가 원문(raw)로 역추적 가능해야 한다.
  3. 파일명/경로만 보고 source, date, object type을 알 수 있어야 한다.
  4. 재실행 시 같은 경로/키 체계를 사용해야 한다.

2. Raw 저장 규칙

2.1 공통 경로 형식

data/raw/{source}/{ingestion_date}/{object_scope}/...

예시:

data/raw/sec/2026-03-12/cik_0000789019/0001193125-26-027198/submissions.json
data/raw/sec/2026-03-12/cik_0000789019/0001193125-26-027198/filing.txt
data/raw/sec/2026-03-12/cik_0000789019/0001193125-26-027198/exhibit_99_1.html

data/raw/alpaca/2026-03-12/daily/AAPL.json

data/raw/fred/2026-03-12/series/DGS10.json

data/raw/finra/2026-03-12/short_volume/2026-03-11.txt

2.2 Sidecar 메타데이터

각 raw object마다 .meta.json sidecar를 생성합니다.

예:

submissions.json
submissions.json.meta.json

2.3 Sidecar 필수 필드

{
  "run_id": "2026-03-12T21:05:14Z_sec_submissions_poll_001",
  "job_name": "sec_submissions_poll",
  "source": "sec",
  "source_url": "https://...",
  "http_status": 200,
  "fetched_at": "2026-03-12T21:05:14Z",
  "content_type": "application/json",
  "payload_bytes": 18293,
  "sha256": "...",
  "mode": "poll",
  "source_identifier": {
    "cik": "0000789019",
    "accession": "0001193125-26-027198"
  },
  "parser_hint": {
    "object_type": "sec_submissions"
  }
}

2.4 Raw 쓰기 원칙

  • 임시 파일에 먼저 씁니다.
  • checksum 계산 후 원자적 rename을 합니다.
  • sidecar까지 성공해야 raw 저장 성공으로 간주합니다.
  • sidecar 저장 전에는 job_runs.status = raw_saved로 올리지 않습니다.

3. Staging 저장 규칙

staging은 파싱/정규화의 중간 결과입니다.

경로 형식:

data/staging/{source}/{logical_date}/{object_type}/{entity_key}.jsonl

예시:

data/staging/sec/2026-03-12/filing_headers/cik_0000789019.jsonl
data/staging/sec/2026-03-12/exhibit_inventory/0001193125-26-027198.jsonl

data/staging/alpaca/2026-03-12/daily_bars/AAPL.jsonl

data/staging/fred/2026-03-12/series/DGS10.jsonl

data/staging/finra/2026-03-12/short_volume/2026-03-11.jsonl

원칙:

  • staging은 재생성 가능 데이터입니다.
  • raw가 진실의 원천이고, staging은 파생 데이터입니다.
  • staging은 overwrite 가능하지만 lineage가 남아야 합니다.

4. Canonical Record 계약

4.1 SEC Document Header Record

{
  "document_id": "sec:0001193125-26-027198",
  "source": "sec",
  "cik": "0000789019",
  "accession": "0001193125-26-027198",
  "form_type": "8-K",
  "filing_date": "2026-01-28",
  "acceptance_datetime": "2026-01-28T16:13:02Z",
  "primary_document": "msft-8k.htm",
  "has_xbrl": true,
  "raw_path": "data/raw/.../filing.txt",
  "raw_sha256": "...",
  "run_id": "..."
}

4.2 SEC Exhibit Record

{
  "artifact_id": "sec_artifact:0001193125-26-027198:ex99_1",
  "document_id": "sec:0001193125-26-027198",
  "artifact_name": "ex99_1.htm",
  "artifact_type": "exhibit_99_1",
  "mime_type": "text/html",
  "raw_path": "data/raw/.../exhibit_99_1.html",
  "raw_sha256": "...",
  "run_id": "..."
}

4.3 Alpaca Canonical Bar Record

{
  "source": "alpaca",
  "symbol": "AAPL",
  "timeframe": "1D",
  "ts": "2026-03-11T21:00:00Z",
  "trading_date": "2026-03-11",
  "open": 212.31,
  "high": 214.05,
  "low": 211.62,
  "close": 213.98,
  "volume": 48761234,
  "trade_count": 302119,
  "vwap": 213.12,
  "raw_path": "data/raw/.../AAPL.json",
  "raw_sha256": "...",
  "run_id": "..."
}

4.4 FRED Observation Record

{
  "source": "fred",
  "series_id": "DGS10",
  "observation_date": "2026-03-11",
  "value": 4.13,
  "frequency": "Daily",
  "units": "Percent",
  "raw_path": "data/raw/.../DGS10.json",
  "raw_sha256": "...",
  "run_id": "..."
}

4.5 FINRA Short Volume Record

{
  "source": "finra",
  "trade_date": "2026-03-11",
  "symbol": "AAPL",
  "short_volume": 14122112,
  "total_volume": 42211884,
  "short_volume_ratio": 0.3345,
  "raw_path": "data/raw/.../2026-03-11.txt",
  "raw_sha256": "...",
  "run_id": "..."
}

5. Structured Write 규칙

5.1 PostgreSQL

운영 상태/메타데이터는 PostgreSQL에 저장합니다.

대표 테이블:

  • job_runs
  • source_checkpoints
  • raw_objects
  • documents
  • document_artifacts
  • xbrl_facts
  • macro_series_observations
  • short_sale_volume_daily

규칙:

  • 운영 테이블은 upsert 기반
  • natural key 또는 idempotency key를 반드시 둠
  • created_at, updated_at, run_id 필수

5.2 Parquet

대량 시계열/분석용 데이터는 Parquet로 적재합니다.

경로 예시:

data/parquet/market_bars_daily/trading_date=2026-03-11/part-000.parquet
data/parquet/market_bars_intraday/trading_date=2026-03-11/symbol=AAPL/part-000.parquet
data/parquet/fred/series_id=DGS10/part-000.parquet
data/parquet/finra_short_volume/trade_date=2026-03-11/part-000.parquet

규칙:

  • partition overwrite는 날짜/심볼 범위 단위로 제한
  • late-arriving data는 해당 partition 재작성
  • write manifest로 어떤 partition이 언제 갱신됐는지 기록

6. Lineage 계약

모든 staging/structured 레코드는 최소 아래 필드를 가져야 합니다.

  • source
  • run_id
  • raw_path
  • raw_sha256
  • ingested_at

이 5개가 없으면 downstream에서 사용 금지입니다.

7. 상태 필드 규칙

job_runs.status는 아래 enum만 허용합니다.

  • created
  • running
  • raw_saved
  • staged
  • structured_written
  • validated
  • completed
  • failed_retriable
  • failed_terminal
  • quarantined

8. 중복 방지

중복 방지는 아래 3단계로 합니다.

  1. raw checksum 중복 검사
  2. staging natural key 중복 검사
  3. structured upsert key 검사

어느 단계에서도 중복이 발생하면 경고를 남기고 동일성 비교 후 no-op 처리합니다.

9. 운영자가 빠르게 확인해야 할 경로

최소 아래 경로는 사람이 쉽게 찾을 수 있어야 합니다.

  • 최근 실패 잡 로그
  • quarantine raw
  • 특정 accession 관련 raw/staging/structured lineage
  • 특정 심볼/거래일 bars 파일
  • 특정 FRED series 최근 observation

10. 완료 기준

  • 임의의 structured row에서 raw_path를 따라가면 원문을 확인할 수 있어야 합니다.
  • raw object checksum이 바뀌면 새 버전 또는 경고가 생성되어야 합니다.
  • 동일 run을 다시 실행해도 동일 natural key에 대해 중복 row가 생기지 않아야 합니다.