본문 바로가기

[Toy Project] 자동매매

[Toy Project] 자동매매 프로그램 만들기 - 3. pyupbit 모듈 알아보기

728x90
반응형

 

[목차]

 

1. pyupbit 모듈 설치

 

2. 암호화폐 목록 얻기

 

3. 암호화폐 현재가 얻기

 

4. 암호화폐 과거 데이터 조회

 

5. 암호화폐 호가 조회

 

6. 잔고 조회

 

7. 지정가 매수/매도

 

8. 시장가 매수/매도

 

9. 주문 취소/조회

 

 

 

  1. pyupbit 모듈 설치

 

pyupbit 모듈이란, 업비트 API를 파이썬에서 쉽게 사용하기 위해서 저자들이 개발한 모듈이다. 굳이 API를 호출할 필요 없이 pyupbit 모듈을 이용하면 간편한 경우가 많다. 

 

pyupbit githubwikidocs.net/31063 를 참고하여 작성하였다. 

 

먼저 pyupbit 모듈을 설치해보자. 프롬프트 창에 "pip install pyupbit"를 입력한다. 

 

그 후, 다음 코드를 실행했을 때 오류가 발생하지 않는다면 pyupbit 모듈이 잘 설치가 된 것이다. 

import pyupbit

print(pyupbit.Upbit) # <class 'pyupbit.exchange_api.Upbit'>

 

이제, pyupbit를 이용할 수 있는 대표적인 기능 몇 가지를 알아보자. 

 

 

  2. 암호화폐 목록 얻기

 

암호화폐를 거래하기 위해서는 각 화폐별 ticker가 필요하다. get_tickers 함수를 이용하면 업비트에서 거래할 수 있는 모든 암호화폐의 문자열 ticker를 리스트로 반환해준다. 

import pyupbit

print(pyupbit.get_tickers())

# OUTPUT
['KRW-BTC', 'KRW-ETH', 'BTC-ETH', 'BTC-LTC', 'BTC-XRP', 'BTC-ETC', ...]

 

업비트에서는 원화(KRW)뿐만 아니라 BTC, USDT 마켓 또한 지원하므로 주로 이용하는 원화 마켓의 암호화폐를 선별하고 싶다면 다음과 같이 옵션을 추가해주어야 한다.

import pyupbit

print(pyupbit.get_tickers(fiat="KRW"))

# OUTPUT
['KRW-BTC', 'KRW-ETH', 'KRW-NEO', 'KRW-MTL', 'KRW-LTC', 'KRW-XRP', ...]

 

fiat은 우리가 사용하는 종이 화폐, 즉 명목화폐(fiat money)에서 나온 말이다. 동일한 방법으로 BTC / USDT 마켓의 암호화폐도 골라낼 수 있다.

 

 

  3. 암호화폐 현재가 얻기

 

get_current_price 함수를 이용하면 암호화폐의 마지막 체결 가격, 즉 현재가를 얻을 수 있다. 인자에 암호화폐의 ticker를 넣어주면 float형으로 값을 반환한다. 

import pyupbit

print(pyupbit.get_current_price("KRW-BTC"))

# OUTPUT 
64069000.0

 

만약 여러 암호화폐를 한 번에 조회하고 싶다면, ticker들을 담은 리스트를 인자로 넘겨주면 된다. 이 경우에는 반환 값으로 {key : value}가 {ticker : 현재가}인 딕셔너리가 반환된다. 

import pyupbit

print(pyupbit.get_current_price(["KRW-BTC", "KRW-ETH", "KRW-XRP"]))

# OUTPUT 
{'KRW-BTC': 63984000.0, 'KRW-ETH': 5020000.0, 'KRW-XRP': 1695.0}

 

몇 분 사이에 값이 비트코인 가격이 소폭 하락한 것을 볼 수 있다. get_current_price 함수는 한 번에 최대 100개의 암호화폐를 조회할 수 있다.

 

 

  4. 암호화폐 과거 데이터 조회

 

get_ohlcv 함수를 이용하여 인자에 ticker를 넘겨주면 해당 암호화폐의 OHLCV 데이터를 pandas DataFrame으로 반환한다. 

시가 / 고가 / 저가 / 종가 / 거래량 / 거래금액 을 구할 수 있다.

import pyupbit

print(pyupbit.get_ohlcv(ticker="KRW-BTC"))

# OUTPUT
                           open        high         low       close        volume         value
