Skip to content

Repository files navigation

krx-data-pipeline

유지보수 가능하며 운영 환경을 고려하여 설계된 한국 주식 데이터 파이프라인입니다.

  1. FinanceDataReader 및 pykrx를 사용하여 KOSPI / KOSDAQ 종목 유니버스를 동기화합니다 (종목 마스터 관리).
  2. pykrx를 사용하여 상장일로부터 종목별 일봉(OHLCV) 이력 데이터를 수집합니다.
  3. OpenDART를 사용하여 재무제표 / 주식수 / 배당 / 자사주 raw 값과 XBRL fact를 수집합니다.
  4. KIS Developers와 KRX MDC 소스를 사용하여 일자별 수급 raw(투자자별 순매수, 공매도 등)를 수집합니다.
  5. FDR / pykrx / KRX / ECOS / FRED 기반 공통 시장·거시 feature raw를 수집합니다.
  6. PostgreSQL은 raw 수집/감사 저장소로 두고, 재무 metric 정규화와 common daily fact 같은 파생 compute는 Parquet → DuckDB 마트에서 재계산합니다.
  7. 깔끔한 포트/어댑터(Ports & Adapters) 아키텍처를 적용하여 수집 로직과 저장소 구현을 분리합니다.
  8. Rust 기반 raw PostgreSQL → Parquet exporter로 대형 raw/reference 테이블을 data_lake/raw_postgres 레이아웃에 manifest/checkpoint와 함께 내보낼 수 있습니다.

목표 제외 범위 (현재 스코프)

  • 분봉/시간봉 (Intraday) 수집은 현재 범위에서 제외됩니다. 확장 포인트는 설계되어 있으나 아직 구현되지 않았습니다.
  • Selenium은 명시적으로 사용하지 않습니다.

빠른 시작 (Quickstart)

필수 조건 (Prerequisites)

  • Python ≥ 3.12
  • uv 패키지 매니저
  • PostgreSQL (실제 운영 환경용)
  • Rust toolchain / Cargo (raw Parquet exporter 실행 또는 개발 시)

설정 (Setup)

# 1. 의존성 패키지 설치
uv sync

# 2. 환경 변수 설정
cp .env.example .env
# .env 파일을 열어 데이터베이스 계정 정보 및 설정을 수정하세요
# `dart` 계열 명령은 OPENDART_API_KEY 또는 OPENDART_API_KEYS가 반드시 설정되어야 동작합니다
# `common sync --sources ecos/fred`는 ECOS_API_KEY / FRED_API_KEY가 필요합니다
# `flows sync-kis`는 KIS_APP_KEY / KIS_APP_SECRET이 필요합니다
# `universe sync --source krx-openapi`, `prices market-cap-backfill`은 AUTH_KEYS(KRX Open API)가 필요합니다

# 3. 데이터베이스 스키마 초기화
uv run krx-collector db init

# 4. 종목 유니버스 동기화
uv run krx-collector universe sync --source krx-openapi --markets kospi,kosdaq

# 5. 일봉(OHLCV) 데이터 백필(수집) — 최초 1회: 전체 히스토리 수집
uv run krx-collector prices backfill --market all

# 5-1. 일봉 데이터 일일 증분 수집 — 두 번째 이후 실행: 마지막 저장일 이후만
uv run krx-collector prices backfill --market all --incremental

# 6. 데이터 정합성 검증 실행
uv run krx-collector validate --date 2025-01-15 --market all

계정 / 재무 / XBRL 파이프라인 (OpenDART)

OpenDART 명령은 .env의 OPENDART_API_KEY 단일 키 또는 OPENDART_API_KEYS 쉼표 구분 멀티 키를 사용합니다. 두 값을 모두 설정하면 중복을 제거한 뒤 OPENDART_API_KEYS 순서 다음에 OPENDART_API_KEY를 병합합니다. 멀티 키 실행 시 공통 executor가 키별 rate-limit, 일시 오류, 비활성 키 상태를 분류하고 가능한 경우 다른 키로 자동 전환합니다. 각 sync 명령은 동일 요청 결과가 이미 DB에 있으면 OpenDART를 다시 호출하지 않고 건너뜁니다.

# 7. OpenDART corp_code 마스터 동기화 및 ticker 매핑 검증
uv run krx-collector dart sync-corp

