return Pasted;
article thumbnail
해당 프로그램은 웹소켓 (업비트, 바이낸스) API를 이용하여 코인 정보를 받은 다음, 코인 정보를 시세차익 기준으로 정렬하여 텔레그램 봇을 통해 사용자에게 코인의 시세 정보(차익 정보)를 제공하는 알림 프로그램이다.

미리보기 방지

 

결과

 

서버

 

- Source Code

main.py
import asyncio

# 거래소 5종 모두 이용할 경우 -> , bybit, okx, bitget 추가
from api import upbit, binance

import util
import traceback
import time
import platform
import requests
import json
import os
from consts import *


class Premium:
    def __init__(self):
        self.exchange_price = {}                # 거래소별 가격 데이터를 저장할 딕셔너리
        self.exchange_accum_trade_price = {}    # 거래소별 거래대금 데이터를 저장할 딕셔너리

    # 해외 거래소의 USD/USDT 가격을 저장하는 함수
    # while 문을 통해 일정 주기를 기준으로 무한히 반복
    async def get_usd_price(self):
        while True:
            try:
                data = requests.get('https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD').json()
                self.exchange_price['USD'] = {'base':data[0]['basePrice']}

                # BUSD/USDT -> USDT/BUSD -> (USDT) 역수를 취함
                res = requests.get('https://api.binance.com/api/v3/ticker/price?symbol=BUSDUSDT')
                self.exchange_price['USDT'] = {'base': 1 / float(res.json()['price'])}
                await asyncio.sleep(DOLLAR_UPDATE)  # 달러 가격 업데이트 주기 (1시간)

            except Exception as e:
                util.send_to_telegram(traceback.format_exc())


    # 거래소별 코인의 누적 거래대금을 조회하여 self.exchange_accum_trade_price 에 저장하는 함수
    # while 문을 통해 일정 주기를 기준으로 무한히 반복
    async def check_exchange_accum_trade_price(self):
        while True:
            try:
                # 거래소별 connect_socket 을 통해 가져와야 할 코인 정보가 있어서 대기
                await asyncio.sleep(ACCUM_TRADE_PRICE_DELAY)

                # 1. Upbit 누적 거래대금 확인
                upbit.get_exchange_accum_trade_price(self.exchange_accum_trade_price)

                # 2. Binance 누적 거래대금 확인
                binance.get_exchange_accum_trade_price(self.exchange_accum_trade_price, self.exchange_price)

                # # 3. Bybit 누적 거래대금 확인
                # bybit.get_exchange_accum_trade_price(self.exchange_accum_trade_price, self.exchange_price)
                #
                # # 4. OKX 누적 거래대금 확인
                # okx.get_exchange_accum_trade_price(self.exchange_accum_trade_price, self.exchange_price)
                #
                # # 5. Bitget 누적 거래대금 확인
                # bitget.get_exchange_accum_trade_price(self.exchange_accum_trade_price, self.exchange_price)

                await asyncio.sleep(ACCUM_TRADE_PRICE_UPDATE)

            except Exception as e:
                util.send_to_telegram(traceback.format_exc())


    # self.exchange_price 에 저장된 거래소별 코인 정보를 비교하고 특정 수치(%)이상 격차 발생시 알림을 전달하는 함수
    async def compare_price(self):
        while True:
            try:
                await asyncio.sleep(COMPARE_PRICE_DELAY)    # 거래소별 connect_socket 을 통해 가져와야 할 코인 정보가 있어서 대기
                util.send_to_telegram('✅')
                base_message = '🔥 프리미엄 정보 🔥\n\n'
                exchange_price = self.exchange_price.copy() # 거래소에서 얻어온 가격 데이터 복사
                message_dict = {}                           # 격차 발생시 알람을 보낼 메시지를 저장해둘 딕셔너리
                message_list = ['']                         # message_dict 에 저장했던 메시지들을 보낼 순서대로 저장한 리스트

                # 버블정렬을 이용하여 데이터를 오름차 순으로 정렬하고 코인 정보를 보여주는 과정
                for key in exchange_price:
                    if key in ['USD', 'USDT']:
                        continue

                    # 거래소 목록 리스트를 생성
                    exchange_list = list(exchange_price[key])

                    # 'exchange_list[i]' = 기준 거래소명, 'base_exchange' = 가격
                    for i in range(0, len(exchange_list) - 1):
                        base_exchange = exchange_list[i]

                        # 가격 데이터가 들어있는 'exchange_price'에 코인이 키 값으로 있고, 거래소 명이 'base_exchange' 에 키 값으로 있는 형태
                        base_exchange_price = round(float(exchange_price[key][base_exchange]), 2) if float(
                            exchange_price[key][base_exchange]) > 0 else float(exchange_price[key][base_exchange])

                        if not base_exchange_price:
                            continue

                        for j in range(i + 1, len(exchange_list)):

                            # 비교 거래소의 가격, 코인의 가격을 저장
                            # 데이터를 꺼내오는 키 값이 'base_exchange' -> 'compare_exchange' 로 바뀌고, 변수명이 변경
                            compare_exchange = exchange_list[j]
                            compare_exchange_price = round(float(exchange_price[key][compare_exchange]), 2) if float(
                                exchange_price[key][compare_exchange]) > 0 else float(exchange_price[key][compare_exchange])

                            # 가격 데이터가 존재하지 않다면 비교할 수 없으므로 넘어감
                            if not compare_exchange_price:
                                continue

                            # 거래소간의 가격 차이(%)
                            diff = round((base_exchange_price - compare_exchange_price) /
                                         base_exchange_price * 100, 3) if base_exchange_price else 0

                            if abs(diff) > NOTI_GAP_STANDARD:
                                message = f'{key}, {base_exchange}_{compare_exchange} 프리미엄({diff}%)\n'
                                message += f'현재가격:{base_exchange_price:,.2f}원/{compare_exchange_price:,.2f}원\n'
                                if self.exchange_accum_trade_price[key][base_exchange] and \
                                        self.exchange_accum_trade_price[key][
                                            compare_exchange]:  # 거래대금 데이터가 있는 경우에만 알림 추가
                                    message += f'거래대금:{self.exchange_accum_trade_price[key][base_exchange]:,.2f}억원/{self.exchange_accum_trade_price[key][compare_exchange]:,.2f}억원\n'
                                message_dict[diff] = message

                # 알림을 보내기 전에 메시지를 정렬
                message_dict = dict(sorted(message_dict.items(), reverse=True))  # 메시지 격차 발생 순으로 정렬
                for i in message_dict:
                    if len(message_list[len(message_list) - 1]) + len(message_dict[i]) < TELEGRAM_MESSAGE_MAX_SIZE:
                        message_list[len(message_list) - 1] += message_dict[i] + '\n'
                    else:
                        message_list.append(message_dict[i] + '\n')

                message_list[0] = base_message + message_list[0]  # 알림 첫줄 구분용 문구 추가

                # 정렬한 메시지를 순서대로 텔레그램 알림 전송
                for message in message_list:
                    util.send_to_telegram(message)

            except Exception as e:
                util.send_to_telegram(traceback.format_exc())


    async def run(self):
        await asyncio.wait([                                                        # 태스크들을 비동기 실행하고 결과를 기다림
            asyncio.create_task(self.get_usd_price()),                              # USD(달러) 데이터 조회/저장
            asyncio.create_task(upbit.connect_websocket(self.exchange_price)),      # Upbit websocket 연결 및 가격정보 조회/저장
            asyncio.create_task(binance.connect_websocket(self.exchange_price)),    # Binance websocket 연결 및 가격정보 조회/저장
            # asyncio.create_task(bybit.connect_websocket(self.exchange_price)),      # Bybit websocket 연결 및 가격정보 조회/저장
            # asyncio.create_task(okx.connect_websocket(self.exchange_price)),        # OKX websocket 연결 및 가격정보 조회/저장
            # asyncio.create_task(bitget.connect_websocket(self.exchange_price)),     # Bitget websocket 연결 및 가격정보 조회/저장
            asyncio.create_task(self.check_exchange_accum_trade_price()),           # 누적 거래대금 조회/저장
            asyncio.create_task(self.compare_price())                               # 가격비교 알림
        ])

