/python-upbit-api

๐Ÿ’™ Python Upbit API Wrapper

Primary LanguagePythonMIT LicenseMIT

Python Upbit API

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

Version Supported Python Versions License PyPI Downloads

Installation

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

pip install python-upbit-api

Quick Start

์ธ์ฆ ์—†์ด ์‚ฌ์šฉํ•˜๊ธฐ

๊ฐ์ข… ์‹œ์„ธ ์ •๋ณด๋ฅผ ์–ป๊ธฐ ์œ„ํ•œ QUOTATION API๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ธ์ฆ ์ •๋ณด ์—†์ด ์ดˆ๊ธฐํ™” ํ›„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
โš ๏ธ EXCHANGE API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด upbit.exceptions.ApiKeyError ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

# 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
# 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 ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ 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
์ฃผ๋ฌธํ•˜๊ธฐ 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
์‹œ์„ธ ์บ”๋“ค ์กฐํšŒ ๋ถ„(Minute) ์บ”๋“ค get_candles_minute
์ผ(Day) ์บ”๋“ค get_candles_day
์ฃผ(Week) ์บ”๋“ค get_candles_week
์›”(Month) ์บ”๋“ค get_candles_month
์‹œ์„ธ ์ฒด๊ฒฐ ์กฐํšŒ ์ตœ๊ทผ ์ฒด๊ฒฐ ๋‚ด์—ญ get_trades_ticks
์‹œ์„ธ ํ˜„์žฌ๊ฐ€ ์กฐํšŒ ํ˜„์žฌ๊ฐ€ ์ •๋ณด get_ticker
์‹œ์„ธ ํ˜ธ๊ฐ€ ์กฐํšŒ ํ˜ธ๊ฐ€ ์ •๋ณด get_orderbook

Requests ์‚ฌ์šฉ

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

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

    # example.py
    from upbit import Upbit
    
    upbit = Upbit()
    res = upbit.get_markets()
    
    data = res.json()
    status_code = res.status_code
  2. requests.adapters.HTTPAdapter ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ์‹œ๋„ ํšŸ์ˆ˜ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    # 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 ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    # 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 ๊ณต์‹ ๋ฌธ์„œ์— ๊ณต๊ฐœํ•œ ์—๋Ÿฌ ์œ ํ˜•์— ๋งž๋Š” ์˜ˆ์™ธ ์Œ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

# 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 ์ž”์—ฌ ์š”์ฒญ ์ˆ˜ ํ™•์ธ ๋ฐฉ๋ฒ•

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

# 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

์•„์ง ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ  ์ด์Šˆ

Changelog

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