반응형

안녕하세요. 이번 포스팅에서는 지난 글에 이어서 tkinter을 이용해 출력하는 것을 보여드리겠습니다. 현재 시간과 현재 포지션, 총 pnl을 출력해보겠습니다.

 

1. 현재 시간 출력

 현재시간은 'datetime'이라는 패키지를 통해 출력해보겠습니다.

import datetime as dt

now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(now_time)

 

 위의 코드의 결과는 아래와 같은데, "연도-월-일 시간-분-초"로 형식을 지정해준 대로 출력되는 모습입니다.

2022-10-19 12:47:32

 

2. tkinter을 이용해 새 창에 출력(시간)

이전 포스팅에서 준비해둔 tkinter 윈도우 창에 현재 시간을 출력해 보겠습니다.

import tkinter
import tkinter.font
import datetime as dt

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')

now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

lb_time = tkinter.Label(font=font, fg='white', background='black')
lb_time.place(x = 0, y = 0)
lb_time.configure(text = now_time)

win.mainloop()

 

 아래 사진이 해당 코드의 결과입니다. 현재의 시간이 잘 출력되는 것을 볼 수 있습니다. tkinter을 통해 레이블의 형식을 지정하고, 레이블을 배치할 위치를 정해준 뒤에 현재시간을 레이블에 집어넣는 코드입니다. 윈도우 창의 배경을 검은색으로 했기 때문에 레이블의 배경색도 검은색으로, 글씨 색은 흰색으로 지정해 주었습니다.

현재 시간 출력

 

3. tkinter을 이용해 새 창에 출력(오픈 포지션)

 이전 포스팅에서 받아온 바이낸스의 선물 포지션을 출력해 보겠습니다. 오픈되어 있는 포지션의 페어이름과 pnl을 출력하고자 합니다.

import tkinter
import tkinter.font
import datetime as dt
import ccxt
import os
import dotenv

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')

now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

lb_time = tkinter.Label(font=font, fg='white', background='black')
lb_time.place(x = 0, y = 0)
lb_time.configure(text = now_time)

dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
apikey = os.environ['bn_apikey']
apisecret = os.environ['bn_secret']

binance = ccxt.binance(config={'apiKey': apikey, 'secret': apisecret})
balance = binance.fetch_balance(params={"type": "future"})
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']))

y=0
x=67
for n in range(len(symbol)):
    y += 16
    globals()['lb_sym_' + symbol[n]] = tkinter.Label(font=font, fg='white', background='black')
    globals()['lb_pnl_' + symbol[n]] = tkinter.Label(font=font, fg='white', 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]))


win.mainloop()

 

 오픈되어있는 포지션의 갯수나 페어의 종류가 매번 다르기 때문에, 현재 오픈된 포지션의 개수를 이용해 for문을 작성했습니다. 또한 globals() 함수를 사용해서, 오픈되어 있는 페어의 이름을 포함한 변수 이름을 사용했습니다. 현재 시간 출력 때와 마찬가지로 배경은 검은색, 글씨는 흰색으로 출력했습니다. 레이블의 위치는 for문을 통해 포지션의 개수에 맞게 y축을 지정했으며, pnl의 위치는 페어의 뒤쪽에 위치하도록 x값을 67로 주었습니다. 결과는 아래와 같습니다.

시간 및 포지션 출력

 

4. 포지션의 글씨 색 조절

 위 사진을 보시면 페어의 이름과 pnl 모두 흰색으로 출력되는데, 페어이름은 롱인지 숏인지에 따라 색상을 바꿔주고, pnl 역시 수익 중인지, 손실 중인지에 따라 바꿔 주겠습니다.

def color(amount):
    if amount >=0:
        return 'green'
    else:
        return 'red'

 

 간단하게 인풋으로 포지션 사이즈와 pnl을 받아서, 롱이거나 수익중이면 녹색으로, 반대로 숏이거나 손실 중이면 빨간색으로 출력하는 함수를 만들어 사용하겠습니다.