# 8. OpenDART 재무 raw 적재 (예: 삼성전자 2025 사업보고서 연결재무)
uv run krx-collector dart sync-financials --tickers 005930 --bsns-years 2025 --reprt-codes 11011 --fs-divs CFS

# 9. OpenDART 주식수 / 배당 / 자사주 raw 적재
uv run krx-collector dart sync-share-info --tickers 005930 --bsns-years 2025 --reprt-codes 11011

# 10. OpenDART XBRL ZIP 파싱 및 fact raw 적재
uv run krx-collector dart sync-xbrl --tickers 005930 --bsns-years 2025 --reprt-codes 11011

전체 사업연도 백필은 서버 checkout에서 host-side 스크립트로 실행합니다. 기본 범위는 2015년부터 전년도까지이며, 최신 연도부터 sync-financials → sync-share-info → sync-xbrl 순서로 raw만 적재합니다. 파생 metric 마트는 백필 후 bin/parquet-compute-all.sh로 재계산합니다. 모든 OpenDART key가 일일 한도에 도달하면 해당 CLI가 exit code 75로 종료되고, 다음 실행 때 이미 저장된 raw는 건너뛰며 이어받습니다.

bin/dart-backfill-all-years.sh

SDC_DART_BACKFILL_START_YEAR=2018 \
SDC_DART_BACKFILL_END_YEAR=2025 \
bin/dart-backfill-all-years.sh

Parquet / DuckDB compute

# 11. sj2 raw 미러 → raw Parquet export → DuckDB 파생 마트/게이트 실행
bin/parquet-compute-all.sh

# feat_*/labels 마트까지 함께 빌드
bin/parquet-compute-all.sh --features

이 단계는 stock_metric_fact와 common_feature_daily_fact를 PostgreSQL에 쓰지 않고 raw Parquet 위에서 재계산합니다. 필요한 의존성은 uv sync --extra research로 설치합니다.

수급 raw (KIS / KRX)

# 12. 종목/일자 기준 수급 raw 적재
uv run krx-collector flows sync --tickers 005930 --start 2026-04-17 --end 2026-04-17

# 일일 catch-up: 저장된 수급 최신일과 가격 최신일 기준으로 최근 window만 갱신
uv run krx-collector flows sync --incremental --lookback-days 14

# KIS 요청 계획만 확인(외부 요청과 token 발급 없음)
uv run krx-collector flows sync-kis --plan-only

# KIS 수급 증분 수집
uv run krx-collector flows sync-kis

flows sync는 KRX MDC JSON endpoint를 직접 호출합니다. 적재 row의 source 컬럼은 KRX로 기록됩니다. KRX MDC가 비로그인 응답을 거부하면 .env의 KRX_ID / KRX_PW 자격증명으로 자동 로그인 후 재시도합니다.

flows sync-kis는 KIS Developers API를 호출하며 적재 row의 source는 KIS로 기록합니다. KIS_APP_KEY, KIS_APP_SECRET, KIS_BASE_URL을 설정해야 합니다.

KIS 데이터 이용 범위

이 프로젝트의 KIS Developers API 데이터는 사용자가 직접 관리하는 비공개 환경에서 개인 연구와 백테스트 용도로만 사용합니다. API key와 수집 데이터에는 사용자 본인만 접근합니다.

현재 다음 용도는 계획하지 않습니다.

  • KIS raw 테이블이나 Parquet 파일 공유
  • KIS 데이터를 GitHub에 업로드
  • 다른 사용자가 조회할 수 있는 API, 웹 서비스 또는 대시보드 제공
  • 종목별 KIS 데이터를 포함한 보고서 배포
  • 상업 모델, 투자자문 또는 고객 대상 서비스에 연결
  • KIS 이용계약이 끝난 뒤에도 데이터를 무기한 보관하는 방침 확정

위 범위가 달라지면 구현이나 배포 전에 KIS Developers 이용약관과 필요한 거래소 정보이용계약을 다시 확인합니다. 이 운영 방침은 제3자 제공을 금지하는 KIS Developers 고객 이용약관을 따르기 위한 현재 프로젝트 범위입니다.

KRX Open API·공공데이터포털 이용 범위