2020-10-26 09:00:00  14687000.0  14920000.0  14358000.0  14764000.0   3031.758804  4.461594e+10
2020-10-27 09:00:00  14772000.0  15457000.0  14683000.0  15312000.0   3964.125320  5.957730e+10
2020-10-28 09:00:00  15300000.0  15557000.0  14635000.0  15060000.0   5752.669847  8.715575e+10
2020-10-29 09:00:00  15060000.0  15379000.0  14703000.0  15207000.0   3516.504745  5.284074e+10
2020-10-30 09:00:00  15207000.0  15460000.0  14899000.0  15340000.0   3753.488127  5.689144e+10
...                         ...         ...         ...         ...           ...           ...
2021-05-09 09:00:00  71728000.0  73129000.0  70147000.0  71505000.0  11786.596492  8.435439e+11
2021-05-10 09:00:00  71506000.0  72460000.0  70175000.0  70902000.0  13095.617952  9.373196e+11
2021-05-11 09:00:00  70902000.0  71750000.0  67597000.0  69741000.0  11913.277828  8.271176e+11
2021-05-12 09:00:00  69714000.0  70499000.0  60854000.0  62257000.0  22173.238069  1.505872e+12
2021-05-13 09:00:00  62380000.0  64987000.0  60200000.0  64445000.0   5088.587170  3.218080e+11

 

get_ohlcv 함수는 다음과 같이 구성되어 있다. 

 

get_ohlcv(ticker='KRW-BTC', interval='day', count=200, to=None, period=0.1) -> Union[DataFrame, None]

 

매개변수로 ticker, interval, count, to, period가 존재하며, 반환 값으로 Union[DataFrame, None]을 갖는다.

 

interval 변수는 조회 단위를 나타낸다. 분(1/3/5/10/15/30/60/240), 일, 주, 월별 데이터를 구할 수 있으며 인자로 넘길 땐 다음과 같다. 

 

[ day / minute1 / minute3 / minute5 / minute10 / minute15 / minute30 / minute60 / minute240 / week / month ]

 

만약 interval을 지정하지 않는다면 기본값은 day이다. 

 

count 변수는 조회 개수를 나타낸다. 최근 영업일부터 이전 count만큼의 영업일까지의 데이터를 가져오게 된다. 

count를 지정하지 않는다면 기본값은 200이다.

 

to 변수는 입력된 시점의 이전까지의 데이터를 얻을 수 있다. 예를 들어 to="20210101"이라고 하면, 2020년 12월 31일부터 이전 count만큼의 영업일까지의 데이터를 가져온다. 즉, 2020-06-15~2020-12-31의 데이터를 가져온다. 

to를 지정하지 않는다면 기본값은 None이며, 이는 현재 일부터 가져오게 된다.

 

period는 데이터를 수집하는 주기를 말한다. count가 200 이하라면 period 옵션은 무시되며, count가 200보다 큰 경우 다른 API와 함께 사용한다면 조회 주기를 늘려주어야 한다. 

import pyupbit

print(pyupbit.get_ohlcv(ticker="KRW-BTC", interval="minute3", count=20))

# OUTPUT
                           open        high         low       close      volume         value
2021-05-13 10:36:00  64072000.0  64109000.0  63900000.0  63918000.0   58.438715  3.741627e+09
2021-05-13 10:39:00  63900000.0  63919000.0  63802000.0  63875000.0   73.630070  4.702404e+09
2021-05-13 10:42:00  63865000.0  64147000.0  63862000.0  64019000.0   60.718397  3.887090e+09
2021-05-13 10:45:00  64014000.0  64182000.0  63987000.0  64152000.0   36.676134  2.349825e+09
2021-05-13 10:48:00  64158000.0  64448000.0  64110000.0  64445000.0   63.697727  4.096094e+09
2021-05-13 10:51:00  64425000.0  64498000.0  64366000.0  64497000.0   78.271995  5.046166e+09
2021-05-13 10:54:00  64480000.0  64800000.0  64468000.0  64786000.0   99.956416  6.458304e+09
2021-05-13 10:57:00  64727000.0  64994000.0  64726000.0  64993000.0   92.597657  6.010476e+09
2021-05-13 11:00:00  64993000.0  64998000.0  64468000.0  64480000.0  110.172045  7.133575e+09
2021-05-13 11:03:00  64490000.0  64950000.0  64468000.0  64577000.0   93.156690  6.030081e+09
2021-05-13 11:06:00  64562000.0  64670000.0  64500000.0  64613000.0   66.252347  4.278387e+09
2021-05-13 11:09:00  64635000.0  64786000.0  64547000.0  64770000.0   57.174851  3.695290e+09
2021-05-13 11:12:00  64750000.0  64993000.0  64700000.0  64993000.0   91.189028  5.915082e+09
2021-05-13 11:15:00  64992000.0  65300000.0  64975000.0  65300000.0  134.847742  8.781921e+09
2021-05-13 11:18:00  65286000.0  65472000.0  64952000.0  64955000.0  117.236921  7.657944e+09
2021-05-13 11:21:00  64952000.0  65182000.0  64952000.0  65060000.0   75.174626  4.891415e+09
2021-05-13 11:24:00  65060000.0  65126000.0  64600000.0  64693000.0   86.530141  5.611444e+09
2021-05-13 11:27:00  64669000.0  64959000.0  64634000.0  64833000.0   72.705191  4.712628e+09
2021-05-13 11:30:00  64833000.0  64863000.0  64499000.0  64650000.0   99.585294  6.435314e+09
2021-05-13 11:33:00  64650000.0  64700000.0  64449000.0  64460000.0   70.165524  4.532421e+09

 