if __name__ == '__main__':
    premium = Premium()
    asyncio.run(premium.run())  # 비동기 함수 호출​

consts.py
import os

# USD (달러 환율)
USD_PRICE = 1308.75     # 2023-03.19.

# Exchanges (거래소 이름)
UPBIT   =     'Upbit'
BINANCE =   'Binance'
BYBIT   =     'Bybit'
OKX     =       'OKX'
BITGET  =    'Bitget'

# All Exchanges (거래소 리스트)
EXCHANGE_LIST = [UPBIT, BINANCE]                        # 업비트와 바이낸스만 불러올 경우
# EXCHANGE_LIST = [UPBIT, BINANCE, BYBIT, OKX, BITGET]    # 5종 거래소 모두 불러올 경우

# API KEYS (API KEY 정보)
UPBIT_API_KEY       = os.getenv('UPBIT_API_KEY')
UPBIT_SECRET_KEY    = os.getenv('UPBIT_SECRET_KEY')

BINANCE_API_KEY     = os.getenv('BINANCE_API_KEY')
BINANCE_SECRET_KEY  = os.getenv('BINANCE_SECRET_KEY')

BYBIT_API_KEY       = os.getenv('BYBIT_API_KEY')
BYBIT_SECRET_KEY    = os.getenv('BYBIT_SECRET_KEY')

