Возникла задача сделать уведомления в Телеграм о сделках на Binance: открытие и закрытие позиций, текущий профит, баланс и прочее. Это актуально если кто-то или что-то торгует на вашем счете и вы хотели бы быть в курсе. Задача выглядела несложной — из Binance API забираем последние сделки и шлём в Телеграм — работы на пару часов. Но на практике это превратилось в квест на пару дней в котором 90% времени ушло на изучение особенностей работы с Binance API, их довольно странную логику и жесткие лимиты.
В итоге, родился минималистичный скрипт на 40 строк кода и новый интересный проект о котором упомяну в конце статьи. Скрипт можно запустить на своем компьютере и уведомления о сделках на вашем счете типа BUY BTCUSDT volume: 0.01 и CLOSE BTCUSDT profit: 10$ полетят в Телеграм.
Подготовка
Для работы скрипта нужны:
-
Ключи API созданные в личном кабинете на Binance. Заходим в «Управление API», жмём на кнопку «Создать API», выбираем «Сгенерированный системой» и копируем API key и Secret key. Убеждаемся, что права у ключей «только чтение».
-
Токен Телеграм бота. Как сделать описывать не буду, инструкций много, смотрите здесь.
-
Telegram id вашего аккаунта в Телеграм. Что бы его узнать, просто отправьте любое сообщение этому боту или аналогичному, таких сервисов много.
Скрипт
# pip install binance-futures-connector, pyTelegramBotAPI import telebot from binance.um_futures import UMFutures binance_api_key = "..." binance_api_secret = "..." bot_token = "..." my_telegram_id = "..." bot = telebot.TeleBot(bot_token) prev_symbols = [] prev_data = [] while True: new_symbols = [] new_data = [] client = UMFutures(key=binance_api_key, secret=binance_api_secret) try: info = client.account(recvWindow=6000) except Exception as e: print(e) break for p in info['positions']: if float(p['positionAmt']) != 0: new_symbols.append(p['symbol']) new_data.append([p['positionAmt'], p['unrealizedProfit']]) if new_symbols != prev_symbols: symbol = list(set(new_symbols) ^ set(prev_symbols))[0] if len(new_symbols) > len(prev_symbols): amount = float(new_data[new_symbols.index(symbol)][0]) text = symbol + " amount: " + str(abs(amount)) if amount > 0: text = "BUY " + text else: text = "SELL " + text else: profit = round(float(prev_data[prev_symbols.index(symbol)][1]), 2) text = "CLOSE " + symbol + " profit, $: " + str(profit) prev_symbols = new_symbols prev_data = new_data print(text) bot.send_message(my_telegram_id, text)
Как он работает
У биржи Binance своё представление о «сделке». Для нас сделка — это основной юнит торговли. У сделки есть точка входа, точка выхода и, как итог, профит или убыток. У Binance такой сущности нет, у них есть «позиция» и «трейд» (речь идет о фьючерсах). Позиция — это открытая в данный момент сделка. После закрытия позиции информация о ней исчезает бесследно и достать ее из истории одним запросом невозможно. А трейд, в свою очередь, — вход или выход из позиции. Т.е. случился трейд — позиция открылась, случился следующий — позиция закрылась. Это все просто для отслеживания, пока вы не увеличили или не уменьшили объем открытой позиции. Тогда трейдов на одну позицию может быть неограниченное количество и начинается путаница.
Кроме этого, просто запросить все трейды нельзя, их можно запрашивать только с указанием конкретной торговой пары. Учитывая, что торговых пар более 200, опросить их все невозможно. По этой же причине нельзя отслеживать и ордера, запрос тоже требует торговую пару.
В итоге, для мониторинга событий остается только две точки входа — Account Information и Get Income History. В первом случае получим всю информацию о счете включая текущие открытые позиции, во втором — все начисления и списания. Get Income History содержит в себе указание на трейд результатом которого стало движение средств. По этому указателю можем достать нужный трейд и получить то, что надо — торговую пару, объем и направление сделки. Формально это самый правильный путь, но нам не подойдет. Он в 6 раз дороже (по ограничениям API) чем запрос Account Information и требует выстраивания цепочки из минимум двух запросов.
Поэтому оставляем первый вариант — Account Information. Всего один запрос и прилетает много информации включая открытые позиции. По наличию или отсутствию открытых позиций можно сделать вывод о случившемся трейде. Да, это выглядит немного криво, но работает и очень экономно.
По такой схеме в приведенном скрипте делаем несложную операцию — проверяем текущие открытые позиции и сравниваем с результатом предыдущей проверки. Если видим разницу то делаем вывод о случившемся событии и шлем уведомление.
Более продвинутый вариант
Все это нормально работает пока ботом пользуются не более 10 человек. А что если их не 10, а 1000? Я задался этим вопросом и попытался найти ответ. Одно за другим рождались технические решения, в итоге всё свелось в проект Binance Connector.

Бот справляется с любым количеством пользователей и уведомляет о любом событии с задержкой всего 3-4 секунды. Понимает по какому типу ордера произошел трейд, видит изменение объема позиции, сообщает о текущем нереализованном профите и многое другое…
Здесь главной проблемой были лимиты Binance API. Как их удалось обойти — тема следующей статьи.
ссылка на оригинал статьи https://habr.com/ru/articles/746832/
Добавить комментарий