feat(orderbook): 10단계 호가 패널 (KIS asking-price 스냅샷)

backend:
- fetch/kis.py: fetch_orderbook(code) — KIS FHKST01010200 (inquire-asking-price-exp-ccn)
  호출. output1 의 askp1~10/bidp1~10 + 잔량 + 합계, output2 의 현재가/전일대비 파싱.
- api/orderbook.py: GET /api/orderbook/{code}. symbols 매칭 안 되면 404, KIS 키 없으면
  skipped_missing_key 상태로 빈 호가 반환 (502 와 구분).
- main.py: orderbook_router 등록.

frontend:
- lib/api.ts: OrderbookResponse 타입 + api.orderbook(code).
- components/OrderbookPanel.tsx: 매도 10단계(위→아래 가격 내림차순) / 현재가(굵게, 전일대비)
  / 매수 10단계. 잔량 막대는 사이드별 max 정규화로 셀 안에서 자라남. ask=파랑, bid=빨강
  (한국 거래소 관행). 10초 폴링.
- app/[code]/page.tsx: 사이드바에 SymbolSidebar 다음으로 OrderbookPanel 마운트.

실시간 ws 가 아니라 HTTP 폴링이라 KIS rate-limit 친화적. 표시 전용 — 주문/체결 endpoint 는
일절 import 하지 않음 (kis.py 문서 정책).
This commit is contained in:
claude-owner
2026-05-28 19:13:35 +09:00
parent 1a6d953d17
commit fed8ff287e
6 changed files with 362 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ import { DisclosuresPanel } from "../../components/DisclosuresPanel";
import { MetricsPanel } from "../../components/MetricsPanel";
import { PeerComparePanel } from "../../components/PeerComparePanel";
import { NewsList } from "../../components/NewsList";
import { OrderbookPanel } from "../../components/OrderbookPanel";
import { PeriodReturns } from "../../components/PeriodReturns";
import { PeriodTabs, periodSpec, type Period } from "../../components/PeriodTabs";
import { PredictionPanel } from "../../components/PredictionPanel";
@@ -153,6 +154,7 @@ export default function CodePage({ params }: { params: { code: string } }) {
</div>
<div className="space-y-4">
<SymbolSidebar code={code} />
<OrderbookPanel code={code} />
<AlertsPanel code={code} name={chart?.name} current={current} />
<RelatedStocks code={code} />
</div>