시장 데이터 자동 수집 + 분석 리포트 저장 + Claude 스킬용 REST API를 제공하는 투자 리서치 플랫폼. FRED/OpenBB/SEC EDGAR/FINRA 수집, FastAPI 백엔드(X-API-Key 인증), APScheduler 정기 수집, SQLite 스토리지. NAS Docker 배포. https://stock.xhhan.com
  • Python 98.4%
  • Dockerfile 1.6%
Find a file
xhh 92fd3a0ff4 feat(collector): FRED 심볼 3개 추가 (DGS30, DFII10, MORTGAGE30US) (#82)
data_gap #9 (DFII10), #10 (DGS30), #13 (MORTGAGE30US) 와 1:1 매칭. 다음 자동 수집 cycle 부터 잡힘.
2026-05-26 02:34:30 +09:00
.claude Phase 2: Streamlit 대시보드 초기 구현 2025-10-31 17:58:32 +09:00
.forgejo/workflows chore: ruff 린터 + pre-commit 훅 도입 2026-04-22 03:21:22 +09:00
docs docs: 토큰 절감 측정 리포트 신설 + 페어 1 등록 (#7) (#71) 2026-04-26 21:27:06 +09:00
frontend/streamlit fix: get_time_series 카테고리별 endpoint 분기 (indicators 404 스팸 제거) (#75) 2026-05-26 02:06:58 +09:00
scripts feat: CME FedWatch 확률 역산 (#8, #42) 2026-04-23 01:21:25 +09:00
src/financial_platform feat(collector): FRED 심볼 3개 추가 (DGS30, DFII10, MORTGAGE30US) (#82) 2026-05-26 02:34:30 +09:00
tests feat: data_gaps 피드백 루프 — capabilities 짝꿍 엔드포인트 (#15) (#72) 2026-04-26 21:41:30 +09:00
.devdbrc Phase 1 완료: OpenBB 기반 금융 데이터 수집 플랫폼 구축 2025-10-22 15:33:55 +09:00
.dockerignore Docker Compose 기반 실행환경 구성 (NAS 배포 준비) 2026-04-21 21:47:48 +09:00
.env.example fix: Tailscale HTTPS 프로브로 전환 — mixed content 해결 (#56) 2026-04-24 19:52:10 +09:00
.gitignore uv.lock 을 저장소에 포함 (Docker 빌드 + 재현성) 2026-04-21 23:50:38 +09:00
.mcp.json Phase 1 완료: OpenBB 기반 금융 데이터 수집 플랫폼 구축 2025-10-22 15:33:55 +09:00
.pre-commit-config.yaml chore: ruff 린터 + pre-commit 훅 도입 2026-04-22 03:21:22 +09:00
.python-version Phase 1 완료: OpenBB 기반 금융 데이터 수집 플랫폼 구축 2025-10-22 15:33:55 +09:00
CLAUDE.md feat: data_gaps 피드백 루프 — capabilities 짝꿍 엔드포인트 (#15) (#72) 2026-04-26 21:41:30 +09:00
docker-compose.yml refactor: Streamlit 레거시 페이지 API 기반 마이그레이션 (#54) 2026-04-26 13:23:07 +09:00
Dockerfile Dockerfile: 런타임에서 /app/src /app/scripts 에 read 권한 복구 2026-04-22 02:08:56 +09:00
main.py Phase 1 완료: OpenBB 기반 금융 데이터 수집 플랫폼 구축 2025-10-22 15:33:55 +09:00
pyproject.toml chore: ruff 린터 + pre-commit 훅 도입 2026-04-22 03:21:22 +09:00
README.md feat: data_gaps 피드백 루프 — capabilities 짝꿍 엔드포인트 (#15) (#72) 2026-04-26 21:41:30 +09:00
uv.lock chore: ruff 린터 + pre-commit 훅 도입 2026-04-22 03:21:22 +09:00

생성일 마지막수정일 상태 타입 접근방식
2025-10-22 2026-04-25 개발중 프로젝트 통합플랫폼

투자 리서치 플랫폼 (financial-data-platform)

시장 데이터 자동 수집 + 분석 리포트 저장 + Claude 스킬용 API를 제공하는 통합 플랫폼.

프로젝트 정체성

이 레포는 [투자 리서치 플랫폼 통합 로드맵]의 데이터 & API 레이어를 담당한다. 원래 OpenBB 기반 수집 전용 프로젝트로 시작했으나, 분산되어 있던 매크로 리포트 워크플로우와 종목 분석 파이프라인을 하나로 묶기 위해 FastAPI 백엔드 + 리포트 저장소까지 확장 중이다.

통합 목표:

  • 토큰 절약 — Claude 스킬이 매번 웹서치하던 정량 데이터를 DB 조회로 대체
  • Obsidian 의존성 탈피 — 리포트를 자체 DB에 저장하고 웹 뷰어로 접근
  • 자동화 — 수집 → 분석 → 발행까지 파이프라인화

연관 프로젝트:

  • reports.xhhan.com — 매크로 리포트 갤러리 (통합 예정)
  • 주식분석 자동화 파이프라인 — 종목 분석 스킬 (통합 예정)

현재 구현 상태 (2026-04-26, v0.3.6 기준)

수집 중인 데이터 (69개 심볼 + 12개 테이블)

경제 지표 (FRED 19개)

  • 유동성 3대 축: M2SL (M2 통화량), RRPONTSYD (역레포), WTREGEN (TGA)
  • 연준 자산: WALCL (Fed Balance Sheet)
  • 금리: FEDFUNDS, DGS10, DGS2, T10YIE (10Y 인플레 기대)
  • 경제 지표: UNRATE, CPIAUCSL, PCEPI, UMCSENT, ICSA
  • 채권 스프레드: BAMLH0A0HYM2 (하이일드), BAMLC0A0CM (IG)
  • 시장 규모: TCMDO, GDP, GFDEBTN
  • 은행 신용: TOTBKCR

주식/ETF (50개)

  • 주요 지수: SPY, QQQ, DIA, IWM
  • SPDR 섹터 11개 전체: XLK, XLF, XLV, XLE, XLY, XLP, XLI, XLB, XLU, XLRE, XLC
  • 팩터: MTUM, QUAL, VLUE, USMV, SIZE
  • 채권 세분화: TLT, SHY, IEF, LQD, HYG
  • 지역: EEM, EFA, EWJ, FXI, EWZ, INDA, EWY
  • 통화/원자재: UUP, FXY, DX-Y.NYB, GC=F, HG=F, CL=F
  • 테마: SMH, ARKK, XBI, GLD, USO, IBIT
  • Fed Funds Futures: ZQ=F (근월물)
  • 주식: AMD, TSLA, FCX
  • 지수: ^VIX, ^W5000

암호화폐BTC-USD

신규 수집 레이어 (리서치용)

  • insider_trades — SEC EDGAR Form 4, watchlist 종목의 내부자 매매
  • margin_debt — FINRA 월간 마진 부채 (1997년부터 29년치)
  • gdpnow_vintages — Atlanta Fed GDPNow 일간 나우캐스트 (#11)
  • fed_expectations — CME FedWatch 월물 체인 기반 회의별 확률 (#8)

DB 구성 (SQLite, ~30 MB, 12개 테이블)

테이블 행 수 비고
equity_prices 74,415 50개 심볼, 6년치
economic_indicators 60,200 19개 FRED 시리즈, 일부 1945년부터
crypto_prices 2,191 BTC 6년치
margin_debt 350 FINRA 월간, 29년치
insider_trades 117 AMD/TSLA/FCX 최근 90일
gdpnow_vintages Atlanta Fed GDPNow 일간 vintage (ALFRED)
fed_expectations CME FedWatch 확률 (관측일 × 회의일)
collection_logs 수집 이력
watchlist 3 분석 대상 종목
api_keys REST API 인증 키 (SHA256 해시)
reports 0 스키마만 (스킬 통합 시)
data_gaps 0 스킬이 못 찾은 데이터 누적 (#15, capabilities 짝꿍)

구현된 수집기

수집기 소스 빈도 상태
OpenBB (openbb_collector.py) FRED / yfinance 일간 운영 중
SEC EDGAR (edgar_collector.py) data.sec.gov 수동/주간 검증 완료
FINRA (finra_collector.py) finra.org XLSX 월간 검증 완료
Atlanta Fed (atlanta_fed_collector.py) FRED ALFRED 일간 운영 중 (#11)
CME FedWatch (cme_fedwatch_collector.py) yfinance ZQ 체인 수동/주간 운영 중 (#8)

빠른 시작

환경 준비

# 패키지 설치
uv sync

# 환경 변수 설정
cp .env.example .env
# .env 편집: FRED_API_KEY, OBB_FRED_API_KEY 입력

# DB 초기화 (최초 1회)
uv run python scripts/init_db.py

# watchlist 시드 (최초 1회)
uv run python scripts/init_watchlist.py

FRED API 키 발급: https://fred.stlouisfed.org/docs/api/api_key.html

데이터 수집

# 전체 일간 수집 (69개 심볼)
uv run python scripts/collect_daily.py

# 단일/복수 심볼 수집
uv run python scripts/collect_single.py SPY QQQ AMD

# 히스토리컬 백필 (특정 기간만)
uv run python scripts/backfill_historical.py --category etfs \
    --start-date 2020-01-01 --end-date 2024-12-31

# SEC EDGAR 내부자 매매 (watchlist 전체, 최근 90일)
uv run python scripts/collect_insider.py --days 90

# FINRA 마진 부채 (월 1회)
uv run python scripts/collect_margin_debt.py

분석 도구

# 섹터 자금 흐름 분석
uv run python scripts/analyze_sector_flows.py

# Streamlit 대시보드
uv run streamlit run frontend/streamlit/app.py
  • 운영 페이지app.py 기동 후 사이드바에서 이동:
    • Collection History (#22) — 수집 이력 heatmap + 최근 실패 로그
    • Data Coverage (#22) — 테이블/심볼 커버리지 + gaps 경고
    • Manual Trigger (#22) — /api/collect/* 버튼식 수동 실행 (Tailscale 전용)
    • API Keys (#46) — 키 발급/폐기/회전 UI (Tailscale 전용)
  • API URL / X-API-Key 는 사이드바 입력 (세션 내 유지). 기본 URL 은 환경변수 API_URL 로 덮어쓸 수 있음.
  • Tailscale 게이트된 페이지는 로컬에서 ADMIN_FORCE_ON=1 환경변수로 우회 가능 (예: ADMIN_FORCE_ON=1 uv run streamlit run frontend/streamlit/app.py).

테스트

# 전체 테스트 (in-memory SQLite, 외부 I/O 없음)
uv run pytest

# 특정 파일
uv run pytest tests/api/test_health.py

# 커버리지 리포트
uv run pytest --cov=src/financial_platform --cov-report=term-missing

PR 이 열리면 Forgejo Actions 가 자동으로 uv run ruff check . + uv run pytest 를 순차 실행한다 (.forgejo/workflows/test.yml). 실패 시 Actions 탭에 빨간 체크. 신규 엔드포인트/수집기는 테스트 동반 작성 을 관례로 한다 (TDD).

커밋 전 자동 린트 (pre-commit)

최초 1회만 아래 명령으로 Git 훅을 설치. 이후 git commit 할 때마다 ruff 가 자동으로 돌고 실패하면 커밋이 차단된다.

uv run pre-commit install        # 1회
uv run pre-commit run --all-files  # 전체 파일 수동 실행

훅 정의는 .pre-commit-config.yaml, 규칙은 pyproject.toml [tool.ruff]. ruff-format 은 전면 재포맷 범위를 피하기 위해 현재 비활성이며, 별도 PR 로 일괄 적용 후 켜질 예정.

API 서버 (로컬 개발)

# 개발 서버 실행 (reload, 기본 포트 8000)
uv run python scripts/run_api.py

# 포트/리로드 제어
uv run python scripts/run_api.py --port 9000 --no-reload

문서:

API 서버 (Docker Compose)

# 빌드 + 기동
docker compose up -d --build

# 최초 1회: DB 초기화 + watchlist 시드
docker compose run --rm api python scripts/init_db.py
docker compose run --rm api python scripts/init_watchlist.py

# API 키 발급 (원문은 한 번만 표시됨)
docker compose run --rm api \
    python scripts/apikey.py create --name "skill-macro" --scopes "read"

# 데이터 수집 트리거
docker compose exec api python scripts/collect_daily.py

# 로그
docker compose logs -f api

# 종료
docker compose down

docker-compose.yml 에는 stock.xhhan.com 으로 라우팅하는 Traefik 라벨이 이미 활성화되어 있다. NAS 의 Traefik 이 traefik-public 네트워크에서 자동으로 이 컨테이너를 잡아 Cloudflare Tunnel 뒤에서 서빙한다. 다른 도메인을 쓰려면 Host( 규칙만 바꾸면 된다.

Streamlit 운영 대시보드 (Docker Compose, #44)

같은 docker-compose.ymlstreamlit 서비스가 포함돼 있어 API 와 함께 기동된다. stock-admin.xhhan.com 으로 Traefik 라우팅.

# API + Streamlit 한 번에 기동
docker compose up -d --build

# Streamlit 만 재빌드
docker compose up -d --build streamlit

# 로그
docker compose logs -f streamlit

배포 준비

Cloudflare Tunnel 이 *.xhhan.com 을 Traefik 으로 와일드카드 포워딩하도록 구성되어 있어 별도 Tunnel/DNS 작업 불필요. docker compose up -d --build 한 번이면 stock-admin.xhhan.com 에 Traefik 라벨 기반으로 자동 라우팅.

접근 방식 (하이브리드)

  • 외부 공개 접근 (https://stock-admin.xhhan.com): Collection History / Data Coverage 를 키 입력 없이 조회. 조회 엔드포인트는 전부 공개라 사이드바 키 불필요.
  • Tailscale 접근 (NAS 호스트의 Tailscale IP :8501 직접): Manual Trigger / API Keys 페이지도 활성. 브라우저에서 JS 프로브로 100.100.100.100 확인해 자동 감지. write 작업에만 API 키 필요 — 사이드바에 write 스코프 키 입력.
  • 로컬 개발 우회: .envADMIN_FORCE_ON=1 → Tailscale 없이 모든 페이지 활성.

Claude 스킬 통합 — capabilities 부터 시작 (#62)

스킬(매크로 리포트, 종목 분석 등) 이 매 실행마다 같은 웹서치를 반복하는 비용을 줄이는 것이 본 플랫폼의 핵심 목표. 스킬은 시작 시점에 다음 한 번을 호출해 "이 플랫폼이 어떤 데이터를 줄 수 있는지" 마크다운으로 흡수한 뒤 필요한 엔드포인트를 호출한다.

curl -s https://stock.xhhan.com/api/meta/capabilities

응답은 text/markdown. JSON 파싱 단계 없이 그대로 LLM 컨텍스트로 흡수된다. 본문에 포함되는 정보:

  • 사용 가능한 엔드포인트 (path + 한 줄 요약, 라우터 스캔으로 자동 생성)
  • 데이터 소스 (FRED / Equity / Crypto 카테고리별 심볼 수)
  • 테이블 커버리지 (행수 + 최신일)
  • 사용 규칙 (인증, CompactSeries 응답 포맷, data-gaps 짝꿍 안내)

응답은 동적 생성 — 새 라우트/심볼/데이터가 추가되면 capabilities 도 자동 반영되므로 스킬 프롬프트는 안 건드려도 최신 능력을 인지한다. 데이터가 비어 있거나 부정확하면 짝꿍 엔드포인트(POST /api/meta/data-gaps, #15) 로 빈틈을 기록 — 다음 수집기 우선순위 자동 도출.

API 인증

조회(GET) 엔드포인트는 공개 — 키 불필요. 쓰기(POST/PATCH/DELETE) 엔드포인트X-API-Key 헤더 + write 스코프 필요. 헬스체크/문서(/api/health, /api/version, /docs, /redoc, /scalar, /openapi.json) 도 공개.

# 키 발급
uv run python scripts/apikey.py create --name "skill-macro" --scopes "read"

# 키 목록 (활성만)
uv run python scripts/apikey.py list

# 키 목록 (폐기 포함)
uv run python scripts/apikey.py list --all

# 폐기
uv run python scripts/apikey.py revoke --name "skill-macro"

# 교체 (기존 폐기 + 같은 이름 재발급)
uv run python scripts/apikey.py rotate --name "skill-macro"

# 조회 호출 (키 불요)
curl http://localhost:8000/api/prices/SPY?limit=3

# 쓰기 호출 (write 스코프 키 필요)
curl -X POST -H "X-API-Key: irp_xxxxxxxxxx..." \
     "http://localhost:8000/api/collect/single?symbols=SPY,QQQ"

개발용 인증 비활성화: .envAPI_AUTH_DISABLED=1 설정 시 모든 요청이 통과. 프로덕션에서는 반드시 비워둘 것. 원문 키는 발급 시 한 번만 표시되며 DB에는 SHA256 해시만 저장된다.

배포 검증 — /api/version

CI/CD 파이프라인 또는 운영자가 "실제로 어떤 커밋이 떠 있는지" 확인하기 위한 엔드포인트. 인증 면제.

curl https://stock.xhhan.com/api/version
# {
#   "version": "0.1.0",
#   "commit": "37f5bd4003f7bfa9326ae6955bf4cd3cad92d2e2",
#   "commit_short": "37f5bd4",
#   "tag": "v0.1.0",
#   "branch": "main",
#   "build_time": "2026-04-21T13:16:32Z"
# }

값은 Docker 빌드 시점 ARG로 주입(GIT_COMMIT, GIT_TAG, GIT_BRANCH, BUILD_TIME). 로컬 docker compose build 시에도 환경변수로 전달 가능:

GIT_COMMIT=$(git rev-parse HEAD) \
GIT_TAG=v0.1.0-dev \
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
    docker compose up -d --build

배포 자동화 (Forgejo Actions + self-hosted Runner)

태그 v*를 push하면 NAS에서 자동으로 빌드·재기동·헬스체크·커밋 일치 검증까지 수행한다. 워크플로 정의는 .forgejo/workflows/deploy.yml.

동작 요약

flowchart LR
    dev["개발자<br/>git tag v0.2.0 && git push --tags"] --> forgejo["Forgejo<br/>(git.xhhan.com)"]
    forgejo -->|"push.tags == v*"| runner["Self-hosted Runner<br/>(NAS)"]
    runner -->|"git checkout tag<br/>docker compose build<br/>docker compose up -d"| nas["NAS Docker"]
    runner -.->|"curl /api/health<br/>curl /api/version → commit 일치 검증"| nas
    runner -->|"성공/실패 상태"| forgejo

Runner 전제

이 레포는 기존에 NAS에서 운영 중인 Forgejo Runner를 재사용한다 (git-pages 등 다른 워크플로가 이 러너로 이미 돌고 있음). 따라서 새 러너를 띄우거나 systemd 서비스를 만들지 않는다.

현재 러너 구성 (홈서버 표준):

항목
방식 Docker Compose (/home/xhh/docker/forgejo-runner)
라벨 docker, ubuntu-latest
네트워크 traefik-public
docker 접근 /var/run/docker.sock 마운트로 host docker 제어

워크플로의 runs-on: docker가 이 라벨과 매칭된다.

Forgejo Actions Secrets 등록 (1회)

저장소 Settings → Actions → Secrets 에 다음 값들을 넣는다. 워크플로가 매 배포마다 Runner 환경변수로 주입해 .env 파일을 재생성한다. 로그에 자동 마스킹되어 안전.

Secret 이름 필수 설명
FRED_API_KEY https://fred.stlouisfed.org/docs/api/api_key.html
OBB_FRED_API_KEY 비워두면 FRED_API_KEY와 동일 값 사용
SEC_CONTACT_EMAIL SEC EDGAR User-Agent용 (선택)

배포 시 .env는 이 Secrets를 소스로 매번 덮어쓰기된다. NAS에 .env를 수동 편집해도 다음 배포에서 초기화되므로, 모든 값은 Secrets를 단일 진실 공급원으로 사용할 것.

배포 디렉토리 준비 (1회)

# NAS에서 — 빈 디렉토리만 만들어 두면 된다. .env는 워크플로가 자동 생성.
mkdir -p /home/xhh/docker/financial-data-platform
cd /home/xhh/docker/financial-data-platform
git clone https://git.xhhan.com/xhh/financial-data-platform.git .

첫 배포 전 로컬에서 원하는 경우에만 수동 기동으로 파일 구조 확인 가능:

# 단 이 시점엔 .env가 없어서 docker compose가 환경변수 경고를 낸다.
# 정식 동작은 태그 push로 워크플로가 .env 생성 + 기동한 뒤부터.
docker compose config >/dev/null && echo "compose 파일 유효"

최초 초기화 (첫 태그 배포 성공 후)

# 컨테이너가 올라온 뒤 DB 테이블/시드/키 발급
docker compose exec api python scripts/init_db.py
docker compose exec api python scripts/init_watchlist.py
docker compose exec api python scripts/apikey.py create --name "initial" --scopes "read,write"
# 원문 키는 한 번만 표시되니 안전 보관

Runner가 배포 디렉토리에 접근하려면

기본적으로 Forgejo Runner 컨테이너는 격리되어 호스트 경로를 볼 수 없다. Runner 쪽 docker-compose.yml에 다음 마운트가 필요:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock   # host docker 제어
  - /home/xhh/docker:/home/xhh/docker           # 배포 디렉토리 접근

두 번째 라인이 없으면 워크플로의 cd "$DEPLOY_DIR"가 실패한다. git-pages 워크플로가 동작 중이라면 이미 설정돼 있을 가능성이 높으니 먼저 확인하고, 없으면 docker-compose.yml에 추가 후 Runner 재기동.

Forgejo 저장소 변수 설정

저장소 Settings → Actions → Variables 에서 필요 시 재정의:

변수 기본값 설명
DEPLOY_DIR /home/xhh/docker/financial-data-platform Runner가 checkout할 디렉토리
API_URL http://localhost:8000 헬스체크/버전 확인용 기준 URL. Runner 컨테이너에서 host API에 접근해야 하므로 http://host.docker.internal:8000 또는 traefik-public 네트워크 내 컨테이너 이름(http://financial-platform-api:8000) 사용 가능

릴리스 플로우

# 로컬에서 태그 생성 + push
git tag v0.2.0
git push origin v0.2.0

Runner가 자동으로:

  1. DEPLOY_DIR로 이동해 해당 태그 체크아웃
  2. GIT_COMMIT/GIT_TAG/BUILD_TIME--build-arg로 주입해 이미지 빌드
  3. docker compose up -d --remove-orphans로 재기동
  4. /api/health 성공 폴링 (최대 60초)
  5. /api/version 응답의 commit이 트리거한 github.sha와 일치하는지 검증
  6. 실패 시 컨테이너 로그 50줄을 워크플로 출력에 첨부

롤백

# 이전 태그로 되감기 (태그를 새 커밋으로 옮길 때는 force)
git tag -f v0.2.0 <이전 안정 커밋>
git push origin v0.2.0 --force

# 또는 NAS에서 수동으로
cd /home/xhh/docker/financial-data-platform
git checkout v0.1.9
docker compose up -d --build

배포 이력은 Forgejo 웹의 Actions 탭에서 확인.


아키텍처

전체 타깃 아키텍처를 한 장의 그림으로 보되, 완료 / 진행 / 예정 상태를 색상으로 구분한다.

flowchart LR
    subgraph 수집["수집 레이어"]
        openbb["OpenBB<br/>FRED · yfinance"]
        edgar["SEC EDGAR<br/>Form 4"]
        finra["FINRA<br/>마진 부채 XLSX"]
        extra["ETF flows · Analyst<br/>CME FedWatch · TIC/QRA"]
        utils["collection_utils<br/>(공통 수집 로직)"]
    end

    subgraph 저장["저장 레이어"]
        sqlite[("SQLite<br/>data/financial_data.db")]
    end

    subgraph 서비스["서비스 레이어"]
        api["FastAPI (Sprint 1+2)<br/>prices · indicators · insider<br/>margin-debt · analysis · system<br/>watchlist · reports · collect · meta"]
        auth["X-API-Key 인증<br/>(SHA256 해시 저장)"]
        scheduler["APScheduler<br/>(일간 09:00 KST + 주간/월간)"]
    end

    subgraph 소비자["소비자"]
        skill["Claude 스킬<br/>(매크로 · 종목 분석)"]
        viewer["reports.xhhan.com<br/>통합 뷰어"]
    end

    openbb --> utils
    edgar --> utils
    finra --> utils
    extra -.-> utils
    utils --> sqlite

    sqlite --> api
    auth --- api
    scheduler -.-> utils
    api -.-> skill
    skill -.->|"리포트 저장"| api
    api -.-> viewer

    classDef done fill:#c8e6c9,stroke:#2e7d32,color:#1b5e20
    classDef wip fill:#fff9c4,stroke:#f9a825,color:#e65100
    classDef planned fill:#eeeeee,stroke:#9e9e9e,color:#424242,stroke-dasharray: 4 3

    class openbb,edgar,finra,utils,sqlite,api,auth,scheduler done
    class extra wip
    class skill,viewer planned
  • 완료 — 수집(OpenBB/EDGAR/FINRA) + 저장(SQLite) + 서비스(FastAPI Sprint 1+2 + X-API-Key 인증) + APScheduler 정기 수집
  • 진행 중 (Phase 2) — 데이터 소스 확장 (ETF flows, 애널리스트, FedWatch 확률, TIC/QRA)
  • 예정 — 스킬 DB 전환(Phase 4), 통합 뷰어(Phase 3)

프로젝트 구조

financial-data-platform/
├── pyproject.toml                       # uv 프로젝트 설정
├── .env.example                         # 환경 변수 템플릿
├── CLAUDE.md                            # Claude 컨텍스트
├── Dockerfile                           # 프로덕션 이미지 (멀티스테이지)
├── docker-compose.yml                   # 개발/NAS 운영
├── .dockerignore
│
├── src/financial_platform/
│   ├── collectors/
│   │   ├── openbb_collector.py          # OpenBB 기반 FRED/yfinance
│   │   ├── edgar_collector.py           # SEC EDGAR Form 4
│   │   ├── finra_collector.py           # FINRA 마진 부채
│   │   └── collection_utils.py          # 공통 수집 로직
│   ├── storage/
│   │   ├── database.py                  # SQLAlchemy 세션/저장 메서드
│   │   └── models.py                    # 12개 테이블 모델 (api_keys, data_gaps 포함)
│   ├── api/                             # FastAPI 백엔드 (Sprint 1)
│   │   ├── main.py                      # 앱, CORS, /docs, /redoc, /scalar
│   │   ├── auth.py                      # X-API-Key 인증 의존성
│   │   ├── deps.py                      # DB 세션 의존성
│   │   ├── schemas/                     # Pydantic 응답 모델
│   │   └── routers/                     # prices·indicators·insider·margin·analysis·system
│   ├── config/
│   │   ├── config.yaml                  # DB 경로, 로그 레벨
│   │   └── indicators.yaml              # 수집 대상 심볼 정의
│   └── utils/
│       ├── logger.py                    # UTF-8 콘솔 로거
│       └── openbb_config.py             # OpenBB API 키 설정
│
├── scripts/
│   ├── init_db.py                       # DB 테이블 생성
│   ├── init_watchlist.py                # watchlist 시드
│   ├── apikey.py                        # API 키 CLI (create/list/revoke/rotate)
│   ├── run_api.py                       # API 개발 서버 실행
│   ├── collect_daily.py                 # 전체 일간 수집
│   ├── collect_single.py                # 단일/복수 심볼
│   ├── collect_insider.py               # SEC EDGAR Form 4
│   ├── collect_margin_debt.py           # FINRA 마진 부채
│   ├── backfill_historical.py           # 히스토리컬 백필
│   └── analyze_sector_flows.py          # 섹터 자금 흐름 분석
│
├── frontend/streamlit/                  # Streamlit 프로토타입
├── data/                                # SQLite DB (Git 제외)
└── tests/

로드맵 요약

상세 계획은 [투자 리서치 플랫폼 통합 로드맵] 문서 참조. 이 레포 기준 체크포인트:

완료

  • OpenBB 수집기 (FRED 19 + 주식/ETF 50 + BTC)
  • SQLite 스토리지 + SQLAlchemy 모델 10종 (api_keys 포함)
  • SEC EDGAR Form 4 수집기
  • FINRA 마진 부채 수집기
  • 백필 스크립트 (기간 지정 가능)
  • Streamlit 대시보드 프로토타입
  • FastAPI 백엔드 Sprint 1 — 10개 엔드포인트
    • Market Data: /api/prices/{symbol}, /api/prices/batch/{symbols}
    • Indicators: /api/indicators/{symbol}, /api/indicators/latest
    • Insider: /api/insider/{ticker}/summary
    • Margin Debt: /api/margin-debt/recent
    • Analysis: /api/analysis/liquidity-snapshot, /api/analysis/yield-curve
    • System: /api/health, /api/meta/symbols, /api/meta/capabilities (#62, 스킬 디스커버리 진입점 — 마크다운 응답)
  • X-API-Key 인증 — SHA256 해시 저장, CLI 발급/폐기/교체
  • 자동 문서화 — Swagger UI /docs, ReDoc /redoc, Scalar /scalar
  • CompactSeries 응답 포맷 — 시계열 토큰 30~40% 절감
  • Docker Compose 구성 — 멀티스테이지 Dockerfile + NAS 운영 템플릿
  • NAS 자동 배포 (v0.1.0) — Forgejo Actions + 전용 Runner(커스텀 이미지)로 태그 push → 빌드 → compose up → 헬스체크 → 커밋 해시 검증. Secrets 기반 .env 자동 생성.
  • Traefik + Cloudflare Tunnel 연동https://stock.xhhan.com 으로 외부 노출, SSL은 Cloudflare 종단
  • Quality Foundation (v0.2.0) — pytest + httpx TestClient 인프라, PR CI 자동 실행 (Forgejo Actions test.yml). v0.3.6 기준 113 테스트 운영 중. deps.get_session 트랜잭션 회귀 테스트 포함.
  • ruff + pre-commit (#32)ruff check 를 CI 단계와 커밋 훅 양쪽에서 강제. pyproject.toml 에 rule set 정의. .pre-commit-config.yaml 의 훅이 --fix 로 자동 수정까지 수행.
  • Sprint 2 주요 API 완료:
    • /api/watchlist CRUD (#17)
    • /api/reports POST/GET/PATCH + 종목별 이력 (#25) — Share Note 탈피 핵심
    • /api/meta/coverage — 테이블/심볼별 커버리지 + gaps 분석 (#28)
    • /api/collect/* 트리거 5개 + logs/history (#29)
    • /api/admin/keys/* CRUD + /bootstrap (#46, #50) — 내부망 전용, CLI 없이 브라우저에서 키 관리
  • APScheduler 정기 수집 (#5, #31) — FastAPI lifespan 에서 BackgroundScheduler 기동. KST 기준 매일 09:00 collect_daily, 매주 월 09:30 collect_insider, 매월 3주차 화 10:00 collect_margin_debt. SCHEDULER_ENABLED=0 으로 비활성화 가능 (테스트 기본값).
  • 공개 조회 API (#49) — 조회 엔드포인트 전부 키 없이 호출 가능. 쓰기 엔드포인트만 X-API-Key + write 스코프 요구. /api/admin/*require_private_origin 으로 공개 인터넷 원천 차단 (#50).
  • Phase 2 데이터 소스 2종 — Atlanta Fed GDPNow 일간 vintage (#11), CME FedWatch 월물 체인 확률 역산 (#8)
  • Streamlit 운영 대시보드 (v0.3.x) — NAS 배포. https://stock-admin.xhhan.com 공개.
    • 공개: Collection History / Data Coverage (키 없이 조회)
    • Tailscale 전용: Manual Trigger / API Keys — ADMIN_PROBE_URL 기반 자동 감지 + 수동 토글 fallback
  • 스킬 디스커버리 진입점 (v0.3.6)GET /api/meta/capabilities 가 사용 가능한 엔드포인트/심볼/테이블을 LLM 친화 마크다운으로 제공 (#62). Claude 스킬이 시작 시 한 번 fetch 해 본 API 우선 호출 — 통합 로드맵의 토큰 절감 가설 검증 진입점.
  • 운영 대시보드 DB 용량 표시 (v0.3.6)/api/meta/coverage 응답에 db_size_bytes (#55). Data Coverage 페이지 상단 메트릭 (KB/MB/GB 자동 단위).
  • Streamlit 레거시 페이지 API 마이그레이션 (v0.3.6) — Market_Coverage / Sector_Flows / Indicator_Detail 페이지가 더 이상 SQLite 파일을 직접 읽지 않음. 컨테이너에서 ./data:/app/data:ro 볼륨 마운트 제거 → 공격면 축소 (#54).
  • data_gaps 피드백 루프 (#15) — capabilities 짝꿍 엔드포인트 POST/GET/PATCH /api/meta/data-gaps + /summary. 스킬이 본 플랫폼에서 못 찾은 데이터를 append-only 로 누적, 주기적 리뷰로 다음 수집기 우선순위에 환원.

진행 중 (Phase 2 일부)

  • watchlist 확장 (현재 3종목)

다음 (Phase 2 → Phase 3 게이트)

  • #6 Claude 스킬 시범 전환 (유동성 분석 → /api/analysis/liquidity-snapshot) — Phase 2 핵심 검증
  • #7 토큰 절감 측정 리포트 — docs/token-savings.md 에 페어 누적 중 (1/5)
  • #55 운영 대시보드에 DB 용량 표시
  • #13 Docker 이미지 크기 축소

보류 (조건부 재개)

  • #9 ETF 자금 흐름 — 무료 소스 전멸 (etf.com Cloudflare 차단, ICI 멤버십), 유료 API 결정 필요
  • #10 Treasury TIC/QRA — 스코프 과다 (TIC 다차원 + QRA 이벤트 문서), 설계 토론 선행
  • #12 애널리스트 목표가 — FMP/Benzinga 유료 결정 대기

이후 단계

  • Phase 3 — 리포트 뷰어 통합 (reports.xhhan.com 리팩토링)
  • Phase 4 — 스킬 DB 조회 전환, 예측 정확도 추적, 토큰 비용 추적

알려진 제약

  • FRED RRPONTSYD (역레포 잔액): OpenBB fred_series provider가 이 특정 시리즈에 빈 응답을 반환. FRED REST API 직접 호출하면 정상 (openbb_collector.fetch_fred_series 가 자동 fallback).
  • Streamlit 컨테이너가 data/ 볼륨 read-only 마운트: 레거시 프로토타입 페이지가 SQLite 를 직접 읽기 때문. #54 완료 시 제거 예정.

기술 스택

백엔드

  • 패키지 관리: uv
  • Python: 3.11+
  • 데이터 수집: OpenBB Platform, yfinance, requests (SEC/FINRA)
  • 데이터 저장: SQLite + SQLAlchemy (MVP) → PostgreSQL (확장 시)
  • API: FastAPI + Uvicorn (Sprint 1+2 완료) + Pydantic 스키마
  • 문서화: Swagger UI / ReDoc / Scalar (자동 생성)
  • 인증: X-API-Key 헤더 (SHA256 해시 저장, CLI 관리)
  • 스케줄링: APScheduler (운영 중, KST cron — 일간/주간/월간)
  • 데이터 처리: pandas, numpy, openpyxl

프론트엔드

  • 현재: Streamlit (프로토타입)
  • Phase 3: 기존 Flask 갤러리(reports.xhhan.com) 확장 또는 React/Next.js

인프라

  • Docker Compose (멀티스테이지 Dockerfile, 비루트 실행, healthcheck)
  • Traefik 라우팅 (compose 템플릿 주석으로 준비됨)
  • NAS 셀프호스팅 (Forgejo + Docker)

개발 도구

  • 린터: ruff (pyproject.toml [tool.ruff]), CI + pre-commit 양쪽에서 강제
  • 훅: pre-commit — 커밋 직전 ruff check --fix 자동 실행
  • 테스트: pytest + httpx TestClient (105 케이스, PR 에서 자동 실행)

개발 가이드라인

코딩 스타일

  • 주석과 커밋 메시지: 한국어
  • 변수/함수명: 영어 snake_case
  • 클래스명: 영어 PascalCase
  • 이모지 사용 금지

핵심 원칙

  • API 키는 .env에 저장, python-dotenv로 로드
  • 에러 처리: 재시도 로직, 구조적 로깅, 유니크 제약으로 중복 방지
  • DRY: 공통 수집 로직을 collection_utils.py에 집중
  • 단일 책임: 수집(collectors/) / 저장(storage/) / 분석(scripts/) 분리

주요 명령어

# 패키지 관리
uv add <package>                         # 의존성 추가
uv add --dev <package>                   # 개발 의존성
uv sync                                  # 동기화

# 실행
uv run python <script>                   # 스크립트 실행
uv run pytest                            # 테스트 (105 케이스)
uv run ruff check .                      # 린트 (CI 와 동일)
uv run ruff check . --fix                # 안전 자동 수정
uv run pre-commit install                # 커밋 훅 설치 (최초 1회)
uv run pre-commit run --all-files        # 전체 파일 훅 수동 실행

OpenBB 패턴

from openbb import obb

# FRED 경제 지표
data = obb.economy.fred_series("M2SL")

# 주식/ETF
spy = obb.equity.price.historical("SPY", provider="yfinance")

SEC EDGAR 수집기 사용

from financial_platform.collectors.edgar_collector import EdgarCollector

c = EdgarCollector()
cik = c.lookup_cik("AMD")                # 2488
filings = c.fetch_form4_list(cik)
for f in filings[:3]:
    trades = c.fetch_form4_detail(
        cik, f["accession_no"], f["primary_doc"]
    )

SEC 에티켓: SEC_CONTACT_EMAIL 환경변수로 User-Agent 커스터마이즈 가능. 요청 간격 0.15초, 429/403 시 지수 백오프.


데이터 소스 선정 원칙

  1. 공식 무료 API 우선 — SEC EDGAR, FINRA, FRED
  2. 장기 안정성 > 최신 정확도 — 스크래핑보다 CSV/JSON 다운로드
  3. 유료 API는 대체재가 없을 때만 — FMP, Benzinga는 Phase 4 이후 결정
  4. 원시 데이터 확보 > 파생 지표 즉시 구현 — 예: ZQ=F 가격 먼저 저장, FedWatch 확률 계산은 Phase 3

현재 활용 중인 무료 데이터 소스

소스 제공 데이터 제한
FRED 경제 지표 전체 API 키 필수, rate limit 관대
yfinance (OpenBB) 주식/ETF/선물/암호화폐 가격 제한 없음 (비공식)
SEC EDGAR Form 4 내부자 매매, 기타 filing 10 req/sec, User-Agent 필수
FINRA 월간 마진 부채 공개 XLSX 다운로드

향후 탐색 대상

소스 제공 데이터 도입 예상 시점
CME (내부) FedWatch 확률 Phase 3, 스크래핑 안정성 검토 후
Atlanta Fed Market Probability Tracker Phase 3, CSV 다운로드 자동화
Treasury.gov TIC, QRA Phase 2 후반
ICI ETF 자금 흐름 주간 Phase 2 후반
etf.com Creation/Redemption 단위 Phase 2~3, 스크래핑 법적 검토

업데이트 주기 (현재)

  • 일별 (월~금 수집 권장) — 가격 데이터, VIX, 금리, ETF, 하이일드 스프레드, RRP
  • 주간 (월요일) — M2, WALCL, 은행 신용
  • 월간 (지표 발표일+1) — 실업률, CPI, PCE, FINRA 마진 부채
  • 이벤트 기반 — SEC Form 4 (내부자 매매는 2영업일 내 제출)

관련 문서

라이선스

개인 프로젝트. 외부 데이터 소스 라이선스는 각 제공자 정책 준수 (OpenBB AGPLv3, SEC/FINRA/FRED 공개).