간밤에 큰 이슈가 있었습니다. FTX의 거래소 토큰인 FTT 가격은 25.8달러 → 2.73달러까지 떨어져서 대략 -90% 하락했었습니다. 현재는 6달러 부근에 거래중이네요. 뿐만 아니라 비트코인과 다른 알트코인들 역시 큰 하락이 있었습니다. 지난 24시간동안 9억 달러 이상 청산되었습니다.
먼저 f12를 눌러 개발자 모드에 진입해줍니다. 그 후 사진의 1번(검사할 페이지 요소 선택)을 클릭한 뒤 크롤링하고자 하는 부분인 2번(현재의 환율)을 클릭합니다. 그럼 html에서 환율에 해당하는 부분이 선택되게 됩니다. 해당 부분은 아래와 같습니다. 파이썬에서 이 부분을 이용해 환율을 가져와 보도록 하겠습니다.
from urllib.request import Request, urlopen
from bs4 import BeautifulSoup
req = Request('https://kr.investing.com/currencies/usd-krw', headers={'User-Agent': 'Mozilla/5.0'})
html = urlopen(req)
soup = BeautifulSoup(html, 'html.parser')
dollar = soup.find("span", attrs={"class":"text-2xl"}).get_text()
dollar = float(dollar.replace(",", ""))
print(dollar)
크롤링하고자 하는 사이트의 URL을 입력하고, 사이트의 차단을 방지하고자 headers값을 넣어줍니다. beautifulsoup을 통해 html을 가져와주고, 앞서 사이트에서 분석한 html부분을 이용해 환율을 얻어줍니다. 해당 부분의 태그인 span과 속성인 class="text-2xl"을 soup.find를 통해 찾아주고, get_text()를 이용해 텍스트 부분(1,403.91)만 얻어줍니다. 후에 계산을 위해 ','를 제거해주고, str에서 float로 바꿔주었습니다. 결과는 아래와 같습니다.
1403.91
3. 환율 적용(계산)
이전 포스팅에서 가져온 업비트와 바이낸스의 보유자산에 환율을 곱해서 원화와 달러로 얼마인지 계산해 보겠습니다.
이전에 작성한 코드의 보유자산에 환율을 대입해 모든 거래소의 총가치를 계산하고 출력했습니다. 결과는 아래와 같습니다.
Total Finance
추가적으로 수정한 사항을 적자면, 각각의 포스팅(업비트/바이낸스/환율)에서 작성한 코드들을 def 해주었고, 환율 계산을 위해 필요한 값들을 global을 통해 전역 변수로 지정해주었습니다. 각 거래소별로 보유자산을 받아오기 전에 문구를 출력해, 과정을 알 수 있게 했습니다.
다음 포스팅에서는 계산한 결과들 중 필요한 정보들만 엑셀에 저장해, 지난 자산흐름을 알아보기 쉽게 해 보겠습니다. 읽어주셔서 감사합니다.
안녕하세요. 이번 포스팅에서는 바이낸스의 보유자산을 조회하는 코드를 포스팅해보겠습니다. ccxt를 이용해 바이낸스의 계좌를 조회해 볼 텐데, 바이낸스의 계좌는 Fiat and Spot, Margin, Futures, Earn 등이 있습니다. 그중 제가 사용하는 Fiat and Spot과 Futures 지갑을 조회해보겠습니다.
ccxt의 'fetch_balance'를 통해 각 계좌의 보유 수량을 불러왔습니다. 두 가지 데이터를 합한 뒤 수량이 0 이상인 값들만 남겨주었습니다.
결과는 아래와 같습니다. (수정된 예시입니다.) 앞서 작성한 업비트와 마찬가지로 상장되어있지 않은 코인도 존재하고, 소량만 있어 가치가 낮은 코인들도 존재합니다. 또한 현물 계좌와 선물계좌의 데이터를 합쳐서, 중복된 데이터들도 존재합니다. 이러한 항목들을 정리하는 코드를 작성해 보겠습니다. (텍스트 가시성에 문제가 있어 사진으로 첨부합니다.)
spot and coin-m
2. 중복 데이터 취합
먼저 현물과 선물의 계좌에 같은 종류의 코인이 있는 경우 이를 더하는 코드를 작성해 보겠습니다.
중복되지 않은 항목은 df에, 중복된 항목들 중 spot은 df1, coin-m은 df2에 할당해주었습니다. 반복문을 통해 df1과 df2의 name이 같은 항목들끼리 balance 값을 더해 새로운 리스트에 지정해주었습니다. 그 뒤 중복되지 않은 항목들과 합해서, 중복된 항들을 모두 없앴습니다.
ccxt의 fetch_tickers를 통해 마켓정보(페어 및 가격 등)를 불러왔습니다. 이후 if문을 통해 각 코인 별 USDT 페어가 존재하는 경우에만 다음 코드를 실행하도록 했습니다. 테더 페어가 존재하는 경우, 가격정보를 받아와서 보유 중인 수량과 곱해 usd가치가 10$ 이상인 경우만 리스트에 저장해주었습니다.
비상장/소액 코인 정리
usdt 페어가 있는 경우만 남기다 보니, 보유 중인 usdt가 사라진 모습입니다. 다음 항목에서 현물 테더와 선물 usds의 스테이블 코인들을 더해서 정리하겠습니다.
보시면 KRW, ETH, XRP처럼 거래 가능하고, 일정 금액 이상의 가치를 가진 것들이 있습니다. 반면에 EOS, TRX처럼 극 소량만 있어서 별 가치가 없는 항목들도 있습니다. 또한 VTHO, APENFT와 같이 거래소에 상장되어 있지 않은 코인들도 존재합니다. 이런 가치가 낮은 항목들을 제거하는 코드를 추가로 작성하겠습니다.
2. 비상장 항목 제외 및 가격 조회
앞서 말한 것처럼 업비트 거래소에 상장되어있지 않은 코인을 제거하고, 남은 코인들의 현재 가격을 가져와보겠습니다.
업비트에는 원화/BTC/usdt 페어가 존재하는데 주로 원화 마켓을 이용하기 때문에 KRW페어만 남기고 제거하는 코드를 작성했습니다. 원화 마켓의 코인만 남기기 위해 try문을 사용해, 조회가 되면 append, 에러가 발생하면 pass 하도록 했습니다. 앞선 코드에서 얻은 보유한 항목들에 '/KRW'를 붙이고 현재 가격을 조회해서, 조회가 되는 항목들만 리스트에 저장했습니다.
안녕하세요. 이번 포스팅에서는 이전에 작성했던 코드들을 취합 및 수정하고, 메모장 기능을 추가한 코드를 포스팅하도록 하겠습니다.
1. 메모장 추가
tkinter의 Text를 이용하여 메모할 수 있도록 공간을 마련했습니다. '.env' 파일에 memoBefore이라는 key로 메모 내용을 저장하고 불러와서 text에 insert 하여, 코드 실행 시 자동적으로 이전의 메모를 불러오고, 메모 내용에 변화가 있을 시 해당 내용을 '.env' 파일에 수정할 수 있게 했습니다.
2. 수정사항
가독성을 위해 기본 글씨색을 노란색으로 수정해 주었고, 메모장 내의 깜빡이는 커서 색은 흰색으로 할당해주었습니다.(insertbackground)
새로고침 할 경우 이전내용이 삭제가 안되고 남아있는 경우가 발생해 (특히 포지션 개수가 줄어드는 경우), 업데이트 이전의 레이블을 destroy 하는 방법을 생각했으나 코드가 복잡해질 것 같아, 새로고침 할 때 다른 레이블들을 덮어버릴 큰 레이블 하나를 배치하는 것으로 대신했습니다.
작동 모습
3. 코드
import ccxt
import os
import dotenv
import tkinter
import tkinter.font
from tkinter import *
import datetime as dt
import threading
import time
dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
apikey = os.environ['bn_apikey']
apisecret = os.environ['bn_secret']
memoBefore = os.environ['memoBefore']
############################################################
# 폰트색상
def color(amount):
if amount >=0:
return 'green'
else:
return 'red'
############################################################
# 윈도우 생성
def gui():
global font
win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('155x400')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')
#메모장
text = Text(win, bg = 'black', insertbackground='white', height=10, width=17, fg='yellow',font=tkinter.font.Font(family="Arial", size=12, weight='bold'))
text.place(x = 0, y =200)
text.insert(END, memoBefore)
binance = ccxt.binance(config={'apiKey': apikey, 'secret': apisecret})
############################################################
# 새로고침
def update():
############################################################
# 선물 포지션 불러오기
def from_binance():
global symbol
global size
global pnl
while True:
try:
balance = binance.fetch_balance(params={"type": "future"})
break
except:
time.sleep(5)
positions = balance['info']['positions']
# 오픈 포지션 분리
symbol = []
size = []
pnl = []
for position in positions:
if position['initialMargin'] != '0':
symbol.append(position['symbol'])
size.append(position['notional'])
pnl.append(float(position['unrealizedProfit']))
############################################################
# 레이블 배치
def arrange_label():
# 지우기
lb_clear = tkinter.Label(width=20, height=10, background='black')
lb_clear.place(x=0, y=0)
# 현재시간 표시
y = 0
lb_time = tkinter.Label(font=font, fg='yellow', background='black')
lb_time.place(x = 0, y = y)
now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
lb_time.configure(text = now_time)
# 현재포지션 표시
for n in range(len(symbol)):
# 포지션 배치
x = 70
y += 16.5
globals()['lb_sym_' + symbol[n]] = tkinter.Label(font=font, fg=color(float(size[n])), background='black')
globals()['lb_pnl_' + symbol[n]] = tkinter.Label(font=font, fg=color(pnl[n]), background='black')
globals()['lb_sym_' + symbol[n]].place(x = 0, y = y)
globals()['lb_pnl_' + symbol[n]].place(x = x, y = y)
globals()['lb_sym_' + symbol[n]].configure(text = "{0}".format(symbol[n]))
globals()['lb_pnl_' + symbol[n]].configure(text = "{0:.2f} $".format(pnl[n]))
# total pnl
pnl_tot = sum(pnl)
y = y+16.5
lb_tot = tkinter.Label(font=font, fg = color(sum(pnl)), background='black')
lb_tot.place(x=0, y=y)
lb_tot.configure(text = "Total pnl: {0:.2f} $".format(pnl_tot))
############################################################
# 메모장 내용 저장
def saveMemo():
global memoBefore
memoText = text.get(1.0, 'end-1c')
if memoText != memoBefore:
dotenv.set_key(dotenv_file, 'memoBefore', memoText)
memoBefore = memoText
from_binance()
arrange_label()
saveMemo()
threading.Timer(5, update).start()
update()
win.mainloop()
gui()
여기까지 tkinter을 이용해 새로운 윈도우에 필요한 정보들(시간, 포지션, 메모)을 띄울 수 있는 코드를 작성해 보았습니다. 향후 추가적인 기능을 넣거나, 에러 발생 시 추가 업데이트 예정입니다. 읽어주셔서 감사합니다.