KRX Open API 데이터도 KIS와 같은 비공개 개인 연구·백테스트 범위에서만 사용합니다. KRX Open API 이용약관에 따라 다음 운영 조건을 적용합니다.

  • 비상업 목적으로만 사용하고 API 결과나 수집 데이터를 제3자에게 제공하지 않습니다.
  • KRX 데이터를 사용한 화면을 만들면 한국거래소 통계정보를 사용했다는 문구를 표시합니다.
  • source=KRX_OPENAPI provenance를 raw와 파생 산출물에 유지합니다.
  • 인증키 이용기간을 연장하지 않거나 계약이 끝나면 KRX 데이터 수집과 분석 사용을 중단합니다. 기존 raw·Parquet은 연장 또는 삭제 방침을 정할 때까지 compute 입력에서 격리하며, 계약 종료 뒤에도 계속 이용하거나 무기한 보관하는 방침은 두지 않습니다.
  • 공개, 제3자 제공 또는 상업 이용이 필요해지면 구현 전에 KRX 데이터 상품·분배 계약을 다시 확인합니다.

공공데이터포털의 금융위원회_주식시세정보는 무료이며 이용허락범위 제한 없음으로 제공됩니다. 현재 DATAGO_KEY는 KRX Open API 값 대조용으로만 설정할 수 있고 정기 수집 경로에는 연결돼 있지 않습니다. 나중에 수집 경로로 사용하더라도 source와 데이터셋 ID 15094808을 provenance에 남깁니다.

공통 시장 / 거시 feature

공통 feature 계층은 source별 raw 관측치(common_feature_observation_raw)와 수집 driver 설정(common_feature_series)을 적재합니다. KRX 거래일 기준 long fact(common_feature_daily_fact)는 PostgreSQL에 쓰지 않고 Parquet compute 단계에서 DuckDB 마트로 재계산합니다.

# 13. 공통 feature series seed
uv run krx-collector common seed-catalog --init-schema

# 14. 일간 시장 feature raw 적재 (FDR/KRX)
uv run krx-collector common sync --sources fdr,krx --start 2026-01-01 --end 2026-06-13

# 15. 거시 feature raw 적재 (ECOS/FRED, API key 필요)
uv run krx-collector common sync --sources ecos,fred --start 2024-01-01 --end 2026-06-13 --force

운영 wrapper는 raw source sync만 담당합니다. 파생 daily fact, coverage, readiness는 docs/operations.md의 "Parquet compute 파이프라인" 절차로 실행합니다.

현재 flows sync 1차 구현은 다음 metric을 대상으로 합니다.

  • foreign_holding_shares
  • foreign_net_buy_volume
  • institution_net_buy_volume
  • individual_net_buy_volume
  • short_selling_volume
  • short_selling_value
  • short_selling_balance_quantity

borrow_balance_quantity는 KRX MDC provider에 아직 안정 경로를 붙이지 않아 pending 상태입니다.

신규 파이프라인들은 외부 API 장애 시 자동 재시도/rate-limit/jitter를 수행하며, 최종적으로 일부 요청이 실패해도 파이프라인은 정상 종료됩니다. 이 경우 ingestion_runs.status가 partial로 기록되고 counts.error_count / partial_failure_count / completed_request_count 값이 함께 저장됩니다. OpenDART 실행은 추가로 opendart_key_count, key_rotation_count, rate_limit_count, key_disable_count, all_rate_limited_count, all_disabled_count, request_invalid_count, retryable_error_count, terminal_error_count, status_<code>_count 같은 키/상태코드 메트릭을 기록합니다. 해석/복구 절차는 docs/operations.md를 참고하세요.

중복 실행 방지

  • dart sync-corp: dart_corp_master에 데이터가 있으면 corp-code ZIP 다운로드를 건너뜁니다.
  • dart sync-financials: (corp_code, bsns_year, reprt_code, fs_div) raw 행이 있으면 해당 재무제표 요청을 건너뜁니다.
  • dart sync-share-info: 주식수, 배당, 자사주 각각에 대해 해당 raw 행이 있으면 해당 요청만 건너뜁니다.
  • dart sync-xbrl: (corp_code, bsns_year, reprt_code, rcept_no) XBRL 문서가 있으면 ZIP 다운로드/파싱을 건너뜁니다.
  • common sync: 명시 기간 실행은 기존 raw coverage가 있으면 건너뛰며, --force를 주면 재조회합니다. --incremental은 기존 raw baseline 이후만 갱신합니다.
  • ops freshness-report: read-only 리포트입니다.
  • bin/parquet-compute-all.sh: Parquet/DuckDB derived mart를 재생성하며 PostgreSQL에는 쓰지 않습니다.

