An open API service indexing awesome lists of open source software.

https://github.com/designmeme/python-upbit-api

๐Ÿ’™ Python Upbit API Wrapper
https://github.com/designmeme/python-upbit-api

python-api-wrapper upbit upbit-api

Last synced: about 2 months ago
JSON representation

๐Ÿ’™ Python Upbit API Wrapper

Awesome Lists containing this project

README

          

# Python Upbit API

๐Ÿ’™ Python Upbit API๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ๋ช…๋ฃŒํ•œ Upbit API Wrapper ์ž…๋‹ˆ๋‹ค. ๐Ÿ‘

[![Version](https://img.shields.io/pypi/v/python-upbit-api)][pypi]
[![Supported Python Versions](https://img.shields.io/pypi/pyversions/python-upbit-api)][pypi]
[![License](https://img.shields.io/pypi/l/python-upbit-api)][license]
[![PyPI Downloads](https://img.shields.io/pypi/dm/python-upbit-api)][downloads]

## Installation

pip ๋ช…๋ น์–ด๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```shell
pip install python-upbit-api
```

## Quick Start

### ์ธ์ฆ ์—†์ด ์‚ฌ์šฉํ•˜๊ธฐ
๊ฐ์ข… ์‹œ์„ธ ์ •๋ณด๋ฅผ ์–ป๊ธฐ ์œ„ํ•œ **QUOTATION API๋งŒ** ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ธ์ฆ ์ •๋ณด ์—†์ด ์ดˆ๊ธฐํ™” ํ›„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ EXCHANGE API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด `upbit.exceptions.ApiKeyError` ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

```python
# example.py
from upbit import Upbit

upbit = Upbit()
res = upbit.get_markets()
data = res.json()

upbit.get_accounts() # upbit.exceptions.ApiKeyError ๋ฐœ์ƒ
```

### ์ธ์ฆ ์‚ฌ์šฉํ•˜๊ธฐ

์ธ์ฆ์ด ํ•„์š”ํ•œ **EXCHANGE API**๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ธ์ฆ ์ •๋ณด๋ฅผ ์ดˆ๊ธฐํ™”์‹œ ๋“ฑ๋ก ํ›„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ™†๐Ÿปโ€โ™€๏ธ QUOTATION API๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

`.env` ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ์— ๋ฐœ๊ธ‰ ๋ฐ›์€ ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
```
UPBIT_OPEN_API_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UPBIT_OPEN_API_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

```python
# example.py
import os
from upbit import Upbit

access_key = os.environ.get('UPBIT_OPEN_API_ACCESS_KEY')
secret_key = os.environ.get('UPBIT_OPEN_API_SECRET_KEY')
upbit = Upbit(access_key, secret_key)
res = upbit.get_accounts()
data = res.json()
```

## Features

### ์—…๋น„ํŠธ REST API๋ฅผ ๋ชจ๋‘ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณต

[์—…๋น„ํŠธ REST API][upbit docs api]๋ฅผ `Upbit` ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
์ž์„ธํ•œ ๋‚ด์šฉ์€ [upbit.py](https://github.com/designmeme/python-upbit-api/blob/main/upbit/upbit.py) ํŒŒ์ผ ๋‚ด docstring ์ฐธ์กฐ.

| | | ๋ฉ”์„œ๋“œ๋ช… |
|----|:-----------------------------|:---------------------------|
| ์ž์‚ฐ | ์ „์ฒด ๊ณ„์ขŒ ์กฐํšŒ | get_accounts |
| ์ฃผ๋ฌธ | ์ฃผ๋ฌธ ๊ฐ€๋Šฅ ์ •๋ณด | get_order_chance |
| | ๊ฐœ๋ณ„ ์ฃผ๋ฌธ ์กฐํšŒ | get_order |
| | ์ฃผ๋ฌธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_orders |
| | id๋กœ ์ฃผ๋ฌธ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_orders_by_id |
| | ์ฒด๊ฒฐ ๋Œ€๊ธฐ ์ฃผ๋ฌธ (Open Order) ์กฐํšŒ | get_open_orders |
| | ์ข…๋ฃŒ๋œ ์ฃผ๋ฌธ (Closed Order) ์กฐํšŒ | get_closed_orders |
| | ์ฃผ๋ฌธ ์ทจ์†Œ ์ ‘์ˆ˜ | delete_order |
| | ์ฃผ๋ฌธ ์ผ๊ด„ ์ทจ์†Œ ์ ‘์ˆ˜ | delete_orders |
| | id๋กœ ์ฃผ๋ฌธ๋ฆฌ์ŠคํŠธ ์ทจ์†Œ ์ ‘์ˆ˜ | delete_orders_by_id |
| | ์ฃผ๋ฌธํ•˜๊ธฐ | create_order |
| ์ถœ๊ธˆ | ์ถœ๊ธˆ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_withdraws |
| | ๊ฐœ๋ณ„ ์ถœ๊ธˆ ์กฐํšŒ | get_withdraw |
| | ์ถœ๊ธˆ ๊ฐ€๋Šฅ ์ •๋ณด | get_withdraw_chance |
| | ๋””์ง€ํ„ธ ์ž์‚ฐ ์ถœ๊ธˆํ•˜๊ธฐ | create_withdraw_coin |
| | ์›ํ™” ์ถœ๊ธˆํ•˜๊ธฐ | create_withdraw_krw |
| | ์ถœ๊ธˆ ํ—ˆ์šฉ ์ฃผ์†Œ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_withdraw_addresses |
| ์ž…๊ธˆ | ์ž…๊ธˆ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_deposits |
| | ๊ฐœ๋ณ„ ์ž…๊ธˆ ์กฐํšŒ | get_deposit |
| | ์ž…๊ธˆ ์ฃผ์†Œ ์ƒ์„ฑ ์š”์ฒญ | create_coin_address |
| | ์ „์ฒด ์ž…๊ธˆ ์ฃผ์†Œ ์กฐํšŒ | get_coin_addresses |
| | ๊ฐœ๋ณ„ ์ž…๊ธˆ ์ฃผ์†Œ ์กฐํšŒ | get_coin_address |
| | ์›ํ™” ์ž…๊ธˆํ•˜๊ธฐ | create_deposit_krw |
| | ๊ณ„์ •์ฃผ ํ™•์ธ(ํŠธ๋ž˜๋ธ”๋ฃฐ ๊ฒ€์ฆ)๊ฐ€๋Šฅ ๊ฑฐ๋ž˜์†Œ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_vasps |
| | ์ž…๊ธˆ UUID๋กœ ํŠธ๋ž˜๋ธ”๋ฃฐ ๊ฒ€์ฆํ•˜๊ธฐ | verify_travel_rule_by_uuid |
| | ์ž…๊ธˆ TxID๋กœ ํŠธ๋ž˜๋ธ”๋ฃฐ ๊ฒ€์ฆํ•˜๊ธฐ | verify_travel_rule_by_txid |
| ์„œ๋น„์Šค ์ •๋ณด | ์ž…์ถœ๊ธˆ ํ˜„ํ™ฉ | get_wallet_status |
| | API ํ‚ค ๋ฆฌ์ŠคํŠธ ์กฐํšŒ | get_api_keys |
| ์‹œ์„ธ ์ข…๋ชฉ ์กฐํšŒ | ๋งˆ์ผ“ ์ฝ”๋“œ ์กฐํšŒ | get_markets |
| ์‹œ์„ธ ์บ”๋“ค ์กฐํšŒ | ์ดˆ(Second) ์บ”๋“ค | get_candles_second |
| | ๋ถ„(Minute) ์บ”๋“ค | get_candles_minute |
| | ์ผ(Day) ์บ”๋“ค | get_candles_day |
| | ์ฃผ(Week) ์บ”๋“ค | get_candles_week |
| | ์›”(Month) ์บ”๋“ค | get_candles_month |
| | ์—ฐ(Year) ์บ”๋“ค | get_candles_year |
| ์‹œ์„ธ ์ฒด๊ฒฐ ์กฐํšŒ | ์ตœ๊ทผ ์ฒด๊ฒฐ ๋‚ด์—ญ | get_trades_ticks |
| ์‹œ์„ธ ํ˜„์žฌ๊ฐ€ ์กฐํšŒ | ํ˜„์žฌ๊ฐ€ ์ •๋ณด | get_ticker |
| ์‹œ์„ธ ํ˜„์žฌ๊ฐ€ ์กฐํšŒ | ๋งˆ์ผ“ ๋‹จ์œ„ ํ˜„์žฌ๊ฐ€ ์ •๋ณด | get_tickers_by_quote |
| ์‹œ์„ธ ํ˜ธ๊ฐ€ ์กฐํšŒ | ํ˜ธ๊ฐ€ ์ •๋ณด | get_orderbook |
| | ํ˜ธ๊ฐ€ ๋ชจ์•„๋ณด๊ธฐ ๋‹จ์œ„ ์ •๋ณด | get_orderbook_levels |
| | ํ˜ธ๊ฐ€ ์ •์ฑ… ์กฐํšŒ | get_orderbook_instruments |

### Requests ์‚ฌ์šฉ
[Requests][requests] ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

1. `requests.Response` ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

```python
# example.py
from upbit import Upbit

upbit = Upbit()
res = upbit.get_markets()

data = res.json()
status_code = res.status_code
```

2. `requests.adapters.HTTPAdapter` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ์‹œ๋„ ํšŸ์ˆ˜ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```python
# example.py
from upbit import Upbit
import requests

adapter = requests.adapters.HTTPAdapter(max_retries=3)

upbit = Upbit(http_adapter=adapter)
```

3. `requests.Session.request` ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ `timeout` ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```python
# example.py
from upbit import Upbit

upbit = Upbit(timeout=(10, 5)) # ๋ชจ๋“  ์š”์ฒญ์— ์„ค์ •ํ•  timeout

res = upbit.get_markets(timeout=10) # ์ด ์š”์ฒญ์—๋งŒ ์„ค์ •ํ•  timeout
```

### ์˜ˆ์™ธ ํด๋ž˜์Šค ์ œ๊ณต
๋ชจ๋“  API ์š”์ฒญ์—์„œ ๋ฐœ์ƒํ•œ `requests.exceptions.HTTPError` ์˜ˆ์™ธ๋Š” ์ด ์˜ˆ์™ธ๋ฅผ ์ƒ์†ํ•œ `upbit.exceptions.UpbitHTTPError` ์˜ˆ์™ธ๋กœ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ Upbit ๊ณต์‹ ๋ฌธ์„œ์— ๊ณต๊ฐœํ•œ ์—๋Ÿฌ ์œ ํ˜•์— ๋งž๋Š” ์˜ˆ์™ธ ์Œ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
* [์š”์ฒญ ์ˆ˜ ์ œํ•œ](https://docs.upbit.com/docs/user-request-guide)
* [API ์ฃผ์š” ์—๋Ÿฌ ์ฝ”๋“œ ๋ชฉ๋ก](https://docs.upbit.com/docs/api-%EC%A3%BC%EC%9A%94-%EC%97%90%EB%9F%AC-%EC%BD%94%EB%93%9C-%EB%AA%A9%EB%A1%9D)

```python
# example.py
from upbit import Upbit, TooManyRequests, UpbitClientError, UpbitServerError

upbit = Upbit()
try:
res = upbit.get_markets()
except TooManyRequests as e:
status_code = e.response.status_code # 429
# ...์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ฝ”๋“œ
except UpbitClientError as e:
res = e.response
# ...์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ฝ”๋“œ
except UpbitServerError as e:
res = e.response
# ...์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ฝ”๋“œ
```

### ์ž”์—ฌ ์š”์ฒญ ์ˆ˜ ํ™•์ธ
์—…๋น„ํŠธ API `Remaining-Req` ์‘๋‹ต ํ—ค๋”์— ๋‹ด๊ธด ์ž”์—ฌ ์š”์ฒญ ์ˆ˜๋ฅผ `upbit.models.RemainingReq` ๊ฐ์ฒด๋กœ ์ œ๊ณต๋˜์–ด ์ •๋ณด์— ์‰ฝ๊ฒŒ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์š”์ฒญ ๊ทธ๋ฃน๋ณ„ ์ตœ์‹  ๊ฐ’์„ ํ”„๋กœํผํ‹ฐ์— ์ €์žฅํ•˜๋ฉฐ `get_remaining_reqs()` ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ทธ๋ฃน์˜ ์ตœ์‹  ์ž”์—ฌ ์š”์ฒญ ์ˆ˜ ๊ฐ์ฒด๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : [Exchange API ์ž”์—ฌ ์š”์ฒญ ์ˆ˜ ํ™•์ธ ๋ฐฉ๋ฒ•](https://docs.upbit.com/docs/user-request-guide#exchange-api-%EC%9E%94%EC%97%AC-%EC%9A%94%EC%B2%AD-%EC%88%98-%ED%99%95%EC%9D%B8-%EB%B0%A9%EB%B2%95)

```python
# example.py
from upbit import Upbit
from upbit.models import RemainingReq

upbit = Upbit()
res = upbit.get_candles_day('KRW-BTC')
rr: RemainingReq = upbit.get_remaining_reqs('candles')
rr.minute
rr.updated

# ์‘๋‹ต ํ—ค๋”๋„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
rr_text = res.headers['Remaining-Req'] # 'group=candles; min=59; sec=4'
```

### ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ชจ๋ธ ์ œ๊ณต
Upbit API ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์‚ฌ์šฉํ•  ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ํƒ€์ž…์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

```python
# example.py
from upbit.models import OrderSide

# ...

# Type Hint
order_side: OrderSide = 'bid'
res = upbit.create_order(market='KRW-BTC', side=order_side, ord_type='limit', price='100', volume='0.01')
```

### Docstring & Type Hint
์ž˜ ์ž‘์„ฑํ•œ Docstring ๋‚ด์šฉ๊ณผ ํƒ€์ž…์œผ๋กœ IDE์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ“๐Ÿ’ก

## WebSocket
์•„์ง ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. [์ฐธ๊ณ  ์ด์Šˆ](https://github.com/designmeme/python-upbit-api/issues/7)

## Changelog
์ตœ์‹  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์•„๋ž˜์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- [CHANGELOG.md][changelog]
- [PyPI Releases][releases]

[pypi]: https://pypi.org/project/python-upbit-api/
[releases]: https://pypi.org/project/python-upbit-api/#history
[changelog]: https://github.com/designmeme/python-upbit-api/blob/main/CHANGELOG.md
[license]: https://github.com/designmeme/python-upbit-api/blob/main/LICENSE
[downloads]: https://pypistats.org/packages/python-upbit-api
[requests]: https://requests.readthedocs.io/en/latest/
[upbit docs api]: https://docs.upbit.com/reference/