pydbsec 0.1.0__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.
- pydbsec-0.1.0/.github/workflows/ci.yml +47 -0
- pydbsec-0.1.0/.github/workflows/publish.yml +29 -0
- pydbsec-0.1.0/.gitignore +19 -0
- pydbsec-0.1.0/LICENSE +21 -0
- pydbsec-0.1.0/PKG-INFO +179 -0
- pydbsec-0.1.0/README.md +146 -0
- pydbsec-0.1.0/docs/awesome-quant-pr.md +57 -0
- pydbsec-0.1.0/docs/blog-draft.md +173 -0
- pydbsec-0.1.0/examples/async_usage.py +27 -0
- pydbsec-0.1.0/examples/basic_usage.py +52 -0
- pydbsec-0.1.0/pyproject.toml +71 -0
- pydbsec-0.1.0/src/pydbsec/__init__.py +28 -0
- pydbsec-0.1.0/src/pydbsec/api/__init__.py +5 -0
- pydbsec-0.1.0/src/pydbsec/api/domestic.py +403 -0
- pydbsec-0.1.0/src/pydbsec/api/futures.py +35 -0
- pydbsec-0.1.0/src/pydbsec/api/overseas.py +406 -0
- pydbsec-0.1.0/src/pydbsec/auth.py +156 -0
- pydbsec-0.1.0/src/pydbsec/client.py +158 -0
- pydbsec-0.1.0/src/pydbsec/constants.py +70 -0
- pydbsec-0.1.0/src/pydbsec/exceptions.py +45 -0
- pydbsec-0.1.0/src/pydbsec/http.py +210 -0
- pydbsec-0.1.0/src/pydbsec/models/__init__.py +5 -0
- pydbsec-0.1.0/src/pydbsec/models/balance.py +178 -0
- pydbsec-0.1.0/src/pydbsec/models/order.py +28 -0
- pydbsec-0.1.0/src/pydbsec/models/quote.py +45 -0
- pydbsec-0.1.0/src/pydbsec/py.typed +0 -0
- pydbsec-0.1.0/tests/__init__.py +0 -0
- pydbsec-0.1.0/tests/test_auth.py +102 -0
- pydbsec-0.1.0/tests/test_client.py +181 -0
- pydbsec-0.1.0/tests/test_http.py +92 -0
- pydbsec-0.1.0/tests/test_models.py +124 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Lint with ruff
|
|
28
|
+
run: ruff check src/ tests/
|
|
29
|
+
|
|
30
|
+
- name: Run tests
|
|
31
|
+
run: pytest tests/ -v
|
|
32
|
+
|
|
33
|
+
type-check:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- name: Set up Python
|
|
39
|
+
uses: actions/setup-python@v5
|
|
40
|
+
with:
|
|
41
|
+
python-version: "3.12"
|
|
42
|
+
|
|
43
|
+
- name: Install dependencies
|
|
44
|
+
run: pip install -e ".[dev]"
|
|
45
|
+
|
|
46
|
+
- name: Type check with mypy
|
|
47
|
+
run: mypy src/pydbsec/ --ignore-missing-imports
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install build
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
pydbsec-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.eggs/
|
|
8
|
+
*.egg
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
.env
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
*.so
|
|
16
|
+
.DS_Store
|
|
17
|
+
|
|
18
|
+
# Reference project (not part of this library)
|
|
19
|
+
quantus-fastapi/
|
pydbsec-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 STOA Company
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pydbsec-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pydbsec
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python wrapper for DB Securities (DB증권) OpenAPI — Stock trading, balance, quotes, charts for Korean & US markets
|
|
5
|
+
Project-URL: Homepage, https://github.com/STOA-company/pydbsec
|
|
6
|
+
Project-URL: Repository, https://github.com/STOA-company/pydbsec
|
|
7
|
+
Project-URL: Issues, https://github.com/STOA-company/pydbsec/issues
|
|
8
|
+
Author: STOA Company
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: DB증권,algorithmic-trading,api,api-wrapper,auto-trading,db-securities,dbsec,finance,korea,korean-stock,openapi,pykis,pykrx,quant,stock,trading,us-stock
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: httpx>=0.27.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# pydbsec
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/pydbsec/)
|
|
37
|
+
[](https://pypi.org/project/pydbsec/)
|
|
38
|
+
[](https://github.com/STOA-company/pydbsec/actions)
|
|
39
|
+
[](https://opensource.org/licenses/MIT)
|
|
40
|
+
|
|
41
|
+
**DB증권 OpenAPI Python 래퍼** — 3줄이면 잔고 조회, 5줄이면 자동매매
|
|
42
|
+
|
|
43
|
+
> DB증권 OpenAPI를 쉽게 사용할 수 있는 Python 라이브러리입니다.
|
|
44
|
+
> [한국투자증권의 PyKIS](https://github.com/Soju06/python-kis)처럼, DB증권도 Python 한 줄이면 됩니다.
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from pydbsec import PyDBSec
|
|
48
|
+
|
|
49
|
+
client = PyDBSec(app_key="...", app_secret="...")
|
|
50
|
+
print(client.domestic.price("005930").current_price) # 삼성전자 현재가
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **국내 주식**: 잔고 조회, 시세, 매수/매도, 차트, 거래내역
|
|
56
|
+
- **해외 주식**: 잔고 조회, 시세, 매수/매도, 차트, 거래내역
|
|
57
|
+
- **선물/옵션**: 잔고 조회
|
|
58
|
+
- **Sync + Async**: `PyDBSec` (동기) / `AsyncPyDBSec` (비동기)
|
|
59
|
+
- **Type-safe**: Pydantic v2 모델로 응답 타입 보장
|
|
60
|
+
- **Auto token refresh**: OAuth2 토큰 자동 갱신
|
|
61
|
+
- **Auto pagination**: 연속 조회 자동 처리
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install pydbsec
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from pydbsec import PyDBSec
|
|
73
|
+
|
|
74
|
+
client = PyDBSec(app_key="YOUR_APP_KEY", app_secret="YOUR_APP_SECRET")
|
|
75
|
+
|
|
76
|
+
# 국내 주식 잔고 조회
|
|
77
|
+
balance = client.domestic.balance()
|
|
78
|
+
print(f"예탁총액: {balance.deposit_total:,.0f}원")
|
|
79
|
+
print(f"주문가능: {balance.available_cash:,.0f}원")
|
|
80
|
+
for pos in balance.positions:
|
|
81
|
+
print(f" {pos.stock_name}: {pos.quantity}주 (평가손익: {pos.pnl_amount:,.0f}원)")
|
|
82
|
+
|
|
83
|
+
# 주가 조회
|
|
84
|
+
price = client.domestic.price("005930") # 삼성전자
|
|
85
|
+
print(f"현재가: {price.current_price:,.0f}원 ({price.change_rate:+.2f}%)")
|
|
86
|
+
|
|
87
|
+
# 매수 주문
|
|
88
|
+
result = client.domestic.buy("005930", quantity=10, price=70000)
|
|
89
|
+
print(f"주문번호: {result.order_no}")
|
|
90
|
+
|
|
91
|
+
# 해외 주식
|
|
92
|
+
us_price = client.overseas.price("AAPL", market="FN") # NASDAQ
|
|
93
|
+
print(f"AAPL: ${us_price.current_price:.2f}")
|
|
94
|
+
|
|
95
|
+
# 세션 종료
|
|
96
|
+
client.close()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Context Manager
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
with PyDBSec(app_key="...", app_secret="...") as client:
|
|
103
|
+
balance = client.domestic.balance()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Async
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import asyncio
|
|
110
|
+
from pydbsec import AsyncPyDBSec
|
|
111
|
+
|
|
112
|
+
async def main():
|
|
113
|
+
async with AsyncPyDBSec(app_key="...", app_secret="...") as client:
|
|
114
|
+
balance = await client.domestic.balance()
|
|
115
|
+
price = await client.domestic.price("005930")
|
|
116
|
+
|
|
117
|
+
asyncio.run(main())
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API Reference
|
|
121
|
+
|
|
122
|
+
### `client.domestic` — 국내 주식
|
|
123
|
+
|
|
124
|
+
| Method | Description |
|
|
125
|
+
|--------|-------------|
|
|
126
|
+
| `balance()` | 잔고 조회 |
|
|
127
|
+
| `price(stock_code)` | 현재가 조회 |
|
|
128
|
+
| `order_book(stock_code)` | 호가 조회 |
|
|
129
|
+
| `tickers()` | 종목 목록 |
|
|
130
|
+
| `buy(stock_code, quantity, price)` | 매수 주문 |
|
|
131
|
+
| `sell(stock_code, quantity, price)` | 매도 주문 |
|
|
132
|
+
| `cancel(order_no, stock_code, quantity)` | 주문 취소 |
|
|
133
|
+
| `deposit()` | 예수금 조회 |
|
|
134
|
+
| `orderable_quantity(stock_code, price)` | 주문가능수량 |
|
|
135
|
+
| `transaction_history()` | 체결/미체결 내역 |
|
|
136
|
+
| `trading_history(start_date, end_date)` | 거래 내역 |
|
|
137
|
+
| `daily_trade_report(date)` | 일별 거래 보고서 |
|
|
138
|
+
| `chart(stock_code, period=...)` | 차트 데이터 |
|
|
139
|
+
|
|
140
|
+
### `client.overseas` — 해외 주식
|
|
141
|
+
|
|
142
|
+
| Method | Description |
|
|
143
|
+
|--------|-------------|
|
|
144
|
+
| `balance()` | 잔고 조회 |
|
|
145
|
+
| `price(stock_code, market=...)` | 현재가 조회 |
|
|
146
|
+
| `order_book(stock_code, market=...)` | 호가 조회 |
|
|
147
|
+
| `tickers(market=...)` | 종목 목록 |
|
|
148
|
+
| `buy(stock_code, quantity, price)` | 매수 주문 |
|
|
149
|
+
| `sell(stock_code, quantity, price)` | 매도 주문 |
|
|
150
|
+
| `cancel(order_no, stock_code, quantity)` | 주문 취소 |
|
|
151
|
+
| `deposit()` | 예수금 조회 |
|
|
152
|
+
| `transaction_history(start_date, end_date)` | 거래 내역 |
|
|
153
|
+
| `chart(stock_code, period=...)` | 차트 데이터 |
|
|
154
|
+
|
|
155
|
+
### `client.futures` — 선물/옵션
|
|
156
|
+
|
|
157
|
+
| Method | Description |
|
|
158
|
+
|--------|-------------|
|
|
159
|
+
| `balance()` | 선물옵션 잔고 조회 |
|
|
160
|
+
|
|
161
|
+
### Market Codes
|
|
162
|
+
|
|
163
|
+
**국내 시세**: `"UJ"` (주식), `"E"` (ETF), `"EN"` (ETN)
|
|
164
|
+
|
|
165
|
+
**해외 시세**: `"FY"` (NYSE), `"FN"` (NASDAQ), `"FA"` (AMEX)
|
|
166
|
+
|
|
167
|
+
**해외 종목조회**: `"NY"` (NYSE), `"NA"` (NASDAQ), `"AM"` (AMEX)
|
|
168
|
+
|
|
169
|
+
## Prerequisites
|
|
170
|
+
|
|
171
|
+
DB증권 OpenAPI 사용을 위해:
|
|
172
|
+
|
|
173
|
+
1. [DB증권 계좌 개설](https://www.dbsec.co.kr)
|
|
174
|
+
2. [OpenAPI 사용 신청](https://openapi.dbsec.co.kr)
|
|
175
|
+
3. App Key / App Secret 발급
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
pydbsec-0.1.0/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# pydbsec
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pydbsec/)
|
|
4
|
+
[](https://pypi.org/project/pydbsec/)
|
|
5
|
+
[](https://github.com/STOA-company/pydbsec/actions)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
**DB증권 OpenAPI Python 래퍼** — 3줄이면 잔고 조회, 5줄이면 자동매매
|
|
9
|
+
|
|
10
|
+
> DB증권 OpenAPI를 쉽게 사용할 수 있는 Python 라이브러리입니다.
|
|
11
|
+
> [한국투자증권의 PyKIS](https://github.com/Soju06/python-kis)처럼, DB증권도 Python 한 줄이면 됩니다.
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from pydbsec import PyDBSec
|
|
15
|
+
|
|
16
|
+
client = PyDBSec(app_key="...", app_secret="...")
|
|
17
|
+
print(client.domestic.price("005930").current_price) # 삼성전자 현재가
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- **국내 주식**: 잔고 조회, 시세, 매수/매도, 차트, 거래내역
|
|
23
|
+
- **해외 주식**: 잔고 조회, 시세, 매수/매도, 차트, 거래내역
|
|
24
|
+
- **선물/옵션**: 잔고 조회
|
|
25
|
+
- **Sync + Async**: `PyDBSec` (동기) / `AsyncPyDBSec` (비동기)
|
|
26
|
+
- **Type-safe**: Pydantic v2 모델로 응답 타입 보장
|
|
27
|
+
- **Auto token refresh**: OAuth2 토큰 자동 갱신
|
|
28
|
+
- **Auto pagination**: 연속 조회 자동 처리
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install pydbsec
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from pydbsec import PyDBSec
|
|
40
|
+
|
|
41
|
+
client = PyDBSec(app_key="YOUR_APP_KEY", app_secret="YOUR_APP_SECRET")
|
|
42
|
+
|
|
43
|
+
# 국내 주식 잔고 조회
|
|
44
|
+
balance = client.domestic.balance()
|
|
45
|
+
print(f"예탁총액: {balance.deposit_total:,.0f}원")
|
|
46
|
+
print(f"주문가능: {balance.available_cash:,.0f}원")
|
|
47
|
+
for pos in balance.positions:
|
|
48
|
+
print(f" {pos.stock_name}: {pos.quantity}주 (평가손익: {pos.pnl_amount:,.0f}원)")
|
|
49
|
+
|
|
50
|
+
# 주가 조회
|
|
51
|
+
price = client.domestic.price("005930") # 삼성전자
|
|
52
|
+
print(f"현재가: {price.current_price:,.0f}원 ({price.change_rate:+.2f}%)")
|
|
53
|
+
|
|
54
|
+
# 매수 주문
|
|
55
|
+
result = client.domestic.buy("005930", quantity=10, price=70000)
|
|
56
|
+
print(f"주문번호: {result.order_no}")
|
|
57
|
+
|
|
58
|
+
# 해외 주식
|
|
59
|
+
us_price = client.overseas.price("AAPL", market="FN") # NASDAQ
|
|
60
|
+
print(f"AAPL: ${us_price.current_price:.2f}")
|
|
61
|
+
|
|
62
|
+
# 세션 종료
|
|
63
|
+
client.close()
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Context Manager
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
with PyDBSec(app_key="...", app_secret="...") as client:
|
|
70
|
+
balance = client.domestic.balance()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Async
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from pydbsec import AsyncPyDBSec
|
|
78
|
+
|
|
79
|
+
async def main():
|
|
80
|
+
async with AsyncPyDBSec(app_key="...", app_secret="...") as client:
|
|
81
|
+
balance = await client.domestic.balance()
|
|
82
|
+
price = await client.domestic.price("005930")
|
|
83
|
+
|
|
84
|
+
asyncio.run(main())
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
### `client.domestic` — 국내 주식
|
|
90
|
+
|
|
91
|
+
| Method | Description |
|
|
92
|
+
|--------|-------------|
|
|
93
|
+
| `balance()` | 잔고 조회 |
|
|
94
|
+
| `price(stock_code)` | 현재가 조회 |
|
|
95
|
+
| `order_book(stock_code)` | 호가 조회 |
|
|
96
|
+
| `tickers()` | 종목 목록 |
|
|
97
|
+
| `buy(stock_code, quantity, price)` | 매수 주문 |
|
|
98
|
+
| `sell(stock_code, quantity, price)` | 매도 주문 |
|
|
99
|
+
| `cancel(order_no, stock_code, quantity)` | 주문 취소 |
|
|
100
|
+
| `deposit()` | 예수금 조회 |
|
|
101
|
+
| `orderable_quantity(stock_code, price)` | 주문가능수량 |
|
|
102
|
+
| `transaction_history()` | 체결/미체결 내역 |
|
|
103
|
+
| `trading_history(start_date, end_date)` | 거래 내역 |
|
|
104
|
+
| `daily_trade_report(date)` | 일별 거래 보고서 |
|
|
105
|
+
| `chart(stock_code, period=...)` | 차트 데이터 |
|
|
106
|
+
|
|
107
|
+
### `client.overseas` — 해외 주식
|
|
108
|
+
|
|
109
|
+
| Method | Description |
|
|
110
|
+
|--------|-------------|
|
|
111
|
+
| `balance()` | 잔고 조회 |
|
|
112
|
+
| `price(stock_code, market=...)` | 현재가 조회 |
|
|
113
|
+
| `order_book(stock_code, market=...)` | 호가 조회 |
|
|
114
|
+
| `tickers(market=...)` | 종목 목록 |
|
|
115
|
+
| `buy(stock_code, quantity, price)` | 매수 주문 |
|
|
116
|
+
| `sell(stock_code, quantity, price)` | 매도 주문 |
|
|
117
|
+
| `cancel(order_no, stock_code, quantity)` | 주문 취소 |
|
|
118
|
+
| `deposit()` | 예수금 조회 |
|
|
119
|
+
| `transaction_history(start_date, end_date)` | 거래 내역 |
|
|
120
|
+
| `chart(stock_code, period=...)` | 차트 데이터 |
|
|
121
|
+
|
|
122
|
+
### `client.futures` — 선물/옵션
|
|
123
|
+
|
|
124
|
+
| Method | Description |
|
|
125
|
+
|--------|-------------|
|
|
126
|
+
| `balance()` | 선물옵션 잔고 조회 |
|
|
127
|
+
|
|
128
|
+
### Market Codes
|
|
129
|
+
|
|
130
|
+
**국내 시세**: `"UJ"` (주식), `"E"` (ETF), `"EN"` (ETN)
|
|
131
|
+
|
|
132
|
+
**해외 시세**: `"FY"` (NYSE), `"FN"` (NASDAQ), `"FA"` (AMEX)
|
|
133
|
+
|
|
134
|
+
**해외 종목조회**: `"NY"` (NYSE), `"NA"` (NASDAQ), `"AM"` (AMEX)
|
|
135
|
+
|
|
136
|
+
## Prerequisites
|
|
137
|
+
|
|
138
|
+
DB증권 OpenAPI 사용을 위해:
|
|
139
|
+
|
|
140
|
+
1. [DB증권 계좌 개설](https://www.dbsec.co.kr)
|
|
141
|
+
2. [OpenAPI 사용 신청](https://openapi.dbsec.co.kr)
|
|
142
|
+
3. App Key / App Secret 발급
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# awesome-quant PR Draft for pydbsec
|
|
2
|
+
|
|
3
|
+
## Target Section
|
|
4
|
+
|
|
5
|
+
**Python > Trading & Backtesting**
|
|
6
|
+
|
|
7
|
+
This section (line 84 of the README) contains broker API wrappers and trading
|
|
8
|
+
libraries. Comparable entries already in this section include:
|
|
9
|
+
|
|
10
|
+
- `tda-api` - "Gather data and trade equities, options, and ETFs via TDAmeritrade."
|
|
11
|
+
- `alpaca-trade-api` - "Python interface for retrieving real-time and historical prices from Alpaca API as well as trade execution."
|
|
12
|
+
- `pysentosa` - "Python API for sentosa trading system."
|
|
13
|
+
- `metatrader5` - "API Connector to MetaTrader 5 Terminal" (listed under Data Sources but also relevant)
|
|
14
|
+
- `PRISM-INSIGHT` - "AI-powered stock analysis system ... via KIS API, supporting Korean & US markets."
|
|
15
|
+
- `vnpy` - "VeighNa is a Python-based open source quantitative trading system development framework."
|
|
16
|
+
|
|
17
|
+
pydbsec fits here because it is a broker API wrapper that supports both trading
|
|
18
|
+
(buy/sell orders) and market data retrieval (prices, charts, balances), similar
|
|
19
|
+
to `tda-api` and `alpaca-trade-api`.
|
|
20
|
+
|
|
21
|
+
## Exact Line to Add
|
|
22
|
+
|
|
23
|
+
Add the following line at the end of the "Trading & Backtesting" section
|
|
24
|
+
(before the blank line preceding `### Risk Analysis`):
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
- [pydbsec](https://github.com/STOA-company/pydbsec) - Python wrapper for DB Securities (DB증권) OpenAPI with sync/async support.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Draft PR
|
|
31
|
+
|
|
32
|
+
### Title
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Add pydbsec - Python wrapper for DB Securities OpenAPI
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Description
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
## Add pydbsec to Python > Trading & Backtesting
|
|
42
|
+
|
|
43
|
+
[pydbsec](https://github.com/STOA-company/pydbsec) is a Python wrapper for
|
|
44
|
+
the DB Securities (DB증권) OpenAPI, a Korean brokerage.
|
|
45
|
+
|
|
46
|
+
**Features:**
|
|
47
|
+
- Domestic (KRX) and overseas (US, etc.) stock trading and market data
|
|
48
|
+
- Balance inquiry, price quotes, order execution, chart data
|
|
49
|
+
- Sync (`PyDBSec`) and async (`AsyncPyDBSec`) clients
|
|
50
|
+
- Type-safe responses with Pydantic v2
|
|
51
|
+
- Automatic OAuth2 token refresh and pagination handling
|
|
52
|
+
- Published on PyPI: `pip install pydbsec`
|
|
53
|
+
|
|
54
|
+
This addition complements existing Korean market entries like PRISM-INSIGHT
|
|
55
|
+
(KIS API) and FinanceDataReader, and follows the same pattern as other broker
|
|
56
|
+
API wrappers in the section (tda-api, alpaca-trade-api, pysentosa).
|
|
57
|
+
```
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# DB증권 OpenAPI Python 자동매매 — pydbsec으로 3줄이면 끝
|
|
2
|
+
|
|
3
|
+
DB증권 계좌로 자동매매를 구현하고 싶은데, 공식 Python SDK가 없어서 막막했던 적 있으신가요?
|
|
4
|
+
|
|
5
|
+
## 문제: DB증권 API를 Python으로 쓰려면 직접 HTTP 요청을 짜야 했다
|
|
6
|
+
|
|
7
|
+
DB증권 OpenAPI는 REST 기반이지만 Python 래퍼가 없었습니다. 그래서 토큰 발급부터 시세 조회까지 전부 직접 구현해야 했죠. 한국투자증권에는 [PyKIS](https://github.com/Soju06/python-kis)가 있고, 키움에는 `pykiwoom`이 있는데 DB증권만 빠져 있었습니다.
|
|
8
|
+
|
|
9
|
+
실제로 삼성전자 현재가 하나 조회하려면 이런 코드를 작성해야 했습니다:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import httpx
|
|
13
|
+
from datetime import datetime, timedelta
|
|
14
|
+
|
|
15
|
+
# 1) 토큰 발급
|
|
16
|
+
token_resp = httpx.post(
|
|
17
|
+
"https://openapi.dbsec.co.kr:8443/oauth2/token",
|
|
18
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
19
|
+
data={
|
|
20
|
+
"grant_type": "client_credentials",
|
|
21
|
+
"appkey": "YOUR_APP_KEY",
|
|
22
|
+
"appsecretkey": "YOUR_APP_SECRET",
|
|
23
|
+
"scope": "oob",
|
|
24
|
+
},
|
|
25
|
+
)
|
|
26
|
+
token_data = token_resp.json()
|
|
27
|
+
access_token = token_data["access_token"]
|
|
28
|
+
expires_at = datetime.now() + timedelta(seconds=int(token_data["expires_in"]))
|
|
29
|
+
|
|
30
|
+
# 2) 시세 조회
|
|
31
|
+
price_resp = httpx.post(
|
|
32
|
+
"https://openapi.dbsec.co.kr:8443/api/v1/quote/kr-stock/inquiry/price",
|
|
33
|
+
headers={
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
"Authorization": f"Bearer {access_token}",
|
|
36
|
+
},
|
|
37
|
+
json={"In": {"InputCondMrktDivCode": "UJ", "InputIscd1": "005930"}},
|
|
38
|
+
)
|
|
39
|
+
result = price_resp.json()
|
|
40
|
+
print(result["Out"]["TrdPrc"]) # 현재가... 그런데 키가 뭐였더라?
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**30줄이 넘습니다.** 토큰 만료 처리는요? 연속 조회(페이지네이션)는요? 에러 처리는요? 코드가 금방 100줄을 넘기고, 본래 하고 싶었던 전략 개발은 뒷전이 됩니다.
|
|
44
|
+
|
|
45
|
+
## 해결: pydbsec — DB증권 전용 Python 래퍼
|
|
46
|
+
|
|
47
|
+
[**pydbsec**](https://github.com/STOA-company/pydbsec)은 DB증권 OpenAPI를 감싼 Python 라이브러리입니다. 한국투자증권의 PyKIS처럼, DB증권도 Python 한 줄이면 됩니다.
|
|
48
|
+
|
|
49
|
+
위의 30줄짜리 코드가 이렇게 바뀝니다:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from pydbsec import PyDBSec
|
|
53
|
+
|
|
54
|
+
client = PyDBSec(app_key="YOUR_APP_KEY", app_secret="YOUR_APP_SECRET")
|
|
55
|
+
print(client.domestic.price("005930").current_price) # 삼성전자 현재가
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**3줄.** 토큰 발급, 갱신, 페이지네이션 전부 내부에서 알아서 처리합니다.
|
|
59
|
+
|
|
60
|
+
## 빠른 시작
|
|
61
|
+
|
|
62
|
+
### 설치
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install pydbsec
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Python 3.10 이상이면 됩니다. 의존성은 `httpx`와 `pydantic` 딱 두 개뿐입니다.
|
|
69
|
+
|
|
70
|
+
### 사전 준비
|
|
71
|
+
|
|
72
|
+
1. [DB증권 계좌 개설](https://www.dbsec.co.kr)
|
|
73
|
+
2. [OpenAPI 포털](https://openapi.dbsec.co.kr)에서 사용 신청
|
|
74
|
+
3. App Key / App Secret 발급
|
|
75
|
+
|
|
76
|
+
### 잔고 조회
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from pydbsec import PyDBSec
|
|
80
|
+
|
|
81
|
+
client = PyDBSec(app_key="YOUR_APP_KEY", app_secret="YOUR_APP_SECRET")
|
|
82
|
+
|
|
83
|
+
balance = client.domestic.balance()
|
|
84
|
+
print(f"예탁총액: {balance.deposit_total:,.0f}원")
|
|
85
|
+
print(f"주문가능: {balance.available_cash:,.0f}원")
|
|
86
|
+
|
|
87
|
+
for pos in balance.positions:
|
|
88
|
+
print(f" {pos.stock_name}: {pos.quantity}주 (손익: {pos.pnl_amount:,.0f}원)")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 매수/매도
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# 삼성전자 10주 지정가 매수
|
|
95
|
+
result = client.domestic.buy("005930", quantity=10, price=70000)
|
|
96
|
+
print(f"주문번호: {result.order_no}")
|
|
97
|
+
|
|
98
|
+
# 시장가 매도
|
|
99
|
+
result = client.domestic.sell("005930", quantity=5, price_type="03")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 해외 주식
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# NASDAQ AAPL 현재가
|
|
106
|
+
aapl = client.overseas.price("AAPL", market="FN")
|
|
107
|
+
print(f"AAPL: ${aapl.current_price:.2f} ({aapl.change_rate:+.2f}%)")
|
|
108
|
+
|
|
109
|
+
# 해외 잔고 조회
|
|
110
|
+
us_balance = client.overseas.balance()
|
|
111
|
+
print(f"해외 평가액: ${us_balance.eval_total:,.2f}")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 비동기(Async) 지원
|
|
115
|
+
|
|
116
|
+
FastAPI나 비동기 봇과 함께 쓸 때 유용합니다:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import asyncio
|
|
120
|
+
from pydbsec import AsyncPyDBSec
|
|
121
|
+
|
|
122
|
+
async def main():
|
|
123
|
+
async with AsyncPyDBSec(app_key="...", app_secret="...") as client:
|
|
124
|
+
balance = await client.domestic.balance()
|
|
125
|
+
price = await client.domestic.price("005930")
|
|
126
|
+
print(f"삼성전자: {price.current_price:,.0f}원")
|
|
127
|
+
|
|
128
|
+
asyncio.run(main())
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Context Manager
|
|
132
|
+
|
|
133
|
+
세션 종료(토큰 해제)를 깔끔하게 처리합니다:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
with PyDBSec(app_key="...", app_secret="...") as client:
|
|
137
|
+
balance = client.domestic.balance()
|
|
138
|
+
# with 블록을 벗어나면 토큰 자동 해제
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 주요 기능 정리
|
|
142
|
+
|
|
143
|
+
| 기능 | 설명 |
|
|
144
|
+
|------|------|
|
|
145
|
+
| **국내 주식** | 잔고, 시세, 호가, 매수/매도, 주문 취소, 차트(분/일/주/월), 체결내역 |
|
|
146
|
+
| **해외 주식** | 잔고, 시세, 호가, 매수/매도, 주문 취소, 차트, 거래내역 |
|
|
147
|
+
| **선물/옵션** | 잔고 조회 |
|
|
148
|
+
| **토큰 자동 관리** | OAuth2 발급/갱신/해제 전부 자동. 만료 10분 전 자동 재발급 |
|
|
149
|
+
| **연속 조회 자동 처리** | 페이지네이션 `cont_yn`/`cont_key` 내부 처리 |
|
|
150
|
+
| **Type-safe** | Pydantic v2 모델로 응답 타입 보장. IDE 자동완성 지원 |
|
|
151
|
+
| **Sync + Async** | `PyDBSec` (동기) / `AsyncPyDBSec` (비동기) 둘 다 지원 |
|
|
152
|
+
| **에러 처리** | `APIError`, `TokenError` 등 구조화된 예외 클래스 |
|
|
153
|
+
|
|
154
|
+
## 왜 pydbsec인가?
|
|
155
|
+
|
|
156
|
+
**직접 HTTP를 짜면 생기는 문제들을 전부 해결합니다:**
|
|
157
|
+
|
|
158
|
+
- 토큰 만료? 자동 감지 후 재발급합니다. `IGW00121` 에러 코드까지 처리합니다.
|
|
159
|
+
- 페이지네이션? 잔고가 여러 페이지에 걸쳐 있어도 자동으로 모아줍니다.
|
|
160
|
+
- 응답 파싱? `Out`, `Out1` 같은 raw 키 대신 `balance.positions`, `price.current_price` 같은 Pythonic한 속성으로 접근합니다.
|
|
161
|
+
- 타입 힌트? Pydantic v2 모델이라 IDE에서 자동완성이 됩니다.
|
|
162
|
+
|
|
163
|
+
## 시작하기
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pip install pydbsec
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
GitHub: [https://github.com/STOA-company/pydbsec](https://github.com/STOA-company/pydbsec)
|
|
170
|
+
|
|
171
|
+
DB증권으로 퀀트 전략을 돌리고 계신 분, 자동매매 봇을 만들고 계신 분이라면 한번 써보세요. Star를 눌러주시면 개발에 큰 힘이 됩니다.
|
|
172
|
+
|
|
173
|
+
버그 리포트, 기능 제안, PR 모두 환영합니다. [Issues](https://github.com/STOA-company/pydbsec/issues)에 남겨주세요.
|