일봉을 구하는 경우 기준 시간을 직접 지정할 수 있다. 

get_daily_ohlcv_from_base 함수를 이용하여 base에 원하는 시간을 입력하면 해당 시간을 기준으로 하루가 계산된다.

import pyupbit

print(pyupbit.get_daily_ohlcv_from_base(ticker="KRW-BTC", base=13))

# OUTPUT
                           open        high         low       close        volume
2021-05-04 13:00:00  68030000.0  69751000.0  66500000.0  69124000.0   4311.390464
2021-05-05 13:00:00  69023000.0  70007000.0  67040000.0  68935000.0  11311.231399
2021-05-06 13:00:00  68910000.0  70853000.0  67186000.0  67498000.0  13871.493052
2021-05-07 13:00:00  67500000.0  69729000.0  66900000.0  69087000.0  10614.771277
2021-05-08 13:00:00  69100000.0  72500000.0  68993000.0  72402000.0  13002.555370
2021-05-09 13:00:00  72455000.0  73129000.0  70147000.0  72099000.0  11998.092245
2021-05-10 13:00:00  72098000.0  72460000.0  68500000.0  69552000.0  13981.115840
2021-05-11 13:00:00  69552000.0  70499000.0  67597000.0  70144000.0  10589.004324
2021-05-12 13:00:00  70170000.0  70499000.0  60200000.0  64451000.0  26736.304001

 

 

  5. 암호화폐 호가 조회

 

암호화폐의 매수/매도 호가 조회는 get_orderbook 함수를 이용한다. 인자로 ticker를 넘겨주고 반환 값으로 딕셔너리로 구성된 리스트를 반환한다. 

import pyupbit

print(pyupbit.get_orderbook(tickers="KRW-BTC"))

# OUTPUT
[{'market': 'KRW-BTC', 'timestamp': 1620874024245, 'total_ask_size': 3.97732861, 'total_bid_size': 2.52959603, 
'orderbook_units': 
[{'ask_price': 64090000.0, 'bid_price': 64070000.0, 'ask_size': 0.00031294, 'bid_size': 0.06156758}, 
{'ask_price': 64093000.0, 'bid_price': 64066000.0, 'ask_size': 0.26436965, 'bid_size': 0.08471909}, 
{'ask_price': 64094000.0, 'bid_price': 64065000.0, 'ask_size': 0.06992863, 'bid_size': 0.16189154}, 
{'ask_price': 64096000.0, 'bid_price': 64064000.0, 'ask_size': 1.98105323, 'bid_size': 0.00156093}, 
{'ask_price': 64098000.0, 'bid_price': 64061000.0, 'ask_size': 0.00204766, 'bid_size': 0.06961012}, 
{'ask_price': 64107000.0, 'bid_price': 64060000.0, 'ask_size': 0.06455513, 'bid_size': 1.16250019}, 
{'ask_price': 64125000.0, 'bid_price': 64029000.0, 'ask_size': 0.00549689, 'bid_size': 0.02838788}, 
{'ask_price': 64127000.0, 'bid_price': 64028000.0, 'ask_size': 0.01021383, 'bid_size': 0.03123633}, 
{'ask_price': 64128000.0, 'bid_price': 64019000.0, 'ask_size': 0.00069257, 'bid_size': 0.00447529}, 
{'ask_price': 64135000.0, 'bid_price': 64018000.0, 'ask_size': 0.19030409, 'bid_size': 0.00234309}, 
{'ask_price': 64138000.0, 'bid_price': 64005000.0, 'ask_size': 0.05639289, 'bid_size': 0.23895895}, 
{'ask_price': 64153000.0, 'bid_price': 64000000.0, 'ask_size': 0.1938, 'bid_size': 0.45682086}, 
{'ask_price': 64156000.0, 'bid_price': 63998000.0, 'ask_size': 1.00601281, 'bid_size': 0.06531679}, 
{'ask_price': 64173000.0, 'bid_price': 63997000.0, 'ask_size': 0.0187122, 'bid_size': 0.02281961},
{'ask_price': 64174000.0, 'bid_price': 63982000.0, 'ask_size': 0.11343609, 'bid_size': 0.13738778}]
}]

 

 

