[비트코인자동매매]2. 상승장 알리미

1.pybithumb

  • 빗썸 거래소의 Public API 이용(공개 API)
  • 빗썸 가입 없이 누구나 사용가능하며, 가상화폐 현재가, 거래량, 호가정보 제공

pip install pybithumb

1) 가상화폐 티커목록 얻기

  • 티커(Ticker) : 가상화폐 고유 이름
    • 빗썸 : 세 자리 이상의 대문자를 이용해 가상화폐 구분
    • ex) bitcoin = "BTC"
  • get_tickers()
import pybithumb

tickers = pybithumb.get_tickers()
print(tickers)
print(len(tickers)) #실제로 거래되고 있는 가상화폐의 수 : 51

2) 현재가 얻기

  • get_current_price()
price = pybithumb.get_current_price("BTC")
print(price)

  • 1초에 한번씩만 값 조회
  • 공개 API는 초당 20회 호출 가능 : 그 이상 초과 요청 시 일정시간동안 사용이 차단되므로 time 모듈의 sleep()함수 이용
import pybithumb
import time

while True:
    # tickers = pybithumb.get_tickers()
    price = pybithumb.get_current_price("BTC")
    print(price)
    time.sleep(1)

  • 가상화폐 티커 목록을 얻은 후 모든 가상화폐의 현재가 출력
import pybithumb
import time

tickers = pybithumb.get_tickers()
for ticker in tickers:
    price = pybithumb.get_current_price(ticker)
    print(ticker, " - price : ", price)
    time.sleep(0.1)

3) 거래소 거래 정보

  • 시가/고가/저가/현재가 : 가상화폐의 방향성을 살펴볼 수 있는 대표적인 지표
  • get_market_detail() : 24시간동안의 저가/고가/거래금액/거래량 가져옴
detail = pybithumb.get_market_detail("BTC")
print(detail)

  • 저가 / 고가/ 평균거래금액 / 거래량 순으로 출력

4) 호가

  • 호가 : 더 비싼 가격에 매도하고 싶고, 더 저렴한 가격에 매수하고 싶어함
    • 매도 호가(ask) : 가상화폐를 팔고자 하는 사람이 제시한 가격과 수량
    • 매수 호가(bid) : 가상화폐를 사고자 하는 사람이 제시한 매수 가격과 수량
  • get_orderbook() : 가상화폐에 대한 호가정보를 딕셔너리로 얻을 수 있음
orderbook = pybithumb.get_orderbook("BTC")
print(orderbook)

for k in orderbook:
    print(k)
  • orderbook print 결과화면
    {'timestamp': '1650196752255', 'payment_currency': 'KRW', 'order_currency': 'BTC', 'bids': [{'price': 50502000.0, 'quantity': 0.2135}, {'price': 50501000.0, 'quantity': 0.7749}, {'price': 50488000.0, 'quantity': 0.1506}, {'price': 50485000.0, 'quantity': 0.0655}, {'price': 50483000.0, 'quantity': 0.4867}], 'asks': [{'price': 50523000.0, 'quantity': 0.0745}, {'price': 50525000.0, 'quantity': 0.2177}, {'price': 50526000.0, 'quantity': 0.031}, {'price': 50527000.0, 'quantity': 0.0188}, {'price': 50534000.0, 'quantity': 0.0409}]}

- orderbook의 key값

  • payment_currency : 'KRW'라는 문자열 타입의 value값을 얻을 수 있음
    • 현재 빗썸은 가상화폐 거래 시 원화 결제만 지원하므로 고정값임
  • order_currenccy : 조회한 가상화폐의 티커
  • timestamp : 호가를 조회한 시간
  • ask : 매도호가
  • bid : 매수호가
orderbook = pybithumb.get_orderbook("BTC")
print(orderbook['payment_currency'])
print(orderbook['order_currency'])
ms = int(orderbook['timestamp'])
dt = datetime.datetime.fromtimestamp(ms/1000)
print(dt)
print(orderbook['bids'])
print(orderbook['asks'])

  • bids, asks : 파이썬 리스트로 총 다섯개의 딕셔너리가 있음
    • 각각 호가(수량과 가격)를 나타냄
      [{'price': 50512000.0, 'quantity': 0.0587}, {'price': 50511000.0, 'quantity': 0.0223}, {'price': 50505000.0, 'quantity': 0.1201}, {'price': 50500000.0, 'quantity': 0.004}, {'price': 50499000.0, 'quantity': 0.0332}][{'price': 50515000.0, 'quantity': 0.079}, {'price': 50518000.0, 'quantity': 0.2007}, {'price': 50525000.0, 'quantity': 0.0718}, {'price': 50529000.0, 'quantity': 0.28}, {'price': 50532000.0, 'quantity': 0.6212}]
  • 매수호가, 매도호가 출력
