반응형

 안녕하세요. 이번 포스팅에서는 이전에 작성했던 코드들을 취합 및 수정하고, 메모장 기능을 추가한 코드를 포스팅하도록 하겠습니다. 

 

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을 이용해 새로운 윈도우에 필요한 정보들(시간, 포지션, 메모)을 띄울 수 있는 코드를 작성해 보았습니다. 향후 추가적인 기능을 넣거나, 에러 발생 시 추가 업데이트 예정입니다. 읽어주셔서 감사합니다.

 

반응형
반응형

 

안녕하세요. 이번 포스팅에서는 바이낸스의 usds-m의 선물 포지션을 조회하고, 새로운 창을 열어서 출력해보겠습니다. 포지션을 조회하는 데는 'ccxt'라는 패키지를, 새로운 창에 출력하는 것은 'tkinter'을 사용해 코딩해보겠습니다. 향후 다른 것들도 추가적으로 출력하는 것을 포스팅할 계획입니다.

 

1. ccxt를 이용한 바이낸스 선물 포지션 조회

import ccxt
import os
import dotenv

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']

print(positions)

dotenv를 이용해 환경변수 저장하는 방법은 아래 포스팅을 참고해주세요.

2022.10.05 - [Python] - 파이썬 dotenv를 이용한 환경변수 저장 및 호출

 

파이썬 dotenv를 이용한 환경변수 저장 및 호출

 블로그 만든 뒤에 처음 작성하는 글이네요. 블로그에 공유하기 위해 중요한 정보(암호) 등을 환경변수로 지정해 다른 파일에 저장하고, 공유시에 다른 사람들에게 노출되는 것을 막고자 합니

bitcoding.tistory.com

 

 

 필요한 패키지들을 import 해주고, 환경변수를 불러온 뒤, 바이낸스의 모든 usds-m의 선물 포지션을 조회하고 출력하는 코드입니다. 해당 코드에서 positions을 출력하면 아래와 같이 usds-m의 모든 페어의 포지션을 출력하게 됩니다.

[{'symbol': 'RAYUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'API3USDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'SUSHIUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'CVCUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'BTSUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'FTMBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'LINKBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'SANDBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'INJUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'HOTUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'TRXBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ZRXUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'QTUMUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'IOTAUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'BTCBUSD', 'initialMargin': '111.56959712', 'maintMargin': '0.39084988', 'unrealizedProfit': '-0.25647121', 'positionInitialMargin': '9.77124712', 'openOrderInitialMargin': '101.79835000', 'leverage': '10', 'isolated': True, 'entryPrice': '19491.2', 'maxNotional': '7500000', 'positionSide': 'BOTH', 'positionAmt': '-0.005', 'notional': '-97.71247121', 'isolatedWallet': '9.74774889', 'updateTime': '1666022402680', 'bidNotional': '0', 'askNotional': '1017.98350000'}, {'symbol': 'WAVESUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'SPELLUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ADAUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'LITUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'XTZUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'BNBUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0.00', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'UNIBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'DARUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 
'HNTUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ETCUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': True, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0.00', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '1647929253005', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'XMRUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0.000', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'YFIUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.000', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'FTTBUSD', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '100000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ETHUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '10', 'isolated': True, 'entryPrice': '0.0', 'maxNotional': '10000000', 'positionSide': 'BOTH', 'positionAmt': '0.000', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '1663227945832', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ALICEUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'ALPHAUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'WOOUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'SFPUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'REEFUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'BATUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'DOGEUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'TRXUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '250000', 'positionSide': 'BOTH', 'positionAmt': '0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'}, {'symbol': 'RLCUSDT', 'initialMargin': '0', 'maintMargin': '0', 'unrealizedProfit': '0.00000000', 'positionInitialMargin': '0', 'openOrderInitialMargin': '0', 'leverage': '20', 'isolated': False, 'entryPrice': '0.0', 'maxNotional': '25000', 'positionSide': 'BOTH', 'positionAmt': '0.0', 'notional': '0', 'isolatedWallet': '0', 'updateTime': '0', 'bidNotional': '0', 'askNotional': '0'},

 상당히 길고 복잡한 결과가 나오게 되는데, 여기서 현재 내가 오픈한 포지션만 조회하도록 추가해보겠습니다.

 

2. 오픈된 포지션 조회

import ccxt
import os
import dotenv

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']))

print(symbol)
print(size)
print(pnl)

 앞선 코드에서 받아온 positions의 initialMargin이 없는 경우를 제외하고, 해당 position의 symbol, size, pnl을 각각의 변수에 저장하고 출력하는 코드입니다. 결과는 아래와 같습니다.

['BTCBUSD', 'ETHBUSD']
['-97.67867686', '5.33319399']
[-0.22267686, 0.06211399]

 이것은 현재 오픈되어 있는 제 포지션입니다. BTCBUSD페어를 97.678 $의 숏포지션을 보유 중이며, pnl은 -0.2226$로 손실 중입니다. ETHBUSD페어는 5.333 $의 롱포지션을 보유 중이며 0.06211$의 수익을 보고 있습니다.

 다른 정보들도 조회 가능하지만, Symbol과 Size, pnl만 출력하고자 합니다.

 

3. tkinter를 이용한 윈도우 창 생성

import tkinter

win = tkinter.Tk ()
win.title("Traiding Tools")
win.configure(background='black')
win.geometry('200x200+165+200')

win.mainloop()

먼저 tkinter을 import 해주고 윈도우 창에 대한 설정들을 추가해줍니다. 창의 이름을 'Trading Tools'로 지정하고, 배경색을 검정으로 지정했습니다. 코드의 6번째 줄의 "win.geometry('200x200+165+200')"를 통해서 창의 크기와 위치를 지정할 수 있습니다. 200x200은 창의 크기이고, 뒤의 165+200은 코드 실행 시 창이 나타나는 위치를 지정한 것입니다. 코드를 실행하면 아래와 같이 검은 배경의 창이 실행되는 것을 볼 수 있습니다.

tkinter을 이용한 윈도우 창 출력

 

 이번 포스팅에서는 ccxt를 이용해 오픈된 포지션을 조회하고. tkinter를 이용해 윈도우 창을 출력해보았습니다. 다음 포스팅에서는 조회한 오픈된 포지션과 현재시간을 tkinter를 이용해 출력하는 것에 대해 이어서 포스팅하겠습니다. 읽어주셔서 감사합니다.

반응형

+ Recent posts