OKX_API_KEY         = os.getenv('OKX_API_KEY')
OKX_SECRET_KEY      = os.getenv('OKX_SECRET_KEY')
OKX_PASS            = os.getenv('OKX_PASS')

BITGET_API_KEY      = os.getenv('BITGET_API_KEY')
BITGET_SECRET_KEY   = os.getenv('BITGET_SECRET_KEY')
BITGET_PASS         = os.getenv('BITGET_PASS')

# TELEGRAM (텔레그램 정보)
TELEGRAM_BOT_TOKEN          = os.getenv('TELEGRAM_BOT_TOKEN')
TELEGRAM_CHAT_ID            = os.getenv('TELEGRAM_CHAT_ID')
TELEGRAM_MESSAGE_MAX_SIZE   = 4095  # 텔레그램 메시지 최대길이

# SOCKET (웹소켓)
SOCKET_PING_INTERVAL        = 20    # 20초
SOCKET_RETRY_TIME           = 30    # 30초
SOCKET_PING_TIMEOUT         = 30    # 30초

# DELAY (딜레이, 주기)
DOLLAR_UPDATE               = 60 * 60   # 달러 가격 업데이트 주기 (1시간)
ACCUM_TRADE_PRICE_DELAY     = 3 * 60    # 누적 거래 대금조회 최초 실행대기 (3분)
ACCUM_TRADE_PRICE_UPDATE    = 60 * 60   # 누적 거래 대금조회 업데이트 주기 (1시간)
COMPARE_PRICE_DELAY         = 5 * 60    # 가격 비교 최초 실행대기 (5분)
TIME_DIFF_CHECK_DELAY       = 30 * 60   # 바이낸스 서버와 시간비교 주기 (30분)

# ETC (누적 거래 대금)
MILLION             = 100000000     # 억 (단위)
NOTI_GAP_STANDARD   = 1.0           # 거래소간 차이가 발생할 때 알림을 보낼 기준(%)​

util.py
from consts import *
import telegram
import time
from datetime import datetime, timedelta


bot = None


# 텔레그램 봇을 통해 메시지를 전송하는 함수
def send_to_telegram(message):
    global bot
    if not bot:
        if TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID:
            bot = telegram.Bot(token=TELEGRAM_BOT_TOKEN)
        else:
            raise Exception('TELEGRAM_PATH Undefined.')

    retries = 0
    max_retries = 3

    while retries < max_retries and bot:
        try:
            print(message)
            bot.send_message(text=message[:TELEGRAM_MESSAGE_MAX_SIZE], chat_id=TELEGRAM_CHAT_ID)
            return True

        except telegram.error.TimedOut as timeout:
            time.sleep(5 * retries)
            retries += 1
            print('Telegram got a error! retry...')

        except Exception as e:
            bot = None
            retries = max_retries

        if retries == max_retries:
            bot = telegram.Bot(token=TELEGRAM_BOT_TOKEN)
            print('Telegram failed to retry...')


# 소켓 연결이 끊어진 경우, 이전까지 받아온 데이터들은 더이상 유효하지 않기 때문에 데이터를 삭제하는 역할을 하는 함수 (데이터 중복 삭제)
# 'exchange_price' 내의 데이터를 삭제
def clear_exchange_price(exchange, exchange_price):
    for ticker in exchange_price:
        if exchange in exchange_price[ticker]:
            del exchange_price[ticker][exchange]


# 매일 오전 9시(지정된 시간)인지 확인하여 시간이 넘었다면 소켓 초기화 (websocket 재연결 목적)
def is_need_reset_socket(start_time):
    now = datetime.now()
    start_date_base_time = start_time.replace(hour=9, minute=0, second=0, microsecond=0)
    next_base_time = (start_time + timedelta(days=1)).replace(hour=9, minute=0, second=0, microsecond=0)

    if start_time < start_date_base_time:
        if start_date_base_time < now:
            return True
        else:
            return

    if next_base_time < now:
        return True
    else:
        return​

