Упрощаем отслеживание активов
Как установить API Binance
Binance предоставляет два типа доступа к API: реальный и тестовый.
Настраиваем реальный API Binance
Реальный API обеспечивает прямой доступ к аккаунту. В нем будут отражены любые сделки, совершенные через этот API. Поэтому использовать его следует с осторожностью.
Для начала нужно зарегистрироваться на Binance.
После регистрации вам будет предложено установить двухфакторную аутентификацию (2FA). Вы также можете подключить ее самостоятельно в настройках безопасности.
Затем переходим во вкладку API Management в настройках. Вам будет предложено установить метки для ключей API. Эта функция пригодится тем, у кого есть несколько ключей, связанных с одним аккаунтом.
Указываем метки и нажимаем Create API. После этого нужно пройти аутентификацию еще раз. Затем отобразятся API Key и Secret Key. Скопируйте их в безопасное место. По умолчанию получить доступ к ключам можно следующим способом, который можно изменить:
Мы будем использовать ключи как реального, так и тестового API, чтобы понять, как с ними работать. С целью не засорять реальный аккаунт установим доступ только для чтения для ключей реального API:
Сохранять ключи реального API мы будем в файл secret.cfg
, как показано ниже. Не забывайте, что нельзя ни с кем делиться этим файлом.
[BINANCE]
ACTUAL_API_KEY = <your-actual-api-key>
ACTUAL_SECRET_KEY = <your-actual-secret-key>
Настраиваем тестовый API Binance
Тестовый API Binance полностью имитирует взаимодействие с реальным API. Рекомендуем для начала повзаимодействовать с ним, чтобы убедиться в корректности работы приложения.
Для начала необходимо войти в систему: https://testnet.binance.vision/ (на данный момент вход поддерживается только с GitHub).
Затем нажмите на Generate HMAC_SHA256 Key (Сгенерировать ключ HMAC_SHA256) и снова укажите метки для ключей. Отобразившиеся после создания ключи также скопируйте в безопасное место. Все подробности о тестовом API можно прочитать на главной странице.
Теперь добавим ключи тестового API в файл secret.cfg
, как показано ниже:
[BINANCE]
ACTUAL_API_KEY = <your-actual-api-key>
ACTUAL_SECRET_KEY = <your-actual-secret-key>
TEST_API_KEY = <your-test-api-key>
TEST_SECRET_KEY = <your-test-secret-key>
Мы успешно настроили ключи реального и тестового API и сохранили их в файле secret.cfg
. Теперь можно переходить к получению данных.
Как получить данные с помощью API Binance
Устанавливаем библиотеку python-binance
Binance не предоставляет библиотеку Python для взаимодействия с API. Поэтому мы воспользуемся популярным сторонним инструментом под названием python-binance
.
Устанавливаем python-binance
с помощью следующей команды:
$ pip install python-binance
Получаем информацию об аккаунте
В этом разделе мы воспользуемся тестовым аккаунтом. По умолчанию в нем будет отображаться баланс различных криптовалют. У python-binance
нет доступа к тестовому API, поэтому мы поменяем URL-адрес конечной точки.
Код ниже предоставляет информацию о тестовом аккаунте:
# Импорт библиотек
from binance.client import Client
import configparser
# Загрузка ключей из файла config
config = configparser.ConfigParser()
config.read_file(open('<path-to-your-config-file>'))
test_api_key = config.get('BINANCE', 'TEST_API_KEY')
test_secret_key = config.get('BINANCE', 'TEST_SECRET_KEY')
client = Client(test_api_key, test_secret_key)
client.API_URL = 'https://testnet.binance.vision/api' # Это нужно, чтобы изменить URL-адрес конечной точки тестового аккаунта
info = client.get_account() # Получение информации об аккаунте
print(info)
Мы получаем такие важные данные, как тип аккаунта (accountType
), баланс, разрешение и прочие.
Теперь получим баланс ETH:
balance = client.get_asset_balance(asset='ETH')
print(balance)
Библиотека python-binance
предоставляет много возможностей. Подробную информацию о ней можно найти в документации.
Получаем архивные данные
Тестовый API выдает фиктивные архивные данные. Поэтому мы воспользуемся реальным API и его ключами.
Ниже показано, как получить стоимость ETH на Binance с самой ранней даты до текущего дня:
# Импорт библиотек
from binance.client import Client
import configparser
import pandas as pd
# Загрузка ключей из файла config
config = configparser.ConfigParser()
config.read_file(open('<path-to-your-config-file>'))
actual_api_key = config.get('BINANCE', 'ACTUAL_API_KEY')
actual_secret_key = config.get('BINANCE', 'ACTUAL_SECRET_KEY')
client = Client(actual_api_key, actual_secret_key)
# Получение самой ранней доступной даты на Binance
earliest_timestamp = client._get_earliest_valid_timestamp('ETHUSDT', '1d') # Здесь "ETHUSDT" - валютная пара, а "1d" - временной интервал
print(earliest_timestamp)
# Получение архивных данных (Candle data или Kline)
candle = client.get_historical_klines("ETHUSDT", "1d", earliest_timestamp, limit=1000)
print(candle[1])
Вывод выше представляет следующие параметры, упомянутые в документации Binance API:
Преобразовываем полученные данные в датафрейм и сохраняем его как файл CSV:
eth_df = pd.DataFrame(candle, columns=['dateTime', 'open', 'high', 'low', 'close', 'volume', 'closeTime', 'quoteAssetVolume', 'numberOfTrades', 'takerBuyBaseVol', 'takerBuyQuoteVol', 'ignore'])
eth_df.dateTime = pd.to_datetime(eth_df.dateTime, unit='ms')
eth_df.closeTime = pd.to_datetime(eth_df.closeTime, unit='ms')
eth_df.set_index('dateTime', inplace=True)
eth_df.to_csv('eth_candle.csv')
print(eth_df.tail(10))
Получаем данные в реальном времени
Чтобы передавать данные в реальном времени, можно воспользоваться WebSocket Binance. Вот как это сделать:
# Импорт библиотек
from binance.client import Client
import configparser
from binance.websockets import BinanceSocketManager
from twisted.internet import reactor
# Загрузка ключей из файла config
config = configparser.ConfigParser()
config.read_file(open('<path-to-your-config-file>'))
actual_api_key = config.get('BINANCE', 'ACTUAL_API_KEY')
actual_secret_key = config.get('BINANCE', 'ACTUAL_SECRET_KEY')
client = Client(actual_api_key, actual_secret_key)
def streaming_data_process(msg):
"""
Function to process the received messages
param msg: input message
"""
print(f"message type: {msg['e']}")
print(f"close price: {msg['c']}")
print(f"best ask price: {msg['a']}")
print(f"best bid price: {msg['b']}")
print("---------------------------")
# Запуск WebSocket
bm = BinanceSocketManager(client)
conn_key = bm.start_symbol_ticker_socket('ETHUSDT', streaming_data_process)
bm.start()
Ниже показано, как остановить потоковую передачу данных и закрыть WebSocket:
# Остановка websocket
bm.stop_socket(conn_key)
# Websocket использует цикл reactor из библиотеки Twisted. Метод выше
# остановит соединение с веб-сокетом, но не цикл reactor, поэтому код может
# выйти не сразу.
# Поэтому нужно указать
reactor.stop()
Итак, мы научились получать данные несколькими способами. Теперь можно переходить к созданию дашборда Plotly.
Как создать дашборд с помощью Plotly
В этом разделе мы создадим дашборд с помощью Plotly, который будет отслеживать криптовалютный портфель тестового аккаунта в реальном времени и изменять его общую стоимость в зависимости от получаемых данных.
Вот как будет выглядеть финальная версия дашборда. Детали внешнего вида можно изменить позднее:
В дашборд включены следующие функции:
- Индикатор: общая стоимость портфеля в USDT.
- Индикатор: общая стоимость портфеля в BTC.
- Индикатор: конвертация BNB/USDT.
- Круговая диаграмма: распределение портфеля (в USDT).
- Столбчатая диаграмма: распределение токенов.
Теперь рассмотрим код.
- Импортируем все необходимые библиотеки:
# Импорт библиотек
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
from binance.client import Client
import configparser
from binance.websockets import BinanceSocketManager
import time
2. Прочитываем все ключи, устанавливаем соединение и получаем информацию об аккаунте:
# Загрузка ключей из файла config
config = configparser.ConfigParser()
config.read_file(open(
'/home/venom/GitHub/blog_code/building_cryptocurrency_dashboard_plotly_binanceAPI/secret.cfg'))
test_api_key = config.get('BINANCE', 'TEST_API_KEY')
test_secret_key = config.get('BINANCE', 'TEST_SECRET_KEY')
# Установка соединения
client = Client(test_api_key, test_secret_key)
client.API_URL = 'https://testnet.binance.vision/api' # Это нужно, чтобы изменить URL-адрес конечной точки тестового аккаунт
# Получение информации об аккаунте для проверки баланса
info = client.get_account() # Получение информации об аккаунте
# Сохранение различных токенов и соответствующих величин в списках
assets = []
values = []
for index in range(len(info['balances'])):
for key in info['balances'][index]:
if key == 'asset':
assets.append(info['balances'][index][key])
if key == 'free':
values.append(info['balances'][index][key])
token_usdt = {} # Словарь для хранения стоимости валютной пары в USDT
token_pairs = [] # Список для хранения различных пар токенов
# Создание пар токенов и сохранение их в список
for token in assets:
if token != 'USDT':
token_pairs.append(token + 'USDT')
3. Определяем функции, которые будут обрабатывать потоковые данные и рассчитывать показатели на их основе:
def streaming_data_process(msg):
"""
Function to process the received messages and add latest token pair price
into the token_usdt dictionary
:param msg: input message
"""
global token_usdt
token_usdt[msg['s']] = msg['c']
def total_amount_usdt(assets, values, token_usdt):
"""
Function to calculate total portfolio value in USDT
:param assets: Assets list
:param values: Assets quantity
:param token_usdt: Token pair price dict
:return: total value in USDT
"""
total_amount = 0
for i, token in enumerate(assets):
if token != 'USDT':
total_amount += float(values[i]) * float(
token_usdt[token + 'USDT'])
else:
total_amount += float(values[i]) * 1
return total_amount
def total_amount_btc(assets, values, token_usdt):
"""
Function to calculate total portfolio value in BTC
:param assets: Assets list
:param values: Assets quantity
:param token_usdt: Token pair price dict
:return: total value in BTC
"""
total_amount = 0
for i, token in enumerate(assets):
if token != 'BTC' and token != 'USDT':
total_amount += float(values[i]) \
* float(token_usdt[token + 'USDT']) \
/ float(token_usdt['BTCUSDT'])
if token == 'BTC':
total_amount += float(values[i]) * 1
else:
total_amount += float(values[i]) \
/ float(token_usdt['BTCUSDT'])
return total_amount
def assets_usdt(assets, values, token_usdt):
"""
Function to convert all assets into equivalent USDT value
:param assets: Assets list
:param values: Assets quantity
:param token_usdt: Token pair price dict
:return: list of asset values in USDT
"""
assets_in_usdt = []
for i, token in enumerate(assets):
if token != 'USDT':
assets_in_usdt.append(
float(values[i]) * float(token_usdt[token + 'USDT'])
)
else:
assets_in_usdt.append(float(values[i]) * 1)
return assets_in_usdt
4. Начинаем передавать данные в реальном времени:
# Потоковая передача данных для токенов в портфолио
bm = BinanceSocketManager(client)
for tokenpair in token_pairs:
conn_key = bm.start_symbol_ticker_socket(tokenpair, streaming_data_process)
bm.start()
time.sleep(5) # Это дает всем парам токенов достаточно времени, чтобы установить соединение
5. Определяем макет, графики и хостинг:
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])
server = app.server
app.layout = html.Div([
html.Div([
html.Div([
dcc.Graph(
id='figure-1',
figure={
'data': [
go.Indicator(
mode="number",
value=total_amount_usdt(assets, values, token_usdt),
)
],
'layout':
go.Layout(
title="Portfolio Value (USDT)"
)
}
)], style={'width': '30%', 'height': '300px',
'display': 'inline-block'}),
html.Div([
dcc.Graph(
id='figure-2',
figure={
'data': [
go.Indicator(
mode="number",
value=total_amount_btc(assets, values, token_usdt),
number={'valueformat': 'g'}
)
],
'layout':
go.Layout(
title="Portfolio Value (BTC)"
)
}
)], style={'width': '30%', 'height': '300px',
'display': 'inline-block'}),
html.Div([
dcc.Graph(
id='figure-3',
figure={
'data': [
go.Indicator(
mode="number",
value=float(token_usdt['BNBUSDT']),
number={'valueformat': 'g'}
)
],
'layout':
go.Layout(
title="BNB/USDT"
)
}
)],
style={'width': '30%', 'height': '300px', 'display': 'inline-block'})
]),
html.Div([
html.Div([
dcc.Graph(
id='figure-4',
figure={
'data': [
go.Pie(
labels=assets,
values=assets_usdt(assets, values, token_usdt),
hoverinfo="label+percent"
)
],
'layout':
go.Layout(
title="Portfolio Distribution (in USDT)"
)
}
)], style={'width': '50%', 'display': 'inline-block'}),
html.Div([
dcc.Graph(
id='figure-5',
figure={
'data': [
go.Bar(
x=assets,
y=values,
name="Token Quantities For Different Assets",
)
],
'layout':
go.Layout(
showlegend=False,
title="Tokens distribution"
)
}
)], style={'width': '50%', 'display': 'inline-block'}),
dcc.Interval(
id='1-second-interval',
interval=1000, # 1000 milliseconds
n_intervals=0
)
]),
])
@app.callback(Output('figure-1', 'figure'),
Output('figure-2', 'figure'),
Output('figure-3', 'figure'),
Output('figure-4', 'figure'),
Output('figure-5', 'figure'),
Input('1-second-interval', 'n_intervals'))
def update_layout(n):
figure1 = {
'data': [
go.Indicator(
mode="number",
value=total_amount_usdt(assets, values, token_usdt),
)
],
'layout':
go.Layout(
title="Portfolio Value (USDT)"
)
}
figure2 = {
'data': [
go.Indicator(
mode="number",
value=total_amount_btc(assets, values, token_usdt),
number={'valueformat': 'g'}
)
],
'layout':
go.Layout(
title="Portfolio Value (BTC)"
)
}
figure3 = {
'data': [
go.Indicator(
mode="number",
value=float(token_usdt['BNBUSDT']),
number={'valueformat': 'g'}
)
],
'layout':
go.Layout(
title="BNB/USDT"
)
}
figure4 = {
'data': [
go.Pie(
labels=assets,
values=assets_usdt(assets, values, token_usdt),
hoverinfo="label+percent"
)
],
'layout':
go.Layout(
title="Portfolio Distribution (in USDT)"
)
}
figure5 = {
'data': [
go.Bar(
x=assets,
y=values,
name="Token Quantities For Different Assets",
)
],
'layout':
go.Layout(
showlegend=False,
title="Tokens distribution"
)
}
return figure1, figure2, figure3, figure4, figure5
if __name__ == '__main__':
app.run_server(host='127.0.0.1', port='8050', debug=True)
Вот и все! Этот код позволяет отслеживать криптовалютный портфель тестового аккаунта. Его можно с легкостью настроить и для реального аккаунта без изменения URL-адреса конечной точки.
Весь код можно найти в репозитории на GitHub.
Читайте также:
- Разработка инфраструктуры и торговых ботов для ИИ-трейдинга
- 4 принципа успешной поисковой системы и не только
- Введение в блокчейн - основу криптовалют
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Mayank Vadsola: Building a cryptocurrency dashboard using Plotly and Binance API