백필 모드 요약

  • 기본 모드 (gap detection): 거래일 캘린더 기준으로 누락된 모든 영업일을 찾아 채웁니다. 최초 백필이나 히스토리 보강에 적합합니다. 각 티커마다 MIN(trade_date)로 자동 클램핑되어 상장 이전(또는 pykrx가 제공하지 못하는 과거) 구간을 매번 재요청하지 않습니다.
  • --incremental 모드: 각 티커의 MAX(trade_date) 이후만 단일 연속 구간으로 수집합니다. gap 검출을 건너뛰므로 매일 돌리는 catch-up 작업에 가장 빠릅니다.

python -m으로 실행하기

uv run python -m krx_collector universe sync --source pykrx

원격 DB를 로컬 PostgreSQL로 동기화하기

sj2-server에서 매일 수집한 데이터를 로컬 PostgreSQL로 가져와 로컬에서도 바로 분석할 수 있도록 db sync-remote 명령을 제공합니다. 로컬 PostgreSQL 접속 정보는 .env의 DB_DSN 또는 DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD를 사용합니다. 원격 PostgreSQL 접속 정보는 기본적으로 /Users/whishaw/wss_p/stock_data_collector_secrets/db_info에서 읽습니다.

# 기본 증분 동기화
uv run krx-collector db sync-remote

원격 DB 호스트가 로컬에서 직접 열리지 않고 sj2-server SSH 접속을 통해서만 접근 가능하다면 SSH 터널 옵션을 함께 사용하세요.

# SSH 터널을 통한 증분 동기화
uv run krx-collector db sync-remote --ssh-host whi@sj2-server

동기화 모드

db sync-remote는 학습 데이터 ETL에 필요한 raw/reference mirror 테이블 13개를 관리 대상으로 삼습니다. 모든 모드는 SSH 터널 옵션(--ssh-host, --ssh-local-port)과 자유롭게 조합할 수 있습니다.

1. 증분 동기화 (기본)

기본 실행은 관리 대상 13개 테이블 전체를 로컬 DB 상태 기준으로 증분 upsert 합니다.

uv run krx-collector db sync-remote --ssh-host whi@sj2-server

updated_at, fetched_at과 surrogate key를 조합한 복합 cursor를 사용하므로 동일 시각 행이 배치 경계에서 누락되지 않습니다. raw 테이블은 natural-key conflict가 발생해도 원격의 raw_id, document_id 같은 surrogate id를 로컬에 보존합니다. daily_ohlcv는 sync_checkpoints에 재개 cursor를 저장해 중단 지점에서 이어받습니다.

catalog/link/snapshot 성격의 작은 mirror 테이블은 remote 전체를 scan한 뒤 원격에 없는 로컬 row를 prune합니다. prune은 FK child-first 순서로 수행되며, unsafe한 부분 table 조합은 실행 전에 거부됩니다.

2. --full-refresh

관리 대상 13개 테이블을 TRUNCATE 후 원격 데이터를 처음부터 다시 적재합니다. 로컬 복제본이 손상됐거나 첫 동기화일 때 사용합니다. sync_checkpoints와 로컬 ingestion_runs는 remote mirror 대상이 아니므로 유지됩니다. 이 경로는 선택된 managed table을 transaction 안에서 truncate한 뒤 PostgreSQL binary COPY로 적재합니다.

uv run krx-collector db sync-remote --ssh-host whi@sj2-server --full-refresh

3. --tables

특정 관리 테이블만 검증하거나 보강할 때 쉼표 구분 목록으로 지정합니다. 필요한 FK parent 테이블은 자동으로 sync plan 앞쪽에 포함됩니다. --all-tables와는 동시에 사용할 수 없습니다.

uv run krx-collector db sync-remote \
  --ssh-host whi@sj2-server \
  --tables dart_financial_statement_raw,dart_xbrl_fact_raw

부분 --full-refresh 또는 prune에서 선택한 parent를 참조하는 child table이 빠져 있으면 mirror 일관성을 위해 실행을 거부합니다.