upbit.py
import traceback
import pyupbit
import requests

from consts import *
import util
import asyncio
import websockets
import json
import socket
from datetime import datetime
import uuid
import pandas as pd


# Docs : https://pyupbit.readthedocs.io/en/latest/
exchange = UPBIT


# 원화(KRW) 마켓과 BTC 마켓간의 중복된 정보를 삭제하고, 하나의 리스트로 통합하여 리턴하는 함수
def get_all_ticker():

    # 원화 마켓의 코인 정보를 로드
    krw_ticker = pyupbit.get_tickers(fiat='KRW')

    # BTC 마켓의 코인 정보를 로드
    btc_ticker = pyupbit.get_tickers(fiat='BTC')

    # BTC 마켓에 있는 코인목록 중에 원화 마켓에 있는 정보를 삭제
    only_in_btc = [ticker for ticker in btc_ticker if 'KRW-' + ticker.split('-')[1] not in krw_ticker]

    # 중복없는 코인목록을 만들기 위해 원화 마켓에 있는 코인목록과 'only_in_btc' 코인목록을 합쳐서 반환
    return krw_ticker + only_in_btc


# 거래대금 정보를 리턴하는 함수
def get_exchange_accum_trade_price(exchange_accum_trade_price):
    print(exchange + " get_exchange_accum_trade_price")

    # BTC 가격 불러오기.
    btc_price = pyupbit.get_current_price('KRW-BTC')

    # 전체 누적 거래대금 조회.
    res = requests.get('https://api.upbit.com/v1/ticker', {'markets': get_all_ticker()}).json()

    for i in res:
        ticker = i['market'].split('-')[1]  # 코인 티커 (KRW-BTC 중 BTC)
        currency = i['market'].split('-')[0]  # 코인 티커 (KRW-BTC 중 KRW)

        # ticker(코인 정보)가 아직 Dictionary 에 저장되어 있지 않다고 하면 초기화
        if ticker not in exchange_accum_trade_price:
            # ex) exchange_accum_trade_price[symbol] = {'Upbit': None, 'Binance': None, 'Bybit': None, 'OKX': None, 'Bitget': None}
            exchange_accum_trade_price[ticker] = dict.fromkeys(EXCHANGE_LIST, None)

        # currency(기준 통화)가 만약에 'BTC'이면 값을 저장할 때
        if currency == 'BTC':

            # 누적 거래대금에 BTC 가격을 곱하고, 억 단위로 표현하기 위해서 나누기 억을하고 반올림
            exchange_accum_trade_price[ticker][exchange] = round(i['acc_trade_price_24h'] * btc_price / MILLION, 2)

        # currency(기준 통화)가 'BTC'가 아니면 / KRW(원화)일 때
        else:

            # 누적 거래대금에 BTC 가격을 곱하지 않음
            exchange_accum_trade_price[ticker][exchange] = round(i['acc_trade_price_24h'] / MILLION, 2)