import tkinter
import tkinter.font
import datetime as dt
import ccxt
import os
import dotenv

def color(amount):
    if amount >=0:
        return 'green'
    else:
        return 'red'

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')

now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

lb_time = tkinter.Label(font=font, fg='white', background='black')
lb_time.place(x = 0, y = 0)
lb_time.configure(text = now_time)

dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
apikey = os.environ['bn_apikey']
apisecret = os.environ['bn_secret']

binance = ccxt.binance(config={'apiKey': apikey, 'secret': apisecret})
balance = binance.fetch_balance(params={"type": "future"})
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']))

y=0
x=67
for n in range(len(symbol)):
    y += 16
    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]))


win.mainloop()

 color 함수를 이용해 숏포지션인 BTCBUSD는 빨간색, 수익중인 0.97$은 녹색, 롱포지션인 ETHBUSD는 녹색, 손실 중인 -0.05$은 빨간색으로 잘 출력되는 것을 확인할 수 있습니다.

포지션에 따른 색상 표현

 

5. 총 pnl 출력

 모든 포지션의 pnl을 더해서 출력하는 코드를 추가해 보겠습니다.

import tkinter
import tkinter.font
import datetime as dt
import ccxt
import os
import dotenv

def color(amount):
    if amount >=0:
        return 'green'
    else:
        return 'red'

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')

now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

lb_time = tkinter.Label(font=font, fg='white', background='black')
lb_time.place(x = 0, y = 0)
lb_time.configure(text = now_time)

dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
apikey = os.environ['bn_apikey']
apisecret = os.environ['bn_secret']

binance = ccxt.binance(config={'apiKey': apikey, 'secret': apisecret})
balance = binance.fetch_balance(params={"type": "future"})
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']))

y=0
x=67
for n in range(len(symbol)):
    y += 16
    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]))

pnl_tot = sum(pnl)
y = y+16
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))


win.mainloop()

 

 pnl을 모두 더해 total pnl을 색상에 맞게 출력했습니다. 결과는 아래와 같습니다.

총 손익 출력

 

6. 업데이트 기능

 현재시간과 포지션은 지속적으로 바뀌기 때문에, 계속해서 새로고침 하는 코드를 만들어 보겠습니다.

import tkinter
import tkinter.font
import datetime as dt
import ccxt
import os
import dotenv
import time
import threading

def color(amount):
    if amount >=0:
        return 'green'
    else:
        return 'red'

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200')
font=tkinter.font.Font(family="Arial", size=10, slant="italic", weight='bold')

lb_time = tkinter.Label(font=font, fg='white', background='black')
lb_time.place(x = 0, y = 0)

dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
apikey = os.environ['bn_apikey']
apisecret = os.environ['bn_secret']

def update():
    now_time = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    lb_time.configure(text = now_time)
    
    binance = ccxt.binance(config={'apiKey': apikey, 'secret': apisecret})
    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']))

    y=0
    x=67
    for n in range(len(symbol)):
        y += 16
        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]))

    pnl_tot = sum(pnl)
    y = y+16
    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))

    threading.Timer(5, update).start()

update()

win.mainloop()

 

 threading 패키지를 이용해 5초마다 업데이트 되도록 해주었습니다. 바이낸스에서 api를 이용해 데이터를 받아올 때, 자주 받아오게 되면 에러가 나는 경우가 있습니다. 이것을 해결하고자 while과 try문, time 패키지를 이용해 에러 발생 시에, 5초 뒤 다시 받아오도록 했습니다. 새로고침이 필요한 부분을 update로 묶어주어 지속적으로 데이터를 받아와 출력하는 코드입니다.

 

 

 다음 포스팅은 위의 코드를 정리하고, 차후 다른 기능이 필요한 경우 추가적으로 넣도록 하겠습니다. 읽어주셔서 감사합니다. 

반응형

+ Recent posts