market은 ticker이고 timestamp는 조회시간(단위 : ms)이며, total_ask_size, total_bid_size는 총 매도/매수 크기를 말한다. 

orderbook_units는 딕셔너리가 원소인 리스트이며, ask_price는 매도 호가, bid_price는 매수 호가, ask_size는 매도 호가 수량, bid_size는 매수 호가 수량을 의미한다. 

get_orderbook에 여러 ticker를 넘겨주면 마찬가지로 한 번에 여러 암호화폐에 대한 호가를 구할 수 있다. 

 

 

  6. 잔고 조회

 

잔고를 조회하기 위해서는 API 사용 신청을 한 후 발급받았던 access key와 secret key가 필요하다. 이를 이용하여 Upbit 클래스의 인스턴스를 생성한 후, get_balances 함수를 이용하면 잔고를 조회할 수 있다. 

 

import pyupbit

access = "User access key" # access key 직접 입력
secret = "User secret key" # secret key 직접 입력

upbit = pyupbit.Upbit(access, secret)
print(upbit.get_balances())

# OUTPUT
[{'currency': 'KRW', 'balance': '0.68421149', 'locked': '0.0', 'avg_buy_price': '0', 'avg_buy_price_modified': True, 'unit_currency': 'KRW'}, 
{'currency': 'XRP', 'balance': '0.00000081', 'locked': '0.0', 'avg_buy_price': '1815', 'avg_buy_price_modified': False, 'unit_currency': 'KRW'}]    

 

코인을 하고 남은 흔적들이 있다. 현재 원화가 0.68원 정도, 아주 소량의 리플이 존재하는 것을 볼 수 있다. 

avg_buy_price는 평균 매수가를 의미하고, avg_buy_price_modified는 평균 매수가가 수정되었는지 여부를 나타낸다. 

 

get_balances 함수는 실제로 get_balances(contain_req=False) -> Union[tuple, None] 로 이루어져 있다. 

만약 get_balances에 True를 넣어주면, API를 호출할 수 있는 빈도의 제한을 추가로 반환한다.

import pyupbit

access = "User access key" # access key 직접 입력
secret = "User secret key" # secret key 직접 입력

upbit = pyupbit.Upbit(access, secret)
print(upbit.get_balances())

# OUTPUT
([{'currency': 'KRW', 'balance': '0.68421149', 'locked': '0.0', 'avg_buy_price': '0', 'avg_buy_price_modified': True, 'unit_currency': 'KRW'}, 
{'currency': 'XRP', 'balance': '0.00000081', 'locked': '0.0', 'avg_buy_price': '1815', 'avg_buy_price_modified': False, 'unit_currency': 'KRW'}], 
{'group': 'default', 'min': 899, 'sec': 29})  

 

API는 각 API마다 어떤 그룹에 속해있고, 그룹 단위로 호출을 제한한다. 위의 결과는 1분에 최대 899번, 1초당 최대 29번 API를 호출할 수 있다는 의미이다. 

 

만약 특정 암호화폐나 원화에 대해서 잔고가 궁금하다면 get_balance 함수를 이용하면 된다. 

인자로는 ticker를 넘겨준다. 

import pyupbit

access = "User access key" # access key 직접 입력
secret = "User secret key" # secret key 직접 입력

upbit = pyupbit.Upbit(access, secret)
print(upbit.get_balance("KRW"))

# OUTPUT
0.68421149

print(upbit.get_balance("KRW-XRP"))

# OUTPUT
8.1e-07

 

 

  7. 지정가 매수/매도

 

지정한 가격에 매도할 때에는 sell_limit_order 함수를, 매수할 때에는 buy_limit_order 함수를 이용한다. 