orderbook = pybithumb.get_orderbook("BTC")

bids = orderbook['bids']
asks = orderbook['asks']

for bid in bids:
    price = bid['price']
    quant = bid['quantity']
    print('매수호가 : ', price, '매수잔량 : ', quant)
    
for ask in asks:#각각의 가격과 잔고는 'price', 'quantity'라는 키에 저장된 딕셔너리형태
    print(ask)

5) 여러가상화폐에 대한 정보 한 번에 얻기

  • get_current_price("ALL") : 빗썸에서 거래되는 모든 가상화폐에 대한 현재가를 조회
all = pybithumb.get_orderbook("ALL")
for k, v in all.items():
    print(k, v)
  • key : status
  • value : data
    • key: 가상화폐의 티커
    • value : 가격정보
      • closing_price(key) : 최종 체결가(value)

ENJ {'opening_price': '69', 'closing_price': '66', 'min_price': '66', 'max_price': '71', 'average_price': '68.6902', 'units_traded': '31112008.062182424015', 'volume_1day': '31112008.062182424015', 'volume_7day': '305304299.66063367358992023', 'buy_price': '66', 'sell_price': '67', '24H_fluctate': -3, '24H_fluctate_rate': '-4.34'}
PST {'opening_price': '353', 'closing_price': '339', 'min_price': '336', 'max_price': '362', 'average_price': '351.2558', 'units_traded': '3321414.5559280172538', 'volume_1day': '3321414.5559280172538', 'volume_7day': '27460648.10254002814311293', 'buy_price': '339', 'sell_price': '340', '24H_fluctate': -14, '24H_fluctate_rate': '-3.96'}

  • 모든 가상화폐의 현재가 출력
all = pybithumb.get_current_price("ALL")
for ticker, data in all.items() :
     print(ticker, data['closing_price'])

6) 예외처리

  • 비트코인 현재가 0.2초마다 조회 후 현재가 1/10 출력
while True:
    price = pybithumb.get_current_price("BTC")
    try:
        print(price/10) # price=None이 되는 경우 에러발생함
    except:
        print("에러", price)
    time.sleep(0.2)

2. 상승장 알리미

1) 이동평균을 사용한 상승장/하락장 구분

  • 종가의 이동평균(Moving Average)
    • 이동평균 < 현재가 : 상승장
    • 이동평균 > 현재가 : 하락장

  • ex) 2.26 현재가 : 1000원
    • 5일간의 리플종가 이동평균 : 920
    • 상승장

2) 거래소 과거 시세 얻기

  • get_ohclv() : 웹 스크래핑을 통해 일봉 데이터를 가져옴
import pybithumb

btc = pybithumb.get_ohlcv("BTC")
print(btc) #DataFrame 객체 출력

  • 최근 데이터는 DataFrame의 끝에 저장되어 있음
import pybithumb

btc = pybithumb.get_ohlcv("BTC")
c = btc['close']
print(c)#Series 객체 출력

3) 이동평균 계산

  • rolling(), mean() : 반복문 사용없이 모든 데이터의 이동평균을 자동 계산
import pybithumb

btc = pybithumb.get_ohlcv("BTC")
c = btc['close']

m5 = c.rolling(5).mean()
print(m5)

4) 상승장, 하락장 구분하는 함수 구현

  • 전날 이동평균과 현재가 비교해야함
    • 전날 이동평균값은 어디에 저장? : 끝에서 두번째에 위치
import pybithumb

df = pybithumb.get_ohlcv("BTC")
m5 = df['close'].rolling(5).mean()
last_m5 = m5[-2] #전날 이동평균

price = pybithumb.get_current_price("BTC")

if price > last_m5:
    print("상승장")
else:
    print("하락장")

5) 가상화폐별 상승장/하락장 판단하기

  • 빗썸에서 거래되는 모든 가상화폐에 대한 상승장, 하락장 판단
import pybithumb

def bull_market(ticker):
    df = pybithumb.get_ohlcv("BTC")
    m5 = df['close'].rolling(5).mean()
    last_m5 = m5[-2]

    price = pybithumb.get_current_price("BTC")

    if price > last_m5:
        return True
    else:
        return False

tickers = pybithumb.get_tickers()
for ticker in tickers:
    is_bull = bull_market(ticker)
    if is_bull:
        print(ticker,"상승장")
    else:
        print(ticker,"하락장")

6)UI 생성 / UI 파일 불러오기

1️⃣ tableWidget 메인화면에 끌어다놓기