4. --all-tables (반드시 --full-refresh와 함께)

관리 대상 mirror 테이블의 로컬 schema drift까지 교정해야 할 때 사용하는 schema-reset copy 경로입니다. 대상 로컬 테이블만 drop 후 sql/postgres_ddl.sql을 다시 적용하고, 원격 데이터를 바이너리 COPY로 통째 복제합니다. --full-refresh를 함께 지정하지 않으면 즉시 에러로 중단됩니다.

uv run krx-collector db sync-remote --ssh-host whi@sj2-server --full-refresh --all-tables

--all-tables와 일반 기본 sync의 관리 대상은 동일한 13개 테이블입니다.

동기화 대상:

  • stock_master
  • stock_master_snapshot
  • stock_master_snapshot_items
  • daily_ohlcv
  • krx_security_flow_raw
  • dart_corp_master
  • dart_financial_statement_raw
  • dart_share_count_raw
  • dart_shareholder_return_raw
  • dart_xbrl_document
  • dart_xbrl_fact_raw
  • common_feature_series
  • common_feature_observation_raw

remote mirror에서 제외되는 로컬 운영 테이블:

  • sync_checkpoints: 로컬 증분 sync 재개 cursor
  • ingestion_runs: 로컬 sync 실행 audit row

--all-tables 모드는 다음 순서로 동작합니다.

  1. 대상 테이블 schema reset — 위 대상 로컬 테이블만 drop 후 sql/postgres_ddl.sql을 다시 적용합니다. 대상 밖의 public 테이블은 삭제하지 않습니다.
  2. 사전 검증 — 대상 테이블이 원격/로컬 양쪽에 모두 있는지와 컬럼 구성(이름·순서)이 일치하는지 확인합니다. 불일치가 있으면 truncate 전에 즉시 오류로 중단됩니다.
  3. 위상 정렬 후 truncate — 외래키 의존성을 따라 부모 → 자식 순으로 정렬한 뒤 TRUNCATE ... RESTART IDENTITY로 대상 테이블만 비웁니다. 순환 FK가 발견되면 오류로 중단됩니다.
  4. 바이너리 COPY 스트리밍 — 각 테이블을 PostgreSQL COPY ... (FORMAT BINARY)로 OS 파이프를 통해 원격→로컬 스트리밍합니다. 큰 테이블도 메모리 스파이크 없이 처리됩니다.
  5. 시퀀스 복제 — 각 테이블이 소유한 시퀀스의 last_value/is_called를 setval로 그대로 복제합니다.
  6. 체크포인트 정렬 — 마지막으로 daily_ohlcv 증분 체크포인트를 로컬에 적재된 데이터 기준으로 다시 써서, 이후 증분 sync가 올바르게 재개되도록 보정합니다.

옵션

  • --full-refresh: 관리 대상 mirror 테이블을 truncate 후 처음부터 적재합니다.
  • --all-tables: 관리 대상 mirror 테이블을 schema-reset copy 경로로 복제합니다 (--full-refresh 필수, --tables와 동시 사용 불가).
  • --tables: 쉼표 구분 관리 테이블 목록만 sync합니다. 필요한 FK parent 테이블은 자동 포함됩니다 (--all-tables와 동시 사용 불가).
  • --db-info-path: 원격 DB 정보 파일 경로를 변경합니다.
  • --batch-size: 증분 동기화에서 한 번에 읽어올 행 수를 조절합니다 (--all-tables 모드에서는 사용되지 않습니다).
  • --remote-host: db_info의 host 값을 다른 호스트명으로 덮어씁니다.
  • --ssh-host: 지정 시 SSH 로컬 포트 포워딩을 통해 원격 DB에 접속합니다.
  • --ssh-local-port: SSH 터널에 고정 로컬 포트를 사용합니다 (미지정 시 임의의 빈 포트).
  • --ssh-compression / --no-ssh-compression: SSH 터널 사용 시 압축을 켜거나 끕니다. 기본값은 REMOTE_DB_SSH_COMPRESSION 설정을 따릅니다.

Feature / table profiling

수집된 raw/reference 테이블의 통계 프로파일은 profile CLI로 생성합니다. 프로파일링은 행수, 시간 범위, 결측률, 자연키 중복, 카테고리 분포, 수치 분위수, FK/PIT 정합성, freshness, 테이블별 domain check를 실행하고 실행별 manifest를 남깁니다.

