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:
@@ -248,6 +248,27 @@ export type IndicesResponse = {
|
||||
indices: IndexSeries[];
|
||||
};
|
||||
|
||||
export type OrderbookLevel = {
|
||||
level: number;
|
||||
price: number;
|
||||
qty: number;
|
||||
};
|
||||
|
||||
export type OrderbookResponse = {
|
||||
code: string;
|
||||
name: string;
|
||||
market: string;
|
||||
status: "ok" | "skipped_missing_key";
|
||||
ts: string | null;
|
||||
current: number | null;
|
||||
prev_close_diff: number | null;
|
||||
prev_close_pct: number | null;
|
||||
asks: OrderbookLevel[];
|
||||
bids: OrderbookLevel[];
|
||||
ask_total: number;
|
||||
bid_total: number;
|
||||
};
|
||||
|
||||
async function getJson<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
@@ -311,4 +332,6 @@ export const api = {
|
||||
getJson<PeerCompareResponse>(
|
||||
`/api/themes/peer/${encodeURIComponent(code)}?window=${window}&limit=${limit}`,
|
||||
),
|
||||
orderbook: (code: string) =>
|
||||
getJson<OrderbookResponse>(`/api/orderbook/${encodeURIComponent(code)}`),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user