# 웹소켓 연결 이후, 수신한 가격 데이터를 'exchange_price'에 저장하는 함수
async def connect_websocket(exchange_price):
    while True:
        try:
            util.send_to_telegram('[{}] Creating new connection...'.format(exchange))
            util.clear_exchange_price(exchange, exchange_price)
            start_time = datetime.now()

            # Connect(연결)
            async with websockets.connect('wss://api.upbit.com/websocket/v1', ping_interval=None, ping_timeout=None) as websocket:

                # 수신하고 싶은 시세 정보를 나열하는 필드(포맷)
                subscribe_fmt = [
                    {'ticket':  str(uuid.uuid4())[:6]},
                    {
                        'type': 'ticker',
                        'codes': get_all_ticker(),
                        'isOnlyRealtime': True
                    },
                ]

                # 데이터를 json 포맷으로 변환
                subscribe_data = json.dumps(subscribe_fmt)

                # Send(송신)를 통해 웹소켓 서버에서 어떤 데이터를 요청하는지 알 수 있음
                await websocket.send(subscribe_data)

                # Receive(수신)를 통해 데이터를 받아올 수 있음
                while True:
                    try:
                        data = await websocket.recv()
                        data = json.loads(data)

                        if 'code' not in data:  # 응답 데이터(딕셔너리)에 code가 없는 경우 제외
                            print('[Data error]', data)
                            continue

                        currency = data['code'].split('-')[0]   # KRW-BTC -> KRW(기준 통화)
                        ticker = data['code'].split('-')[1]     # KRW-BTC -> BTC(시세조회 대상 코인)

                        # print(ticker, data)               # 결과 출력 테스트 (※ 프로그램을 실행할 때에는 주석처리 필수)
                        # print(ticker, exchange_price)     # 딕셔너리 출력 테스트 (※ 프로그램을 실행할 때에는 주석처리 필수)

                        if ticker not in exchange_price:    # 'exchange_price' 에 코인이 존재하지 않다면 거래소 코인 초기화
                            exchange_price[ticker] = {exchange: None}

                        if currency == 'BTC':   # 기준 통화가 BTC인 경우는 "현재 가격 * BTC 가격" = 원화 환산 가격
                            if 'BTC' in exchange_price:

                                # 변수 데이터중에 'trade_price' 에 현재 가격이 있으므로 아래와 같이 저장
                                # 만약에 'exchange_price' 에 비트코인 가격이 있다면 비트코인 가격과 같이 곱해주고,
                                # 비트코인 가격이 없다고 하면, 계산을 할 수 없으므로 0을 곱해 가격을 0으로 만듬
                                exchange_price[ticker][exchange] = float(data['trade_price']) * \
                                float(exchange_price['BTC'][exchange]) if exchange_price['BTC'] and exchange in exchange_price['BTC'] else 0

                        else:   # 기준 통화가 원화인 경우, 현재 가격(trade_price) 그대로 저장
                            exchange_price[ticker][exchange] = float(data['trade_price'])

                        if util.is_need_reset_socket(start_time):   # 매일 아침 9시(지정된 시간)에 소켓 재연결
                            util.send_to_telegram('[{}] Time to new connection...'.format(exchange))
                            break

                    # 만약에 에러가 발생하면 에러를 출력하고, 'SOCKET_RETRY_TIME' 만큼 대기를 했다가 break 후, 처음부터 다시 진행
                    except Exception as e:
                        print(traceback.format_exc())
                        await asyncio.sleep(SOCKET_RETRY_TIME)
                        break
                await websocket.close()
        except Exception as e:
            print(traceback.format_exc())
            await asyncio.sleep(SOCKET_RETRY_TIME)


if __name__ == '__main__':
    exchange_accum_trade_price = {}
    get_exchange_accum_trade_price(exchange_accum_trade_price)
    print(exchange_accum_trade_price)​

binance.py
import traceback
import requests

from consts import *
import util
import asyncio
import websockets
import json
import socket
from datetime import datetime


# Docs : https://binance-docs.github.io/apidocs/spot/en/
exchange = BINANCE


def get_all_ticker():

    # requests.get 을 이용해 요청.
    res = requests.get('https://api.binance.com/api/v3/exchangeInfo')

    # 응답이 오면 응답을 json 형태로 변환
    res = res.json()

    # @miniTicker 를 붙이는 이유
    # : 웹소켓에서 데이터를 요청할 때, 페어명을 이처럼 붙여서 보내달라고 하기 때문
    return [s['symbol'].lower() + '@miniTicker' for s in res['symbols'] if 'USDT' in s['symbol']]


# 거래대금 정보를 리턴하는 함수
# 해외 거래소는 파라미터를 하나 더 받음 -> exchange_price : 거래소 별로 코인 가격을 저장하고 있을 예정
# exchange_price 파라미터가 필요한 이유? -> 해외 거래소에 상장된 코인들은 USDT로 구매 가능한 USDT 페어들을 대상으로 프리미엄을 확인
# 원 달러 가격을 exchange_price 에 저장하고 조회
def get_exchange_accum_trade_price(exchange_accum_trade_price, exchange_price):
    print(exchange + " get_exchange_accum_trade_price")

    # 'exchange_price' 에서 USD 를 키로 갖고, 딕셔너리로 'base' 라는 곳에 달러 가격을 저장
    # 만약에 달러 가격이 저장되어 있지 않다고 하면(연동되어 있지 않으면), 계산이 불가하기 때문에 0
    USD = exchange_price['USD']['base'] if 'USD' in exchange_price else 0

    # 'exchange_price' 에서 USDT 를 키로 갖고, 딕셔너리로 'base' 라는 곳에 USDT 가격을 저장
    # 만약에 달러 가격이 저장되어 있지 않다고 하면(연동되어 있지 않으면), 에러없이 계산되기 위해서 1
    USDT = exchange_price['USDT']['base'] if 'USDT' in exchange_price else 1

    # API 주소로 요청을 보내면 바이낸스에 상장된 현물의 24시간 거래누적 대금을 조회하여 'res' 에 저장
    res = requests.get('https://api.binance.com/api/v3/ticker/24hr').json()

    for i in res:
        if i['symbol'].endswith('USDT'):
            ticker = i['symbol'].split('USDT')[0]

            # ticker(코인 정보)가 아직 딕셔너리에 저장되어 있지 않다고 하면 초기화
            if ticker not in exchange_accum_trade_price:
                # ex) exchange_accum_trade_price[symbol] = {'Upbit': None, 'Binance': None, 'Bybit': None, 'OKX': None, 'Bitget': None}
                exchange_accum_trade_price[ticker] = dict.fromkeys(EXCHANGE_LIST, None)

            # 누적 거래대금(quoteVolume)에 USD(달러) 가격을 곱해주고, USD와 USDT 간의 가격의 격차를 줄이기 위하여 USDT 를 곱함
            exchange_accum_trade_price[ticker][exchange] = round(float(i['quoteVolume']) * USD * USDT / MILLION, 2)


