kwcli 1.0.0__tar.gz → 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kwcli-1.0.0 → kwcli-1.0.3}/PKG-INFO +42 -77
- {kwcli-1.0.0 → kwcli-1.0.3}/README.md +40 -75
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/auth.py +13 -2
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/client.py +13 -2
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/errors.py +55 -2
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/runtime.py +86 -11
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/secrets.py +23 -0
- kwcli-1.0.3/kiwoom/core/settings.py +114 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/types.py +12 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/ws_client.py +2 -4
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/README.md +36 -55
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/mapped.py +17 -1
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/spec.py +30 -2
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/streams.py +6 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/README.md +5 -6
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/api_commands.csv +42 -42
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/arguments.csv +10 -10
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/output.py +9 -3
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/registry.py +2 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/setup.py +3 -18
- {kwcli-1.0.0 → kwcli-1.0.3}/pyproject.toml +1 -1
- kwcli-1.0.0/kiwoom/core/settings.py +0 -64
- {kwcli-1.0.0 → kwcli-1.0.3}/LICENSE.md +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/_data/kiwoom_api_spec.json +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/platform_paths.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/profiles.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/core/token_store.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/decoders.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/events.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/packets.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/schemas.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/realtime/stream.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom/specs.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/__main__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/argument_maps.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/arguments.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/auth_context.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/banner.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/auth.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/exchange.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/groups.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/orders.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/commands/stocks.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/doctor.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/errors.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/executor/__init__.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/executor/condition.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/executor/rest.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/executor/waits.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/executor/websocket.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/main.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/coupled_arguments.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/order_confirmation_commands.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/order_confirmation_fields.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/order_price_policies.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/order_value_labels.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/maps/positional_arguments.csv +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/order_confirmation.py +0 -0
- {kwcli-1.0.0 → kwcli-1.0.3}/kiwoom_cli/safety.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: kwcli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Kiwoom OpenAPI toolkit
|
|
5
5
|
License-File: LICENSE.md
|
|
6
6
|
Requires-Python: >=3.13
|
|
@@ -11,19 +11,13 @@ Requires-Dist: requests>=2.33.1
|
|
|
11
11
|
Requires-Dist: websockets>=15.0.1
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
|
|
14
|
-
# Kiwoom CLI
|
|
14
|
+
# 키움증권 CLI (Kiwoom CLI)
|
|
15
15
|
|
|
16
|
-
`kiwoomcli`는 키움증권 OpenAPI를 위한 커맨드라인 클라이언트입니다. 터미널에서
|
|
17
|
-
키움 OpenAPI 데이터를 조회하고, 인증 상태를 관리하며, 안전장치가 적용된 주문
|
|
18
|
-
작업을 수행해야 하는 사람과 AI 에이전트를 위한 **탐색(discovery) 중심**의 운영
|
|
19
|
-
도구입니다.
|
|
16
|
+
`kiwoomcli`는 키움증권 OpenAPI를 위한 커맨드라인 클라이언트입니다. 터미널에서 키움 OpenAPI 데이터를 조회하고, 인증 상태를 관리하며, 안전장치가 적용된 주문 작업을 수행해야 하는 사람과 AI 에이전트를 위한 **탐색(discovery) 중심**의 운영 도구입니다.
|
|
20
17
|
|
|
21
18
|
배포 패키지 이름은 `kwcli` 이며, 설치 후 사용하는 콘솔 명령은 `kiwoomcli` 입니다.
|
|
22
19
|
|
|
23
|
-
> **키움증권 공식 프로젝트**
|
|
24
|
-
> 본 프로젝트는 **키움증권(Kiwoom Securities)이 공식적으로 제공·관리**하는 도구입니다.
|
|
25
|
-
> PyPI 패키지 [`kwcli`](https://pypi.org/project/kwcli/)는 키움증권이 게시한 공식 배포본입니다.
|
|
26
|
-
> 키움 REST API 공식 포털: <https://openapi.kiwoom.com> (API 가이드: <https://openapi.kiwoom.com/guide/apiguide>)
|
|
20
|
+
> **키움증권 공식 프로젝트** 본 프로젝트는 **키움증권(Kiwoom Securities)이 공식적으로 제공·관리**하는 도구입니다. PyPI 패키지 [`kwcli`](https://pypi.org/project/kwcli/)는 키움증권이 게시한 공식 배포본입니다. 키움 REST API 공식 포털: <https://openapi.kiwoom.com> (API 가이드: <https://openapi.kiwoom.com/guide/apiguide>)
|
|
27
21
|
|
|
28
22
|
## 설치
|
|
29
23
|
|
|
@@ -43,9 +37,7 @@ kiwoomcli setup
|
|
|
43
37
|
|
|
44
38
|
## 빠른 시작
|
|
45
39
|
|
|
46
|
-
일상적인 흐름은 **먼저 탐색하고, 그다음 명령 하나를 실행**하는 것입니다. 어떤
|
|
47
|
-
명령이든 `-h`를 붙이면 실시간으로 매핑된 계약 정보(요약 / 동작 / 예시 / OpenAPI
|
|
48
|
-
매핑)를 볼 수 있습니다.
|
|
40
|
+
일상적인 흐름은 **먼저 탐색하고, 그다음 명령 하나를 실행**하는 것입니다. 어떤 명령이든 `-h`를 붙이면 실시간으로 매핑된 계약 정보(요약 / 동작 / 예시 / OpenAPI 매핑)를 볼 수 있습니다.
|
|
49
41
|
|
|
50
42
|
```sh
|
|
51
43
|
kiwoomcli setup # 온보딩: 별칭, demo/real, 키, 검증
|
|
@@ -60,19 +52,9 @@ kiwoomcli domestic orders buy --code 005930 --qty 1 --price 70000 --order-type l
|
|
|
60
52
|
|
|
61
53
|
## 인증과 프로필
|
|
62
54
|
|
|
63
|
-
- `kiwoomcli setup`은 온보딩 초기화 명령입니다.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
호출로 검증하고, 현재 프로필을 지정한 다음 준비 상태 요약을 출력합니다.
|
|
67
|
-
비대화형 셸에서는 멈추지 않고 안내 메시지와 함께 실패합니다(`--mode` 전달).
|
|
68
|
-
- `kiwoomcli doctor`는 읽기 전용 진단 명령입니다. 어떤 인증 컨텍스트가
|
|
69
|
-
선택됐는지(우선순위 `--profile`/`KIWOOM_PROFILE` > `--mode`/`KIWOOM_MODE` >
|
|
70
|
-
현재 프로필), 프로필별 자격 증명/토큰 상태, 권장 조치를 보여줍니다.
|
|
71
|
-
- `--profile NAME`은 저장된 계정 별칭(OS 자격 증명 저장소의 App Key / Secret)을
|
|
72
|
-
사용합니다. `--mode demo|real`은 저장된 별칭을 쓰지 않으며, mode 단독 실행에는
|
|
73
|
-
환경변수가 필요합니다. 이때 환경변수 이름은 모드별로 다릅니다 —
|
|
74
|
-
`real`은 `APP_KEY` / `APP_SECRET`, `demo`는 `APP_KEY_MOCK` / `APP_SECRET_MOCK`.
|
|
75
|
-
자격 증명이 없을 때는 진입 방식에 맞는 해결책을 함께 안내합니다.
|
|
55
|
+
- `kiwoomcli setup`은 온보딩 초기화 명령입니다. 환경을 먼저 점검(OS 자격 증명 저장소 사용 가능 여부, PATH 중복 경고)한 뒤, 계정 별칭 입력 → `demo`/`real` 선택 → App Key/Secret 저장 → 안전한 읽기 전용 호출로 검증 → 현재 프로필 지정 순서로 진행하고, 마지막에 준비 상태 요약을 보여줍니다. 비대화형 셸에서는 멈추지 않고 안내 메시지와 함께 실패합니다(`--mode` 전달).
|
|
56
|
+
- `kiwoomcli doctor`는 읽기 전용 진단 명령입니다. 어떤 인증 컨텍스트가 선택됐는지(우선순위 `--profile`/`KIWOOM_PROFILE` > `--mode`/`KIWOOM_MODE` > 현재 프로필), 프로필별 자격 증명/토큰 상태, 권장 조치를 보여줍니다.
|
|
57
|
+
- `--profile NAME`은 저장된 계정 별칭(OS 자격 증명 저장소의 App Key / Secret)을 사용합니다. `--mode demo|real`은 저장된 별칭을 쓰지 않으며, mode 단독 실행에는 환경변수가 필요합니다. 이때 환경변수 이름은 모드별로 다릅니다 — `real`은 `APP_KEY` / `APP_SECRET`, `demo`는 `APP_KEY_MOCK` / `APP_SECRET_MOCK`. 자격 증명이 없을 때는 진입 방식에 맞는 해결책을 함께 안내합니다.
|
|
76
58
|
|
|
77
59
|
자주 쓰는 인증 명령:
|
|
78
60
|
|
|
@@ -88,13 +70,10 @@ kiwoomcli auth remove <alias>
|
|
|
88
70
|
kiwoomcli auth export [--profile NAME | --mode demo|real] [--dir DIR] [--yes]
|
|
89
71
|
```
|
|
90
72
|
|
|
91
|
-
- `auth clear`는 비밀 정보만 삭제합니다(기본은 토큰 캐시, `--all`을 주면 OS에
|
|
92
|
-
|
|
93
|
-
- `auth remove <alias>`는 계정을 완전히 등록 해제합니다(프로필 항목, 토큰 캐시,
|
|
94
|
-
저장된 자격 증명 모두).
|
|
73
|
+
- `auth clear`는 비밀 정보만 삭제합니다(기본은 토큰 캐시, `--all`을 주면 OS에 저장된 App Key / Secret까지). 별칭 등록 자체는 유지됩니다.
|
|
74
|
+
- `auth remove <alias>`는 계정을 완전히 등록 해제합니다(프로필 항목, 토큰 캐시, 저장된 자격 증명 모두).
|
|
95
75
|
- `auth revoke`는 서버에서 현재 토큰을 폐기하고 로컬 토큰 캐시도 삭제합니다.
|
|
96
|
-
- `auth export`는 저장된 App Key/Secret을 화면에 출력하지 않고 `.env` 파일로
|
|
97
|
-
내보냅니다. 비대화형 환경에서는 `--yes`가 필요합니다.
|
|
76
|
+
- `auth export`는 저장된 App Key/Secret을 화면에 출력하지 않고 `.env` 파일로 내보냅니다. 비대화형 환경에서는 `--yes`가 필요합니다.
|
|
98
77
|
|
|
99
78
|
## 명령 그룹
|
|
100
79
|
|
|
@@ -107,8 +86,7 @@ kiwoomcli spec groups [--format pretty|json|yaml]
|
|
|
107
86
|
kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
108
87
|
```
|
|
109
88
|
|
|
110
|
-
국내 리소스 명령은 주제별 그룹으로 나뉩니다. 대표 예시는 아래와 같습니다(어떤
|
|
111
|
-
명령이든 `-h`를 붙이면 전체 옵션 계약을 볼 수 있습니다).
|
|
89
|
+
국내 리소스 명령은 주제별 그룹으로 나뉩니다. 대표 예시는 아래와 같습니다(어떤 명령이든 `-h`를 붙이면 전체 옵션 계약을 볼 수 있습니다).
|
|
112
90
|
|
|
113
91
|
| 그룹 | 예시 |
|
|
114
92
|
| --- | --- |
|
|
@@ -144,13 +122,9 @@ kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
|
144
122
|
| `exchange` | `kiwoomcli overseas exchange rate --direction krw-to-usd` |
|
|
145
123
|
| `streams` | `kiwoomcli overseas streams trades --exchange NASDAQ --code AAPL --count 1` |
|
|
146
124
|
|
|
147
|
-
전체 API 337개(OAuth 2, 국내주식 206, 미국주식 129)가 로컬 스펙과 CLI
|
|
148
|
-
맵에 포함됩니다. 정확한 옵션은 각 명령의 `-h` 출력으로 확인하세요.
|
|
125
|
+
전체 API 337개(OAuth 2, 국내주식 206, 미국주식 129)가 로컬 스펙과 CLI 맵에 포함됩니다. 정확한 옵션은 각 명령의 `-h` 출력으로 확인하세요.
|
|
149
126
|
|
|
150
|
-
미국주식 `--exchange` 값의 대소문자는 명령별 API 계약을 따릅니다. 종목·시세·
|
|
151
|
-
호가·캔들·계좌·스트림은 `AMEX|NASDAQ|NYSE`, 순위는
|
|
152
|
-
`all|nyse|nasdaq|amex`, 업종의 `period-returns`는
|
|
153
|
-
`ALL|NYSE|AMEX|NASDAQ`을 사용합니다. 항상 해당 명령의 `-h`를 확인하세요.
|
|
127
|
+
미국주식 `--exchange` 값의 대소문자는 명령별 API 계약을 따릅니다. 종목·시세· 호가·캔들·계좌·스트림은 `AMEX|NASDAQ|NYSE`, 순위는 `all|nyse|nasdaq|amex`, 업종의 `period-returns`는 `ALL|NYSE|AMEX|NASDAQ`을 사용합니다. 항상 해당 명령의 `-h`를 확인하세요.
|
|
154
128
|
|
|
155
129
|
## 출력 형식
|
|
156
130
|
|
|
@@ -167,34 +141,25 @@ kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
|
167
141
|
- `json`은 에이전트가 파싱하기 좋은 한 줄 압축 출력입니다.
|
|
168
142
|
- `jsonl`은 한 줄에 JSON 레코드 하나씩 출력합니다(목록 행이나 스트림에 유용).
|
|
169
143
|
- `yaml`은 YAML 형식으로 출력합니다.
|
|
170
|
-
- `--pages`는 REST 연속조회 페이지 수입니다. 기본값은 1이며, 0은 서버가
|
|
171
|
-
제공하는 모든 페이지를 조회합니다. `spec` 명령에는 적용되지 않습니다.
|
|
144
|
+
- `--pages`는 REST 연속조회 페이지 수입니다. 기본값은 1이며, 0은 서버가 제공하는 모든 페이지를 조회합니다. `spec` 명령에는 적용되지 않습니다.
|
|
172
145
|
- REST 명령의 `--named`는 응답 필드 코드를 스펙의 한글명으로 변환합니다.
|
|
173
146
|
|
|
174
|
-
안전장치가 적용된 계좌/주문 조회와 스트림에서는 출력 계층이 계좌 식별자를
|
|
175
|
-
마스킹합니다. 다만 주문번호(`ord_no`, `orig_ord_no` 등)는 `orders modify`/`cancel`
|
|
176
|
-
에 필요하므로 **마스킹하지 않습니다**. 마스킹은 `pretty`, `json`, `jsonl`, `yaml`
|
|
177
|
-
전반에서 동일하게 적용됩니다.
|
|
147
|
+
안전장치가 적용된 계좌/주문 조회와 스트림에서는 출력 계층이 계좌 식별자를 마스킹합니다. 다만 주문번호(`ord_no`, `orig_ord_no` 등)는 `orders modify`/`cancel` 에 필요하므로 **마스킹하지 않습니다**. 마스킹은 `pretty`, `json`, `jsonl`, `yaml` 전반에서 동일하게 적용됩니다.
|
|
178
148
|
|
|
179
149
|
## 스트리밍 (WebSocket)
|
|
180
150
|
|
|
181
|
-
스트림 명령은 포그라운드에서 실행되며 키움 서버 메시지를 출력합니다. 유한한
|
|
182
|
-
실행을 원하면 `--count`/`--duration`을 사용하세요.
|
|
151
|
+
스트림 명령은 포그라운드에서 실행되며 키움 서버 메시지를 출력합니다. 유한한 실행을 원하면 `--count`/`--duration`을 사용하세요.
|
|
183
152
|
|
|
184
153
|
```sh
|
|
185
154
|
kiwoomcli domestic streams trades --code 005930 --count 1 --named --format json
|
|
186
155
|
kiwoomcli overseas streams trades --exchange NASDAQ --code AAPL --count 1 --named --format json
|
|
187
156
|
```
|
|
188
157
|
|
|
189
|
-
- `--count`는 `REAL` 데이터 메시지만 셉니다. `REG`/`REMOVE`/`SYSTEM`은 제어
|
|
190
|
-
|
|
191
|
-
- `--
|
|
192
|
-
합니다.
|
|
193
|
-
- 스트림 명령의 `--named`는 키움 스펙 기반 내장 스키마로 `REAL` 프레임 FID를
|
|
194
|
-
변환합니다. 알 수 없는 FID는 `unknown` 아래에 보존됩니다.
|
|
158
|
+
- `--count`는 `REAL` 데이터 메시지만 셉니다. `REG`/`REMOVE`/`SYSTEM`은 제어 메시지입니다.
|
|
159
|
+
- `--check`는 유한한 등록/수집을 수행하며, `REAL` 틱이 오지 않아도 정상 종료합니다.
|
|
160
|
+
- 스트림 명령의 `--named`는 키움 스펙 기반 내장 스키마로 `REAL` 프레임 FID를 변환합니다. 알 수 없는 FID는 `unknown` 아래에 보존됩니다.
|
|
195
161
|
|
|
196
|
-
장시간 구독을 저장하려면 파일로 출력하고 OS 도구로 프로세스를 백그라운드로
|
|
197
|
-
돌리세요(CLI는 자체 작업 관리자를 제공하지 않습니다).
|
|
162
|
+
장시간 구독을 저장하려면 파일로 출력하고 OS 도구로 프로세스를 백그라운드로 돌리세요(CLI는 자체 작업 관리자를 제공하지 않습니다).
|
|
198
163
|
|
|
199
164
|
```sh
|
|
200
165
|
# 계속 수신하며 이벤트를 파일에 추가 기록
|
|
@@ -207,30 +172,21 @@ nohup kiwoomcli domestic streams trades --codes 005930,000660 --watch --output t
|
|
|
207
172
|
Start-Process kiwoomcli -ArgumentList 'domestic streams trades --codes 005930,000660 --watch --output trades.jsonl'
|
|
208
173
|
```
|
|
209
174
|
|
|
210
|
-
조건검색식의 생성과 수정은 키움 영웅문 HTS에서 합니다. CLI는 HTS에 이미 저장된
|
|
211
|
-
조건식을 목록 조회, 선택, 조회, 구독, 해제만 합니다.
|
|
175
|
+
조건검색식의 생성과 수정은 키움 영웅문 HTS에서 합니다. CLI는 HTS에 이미 저장된 조건식을 목록 조회, 선택, 조회, 구독, 해제만 합니다.
|
|
212
176
|
|
|
213
177
|
## 주문 안전장치
|
|
214
178
|
|
|
215
|
-
국내·미국주식 주문 쓰기 명령(`orders buy/sell/modify/cancel`,
|
|
216
|
-
`credit-*`, `gold-*`)과 미국주식 환전 신청(`overseas exchange request`)에는
|
|
217
|
-
안전장치가 적용됩니다.
|
|
179
|
+
국내·미국주식 주문 쓰기 명령(`orders buy/sell/modify/cancel`, `credit-*`, `gold-*`)과 미국주식 환전 신청(`overseas exchange request`)에는 안전장치가 적용됩니다.
|
|
218
180
|
|
|
219
|
-
- `--confirm`이 없으면 짧은 미전송 주문 요약을 출력하고 주문 API를 호출하지
|
|
220
|
-
않습니다.
|
|
181
|
+
- `--confirm`이 없으면 짧은 미전송 주문 요약을 출력하고 주문 API를 호출하지 않습니다.
|
|
221
182
|
- `--confirm`이 있으면 실제 엔드포인트로 전송합니다.
|
|
222
|
-
- `overseas exchange request`도 `--confirm`이 없으면 미전송 환전 확인만
|
|
223
|
-
|
|
224
|
-
- 주문
|
|
225
|
-
`--order-type limit`에는 `--price`가 필요하고, `--order-type market`에는
|
|
226
|
-
`--price`를 넣으면 안 됩니다. 잘못된 주문 식별자는 전송 전에 보고됩니다.
|
|
227
|
-
- 주문 쓰기는 `--profile`/`--mode`로 인증 대상을 선택합니다. 먼저 데모(모의투자)
|
|
228
|
-
서버에서 검증하세요.
|
|
183
|
+
- `overseas exchange request`도 `--confirm`이 없으면 미전송 환전 확인만 출력하며, `--confirm`이 있어야 실제 환전 API를 호출합니다.
|
|
184
|
+
- 주문 유형별 가격 규칙은 전송 경로 이전에 검증됩니다. 예를 들어 `--order-type limit`에는 `--price`가 필요하고, `--order-type market`에는 `--price`를 넣으면 안 됩니다. 잘못된 주문 식별자는 전송 전에 보고됩니다.
|
|
185
|
+
- 주문 쓰기는 `--profile`/`--mode`로 인증 대상을 선택합니다. 먼저 데모(모의투자) 서버에서 검증하세요.
|
|
229
186
|
|
|
230
187
|
## 용어
|
|
231
188
|
|
|
232
|
-
안정적인 사용자 대상
|
|
233
|
-
종류는 명령 맥락에 따라 결정됩니다.
|
|
189
|
+
각 옵션 이름은 키움 원본 필드명 대신 안정적인 사용자 대상 이름으로 노출됩니다. 구체적으로 어떤 코드를 넣어야 하는지는 명령마다 다릅니다.
|
|
234
190
|
|
|
235
191
|
| 개념 | 옵션 | 예시 |
|
|
236
192
|
| --- | --- | --- |
|
|
@@ -253,7 +209,16 @@ Start-Process kiwoomcli -ArgumentList 'domestic streams trades --codes 005930,00
|
|
|
253
209
|
## 안전 유의사항
|
|
254
210
|
|
|
255
211
|
- 개발과 검증 단계에서는 `demo` 모드를 우선 사용하세요.
|
|
256
|
-
- 자격 증명, 토큰, 계좌번호, 정제되지 않은 실제 호출 출력은 절대 로그로 남기거나
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
212
|
+
- 자격 증명, 토큰, 계좌번호, 정제되지 않은 실제 호출 출력은 절대 로그로 남기거나 커밋하지 마세요.
|
|
213
|
+
- 자격 증명·네트워크·계좌 안전 제약으로 실제 호출이 막히면, CLI는 결과를 지어내지 않고 차단됨/미실행으로 보고합니다.
|
|
214
|
+
|
|
215
|
+
## 알려진 제약
|
|
216
|
+
|
|
217
|
+
- 국내 주문 취소(`domestic orders cancel`)는 `--qty`로 수량 일부만 취소할 수 있지만, 해외 주문 취소(`overseas orders cancel`)는 **전량만** 가능합니다. 해외 주문 정정(`overseas orders modify`)은 수량은 바꿀 수 없고 **가격만** 바꿀 수 있습니다(원주문이 STOP 주문이면 `--stop-price` 필수).
|
|
218
|
+
- `domestic orders list-open`의 `--exchange`는 주문용 값인 `SOR`을 받지 않습니다 — `ALL`로 조회하세요. `overseas accounts open-orders`는 `--exchange`를 `--code` 없이 받지 않습니다(서버 제약) — 종목을 지정하지 않는 미체결 조회는 거래소 없이 전체로 조회하세요.
|
|
219
|
+
- 너무 짧은 간격으로 연속 조회하면 유량 제한(429) 오류가 날 수 있습니다. 반복 호출에는 간격을 두세요.
|
|
220
|
+
- 모의투자(demo) 계좌에서는 환율 조회, 주문가능금액 조회가 거절됩니다(실전 계좌에서만 가능).
|
|
221
|
+
- 계좌마다 거래할 수 있는 시장이 다를 수 있습니다. 해당 계좌가 다루지 않는 시장은 주문이 거절되거나 조회 결과가 오류 없이 빈 목록으로 돌아올 수 있으므로, 결과가 비어 있다면 먼저 `--profile`/`--mode`로 선택한 계좌를 확인하세요. 장 운영 시간이 아닐 때 국내 주문을 시도하면 이와는 다른 이유(장 종료)로 거절됩니다.
|
|
222
|
+
- 현재가 조회(`domestic quotes price`) 응답에는 전일대비 값이 직접 포함되어 있지 않습니다 — 현재가와 전일 종가의 차이로 직접 계산해야 합니다.
|
|
223
|
+
- `auth list`/`auth status`는 `--format json`을 지원하지 않고 사람이 읽는 텍스트만 출력합니다.
|
|
224
|
+
- 일부 계좌 조회 명령(`accounts valuation`/`accounts holdings`)에는 `--named`가 없어, 응답 필드가 키움 원본 코드로 나옵니다.
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
# Kiwoom CLI
|
|
1
|
+
# 키움증권 CLI (Kiwoom CLI)
|
|
2
2
|
|
|
3
|
-
`kiwoomcli`는 키움증권 OpenAPI를 위한 커맨드라인 클라이언트입니다. 터미널에서
|
|
4
|
-
키움 OpenAPI 데이터를 조회하고, 인증 상태를 관리하며, 안전장치가 적용된 주문
|
|
5
|
-
작업을 수행해야 하는 사람과 AI 에이전트를 위한 **탐색(discovery) 중심**의 운영
|
|
6
|
-
도구입니다.
|
|
3
|
+
`kiwoomcli`는 키움증권 OpenAPI를 위한 커맨드라인 클라이언트입니다. 터미널에서 키움 OpenAPI 데이터를 조회하고, 인증 상태를 관리하며, 안전장치가 적용된 주문 작업을 수행해야 하는 사람과 AI 에이전트를 위한 **탐색(discovery) 중심**의 운영 도구입니다.
|
|
7
4
|
|
|
8
5
|
배포 패키지 이름은 `kwcli` 이며, 설치 후 사용하는 콘솔 명령은 `kiwoomcli` 입니다.
|
|
9
6
|
|
|
10
|
-
> **키움증권 공식 프로젝트**
|
|
11
|
-
> 본 프로젝트는 **키움증권(Kiwoom Securities)이 공식적으로 제공·관리**하는 도구입니다.
|
|
12
|
-
> PyPI 패키지 [`kwcli`](https://pypi.org/project/kwcli/)는 키움증권이 게시한 공식 배포본입니다.
|
|
13
|
-
> 키움 REST API 공식 포털: <https://openapi.kiwoom.com> (API 가이드: <https://openapi.kiwoom.com/guide/apiguide>)
|
|
7
|
+
> **키움증권 공식 프로젝트** 본 프로젝트는 **키움증권(Kiwoom Securities)이 공식적으로 제공·관리**하는 도구입니다. PyPI 패키지 [`kwcli`](https://pypi.org/project/kwcli/)는 키움증권이 게시한 공식 배포본입니다. 키움 REST API 공식 포털: <https://openapi.kiwoom.com> (API 가이드: <https://openapi.kiwoom.com/guide/apiguide>)
|
|
14
8
|
|
|
15
9
|
## 설치
|
|
16
10
|
|
|
@@ -30,9 +24,7 @@ kiwoomcli setup
|
|
|
30
24
|
|
|
31
25
|
## 빠른 시작
|
|
32
26
|
|
|
33
|
-
일상적인 흐름은 **먼저 탐색하고, 그다음 명령 하나를 실행**하는 것입니다. 어떤
|
|
34
|
-
명령이든 `-h`를 붙이면 실시간으로 매핑된 계약 정보(요약 / 동작 / 예시 / OpenAPI
|
|
35
|
-
매핑)를 볼 수 있습니다.
|
|
27
|
+
일상적인 흐름은 **먼저 탐색하고, 그다음 명령 하나를 실행**하는 것입니다. 어떤 명령이든 `-h`를 붙이면 실시간으로 매핑된 계약 정보(요약 / 동작 / 예시 / OpenAPI 매핑)를 볼 수 있습니다.
|
|
36
28
|
|
|
37
29
|
```sh
|
|
38
30
|
kiwoomcli setup # 온보딩: 별칭, demo/real, 키, 검증
|
|
@@ -47,19 +39,9 @@ kiwoomcli domestic orders buy --code 005930 --qty 1 --price 70000 --order-type l
|
|
|
47
39
|
|
|
48
40
|
## 인증과 프로필
|
|
49
41
|
|
|
50
|
-
- `kiwoomcli setup`은 온보딩 초기화 명령입니다.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
호출로 검증하고, 현재 프로필을 지정한 다음 준비 상태 요약을 출력합니다.
|
|
54
|
-
비대화형 셸에서는 멈추지 않고 안내 메시지와 함께 실패합니다(`--mode` 전달).
|
|
55
|
-
- `kiwoomcli doctor`는 읽기 전용 진단 명령입니다. 어떤 인증 컨텍스트가
|
|
56
|
-
선택됐는지(우선순위 `--profile`/`KIWOOM_PROFILE` > `--mode`/`KIWOOM_MODE` >
|
|
57
|
-
현재 프로필), 프로필별 자격 증명/토큰 상태, 권장 조치를 보여줍니다.
|
|
58
|
-
- `--profile NAME`은 저장된 계정 별칭(OS 자격 증명 저장소의 App Key / Secret)을
|
|
59
|
-
사용합니다. `--mode demo|real`은 저장된 별칭을 쓰지 않으며, mode 단독 실행에는
|
|
60
|
-
환경변수가 필요합니다. 이때 환경변수 이름은 모드별로 다릅니다 —
|
|
61
|
-
`real`은 `APP_KEY` / `APP_SECRET`, `demo`는 `APP_KEY_MOCK` / `APP_SECRET_MOCK`.
|
|
62
|
-
자격 증명이 없을 때는 진입 방식에 맞는 해결책을 함께 안내합니다.
|
|
42
|
+
- `kiwoomcli setup`은 온보딩 초기화 명령입니다. 환경을 먼저 점검(OS 자격 증명 저장소 사용 가능 여부, PATH 중복 경고)한 뒤, 계정 별칭 입력 → `demo`/`real` 선택 → App Key/Secret 저장 → 안전한 읽기 전용 호출로 검증 → 현재 프로필 지정 순서로 진행하고, 마지막에 준비 상태 요약을 보여줍니다. 비대화형 셸에서는 멈추지 않고 안내 메시지와 함께 실패합니다(`--mode` 전달).
|
|
43
|
+
- `kiwoomcli doctor`는 읽기 전용 진단 명령입니다. 어떤 인증 컨텍스트가 선택됐는지(우선순위 `--profile`/`KIWOOM_PROFILE` > `--mode`/`KIWOOM_MODE` > 현재 프로필), 프로필별 자격 증명/토큰 상태, 권장 조치를 보여줍니다.
|
|
44
|
+
- `--profile NAME`은 저장된 계정 별칭(OS 자격 증명 저장소의 App Key / Secret)을 사용합니다. `--mode demo|real`은 저장된 별칭을 쓰지 않으며, mode 단독 실행에는 환경변수가 필요합니다. 이때 환경변수 이름은 모드별로 다릅니다 — `real`은 `APP_KEY` / `APP_SECRET`, `demo`는 `APP_KEY_MOCK` / `APP_SECRET_MOCK`. 자격 증명이 없을 때는 진입 방식에 맞는 해결책을 함께 안내합니다.
|
|
63
45
|
|
|
64
46
|
자주 쓰는 인증 명령:
|
|
65
47
|
|
|
@@ -75,13 +57,10 @@ kiwoomcli auth remove <alias>
|
|
|
75
57
|
kiwoomcli auth export [--profile NAME | --mode demo|real] [--dir DIR] [--yes]
|
|
76
58
|
```
|
|
77
59
|
|
|
78
|
-
- `auth clear`는 비밀 정보만 삭제합니다(기본은 토큰 캐시, `--all`을 주면 OS에
|
|
79
|
-
|
|
80
|
-
- `auth remove <alias>`는 계정을 완전히 등록 해제합니다(프로필 항목, 토큰 캐시,
|
|
81
|
-
저장된 자격 증명 모두).
|
|
60
|
+
- `auth clear`는 비밀 정보만 삭제합니다(기본은 토큰 캐시, `--all`을 주면 OS에 저장된 App Key / Secret까지). 별칭 등록 자체는 유지됩니다.
|
|
61
|
+
- `auth remove <alias>`는 계정을 완전히 등록 해제합니다(프로필 항목, 토큰 캐시, 저장된 자격 증명 모두).
|
|
82
62
|
- `auth revoke`는 서버에서 현재 토큰을 폐기하고 로컬 토큰 캐시도 삭제합니다.
|
|
83
|
-
- `auth export`는 저장된 App Key/Secret을 화면에 출력하지 않고 `.env` 파일로
|
|
84
|
-
내보냅니다. 비대화형 환경에서는 `--yes`가 필요합니다.
|
|
63
|
+
- `auth export`는 저장된 App Key/Secret을 화면에 출력하지 않고 `.env` 파일로 내보냅니다. 비대화형 환경에서는 `--yes`가 필요합니다.
|
|
85
64
|
|
|
86
65
|
## 명령 그룹
|
|
87
66
|
|
|
@@ -94,8 +73,7 @@ kiwoomcli spec groups [--format pretty|json|yaml]
|
|
|
94
73
|
kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
95
74
|
```
|
|
96
75
|
|
|
97
|
-
국내 리소스 명령은 주제별 그룹으로 나뉩니다. 대표 예시는 아래와 같습니다(어떤
|
|
98
|
-
명령이든 `-h`를 붙이면 전체 옵션 계약을 볼 수 있습니다).
|
|
76
|
+
국내 리소스 명령은 주제별 그룹으로 나뉩니다. 대표 예시는 아래와 같습니다(어떤 명령이든 `-h`를 붙이면 전체 옵션 계약을 볼 수 있습니다).
|
|
99
77
|
|
|
100
78
|
| 그룹 | 예시 |
|
|
101
79
|
| --- | --- |
|
|
@@ -131,13 +109,9 @@ kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
|
131
109
|
| `exchange` | `kiwoomcli overseas exchange rate --direction krw-to-usd` |
|
|
132
110
|
| `streams` | `kiwoomcli overseas streams trades --exchange NASDAQ --code AAPL --count 1` |
|
|
133
111
|
|
|
134
|
-
전체 API 337개(OAuth 2, 국내주식 206, 미국주식 129)가 로컬 스펙과 CLI
|
|
135
|
-
맵에 포함됩니다. 정확한 옵션은 각 명령의 `-h` 출력으로 확인하세요.
|
|
112
|
+
전체 API 337개(OAuth 2, 국내주식 206, 미국주식 129)가 로컬 스펙과 CLI 맵에 포함됩니다. 정확한 옵션은 각 명령의 `-h` 출력으로 확인하세요.
|
|
136
113
|
|
|
137
|
-
미국주식 `--exchange` 값의 대소문자는 명령별 API 계약을 따릅니다. 종목·시세·
|
|
138
|
-
호가·캔들·계좌·스트림은 `AMEX|NASDAQ|NYSE`, 순위는
|
|
139
|
-
`all|nyse|nasdaq|amex`, 업종의 `period-returns`는
|
|
140
|
-
`ALL|NYSE|AMEX|NASDAQ`을 사용합니다. 항상 해당 명령의 `-h`를 확인하세요.
|
|
114
|
+
미국주식 `--exchange` 값의 대소문자는 명령별 API 계약을 따릅니다. 종목·시세· 호가·캔들·계좌·스트림은 `AMEX|NASDAQ|NYSE`, 순위는 `all|nyse|nasdaq|amex`, 업종의 `period-returns`는 `ALL|NYSE|AMEX|NASDAQ`을 사용합니다. 항상 해당 명령의 `-h`를 확인하세요.
|
|
141
115
|
|
|
142
116
|
## 출력 형식
|
|
143
117
|
|
|
@@ -154,34 +128,25 @@ kiwoomcli spec apis [--group <text>] [--limit N] [--format pretty|json|yaml]
|
|
|
154
128
|
- `json`은 에이전트가 파싱하기 좋은 한 줄 압축 출력입니다.
|
|
155
129
|
- `jsonl`은 한 줄에 JSON 레코드 하나씩 출력합니다(목록 행이나 스트림에 유용).
|
|
156
130
|
- `yaml`은 YAML 형식으로 출력합니다.
|
|
157
|
-
- `--pages`는 REST 연속조회 페이지 수입니다. 기본값은 1이며, 0은 서버가
|
|
158
|
-
제공하는 모든 페이지를 조회합니다. `spec` 명령에는 적용되지 않습니다.
|
|
131
|
+
- `--pages`는 REST 연속조회 페이지 수입니다. 기본값은 1이며, 0은 서버가 제공하는 모든 페이지를 조회합니다. `spec` 명령에는 적용되지 않습니다.
|
|
159
132
|
- REST 명령의 `--named`는 응답 필드 코드를 스펙의 한글명으로 변환합니다.
|
|
160
133
|
|
|
161
|
-
안전장치가 적용된 계좌/주문 조회와 스트림에서는 출력 계층이 계좌 식별자를
|
|
162
|
-
마스킹합니다. 다만 주문번호(`ord_no`, `orig_ord_no` 등)는 `orders modify`/`cancel`
|
|
163
|
-
에 필요하므로 **마스킹하지 않습니다**. 마스킹은 `pretty`, `json`, `jsonl`, `yaml`
|
|
164
|
-
전반에서 동일하게 적용됩니다.
|
|
134
|
+
안전장치가 적용된 계좌/주문 조회와 스트림에서는 출력 계층이 계좌 식별자를 마스킹합니다. 다만 주문번호(`ord_no`, `orig_ord_no` 등)는 `orders modify`/`cancel` 에 필요하므로 **마스킹하지 않습니다**. 마스킹은 `pretty`, `json`, `jsonl`, `yaml` 전반에서 동일하게 적용됩니다.
|
|
165
135
|
|
|
166
136
|
## 스트리밍 (WebSocket)
|
|
167
137
|
|
|
168
|
-
스트림 명령은 포그라운드에서 실행되며 키움 서버 메시지를 출력합니다. 유한한
|
|
169
|
-
실행을 원하면 `--count`/`--duration`을 사용하세요.
|
|
138
|
+
스트림 명령은 포그라운드에서 실행되며 키움 서버 메시지를 출력합니다. 유한한 실행을 원하면 `--count`/`--duration`을 사용하세요.
|
|
170
139
|
|
|
171
140
|
```sh
|
|
172
141
|
kiwoomcli domestic streams trades --code 005930 --count 1 --named --format json
|
|
173
142
|
kiwoomcli overseas streams trades --exchange NASDAQ --code AAPL --count 1 --named --format json
|
|
174
143
|
```
|
|
175
144
|
|
|
176
|
-
- `--count`는 `REAL` 데이터 메시지만 셉니다. `REG`/`REMOVE`/`SYSTEM`은 제어
|
|
177
|
-
|
|
178
|
-
- `--
|
|
179
|
-
합니다.
|
|
180
|
-
- 스트림 명령의 `--named`는 키움 스펙 기반 내장 스키마로 `REAL` 프레임 FID를
|
|
181
|
-
변환합니다. 알 수 없는 FID는 `unknown` 아래에 보존됩니다.
|
|
145
|
+
- `--count`는 `REAL` 데이터 메시지만 셉니다. `REG`/`REMOVE`/`SYSTEM`은 제어 메시지입니다.
|
|
146
|
+
- `--check`는 유한한 등록/수집을 수행하며, `REAL` 틱이 오지 않아도 정상 종료합니다.
|
|
147
|
+
- 스트림 명령의 `--named`는 키움 스펙 기반 내장 스키마로 `REAL` 프레임 FID를 변환합니다. 알 수 없는 FID는 `unknown` 아래에 보존됩니다.
|
|
182
148
|
|
|
183
|
-
장시간 구독을 저장하려면 파일로 출력하고 OS 도구로 프로세스를 백그라운드로
|
|
184
|
-
돌리세요(CLI는 자체 작업 관리자를 제공하지 않습니다).
|
|
149
|
+
장시간 구독을 저장하려면 파일로 출력하고 OS 도구로 프로세스를 백그라운드로 돌리세요(CLI는 자체 작업 관리자를 제공하지 않습니다).
|
|
185
150
|
|
|
186
151
|
```sh
|
|
187
152
|
# 계속 수신하며 이벤트를 파일에 추가 기록
|
|
@@ -194,30 +159,21 @@ nohup kiwoomcli domestic streams trades --codes 005930,000660 --watch --output t
|
|
|
194
159
|
Start-Process kiwoomcli -ArgumentList 'domestic streams trades --codes 005930,000660 --watch --output trades.jsonl'
|
|
195
160
|
```
|
|
196
161
|
|
|
197
|
-
조건검색식의 생성과 수정은 키움 영웅문 HTS에서 합니다. CLI는 HTS에 이미 저장된
|
|
198
|
-
조건식을 목록 조회, 선택, 조회, 구독, 해제만 합니다.
|
|
162
|
+
조건검색식의 생성과 수정은 키움 영웅문 HTS에서 합니다. CLI는 HTS에 이미 저장된 조건식을 목록 조회, 선택, 조회, 구독, 해제만 합니다.
|
|
199
163
|
|
|
200
164
|
## 주문 안전장치
|
|
201
165
|
|
|
202
|
-
국내·미국주식 주문 쓰기 명령(`orders buy/sell/modify/cancel`,
|
|
203
|
-
`credit-*`, `gold-*`)과 미국주식 환전 신청(`overseas exchange request`)에는
|
|
204
|
-
안전장치가 적용됩니다.
|
|
166
|
+
국내·미국주식 주문 쓰기 명령(`orders buy/sell/modify/cancel`, `credit-*`, `gold-*`)과 미국주식 환전 신청(`overseas exchange request`)에는 안전장치가 적용됩니다.
|
|
205
167
|
|
|
206
|
-
- `--confirm`이 없으면 짧은 미전송 주문 요약을 출력하고 주문 API를 호출하지
|
|
207
|
-
않습니다.
|
|
168
|
+
- `--confirm`이 없으면 짧은 미전송 주문 요약을 출력하고 주문 API를 호출하지 않습니다.
|
|
208
169
|
- `--confirm`이 있으면 실제 엔드포인트로 전송합니다.
|
|
209
|
-
- `overseas exchange request`도 `--confirm`이 없으면 미전송 환전 확인만
|
|
210
|
-
|
|
211
|
-
- 주문
|
|
212
|
-
`--order-type limit`에는 `--price`가 필요하고, `--order-type market`에는
|
|
213
|
-
`--price`를 넣으면 안 됩니다. 잘못된 주문 식별자는 전송 전에 보고됩니다.
|
|
214
|
-
- 주문 쓰기는 `--profile`/`--mode`로 인증 대상을 선택합니다. 먼저 데모(모의투자)
|
|
215
|
-
서버에서 검증하세요.
|
|
170
|
+
- `overseas exchange request`도 `--confirm`이 없으면 미전송 환전 확인만 출력하며, `--confirm`이 있어야 실제 환전 API를 호출합니다.
|
|
171
|
+
- 주문 유형별 가격 규칙은 전송 경로 이전에 검증됩니다. 예를 들어 `--order-type limit`에는 `--price`가 필요하고, `--order-type market`에는 `--price`를 넣으면 안 됩니다. 잘못된 주문 식별자는 전송 전에 보고됩니다.
|
|
172
|
+
- 주문 쓰기는 `--profile`/`--mode`로 인증 대상을 선택합니다. 먼저 데모(모의투자) 서버에서 검증하세요.
|
|
216
173
|
|
|
217
174
|
## 용어
|
|
218
175
|
|
|
219
|
-
안정적인 사용자 대상
|
|
220
|
-
종류는 명령 맥락에 따라 결정됩니다.
|
|
176
|
+
각 옵션 이름은 키움 원본 필드명 대신 안정적인 사용자 대상 이름으로 노출됩니다. 구체적으로 어떤 코드를 넣어야 하는지는 명령마다 다릅니다.
|
|
221
177
|
|
|
222
178
|
| 개념 | 옵션 | 예시 |
|
|
223
179
|
| --- | --- | --- |
|
|
@@ -240,7 +196,16 @@ Start-Process kiwoomcli -ArgumentList 'domestic streams trades --codes 005930,00
|
|
|
240
196
|
## 안전 유의사항
|
|
241
197
|
|
|
242
198
|
- 개발과 검증 단계에서는 `demo` 모드를 우선 사용하세요.
|
|
243
|
-
- 자격 증명, 토큰, 계좌번호, 정제되지 않은 실제 호출 출력은 절대 로그로 남기거나
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
199
|
+
- 자격 증명, 토큰, 계좌번호, 정제되지 않은 실제 호출 출력은 절대 로그로 남기거나 커밋하지 마세요.
|
|
200
|
+
- 자격 증명·네트워크·계좌 안전 제약으로 실제 호출이 막히면, CLI는 결과를 지어내지 않고 차단됨/미실행으로 보고합니다.
|
|
201
|
+
|
|
202
|
+
## 알려진 제약
|
|
203
|
+
|
|
204
|
+
- 국내 주문 취소(`domestic orders cancel`)는 `--qty`로 수량 일부만 취소할 수 있지만, 해외 주문 취소(`overseas orders cancel`)는 **전량만** 가능합니다. 해외 주문 정정(`overseas orders modify`)은 수량은 바꿀 수 없고 **가격만** 바꿀 수 있습니다(원주문이 STOP 주문이면 `--stop-price` 필수).
|
|
205
|
+
- `domestic orders list-open`의 `--exchange`는 주문용 값인 `SOR`을 받지 않습니다 — `ALL`로 조회하세요. `overseas accounts open-orders`는 `--exchange`를 `--code` 없이 받지 않습니다(서버 제약) — 종목을 지정하지 않는 미체결 조회는 거래소 없이 전체로 조회하세요.
|
|
206
|
+
- 너무 짧은 간격으로 연속 조회하면 유량 제한(429) 오류가 날 수 있습니다. 반복 호출에는 간격을 두세요.
|
|
207
|
+
- 모의투자(demo) 계좌에서는 환율 조회, 주문가능금액 조회가 거절됩니다(실전 계좌에서만 가능).
|
|
208
|
+
- 계좌마다 거래할 수 있는 시장이 다를 수 있습니다. 해당 계좌가 다루지 않는 시장은 주문이 거절되거나 조회 결과가 오류 없이 빈 목록으로 돌아올 수 있으므로, 결과가 비어 있다면 먼저 `--profile`/`--mode`로 선택한 계좌를 확인하세요. 장 운영 시간이 아닐 때 국내 주문을 시도하면 이와는 다른 이유(장 종료)로 거절됩니다.
|
|
209
|
+
- 현재가 조회(`domestic quotes price`) 응답에는 전일대비 값이 직접 포함되어 있지 않습니다 — 현재가와 전일 종가의 차이로 직접 계산해야 합니다.
|
|
210
|
+
- `auth list`/`auth status`는 `--format json`을 지원하지 않고 사람이 읽는 텍스트만 출력합니다.
|
|
211
|
+
- 일부 계좌 조회 명령(`accounts valuation`/`accounts holdings`)에는 `--named`가 없어, 응답 필드가 키움 원본 코드로 나옵니다.
|
|
@@ -328,8 +328,19 @@ class KiwoomAuth:
|
|
|
328
328
|
|
|
329
329
|
@staticmethod
|
|
330
330
|
def _credential_fingerprint(credentials: CredentialSet) -> str:
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
return credential_fingerprint(credentials)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def credential_fingerprint(credentials: CredentialSet) -> str:
|
|
335
|
+
"""Non-reversible identity of an appkey/secret pair.
|
|
336
|
+
|
|
337
|
+
Stored beside a cached token so a token issued for one key pair is never
|
|
338
|
+
reused after the credentials change (`_load_valid_token`), and used by the
|
|
339
|
+
runtime to seed a pre-issued token (`KIWOOM_ACCESS_TOKEN`) with the
|
|
340
|
+
fingerprint the auth object will check it against.
|
|
341
|
+
"""
|
|
342
|
+
raw = f"{credentials.appkey}:{credentials.secretkey}".encode("utf-8")
|
|
343
|
+
return hashlib.sha256(raw).hexdigest()
|
|
333
344
|
|
|
334
345
|
|
|
335
346
|
def _safe_json(response: requests.Response) -> dict:
|
|
@@ -6,10 +6,11 @@ import requests
|
|
|
6
6
|
|
|
7
7
|
from kiwoom.core.auth import KiwoomAuth, get_base_url
|
|
8
8
|
from kiwoom.core.errors import (
|
|
9
|
-
AUTH_RETRY_RETURN_CODES,
|
|
10
9
|
AuthenticationError,
|
|
11
10
|
HTTPRequestError,
|
|
11
|
+
auth_retry_code,
|
|
12
12
|
normalize_return_code,
|
|
13
|
+
raise_for_error_code,
|
|
13
14
|
)
|
|
14
15
|
from kiwoom.core.types import Continuation, KiwoomResponse
|
|
15
16
|
|
|
@@ -81,7 +82,9 @@ class KiwoomClient:
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
return_code = normalize_return_code(data.get("return_code"))
|
|
84
|
-
|
|
85
|
+
# 키움은 만료/무효 토큰을 top-level return_code=8005로도, return_code=3 +
|
|
86
|
+
# return_msg "[8005:...]"로도 돌려준다 — 어느 쪽이든 한 번 재발급 후 재시도.
|
|
87
|
+
if retry_on_auth_failure and auth_retry_code(return_code, data.get("return_msg")) is not None:
|
|
85
88
|
self.auth.recover_from_auth_failure()
|
|
86
89
|
return self.request(
|
|
87
90
|
api_id=resolved_api_id,
|
|
@@ -97,6 +100,14 @@ class KiwoomClient:
|
|
|
97
100
|
if return_code not in (None, 0):
|
|
98
101
|
message = f"{message} (return_code={data['return_code']})"
|
|
99
102
|
raise HTTPRequestError(response.status_code, message)
|
|
103
|
+
|
|
104
|
+
# 키움은 업무 오류도 HTTP 200으로 내려보내고 실패 여부는 본문 return_code에만 담는다.
|
|
105
|
+
if return_code not in (None, 0):
|
|
106
|
+
raise_for_error_code(
|
|
107
|
+
return_code,
|
|
108
|
+
str(data.get("return_msg") or "API 요청에 실패했습니다."),
|
|
109
|
+
)
|
|
110
|
+
|
|
100
111
|
return _build_response(data, response.headers)
|
|
101
112
|
|
|
102
113
|
def fetch_page(
|
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
# Kiwoom auth-expiry return codes that warrant a one-shot credential
|
|
4
5
|
# recovery + retry (shared by the REST client and the WebSocket client).
|
|
5
6
|
AUTH_RETRY_RETURN_CODES = frozenset({8005, 8031, 8103})
|
|
6
7
|
|
|
8
|
+
# Kiwoom often reports a generic top-level ``return_code`` (e.g. 3 = "인증에
|
|
9
|
+
# 실패했습니다") and puts the specific code inside ``return_msg`` as
|
|
10
|
+
# ``[8005:Token이 유효하지 않습니다]`` (REST) or ``CODE=8005`` (WebSocket).
|
|
11
|
+
_EMBEDDED_CODE_RE = re.compile(r"\[(\d{3,5}):|CODE=(\d{3,5})")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def embedded_return_code(return_msg: object) -> int | None:
|
|
15
|
+
"""Return the specific code embedded in a Kiwoom ``return_msg``, if any."""
|
|
16
|
+
match = _EMBEDDED_CODE_RE.search(str(return_msg or ""))
|
|
17
|
+
if match is None:
|
|
18
|
+
return None
|
|
19
|
+
return int(match.group(1) or match.group(2))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def auth_retry_code(return_code: int | None, return_msg: object) -> int | None:
|
|
23
|
+
"""The auth-expiry code (top-level or embedded) that warrants recovery, else None."""
|
|
24
|
+
if return_code in AUTH_RETRY_RETURN_CODES:
|
|
25
|
+
return return_code
|
|
26
|
+
embedded = embedded_return_code(return_msg)
|
|
27
|
+
return embedded if embedded in AUTH_RETRY_RETURN_CODES else None
|
|
28
|
+
|
|
7
29
|
|
|
8
30
|
def normalize_return_code(value: object) -> int | None:
|
|
9
31
|
"""Normalize a Kiwoom ``return_code`` payload value.
|
|
@@ -137,6 +159,13 @@ class DeviceAuthenticationError(AuthenticationError):
|
|
|
137
159
|
self.return_msg = return_msg
|
|
138
160
|
|
|
139
161
|
|
|
162
|
+
class DemoUnsupportedError(APIError):
|
|
163
|
+
"""Raised when the API exists but is not served in demo (모의투자) mode."""
|
|
164
|
+
|
|
165
|
+
def __init__(self, return_code: int, return_msg: str):
|
|
166
|
+
super().__init__(return_code, f"모의투자에서 지원하지 않는 API입니다. ({return_msg})")
|
|
167
|
+
|
|
168
|
+
|
|
140
169
|
INPUT_VALIDATION_CODES = {
|
|
141
170
|
1501,
|
|
142
171
|
1504,
|
|
@@ -151,15 +180,35 @@ INPUT_VALIDATION_CODES = {
|
|
|
151
180
|
1687,
|
|
152
181
|
8020,
|
|
153
182
|
}
|
|
154
|
-
RATE_LIMIT_CODES = {1700}
|
|
155
|
-
SYMBOL_NOT_FOUND_CODES = {1901, 1902}
|
|
183
|
+
RATE_LIMIT_CODES = {1700, 1701, 1702}
|
|
184
|
+
SYMBOL_NOT_FOUND_CODES = {1901, 1902, 1903}
|
|
156
185
|
INVALID_CREDENTIAL_CODES = {8001, 8002, 8011, 8012}
|
|
157
186
|
INVALID_TOKEN_CODES = {8003, 8005, 8006, 8009, 8015, 8016}
|
|
158
187
|
MODE_MISMATCH_CODES = {8030, 8031}
|
|
159
188
|
DEVICE_AUTH_CODES = {8010, 8040, 8050, 8103}
|
|
189
|
+
DEMO_UNSUPPORTED_CODES = {8104}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
_CLASSIFIED_CODES = (
|
|
193
|
+
INPUT_VALIDATION_CODES
|
|
194
|
+
| RATE_LIMIT_CODES
|
|
195
|
+
| SYMBOL_NOT_FOUND_CODES
|
|
196
|
+
| INVALID_CREDENTIAL_CODES
|
|
197
|
+
| INVALID_TOKEN_CODES
|
|
198
|
+
| MODE_MISMATCH_CODES
|
|
199
|
+
| DEVICE_AUTH_CODES
|
|
200
|
+
| DEMO_UNSUPPORTED_CODES
|
|
201
|
+
)
|
|
160
202
|
|
|
161
203
|
|
|
162
204
|
def raise_for_error_code(return_code: int, return_msg: str) -> None:
|
|
205
|
+
# A generic top-level code (3, 5, ...) with a specific code embedded in the
|
|
206
|
+
# message is classified by the embedded code, so callers get the same
|
|
207
|
+
# error class either way; the message keeps Kiwoom's original text.
|
|
208
|
+
if return_code not in _CLASSIFIED_CODES:
|
|
209
|
+
embedded = embedded_return_code(return_msg)
|
|
210
|
+
if embedded in _CLASSIFIED_CODES:
|
|
211
|
+
return_code = embedded
|
|
163
212
|
if return_code in INPUT_VALIDATION_CODES:
|
|
164
213
|
raise InputValidationError(return_code, return_msg)
|
|
165
214
|
if return_code in RATE_LIMIT_CODES:
|
|
@@ -174,4 +223,8 @@ def raise_for_error_code(return_code: int, return_msg: str) -> None:
|
|
|
174
223
|
raise ModeMismatchError(return_code, return_msg)
|
|
175
224
|
if return_code in DEVICE_AUTH_CODES:
|
|
176
225
|
raise DeviceAuthenticationError(return_code, return_msg)
|
|
226
|
+
if return_code in DEMO_UNSUPPORTED_CODES:
|
|
227
|
+
raise DemoUnsupportedError(return_code, return_msg)
|
|
228
|
+
# 1999(예기치 못한 오류)·8200(법인 미지원)처럼 분류해도 대응이 달라지지 않는 코드는
|
|
229
|
+
# 원문 메시지를 그대로 노출하는 APIError로 남긴다.
|
|
177
230
|
raise APIError(return_code, return_msg)
|