Files
kis_bot/docs/증권사_토큰_시세.md
Your Name 36a3e2b4a1 feat: Enhance trading system with new permanent subscription features and order book management
Changes:
- Added a new API endpoint for managing permanent subscriptions, allowing users to enable or disable subscriptions dynamically.
- Implemented a function to fill candle data from Kiwoom, ensuring that only relevant data is inserted into the database.
- Introduced a mechanism to handle master subscription states, improving the management of subscription statuses.
- Updated the database schema to include new fields for managing subscription states and order book filtering.

Impact:
- These enhancements improve the flexibility and reliability of the trading system, allowing for better management of subscriptions and order book data, while reducing the risk of data inconsistencies.

히스토리 align 제거 븅신같은 초기설계 아예 제거
진입모드에 구멍메움
호가진입을 켜도 호가가 안들어올때 호가 안보고 그냥 사버림
2026-08-15 23:01:14 +09:00

212 lines
9.1 KiB
Markdown

# 증권사별 토큰 · 키 · 시세/구독 정리
> 운영 기준 메모 (코드·공식 스펙·실측). **추측 재발급 금지.**
> 관련: `kis_token_manager.py`, `kis_approval_manager.py`, `kis_trader/network/ls_token.py`, `kis_trader/ws/*`, `docs/계정.md`
최종 갱신: 2026-08-15
---
## 0. 한 줄 지도
| 증권사 | 매매 REST | 시세/조회 REST | WS 인증 | WS 구독 한도(실측/코드) | 국내↔해외 |
|--------|-----------|----------------|---------|-------------------------|-----------|
| **한투(KIS)** | access_token (모의/실전 분리) | **시세는 실키** 권장 | **approval_key** (REST 토큰과 별개) | 국내 **41**/세션 | approval **1키=1세션** → hold 시간분할 |
| **키움** | access token (au10001) | 동일 토큰 | WS LOGIN = **같은 토큰** | 그룹당 **100** (`KIWOOM_WS_MAX_SUBSCRIPTIONS`) | 국내 WS 중심 (해외 모멘텀은 한투) |
| **LS** | access_token (`/oauth2/token`) | 동일 토큰 | WS header `token` = **같은 토큰** | 문서상 유연 · 코드는 폭주 가드 | **토큰 1개**로 국내+해외 TR |
공통 사고 유형: **유효 토큰/키를 또 발급** → 상대 경로(국내↔해외·REST↔WS) **무효화**.
---
## 1. 한투 (KIS)
### 1.1 키 종류 (역할 분리)
| 이름 | 발급 | 용도 | 무효화 주의 |
|------|------|------|-------------|
| **접근토큰** `access_token` | `POST /oauth2/tokenP` | 주문·잔고·시세 REST | 잦은 재발급 → 제한(EGW00133 등). **1일 1회 원칙** · 유효 ~24h |
| **approval_key** | `POST /oauth2/Approval` | **WebSocket만** | **6h 이내 재발급 금지**(운영 가드). 새 키 = **기존 WS 세션 무효** |
| AppKey/Secret | 콘솔 | 위 둘의 자격 | 실전/모의 **도메인·키 쌍 분리** |
코드:
- 매매 클라이언트: `KIS_MOCK` 따름 (`kis_trader.main` `self.client`)
- 시세/조회: **항상 실키** (`market_client`) — 모의 도메인 시세 미지원/500 다수
- 토큰 파일 캐시: `kis_token_manager` (실전+모의 **세션 미커버/만료만** 발급)
- approval 파일 캐시: `kis_approval_manager` (국내·해외 WS **공유**)
### 1.2 REST 도메인
| | REST | WS |
|--|------|-----|
| 실전 | `https://openapi.koreainvestment.com:9443` | `ws://ops.koreainvestment.com:21000` |
| 모의 | `https://openapivts.koreainvestment.com:29443` | `ws://ops.koreainvestment.com:31000` |
### 1.3 WebSocket 시세
| TR | 시장 | 내용 | 한도 |
|----|------|------|------|
| `H0STCNT0` | 국내 | 실시간 체결 | **세션당 최대 41종** (`kis_ws.MAX_SUBSCRIPTIONS`) |
| `HDFSCNT0` | 해외 | 실시간(지연) 체결 | 별도 소켓 · **같은 approval** 공유 |
| (호가 등) | 국내 | 주로 REST/다른 TR · 실매 호가필터는 **키움 0D / LS UH1** 경로도 사용 | — |
**국내↔해외 자동전환:** `kis_ws_session_windows`
- 국내 hold 기본 `07:00~20:00` / 해외 `21:00~06:00`
- 갭에서는 **소켓 close만** (approval **재발급 없음**)
- 동시에 두 소켓을 열면 뒤쪽(대개 해외)이 끊김 → **시간분할 필수**
### 1.4 히스토리 · 기타
| 용도 | 경로 |
|------|------|
| 분봉 | REST `inquire-time-itemchartprice` 등 (시세=실키) |
| 틱 적재 | WS → `ws_ticks` / CandleAggregator → `ws_candles` |
| 해외 봉 | `ws_candles.market=US` (HDFSCNT0 롤업) |
| 주문 | REST (모의/실전 = 매매 키) |
env 스위치:
- `STRATEGY_US_MOMENTUM_ENABLED` — 전략 루프 (config_us_momentum)
- `OVERSEAS_WS_ENABLED` — HDFSCNT0 소켓 **기동 시** (env_config)
- `US_MOMENTUM_DRY_RUN` — paper vs 실주문
---
## 2. 키움
### 2.1 토큰
| 항목 | 내용 |
|------|------|
| API | `POST /oauth2/token` (`au10001`) |
| 응답 | `token`, `token_type`, **`expires_dt`** (일시 문자열) |
| 사용처 | REST + **WS LOGIN** (approval 분리 없음) |
| 위험 | **중복 발급 시 이전 토큰 무효** → 시세 WS·조건검색 동시 사망 (과거 사고) |
코드: 공유 캐시 + 서버 거부(805004 등) 시에만 invalidate 후 재발급.
재연결 연타 쿨다운: `KIWOOM_WS_MAX_RECONNECT_*`.
### 2.2 WebSocket
| | 실전 | 모의 |
|--|------|------|
| URL | `wss://api.kiwoom.com:10000/api/dostk/websocket` | `wss://mockapi.kiwoom.com:10000/...` |
| type | 이름 | 용도 |
|------|------|------|
| `0B` | 주식체결 | 틱·현재가·분봉 롤업 |
| `0D` | 주식호가잔량 | 호가필터 / OR 히스토리. **필터 RAM 나이** `WS_ORDERBOOK_FILTER_MAX_AGE_SEC`(기본 0=마지막 장). **저장 TTL** `WS_ORDERBOOK_TICK_MAX_AGE_SEC`(기본 30)과 분리. 사진 한 장도 없으면 `WS_ORDERBOOK_FILTER_REJECT_IF_EMPTY`(기본 true)로 안 삼. 만료로 None 만들어 통과시키지 말 것 |
| `0w` | 종목프로그램매매 | 프로그램 필터 |
| (조건) | 조건검색 실시간 | `kiwoom_condition` 유니버스 |
**구독 한도:** 그룹당 **100종** (`KIWOOM_WS_MAX_SUBSCRIPTIONS`, 기본 100).
실매 운영: 후보 상한 합 + 영구구독 + 보유 ≤ 100.
### 2.3 히스토리
| 용도 | 경로 |
|------|------|
| 분봉 갭 | REST `ka10080` 등 (키움 차트) |
| 틱/호가/프로그램 | WS → RAM + DB (`ws_ticks`, orderbook/program 스냅샷) |
시세 실키 vs 매매 모의는 **한투 쪽 정책**과 혼동하지 말 것. 키움은 주로 **시세/조건** 담당.
---
## 3. LS증권
### 3.1 토큰
| 항목 | 내용 |
|------|------|
| API | `POST https://openapi.ls-sec.co.kr:8080/oauth2/token` |
| grant | `client_credentials` + appkey/appsecretkey |
| 응답 | `access_token`, **`expires_in`/~86400초(24h)** |
| 오류 | `IGW00121` / `IGW00123` (무효·기간만료) → 그때만 재발급 |
| 캐시 | `kis_trader/network/ls_token.py` — 만료 전 재사용 · `LS_TOKEN_MIN_REISSUE_SEC` · **force 남용 금지** |
**국내·해외·조건검색(AFR)·WS 가 토큰 1개 공유.**
세션 전환·워치독 재연결에서 force 재발급하면 **전 경로 무효화** (키움 중복발급과 동형).
`/oauth2/revoke` = 정상 폐기용. 루프에서 쓰지 않음.
### 3.2 WebSocket
| | 실전 | 모의 |
|--|------|------|
| URL | `wss://openapi.ls-sec.co.kr:9443/websocket` | `…:29443/websocket` |
| TR | 시장 | 내용 |
|----|------|------|
| `US3` (기본) / `S3_`·`K3_` | 국내 | 체결 틱 |
| `UH1` 등 | 국내 | 호가 |
| `UVI` 등 | 국내 | VI |
| `JIF` | 국내 | 장운영정보 (워치독 보조) |
| `GSC` | 해외 | 해외 체결 (`82{symbol}` 키) |
소켓 hold (벽시계): `ls_ws_session_windows`
- 국내 `07:00~20:00` / 해외 `21:00~06:00`(해외 구독 있을 때)
- 갭·장외: **소켓 close + 대기**, 토큰 캐시 유지
- 틱 silence 워치독: **정규장 벽시계 우선** (sticky JIF `21`로 장외 연장 금지)
### 3.3 히스토리 · 조건
| 용도 | 경로 |
|------|------|
| 분봉 갭 | REST `t8412``ls_ws_candles` |
| 틱/호가 | WS → `ls_ws_ticks` / `ls_ws_orderbook` |
| 조건식 | AFR `t1860` 등 (`ls_condition`) — JIF/벽시계 AFR 세션 |
---
## 4. 이 봇에서의 역할 분담 (현행)
| 기능 | 주 소스 | 비고 |
|------|---------|------|
| 국내 주문 | **한투** REST | 모의/실전 = `KIS_MOCK` |
| 국내 틱(운영) | **키움** WS (또는 한투 H0STCNT0) | `WS_PROVIDER` / 유니버스 소스에 따름 |
| 국내 호가·프로그램 | **키움** 0D / 0w | 모멘텀 등 |
| 돌파 등 LS 유니버스 | **LS** 조건 + LS 틱/호가 | `BREAKOUT_UNIVERSE_SOURCE=ls_condition` |
| 해외 모멘텀 시세 | **한투** HDFSCNT0 | `permanent_subscriptions` US |
| 해외 모멘텀 주문 | **한투** 해외주문 | `US_MOMENTUM_DRY_RUN` |
### 4.1 전략 ON/OFF vs 소켓
| 스위치 | 테이블 | 효과 | 구독 해제? |
|--------|--------|------|------------|
| `STRATEGY_*_ENABLED` | `config_{strategy}` | 다음 루프부터 **신규매수 중단** (보유 청산은 유지) | **안 함** |
| `STRATEGY_US_MOMENTUM_ENABLED` | `config_us_momentum` | 위와 동일 | **안 함** |
| `OVERSEAS_WS_ENABLED` | `env_config` | **기동 시** 해외 WS 기동 여부 | 기동 전제 · 변경 시 **재시작** |
| `permanent_subscriptions` | DB 테이블 | 영구구독 종목 목록 | UI에서 종목 on/off |
기동 시 OFF였던 전략을 켜려면 **봇 재시작**(쓰레드 미등록).
---
## 5. 재발급 체크리스트 (위반 시 작업 중지)
1. 만료·서버 거부 코드 확인 전에는 **force 발급 금지**
2. KIS approval: 6h 가드 · 국내/해외 **공유 캐시만** · 세션 전환은 **close/open**
3. LS: `expires_in` 캐시 · 세션 hold 전환 시 **oauth 호출 금지**
4. 키움: LOGIN 거부 시에만 invalidate · 재연결 폭주 쿨다운
5. 진단 스크립트도 실매와 **동일 한도**
---
## 6. 코드 앵커
| 주제 | 파일 |
|------|------|
| KIS 접근토큰 | `kis_token_manager.py` |
| KIS approval | `kis_approval_manager.py` |
| KIS 국내 WS | `kis_trader/ws/kis_ws.py` |
| KIS 해외 WS | `kis_trader/ws/kis_ws_overseas.py` |
| KIS hold 창 | `kis_trader/utils/kis_ws_session_windows.py` |
| 키움 WS | `kis_trader/ws/kiwoom_ws.py` |
| LS 토큰 | `kis_trader/network/ls_token.py` |
| LS WS | `kis_trader/ws/ls_ws.py` |
| LS hold 창 | `kis_trader/utils/ls_ws_session_windows.py` |
| 운영 ON/OFF UI | `kis_trader/web/live_config_schema.py` (`strategy_switch`) |