기본 DB 대상:

  • local: 루트 .env의 DB_DSN을 사용합니다.
  • sj2: db sync-remote와 같은 db_info 기반 원격 DB 정보를 사용합니다.

Notebook/HTML/Parquet 산출물까지 만들려면 분석용 optional dependency를 설치합니다. Markdown/JSON만 볼 때는 --formats md,json --no-execute로 가볍게 실행할 수 있습니다.

# 분석용 의존성 설치
uv sync --extra analysis

# 단일 테이블 프로파일
uv run krx-collector profile table daily_ohlcv --target local

# 전체 카탈로그 프로파일(full + light)
uv run krx-collector profile all --target local --weight full,light

# long-format 테이블을 metric_code / feature_code 별로 분리
uv run krx-collector profile table krx_security_flow_raw --target local --drilldown

# 빠른 리뷰용 Markdown + JSON만 생성
uv run krx-collector profile table common_feature_observation_raw \
  --target local \
  --formats md,json \
  --no-execute

# 특정 실행끼리 drift 비교
uv run krx-collector profile diff \
  --target local \
  --baseline reports/feature_profiles/local/2026-06-18/_run_manifest.json \
  --candidate reports/feature_profiles/local/2026-06-19/_run_manifest.json

# 검토한 Markdown/manifest만 docs 아래로 publish
uv run krx-collector profile publish --target local --run-id 2026-06-19

기본 출력 위치는 다음과 같습니다.

reports/feature_profiles/<target>/<run-date>/
  _run_manifest.json
  run_summary.md
  index.html
  tables/
  artifacts/

주요 옵션:

  • --target {local,sj2}: 프로파일링 대상 DB를 선택합니다.
  • --formats ipynb,md,html,json,parquet: 생성할 산출물 포맷을 선택합니다.
  • --drilldown: metric_code, feature_code, series_id 같은 long-format 축을 값별 Markdown으로 분리합니다.
  • --sample-policy {auto,full,sample} / --sample-pct: 대형 테이블의 분위수/Top-N 샘플링 정책을 조절합니다.
  • --query-timeout-sec: 체크별 PostgreSQL statement_timeout을 지정합니다.
  • --out-dir: 기본 reports/feature_profiles 대신 다른 출력 루트를 사용합니다.
  • --run-date: 출력 run-date 디렉터리를 직접 지정합니다.

Raw PostgreSQL → Parquet export

대형 raw/reference 테이블을 PostgreSQL에서 Parquet lake로 내보내는 Rust exporter는 tools/raw-parquet-exporter에 있습니다. 개발 기본 출력은 data_lake/raw_postgres/snapshot_date=<YYYY-MM-DD>/source=<SOURCE>/... 아래에 생성되며, table manifest와 checkpoint를 함께 기록합니다. DB 접속 정보는 루트 .env의 DB_DSN 또는 DB_* 환경 변수를 사용합니다.

지원 전략:

  • raw_id_range: dart_xbrl_fact_raw, dart_financial_statement_raw, dart_shareholder_return_raw, dart_share_count_raw
  • date_month: krx_security_flow_raw, daily_ohlcv
  • full_table: dart_xbrl_document, dart_corp_master, stock_master, stock_master_snapshot, common_feature_series, common_feature_observation_raw
  • snapshot_items: stock_master_snapshot_items

전체 테이블 export는 bin/raw-parquet-export-all.sh를 사용합니다. 아래 명령은 release binary를 빌드한 뒤 configured table 전체를 순차 export하고, 각 table manifest를 검증합니다.

bin/raw-parquet-export-all.sh --snapshot-date 2026-06-19 --force

이 명령의 기본 출력 위치는 다음과 같습니다.

data_lake/raw_postgres/snapshot_date=2026-06-19/source=local_mydb/

테이블별 Parquet 파일은 <table>/schema_version=1/... 아래에 생성되고, manifest/checkpoint는 _manifests/ 아래에 기록됩니다. --force는 같은 snapshot/source/table 출력 디렉터리가 이미 있을 때 해당 table output을 지우고 다시 씁니다. 전체 data_lake/raw_postgres 디렉터리를 통째로 삭제하지는 않습니다. 임시 파일은 data_lake/_tmp/raw_export/<run_id>/... 아래에 생성됩니다.

