1. Введение: что делает бот
Продолжая проект из первой части статьи, бот стал полноценной системой:
принимает сигналы четырёх типов: 5% long / 5% short / 12% long / 12% short
фильтрует их по дисбалансу ордеров в стакане, капитализации (MCAP), cooldown'у
рассчитывает стопы, тейки, трейлинг при необходимости
открывает сделки на BingX demo через свой API-клиент
управляет пользователями через SQLite и Telegram меню
работает асинхронно и обрабатывает десятки сигналов одновременно
Теперь поехали по ключевой функциональности.
Я решил ввести два типа сделок, зависящих от 5% и 12% сигналов. При 12% движении мы открываем позиции в контр-тренд, при 5% движении открываем позиции в продолжение тренда. Такие проценты были выведены путём довольно долгой ручной торговле. На монетках средней и маленькой капитализации это действительно рабочая стратегия. Вероятно, она основана на принципах работы ММ.
Всю эту стратегию я реализовал в телеграмм бота - с ручными настройками каждой из четырех стратегий, с фильтрами. Бот сейчас находится в тестнете и является на 100% бесплатным. Так что вы можете тестировать его не опасаясь за свои деньги - все сделки будут происходить на демо-счёте. ссылка на бота
База данных: как устроено хранение пользователей
Когда проект вырос из простого парсера сигналов в полноценного торгового бота, появилась необходимость хранить индивидуальные настройки каждого пользователя:
API ключи BingX
плечо / маржу
включённые стратегии (5long, 5short, 12long, 12short)
стопы, тейк-профиты
мкап фильтр
фильтр дисбаланса
трейлинг стопы
коэффициенты трейлинга
cooldown на повторные сделки
Именно поэтому был создан SQLite хранилище, ведь оно является отличным решением как по скорости, так и по функциональности.
Создание базы данных
При каждом запуске бот проверяет наличие таблицы users, а если её нет — создаёт.
Структура:
def setup_db(): conn = sqlite3.connect("users.db") c = conn.cursor() c.execute(""" CREATE TABLE IF NOT EXISTS users ( user_id INTEGER PRIMARY KEY, api_key TEXT, api_secret TEXT, leverage REAL DEFAULT 20, margin REAL DEFAULT 10, # Включение стратегий enable_5long INTEGER DEFAULT 1, enable_5short INTEGER DEFAULT 1, enable_12long INTEGER DEFAULT 1, enable_12short INTEGER DEFAULT 1, # Стопы и тейки stop_5long REAL DEFAULT 5, stop_5short REAL DEFAULT 5, stop_12long REAL DEFAULT 12, stop_12short REAL DEFAULT 12, tp_5long TEXT DEFAULT "5,10,15", tp_5short TEXT DEFAULT "5,10,15", tp_12long TEXT DEFAULT "12,18,25", tp_12short TEXT DEFAULT "12,18,25", # Фильтры mcap_filter INTEGER DEFAULT 0, imbalance_filter INTEGER DEFAULT 0, # Трейлинг стоп trailing INTEGER DEFAULT 0, trail_rate_5long REAL DEFAULT 0.005, trail_rate_5short REAL DEFAULT 0.005, trail_rate_12long REAL DEFAULT 0.01, trail_rate_12short REAL DEFAULT 0.01, cooldown INTEGER DEFAULT 0 ); """) conn.commit() conn.close()
Фильтр дисбаланса (Orderbook imbalance)
Это очень важная часть проекта, так как она позволяет опираться при открытии сделок на объективные рыночные данные.
Что делает фильтр:
Получает стаканы сразу с bingX
Анализирует объёмы покупателей и продавцов на глубине 1000 тиков.
Вычисляет формулу дисбаланса:
imbalance = (bid_volume-ask_volume)/(bid_volume+ask_volume)
🧠 За что отвечает imbalance?
показывает давление покупателей / продавцов
отсеивает ложные сигналы
помогает торговать по тренду для 5% сигналов
помогает торговать контртренд для 12% сигналов
def get_bingx_orderbook(symbol: str = "BTC-USDT", limit: int = 100): url = "https://open-api.bingx.com/openApi/swap/v2/quote/depth" params = { "symbol": symbol.replace("/", "-"), # на всякий случай "limit": int(limit) } # Сортируем параметры и добавляем timestamp sorted_keys = sorted(params.keys()) params_str = "&".join([f"{k}={params[k]}" for k in sorted_keys]) timestamp = str(int(time.time() * 1000)) query_string = f"{params_str}×tamp={timestamp}" if params_str else f"timestamp={timestamp}" # Подпись (даже для публичного эндпоинта — BingX требует подпись) signature = hmac.new( SECRETKEY.encode("utf-8"), query_string.encode("utf-8"), hashlib.sha256 ).hexdigest() # Финальный URL final_url = f"{url}?{query_string}&signature={signature}" headers = { "X-BX-APIKEY": APIKEY, # можно пустой } response = requests.get(final_url, headers=headers, timeout=10) data = response.json() if data.get("code") != 0: print(f"[BingX Depth] Ошибка API: {data}") return None bids = [(float(x[0]), float(x[1])) for x in data["data"]["bids"]] asks = [(float(x[0]), float(x[1])) for x in data["data"]["asks"]] return {"bids": bids, "asks": asks, "timestamp": data["data"].get("timestamp")}
Фильтр MCAP (капитализация / white-list)
Этот фильтр защищает от торговли низколиквидными шиткоинами, которые:
могут пампиться сидящими группами
могут закрыть позицию одним большим ордером
не имеют реальной рыночной глубины
Фильтр использует файл с кешем о лоу-кап тикерах, которые есть на bingX. Сторонний скрипт постоянно обновляет этот список и перезаписывает сам файл. Сейчас я использую монетки до 150млн капитализации.
Почему это важно:
90% фейковых пампов происходят на токенах с капитализацией < $100M
ликвидность в стакане низкая, так что актив двигается гораздо легче
можно попасть на сквиз 20–50%. Так как торгуем со стопами, то можно не боятся выноса в большой убыток. А вот хороший профит можно забрать с трейлингом без проблем.
Этот фильтр — один из самых важных для реальной торговли.
Как фильтры работают вместе
Сигнал →
Проверка включена ли стратегия →
MCAP фильтр →
Фильтр дисбаланса стакана →
Открытие позиции →
Трейлинг / тейки / стоп
Handler сигналов: сердце бота
Этот блок — самый важный во всём проекте.
В телеграмм группы (куда собственно и идёт пересылка сообщений о пампах) присылаются текстовые уведомления. Таких группы 2: 12% signals и 5% signals. Handler превращает их в полноценные торговые операции на бирже.
Вот формальная задача:
Принять сообщение → извлечь тикер → определить тип сигнала → пройти фильтры → открыть сделку → установить стопы/тейки → отправить уведомление в Telegram.
Именно это делает следующий обработчик.
1. Получение и первичная фильтрация сигнала
@client.on(events.NewMessage(chats=[channel_5long, channel_12short])) async def handler(event): raw_text = event.message.message or "" text = raw_text.strip() # Фильтруем сигнал — он должен начинаться с 🟢 или 🔴 if not text.startswith("🟢") and not text.startswith("🔴"): return
Сигналы о пампе или дампе приходят только с эмодзи — остальное можно игнорировать. Это экономит ресурсы и избавляет от ложных запусков.
2. Извлечение тикера
ticker_match = re.search(r'\$([A-Z]{2,12})\b', text) if not ticker_match: print("Не найден тикер в сообщении") return token = ticker_match.group(1).upper() symbol = f"{token}-USDT" Здесь бот вытаскивает $BTC, $XRP, $SOL из текста.
Почему важно делать именно так? сигналы могут содержать текст, числа, описание • но формат $TOKEN стабилен
3. Oпределение канала = определение стратегии
chat = await event.get_chat() is_5_channel = chat_id == str(channel_5long_id) or "5%" in chat_title.lower() is_12_channel = chat_id == str(channel_12short_id) or "12%" in chat_title.lower()
4. Определение направления и стратегии
Интересный момент — преобразование сигналов.
5%:
🟢 = long
🔴 = short
12% — наоборот:
🟢 = short
🔴 = long
И код:
side = 'long' if text.startswith("🟢") else 'short' if side == 'long' and is_5_channel: strategy = '5long' elif side == 'long' and is_12_channel: strategy = '12long' side = 'short' elif side == 'short' and is_12_channel: strategy = '12short' side = 'long' elif side == 'short' and is_5_channel: strategy = '5short'
5. Получение пользователей из БД
c.execute("SELECT user_id FROM users WHERE api_key IS NOT NULL AND api_secret IS NOT NULL")
Бот открывает сделки для каждого пользователя с API-ключами, то есть работает сразу для всех подписчиков.
6. Проверка включена ли стратегия
if not settings.get(f"enable_{strategy}", 0): continue
Каждый пользователь вручную включает каждую стратегию с помощью кнопок.
7. Фильтр капитализации (MCAP filter)
if settings.get("mcap_filter", 0): if token not in ALLOWED_TICKERS: continue
Что делает фильтр
Отбирает монетки с низкой ликвидностью, которые ходят гораздо легче и не так подвержены влиянию общего рынка
8. Фильтр дисбаланса ORDBOOK IMBALANCE
До открытия сделки мы рассчитываем дисбаланс ордеров, показал это ранее
✔ Для 5% сигналов — фильтр по тренду
if strategy == "5long" and imbalance < 0: continue if strategy == "5short" and imbalance > 0: continue
✔ Для 12% сигналов — фильтр против тренда
if strategy == "12long" and imbalance > 0: continue if strategy == "12short" and imbalance < 0: continue
То есть бот смотрит, когда монетка действительно готова идти в нашем направлении и есть поддержка в виде ордеров в стакане.
9. Фильтр COOL-DOWN
Чтобы не открывать одну и ту же сделку много раз:
if now - last_trade_times[user_id][trade_key] < cooldown: continue
Открытие позиции
После выполнения всех данных фильтров, их расчёта, пришло время открыть позицию. Подтянув данные из базы данных о тейках и стопах расчитываем цены для них и открываем позицию с помощью bingX клиента (упомянул в прошлой статье). Делаем мы это следующим образом:
stop_pct = settings.get(f"stop_{strategy}", 0.05) sl_level = round(mark_price * (1 - stop_pct) if side == "long" else mark_price * (1 + stop_pct), precision) order = bx.place_market_order(side, qty, symbol, sl_level) tp_str = settings.get(f"tp_{strategy}", "5,10,15") tp_percents = parse_levels(tp_str) tp_prices = [ mark_price * (1 + p) if side=="long" else mark_price * (1 - p) for p in tp_percents] bx.set_multiple_tp(symbol, qty, mark_price, side, tp_prices) trail_act = settings.get(f"trail_active_{strategy}", 0) trail_rate = settings.get(f"trail_rate_{strategy}", 0) if trail_act > 0 and trail_rate > 0: act_price = mark_price * (1 + trail_act) if side == "long" else mark_price * (1 - trail_act) bx.set_trailing(symbol, qty, act_price, trail_rate, side) bot_sender.send_message( user_id, f"Deal opened: {strategy}, imbalance={imbalance:.2f}, stop={stop_pct}, tp={tp_percents}" ) last_trade_times[user_id][trade_key] = now
Что делает handler шаг за шагом
Получение сигнала
→ Проверка формата
→ Извлечение тикера
→ Определение канала (5%/12%)
→ Определение стратегии (5long/12short...)
→ Получение всех пользователей
→ Фильтр "стратегия выключена"
→ Фильтр MCAP
→ Фильтр дисбаланса рынка
→ Фильтр Cooldown
→ Получение биржевой цены
→ Расчёт количества
→ Расчёт стоп-лосса
→ Открытие позиции (MARKET + SL)
→ Выставление тейков
→ Выставление трейлинга
→ Уведомление пользователя
→ Запись времени сделки
Этот обработчик полностью автономен, безопасен и стабилен.
Вывод
Таким образом, мы написали полностью автономную стратегию. Вопрос лишь в том - как каждый пользователь настроит данные стратегии. Важная часть этого бота - комбинирование. Кроме того, если вы уверены, например, в лонговом нарративе на рынке, можно оставить лишь лонговых ботов. Аналогично, если думаете, что рынок будет пдаать в ближайшей перспективе. Этих настроек вполне достаточно для грамотной и полноценной работы по данной торговой стратегии.
Безусловно, сейчас бот находится в тестовом режиме. Обратите внимание что сейчас он в тестнете. Но каждый может его протестировать и подобрать свои настройки. Со временем будут выпущены готовые торговые модели и бот уже будет запущен в mainnet. Так как тут настройки субъективны, то обязательно нужно всё протестировать временем.
Продукт абсолютно бесплатен и будет оставаться таковым - пробуйте и эксперементируйте - @parsertoyosha_bot.