2️⃣ 항목 편집을 통해 행 이름 추가


  • bull.ui로 저장
  • bull.ui는 python파일과 같은 디렉터리에 위치해야 읽을 수 있음
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic

form_class = uic.loadUiType("bull.ui")[0]

class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

7)상승장/하락장 코드 구현 - QTimer ver.

* 가상화폐 목록 추가

  • TableWidget에 row 4개 추가

  • ⭐️해당 ui를 반드시 파이썬 프로젝트 있는 디렉터리 위치에 옮겨야함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *

tickers = ["BTC", "ETH", "BCH", "ETC"]
form_class = uic.loadUiType("bull.ui")[0]

class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setupUi(self)
        timer=QTimer(self)
        timer.start(500)
        timer.timeout.connect(self.timeout) #timeout 발생하면 MyWindow의 timeout 실행되도록 연결함
        
    def timeout(self):
        for i, t in enumerate(tickers):
            item = QTableWidgetItem(t) #각 티커 얻어옴
            self.tableWidget.setItem(i,0,item)
            #해당 티커의 인덱스에 맞는 위치에 추가

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

* 가상화폐 현재가, 5일이동평균, 상승장/하락장 추가하기

  • 얻어온 데이터는 QTableWidgetItem 객체로 만든 후, 이를 QTableWidget에 추가함
    • 문자열 아닌값은 문자열로 변환 필요
import sys

import pybithumb
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *

tickers = ["BTC", "ETH", "BCH", "ETC"]
form_class = uic.loadUiType("bull.ui")[0]

class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setupUi(self)
        timer=QTimer(self)
        timer.start(500) #0.5초마다 내용 업데이트함
        timer.timeout.connect(self.timeout)

    def get_market_infos(self, ticker):
        df = pybithumb.get_ohlcv(ticker)
        m5 = df['close'].rolling(5).mean()
        last_m5 = m5[-2]
        price = pybithumb.get_current_price("BTC")

        state = None
        if price > last_m5:
            state = '상승장'
        else:
            state = '하락장'
        return price, last_m5, state

    def timeout(self):
        for i, t in enumerate(tickers):
            item = QTableWidgetItem(t)
            self.tableWidget.setItem(i,0,item)

            price, last_m5, state = self.get_market_infos(t)
            self.tableWidget.setItem(i, 1, QTableWidgetItem(str(price)))
            self.tableWidget.setItem(i, 2, QTableWidgetItem(str(last_m5)))
            self.tableWidget.setItem(i, 3, QTableWidgetItem(str(state)))
			
app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()


8)상승장/하락장 코드 구현 - 스레드 ver.

  • 스레드 실행 시, 직접 run() 호출이 아니라 스레드 인스턴스 생성 후 start() 호출해야 run() 실행됨
import sys
import pybithumb
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *

tickers = ["BTC", "ETH", "BCH", "ETC"]
form_class = uic.loadUiType("bull.ui")[0]

class Worker(QThread):#스레드 상속 클래스
    finished = pyqtSignal(dict) #사용자 정의 시그널 생성

    def run(self):#스레드 실행 시 수행되는 코드
        while True:
            data = {}

            for ticker in tickers:
                data[ticker] = self.get_market_infos(ticker)

            self.finished.emit(data)#finished라는 이벤트를 발생시킴
            self.msleep(500) #0.5초 슬립

    def get_market_infos(self, ticker):
        try:
            df = pybithumb.get_ohlcv(ticker)
            m5 = df['close'].rolling(5).mean()
            last_m5 = m5[-2]

            price = pybithumb.get_current_price("BTC")

            state = None
            if price > last_m5:
                state = '상승장'
            else:
                state = '하락장'
            return (price, last_m5, state)
        except:
            return (None, None,None)


class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setupUi(self)
        self.tableWidget.setRowCount(len(tickers))
        self.worker = Worker()
        self.worker.finished.connect(self.update_table_widget)
        self.worker.start()
    @pyqtSlot(dict)
    def update_table_widget(self, data):
        try:
            for i, t in data.items():
                index = tickers.index(t)
                self.tableWidget.setItem(index,0,QTableWidgetItem(t))
                self.tableWidget.setItem(index, 1, QTableWidgetItem(str(i[0]))) #현재가
                self.tableWidget.setItem(index, 2, QTableWidgetItem(str(i[1]))) #5일 이동평균
                self.tableWidget.setItem(index, 3, QTableWidgetItem(str(i[2]))) #상승/하락장
        except:
            pass
app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()
  • data.items() : 딕셔너리 형태임
    • 티커
    • 티커에 해당하는 값 : (현재가, 이동평균, 상승/하락장)

좋은 웹페이지 즐겨찾기