주요 옵션:

  • --snapshot-date YYYY-MM-DD: 출력 snapshot partition을 지정합니다.
  • --force: 기존 table output을 덮어씁니다.
  • --no-build: release build를 생략합니다.
  • --no-validate: export 후 manifest 검증을 생략합니다.
  • --validate-samples: raw_id 테이블에 대해 PostgreSQL 원본 샘플과 Parquet 값을 비교합니다.
  • --dry-run: Parquet 파일을 쓰지 않고 export plan만 확인합니다.

대표 실행:

# 전체 configured table export
bin/raw-parquet-export-all.sh

# 기존 snapshot/table 출력 덮어쓰기
bin/raw-parquet-export-all.sh --snapshot-date 2026-06-19 --force

# export plan 확인
cargo run --manifest-path tools/raw-parquet-exporter/Cargo.toml -- \
  plan \
  --tables dart_xbrl_fact_raw

# raw_id 범위 export
cargo run --manifest-path tools/raw-parquet-exporter/Cargo.toml -- \
  export \
  --tables dart_xbrl_fact_raw \
  --start-raw-id 1 \
  --chunk-rows 1000000 \
  --batch-rows 65536 \
  --max-rows-per-file 5000000 \
  --force

# manifest row count와 Parquet metadata 검증
cargo run --manifest-path tools/raw-parquet-exporter/Cargo.toml -- \
  validate \
  --manifest data_lake/raw_postgres/snapshot_date=2026-06-19/source=local_mydb/_manifests/table_manifests/dart_xbrl_fact_raw.json

# raw_id 샘플을 PostgreSQL 원본과 Parquet 값으로 비교
cargo run --manifest-path tools/raw-parquet-exporter/Cargo.toml -- \
  validate-samples \
  --manifest data_lake/raw_postgres/snapshot_date=2026-06-19/source=local_mydb/_manifests/table_manifests/dart_xbrl_fact_raw.json

세부 사용법은 tools/raw-parquet-exporter/README.md를, 설계와 진행 중인 benchmark는 docs/dev/20260619_rust_exporter/raw_parquet_exporter_rust_plan.md와 docs/dev/20260619_rust_exporter/raw_parquet_exporter_benchmark_20260619.md를 참고하세요.

Docker로 실행하기

필수 조건

  • Docker
  • Docker Compose Plugin (docker compose)

Docker 이미지 빌드

docker build -t ghcr.io/sjleekor/sdc:latest .

main 브랜치에 push 하면 GitHub Actions가 동일 이미지를 ghcr.io/sjleekor/sdc로 자동 build/push 하도록 설정되어 있습니다. workflow 파일은 .github/workflows/docker.yml입니다.

단일 컨테이너로 실행

기존 PostgreSQL이 이미 떠 있다면 .env의 DB_DSN 또는 DB_HOST/DB_PORT 값을 맞춘 뒤 다음처럼 실행할 수 있습니다.

docker run --rm --env-file .env ghcr.io/sjleekor/sdc:latest db init
docker run --rm --env-file .env ghcr.io/sjleekor/sdc:latest universe sync --source krx-openapi --markets kospi,kosdaq
docker run --rm --env-file .env ghcr.io/sjleekor/sdc:latest prices backfill --market all --incremental

Docker Compose로 실행

이 저장소에는 PostgreSQL과 collector 실행을 위한 docker-compose.yml이 포함되어 있습니다.

# 1. 환경 변수 파일 준비
cp .env.example .env

docker-compose.yml은 DB 컨테이너 내부 호스트명을 사용하므로, .env에서 DB_DSN을 비우거나 아래처럼 맞추는 것을 권장합니다.

DB_DSN=
DB_HOST=db
DB_PORT=5432
DB_NAME=krx_data
DB_USER=krx_user
DB_PASSWORD=changeme
# 2. PostgreSQL 시작
docker compose up -d

# 3. 스키마 초기화
docker compose run --rm collector db init

# 4. 종목 유니버스 동기화
docker compose run --rm collector universe sync --source krx-openapi --markets kospi,kosdaq

# 5. 일봉 증분 수집
docker compose run --rm collector prices backfill --market all --incremental

# 6. 검증
docker compose run --rm collector validate --market all