# 소켓 연결 후, 실시간 가격까지 저장하는 함수
# exchange_price : 거래소별 가격 데이터를 저장할 딕셔너리
async def connect_websocket(exchange_price):
    while True:
        try:
            util.send_to_telegram('[{}] Creating new connection...'.format(exchange))
            util.clear_exchange_price(exchange, exchange_price)
            start_time = datetime.now()

            # Connect(연결)
            async with websockets.connect('wss://stream.binance.com:9443/ws', ping_interval=None, ping_timeout=None) as websocket:

                # 수신하고 싶은 시세 정보를 나열하는 필드(포맷)
                params_ticker = []
                tickers = get_all_ticker()

                for idx, ticker in enumerate(tickers):
                    params_ticker.append(ticker)

                    # 한꺼번에 데이터를 보내면 에러가 나기 때문에, 50개씩 나눠서 웹소켓에 요청
                    if len(params_ticker) > 50 or idx == len(tickers) - 1:
                        subscribe_fmt = {
                            'method': 'SUBSCRIBE',
                            'params': params_ticker,
                            'id': 1
                        }

                        # 데이터를 json 포맷으로 변환
                        subscribe_data = json.dumps(subscribe_fmt)

                        # Send(송신)를 통해 웹소켓 서버에서 어떤 데이터를 요청하는지 알 수 있음
                        await websocket.send(subscribe_data)
                        await asyncio.sleep(1)
                        params_ticker = []

                # Receive(수신)를 통해 데이터를 받아올 수 있음
                while True:
                    try:
                        data = await websocket.recv()
                        data = json.loads(data)

                        ticker = data['s'].replace('USDT', '') if 's' in data else None

                        if not ticker:  # ticker 가 없는 데이터의 경우 저장 불가
                            continue

                        # print(ticker, data)             # 결과 출력 테스트 (※ 프로그램을 실행할 때에는 주석처리 필수)
                        # print(ticker, exchange_price)   # 딕셔너리 출력 테스트 (※ 프로그램을 실행할 때에는 주석처리 필수)

                        if ticker not in exchange_price:  # 'exchange_price' 에 코인이 존재하지 않다면 거래소 코인 초기화
                            exchange_price[ticker] = {exchange: None}

                        exchange_price[ticker][exchange] = float(data['c']) * (exchange_price['USD']['base'] if 'USD' in exchange_price else 0) \
                                                                * (exchange_price['USDT']['base'] if 'c' in data and 'USDT' in exchange_price else 1)

                        if util.is_need_reset_socket(start_time):  # 매일 아침 9시에 소켓 재연결
                            util.send_to_telegram('[{}] Time to new connection...'.format(exchange))
                            break

                    # 만약에 에러가 발생하면 에러를 출력하고, 'SOCKET_RETRY_TIME' 만큼 대기를 했다가 break 후, 처음부터 다시 진행
                    except Exception as e:
                        print(traceback.format_exc())
                        await asyncio.sleep(SOCKET_RETRY_TIME)
                        break
                await websocket.close()
        except Exception as e:
            print(traceback.format_exc())
            await asyncio.sleep(SOCKET_RETRY_TIME)


if __name__ == '__main__':
    exchange_accum_trade_price = {}
    exchange_price = {'USD': {'base': USD_PRICE}, 'USDT': {'base': 1}}
    get_exchange_accum_trade_price(exchange_accum_trade_price, exchange_price)
    print(exchange_accum_trade_price)​
profile

return Pasted;

@Pasted