마찬가지로 Upbit 클래스의 인스턴스를 통해서 호출할 수 있다. 

 

import pyupbit

access = "User access key" # access key 직접 입력
secret = "User secret key" # secret key 직접 입력

upbit = pyupbit.Upbit(access, secret)
ret = upbit.buy_limit_order("KRW-BTC", 1000000, 1)
print(ret)

# OUTPUT
{'error': {'message': '주문가능한 금액(KRW)이 부족합니다.', 'name': 'insufficient_funds_bid'}}

 

buy_limit_order 함수와 sell_limit_order 함수는 다음과 같이 구성되어 있다. 

 

buy_limit_order(ticker, price, volume, contain_req=False) -> Union[tuple, None]

sell_limit_order(ticker, price, volume, contain_req=False) -> Union[tuple, None]

 

price에 원하는 매수/매도가를 넣고, volume에 매수/매도할 코인 개수를 넣는다. 

위의 예시에서는 비트코인을 100만 원에 1개 매수하려는 코드이다. 잔고가 부족하여 에러가 발생했지만, 만약 잔고가 충분하다면 주문 정보는 딕셔너리로 반환된다. (아래 참고)

 

예시) https://github.com/sharebook-kr/pyupbit 

주문을 통해 반환된 딕셔너리에서 uuid는 주문에 대한 고윳값으로, 이 값을 이용해서 주문을 다시 취소하거나 정정할 수 있다. 

 

 

  8. 시장가 매수/매도

 

시장가 매수/매도는 최우선 매도/매수 호가에 즉시 주문한다. 

시장가 매수는 buy_market_order 함수, 매도는 sell_market_order 함수를 이용한다. 

 

buy_market_order(ticker, price, contain_req=False) -> Union[tuple, None]

sell_market_order(ticker, volume, contain_req=False) -> Union[tuple, None]

 

시장가 매수를 하는 경우에는 매수할 금액을 넣어준다. 수수료가 제외된 금액이므로 만약 10000원 치를 구매한다면 실제로는 수수료 0.05%가 추가된 10005원의 현금을 가지고 있어야 한다. 

시장가 매도를 하는 경우에는 매도할 개수를 넣어준다. 

 

 

  9. 주문 취소/조회

 

주문 취소를 하기 위해선 이전에 주문했던 정보의 uuid를 이용한다. 이 uuid 값을 cancel_order라는 함수의 인자로 넘겨주면 주문이 취소된다. 

 

cancel_order(uuid, contain_req=False) -> Union[tuple, None]

 

주문을 조회하기 위해서는 get_order함수를 이용한다. 형태는 아래와 같다.

 

get_order(ticker_or_uuid, state='wait', kind='normal', contain_req=False) -> Union[tuple, None]

import pyupbit

access = "User access key" # access key 직접 입력
secret = "User secret key" # secret key 직접 입력

upbit = pyupbit.Upbit(access, secret)
ret = upbit.get_order("KRW-BTC") # 미체결 주문
ret = upbit.get_order("KRW-BTC", state="done") # 완료된 주문
ret = upbit.get_order("UUID") # 특정 주문 상세 조회

 

기본적으로 get_order 함수에 ticker만 넣으면 해당 암호화폐에 대한 미체결 주문 정보가 반환된다.

만약 state를 done으로 할당해주면 완료된 주문 정보가 반환된다. 

get_order 함수에 주문의 고유 정보인 uuid를 넣으면 해당 주문에 대한 상세 정보가 반환된다. 이 경우 다른 매개변수들은 무시된다. 

 

 

 

728x90
반응형
  • 질문자1 2021.06.13 14:41 댓글주소 수정/삭제 댓글쓰기

    안녕하세요! 질문 드립니다.
    get_daily_ohlcv_from_base
    에서 count를 사용할 수는 없나요? 기준시 변경 후 백테스트 하려하니 10개밖에 안나오네요 ㅠ

  • 코린이 2021.09.20 19:07 댓글주소 수정/삭제 댓글쓰기

    get_daily_ohlcv_from_base api가 quotation_api.py에 공개되어 있는데
    df를 이용해서 get_ohlcv를 minute60로 불러와서 resample로 새로운 df를 만들어 냅니다.
    get_ohlcv에는 count 변수가 있으니
    get_daily_ohlcv_from_base를 복사해서 본인에 py에 붙여넣기 하시고(오버라이드)
    count 변수를 get_ohlcv를 콜하는 부분에 넣어주시면 됩니다.