collector 서비스는 배치 실행용이므로 docker compose up -d 시에는 기본적으로 db만 상시 실행됩니다.

개발 환경 (Development)

# 개발/테스트 + Parquet/DuckDB research 의존성 포함하여 설치
uv sync --extra dev --extra research

# 테스트 실행
uv run pytest

# 코드 린트(Lint) 검사
uv run ruff check src/ tests/ research/etl/

# 코드 포맷팅
uv run black src/ tests/ research/etl/

프로젝트 구조

krx-data-pipeline/
├── .env.example                      # 환경 변수 템플릿
├── Dockerfile                        # 컨테이너 이미지 정의
├── docker-compose.yml                # PostgreSQL + collector 구성
├── pyproject.toml / uv.lock          # 프로젝트 메타데이터 및 의존성 (uv)
├── sql/
│   └── postgres_ddl.sql              # 전체 스키마 DDL (OHLCV / DART / XBRL / 수급 / common feature / KPI)
├── docs/
│   ├── architecture.md               # 아키텍처 및 데이터 흐름 설명
│   ├── database.md                   # 데이터베이스 스키마 문서
│   ├── operations.md                 # 운영 가이드(Runbook), cron, partial run 해석
│   ├── holidays_krx.csv              # KRX 휴장일 데이터 (trading calendar에서 사용)
│   └── dev/                          # 설계/구현 계획 및 세부 구현 추적표
├── tools/
│   └── raw-parquet-exporter/         # Rust 기반 PostgreSQL raw/reference table → Parquet exporter
├── src/krx_collector/
│   ├── __main__.py                   # `python -m krx_collector` 진입점
│   ├── main.py                       # main() 어댑터 shim
│   ├── cli/app.py                    # argparse 기반 CLI (db/ops/universe/prices/dart/common/flows/validate/profile)
│   ├── domain/                       # 순수 도메인 모델 및 Enum (Source, RunType, RunStatus 등)
│   ├── ports/                        # 프로토콜 인터페이스
│   │                                 #   universe, prices, storage, corp_codes,
│   │                                 #   financials, share_info, xbrl, flows,
│   │                                 #   common_features
│   ├── adapters/                     # Provider 구현체
│   │                                 #   universe_fdr / universe_pykrx / prices_pykrx
│   │                                 #   opendart_common / opendart_corp / opendart_financials /
│   │                                 #   opendart_share_info / opendart_xbrl
│   │                                 #   common_features_fdr / common_features_krx /
│   │                                 #   common_features_ecos / common_features_fred /
│   │                                 #   common_features_pykrx
│   │                                 #   flows_krx
│   ├── service/                      # 유스케이스 오케스트레이션
│   │                                 #   sync_universe, backfill_daily, validate,
│   │                                 #   sync_dart_corp / sync_dart_financials /
│   │                                 #   sync_dart_share_info / sync_dart_xbrl,
│   │                                 #   sync_common_features, freshness,
│   │                                 #   sync_krx_flows, sync_local_db
│   ├── infra/
│   │   ├── calendar/                 # KRX 거래일 계산 유틸리티
│   │   ├── config/                   # pydantic-settings 기반 환경 설정
│   │   ├── db_postgres/              # PostgreSQL 연결, 저장소, 원격 동기화 구현
│   │   └── logging/                  # 구조화 로깅 설정
│   └── util/                         # pipeline.py(재시도/jitter/partial-run finalizer),
│                                     #   시간대(Asia/Seoul) 유틸리티
├── research/                         # Parquet/DuckDB ETL, derived marts, model dataset builders
└── tests/
    ├── unit/                         # 파서 / 매핑 / 재시도 / pipeline util 단위 테스트
    ├── integration/                  # DB 연결, OHLCV end-to-end, 운영 KPI round-trip
    ├── helpers/                      # 테스트용 fake provider/executor 헬퍼
    └── fixtures/                     # flows KRX 응답, 섹터별 KPI 샘플 문서 등 테스트 픽스처

아키텍처 및 추가 문서

라이선스

MIT

MIT 라이선스는 이 저장소의 소스 코드에만 적용됩니다. KIS, KRX, OpenDART, 공공데이터포털 등 외부 원천에서 수집한 raw·Parquet 데이터에는 각 제공기관의 이용조건이 적용되며 이 저장소의 MIT 라이선스로 재배포되지 않습니다.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages