tkrmagid fa817b31e4 feat(chart): ohlcv_daily 비어있으면 자동 refresh
문제: symbols 시드 후 첫 방문 시 ohlcv_daily 가 비어있어서
  - 차트가 빈 캔버스로 렌더링됨
  - 예상차트 보기 → 409 'no ohlcv_daily for {code}; refresh first'
daily_batch (16:00 KST) 또는 수동 POST /api/refresh/{code} 만이 OHLCV 를
채우는 구조였는데, 첫 방문 사용자는 둘 다 트리거 안 됨.

수정: GET /api/chart/{code} 가 ohlcv 0행 + symbol 존재 케이스에서
refresh_code 를 동기 호출 (pykrx OHLCV + trading_value + news + finbert)
후 재조회. idempotent 라 다음 방문부터는 캐시 히트.

lookback_days = max(days, 365) — 차트 요청 범위 + Chronos/LightGBM
학습용 과거 시계열 마진. 첫 호출 ~10-30s, 이후는 즉시.

KRX 가 도커망에서 막힌 환경이면 refresh 가 실패 status 로 끝나고
ohlcv 는 여전히 비어있음 — 기존 동작과 동일 (graceful).
2026-05-21 21:10:44 +09:00

stock_chart_site

개인용 주식 차트 + 단기 예측 사이트. 한국 종목 검색 → 현재 차트 표시 → "예상차트 보기" 클릭 시 Chronos+LightGBM 앙상블로 향후 1~5거래일 예측을 차트에 이어 붙임. 사용자가 한 번이라도 예측을 확인한 종목은 자동 저장해서 다음날 실제 가격과 비교 → 오차/방향성 적중률을 누적 → 앙상블 가중치를 자동 보정.

스펙 원문: /home/claude/EJClaw/groups/stock_predictor/SPEC.md (별도 채팅 그룹).

빠른 시작 (Windows + Docker Desktop + RTX 3070 Ti)

전제: Docker Desktop이 이미 설치되어 있고, GPU 사용하려면 Settings → Resources → WSL Integration → GPU support가 켜져 있어야 합니다.

git clone https://git.tkrmagid.kr/tkrmagid/stock_chart_site.git
cd stock_chart_site
build.bat

build.bat이 자동으로

  1. .env.example.env 복사 (없는 경우)
  2. nvidia-smi 로 GPU 감지 → GPU 있으면 GPU 모드, 없으면 CPU 폴백
  3. docker compose build + up -d

확인:

정지:

docker compose down

빌드 모드 (수동)

build.bat을 안 쓰는 경우 .env가 먼저 있어야 합니다.

# .env 없으면 한 번만 복사
copy .env.example .env

# GPU 모드 (RTX 3070 Ti 등 NVIDIA GPU 사용)
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build

# CPU 모드
docker compose up -d --build

API 키 발급 (모두 무료)

키 없어도 pykrx 기반 일봉/뉴스 RSS 만으로 일단 동작합니다. 다음 키를 받으면 데이터 품질이 좋아집니다.

1) 한국투자증권 KIS OpenAPI (실시간 시세 + EOD)

  1. https://apiportal.koreainvestment.com 회원가입 (한국투자증권 계좌 필요)
  2. 좌측 "Open API 신청" → 모의/실전 중 하나 신청
  3. 발급 완료 후 마이페이지에서 App Key, App Secret, 계좌번호 확인
  4. .env 에 입력:
    KIS_APP_KEY=...
    KIS_APP_SECRET=...
    KIS_ACCOUNT_NO=...
    

2) DART OpenAPI (전자공시 본문)

  1. https://opendart.fss.or.kr 회원가입
  2. 마이페이지 → 인증키 신청 → 즉시 발급
  3. .env 에 입력:
    DART_API_KEY=...
    

3) HuggingFace (선택, 모델 다운로드 가속)

토큰 없어도 공개 모델 (amazon/chronos-bolt-base, snunlp/KR-FinBert) 다운로드가 됩니다. 토큰이 있으면 rate limit이 완화되고 첫 다운로드가 빨라집니다.

  1. https://huggingface.co 회원가입
  2. https://huggingface.co/settings/tokens 에서 Read 토큰 생성
  3. .env 에 입력:
    HUGGINGFACE_TOKEN=hf_...
    

학습/배치 대상 시드 종목 (10개)

검색은 KRX 전 종목을 대상으로 동작하지만, 일별 배치/재학습/메트릭 누적은 아래 10개를 우선 대상으로 합니다. 운영하면서 더 의미있는 종목이 보이면 교체합니다.

분류 종목 코드
대형 인기주 삼성전자 005930
대형 인기주 SK하이닉스 000660
변동성 큰 종목 에코프로비엠 247540
변동성 큰 종목 한미반도체 042700
최근 인기 테마 두산에너빌리티 034020
최근 인기 테마 한화에어로스페이스 012450
최근 인기 테마 HD현대중공업 329180
전통 IT/플랫폼 NAVER 035420
방어주/저변동 KT&G 033780
방어주/저변동 한국가스공사 036460

디렉토리 구조

stock_chart_site/
├── build.bat                       # Windows: 빌드+기동
├── docker-compose.yml              # db + backend + web
├── docker-compose.gpu.yml          # GPU 오버레이 (NVIDIA reservation)
├── .env.example                    # 환경 변수 템플릿
├── backend/
│   ├── Dockerfile                  # CUDA 12.1 + Python 3.11
│   ├── pyproject.toml
│   └── app/
│       ├── main.py                 # FastAPI entry
│       ├── config.py               # env settings
│       ├── db/
│       │   ├── connection.py
│       │   └── migrations/
│       │       └── 001_init.sql    # DB 스키마
│       ├── fetch/                  # KIS / pykrx / DART / 뉴스 (Phase 1)
│       ├── models/                 # Chronos / LightGBM / KR-FinBERT (Phase 2~4)
│       ├── pipelines/              # daily_batch / inference / retrain (Phase 1, 4)
│       └── api/                    # FastAPI 라우터 (Phase 5)
└── web/
    ├── Dockerfile
    ├── package.json
    └── app/
        ├── layout.tsx
        └── page.tsx                # 검색 + 차트 UI (Phase 6)

진행 계획

  • Phase 0 — 스캐폴드: Docker 환경 + DB 스키마 + FastAPI/Next.js + build.bat
  • Phase 1a — pykrx 데이터 파이프: 일봉/외인기관/지수 + DART + 뉴스 RSS + 거시
  • Phase 1b — KIS read-only EOD (스모크 통과)
  • Phase 2 — KR-FinBERT 감성 점수 + 일별 집계 뷰
  • Phase 3 — Chronos zero-shot 예측 어댑터 + 피처 빌더
  • Phase 4 — LightGBM walk-forward + ensemble + 매칭/재학습 잡
  • Phase 5 — FastAPI 엔드포인트 (검색/차트/예측/메트릭/뉴스)
  • Phase 6 — Next.js UI (검색 + 현재 차트 + 예상차트 overlay)
  • Phase 7 (옵션) — 백테스트 페이지 + Chronos/LGBM 단독 shadow 예측

API 엔드포인트 (요약)

메서드 경로 설명
GET /health, /health/db, /health/keys 헬스/외부키 ping
POST /api/refresh/{code}?lookback_days=N 수동 갱신
GET /api/symbols/search?q=&seed_only= 종목 검색 (trigram + prefix)
GET /api/symbols/{code} 종목 메타
GET /api/chart/{code}?days=N OHLCV + 감성 + 외인기관거래대금
POST /api/predict/{code}?horizons=1,3,5 on-demand 앙상블 예측 (user_triggered)
GET /api/predict/{code}/latest 최신 base_date 예측 묶음 (UI overlay)
GET /api/metrics/{code}?window_days=N 종목 hit_rate / mae
GET /api/news/{code}?limit=N&source= 최근 뉴스/공시 + 감성

동작 모델 메모

  • 예측 트리거: 사용자가 "예상차트 보기" 누른 종목에 대해 즉시 inference. 결과는 세 종류 행으로 적재:
    • model='ensemble' (user_triggered=TRUE) — UI 가 표시하는 최종 예측
    • model='chronos' (user_triggered=FALSE, shadow) — Chronos 단독 성능 추적용
    • model='lgbm' (user_triggered=FALSE, shadow) — LGBM 단독 성능 추적용
  • 매칭 배치: 평일 16:30 KST. target_date <= today AND outcomes 미존재 인 모든 행에 대해 target_date 이상 today 이하 범위의 최초 거래일 종가를 actual_close 로 사용 → 주말/공휴일 자동 이월. shadow 행도 함께 매칭됨.
  • 주간 02:00 (일요일): 시드 10종목 × horizons LGBM 재학습. 최근 30일 prediction_outcomes 의 chronos vs lgbm hit_rate 비교 → w_chronos = clamp(0.1, hr_c/(hr_c+hr_l), 0.9) 공식으로 ensemble_weights upsert. 모델별 표본이 10 미만이면 기본값(0.6/0.4) 유지.
  • DB bootstrap: 백엔드 첫 부팅 시 lifespan 에서 idempotent migration + symbols 시드(비어있을 때만 pykrx 전 종목 적재) 자동 수행. BOOTSTRAP_DISABLED=1 로 비활성화 가능.

안전/한계

  • 본인 1인 개인용. 외부 공개/상업 사용 안 함.
  • 자동매매 연결 없음. 예측은 참고용.
  • 백테스트 정확도와 라이브 정확도는 다르며 단기 방향성 모델의 라이브 상한은 보통 55~60%.
Description
No description provided
Readme 381 KiB
Languages
Python 76.4%
TypeScript 18%
Batchfile 3.7%
Dockerfile 1.7%
JavaScript 0.2%