Несколько недель назад я решил создать собственного бота для Polymarket. Полная версия заняла у меня несколько недель.
Я был готов вложить эти усилия, потому что на Polymarket действительно существуют неэффективности, и хотя на рынке уже есть несколько ботов, использующих эти неэффективности для получения прибыли, их все еще недостаточно — возможностей на этом рынке гораздо больше, чем ботов.
Логика построения бота
Логика этого бота основана на стратегии, которую я ранее выполнял вручную, и я автоматизировал ее для повышения эффективности. Этот бот работает на рынке «BTC 15-минутный РОСТ / ПАДЕНИЕ (BTC 15-minute UP/DOWN)».

Бот запускает программу мониторинга в реальном времени, которая автоматически переключается на текущий 15-минутный раунд BTC, передает через WebSocket поток лучших цен покупки/продажи (best bid/ask), отображает фиксированный пользовательский интерфейс в терминале и позволяет осуществлять полное управление с помощью текстовых команд.

В ручном режиме вы можете размещать ордера напрямую.
buy up / buy down : купить на определенную сумму в долларах США.
buyshares up / buyshares down : купить точное количество акций, используя удобные для пользовательского интерфейса лимитные ордера (LIMIT) + GTC (действителен до отмены), исполняемые по текущей лучшей цене продажи (best ask).
Автоматический режим запускает повторяющийся двухэтапный (two-leg) цикл.
На первом этапе он только наблюдает за колебаниями цен в течение windowMin минут после начала каждого раунда. Если любая сторона падает достаточно быстро (как минимум на movePct в течение примерно 3 секунд), он запускает «Первый этап (Leg 1)», покупая ту сторону, которая резко упала.
После завершения Leg 1 бот больше никогда не покупает ту же сторону. Он ждет «Второго этапа (Leg 2, хеджирование)» и запускает его только при выполнении следующего условия: leg1EntryPrice + oppositeAsk <= sumTarget.
При выполнении этого условия он покупает противоположную сторону. После завершения Leg 2 цикл завершается, и бот возвращается в состояние наблюдения, ожидая следующего сигнала резкого падения с теми же параметрами.
Если в процессе цикла раунд меняется, бот прекращает этот открытый цикл и начинает заново со следующих раундов с теми же настройками.
Параметры автоматического режима устанавливаются следующим образом: auto on [sum=0.95] [move=0.15] [windowMin=2]
· shares: размер позиции для обеих сделок.
· sum: порог для хеджирования.
· move (movePct): порог резкого падения (например, 0.15 = 15%).
· windowMin: продолжительность времени от начала каждого раунда, в течение которого разрешено выполнение Leg 1.
Бэктестинг
Логика бота проста: дождаться резкого обвала, купить только что упавшую сторону, а затем дождаться стабилизации цены и провести хеджирование, купив противоположную сторону, гарантируя при этом: priceUP + priceDOWN < 1.
Но эту логику нужно проверить. Действительно ли она работает в долгосрочной перспективе? Что еще более важно, у бота много параметров (количество акций, сумма, процент движения, время окна и т.д.). Какой набор параметров является оптимальным и максимизирует прибыль?
Моя первая идея заключалась в том, чтобы запустить бота в реальной торговле на неделю и посмотреть на результаты. Проблема в том, что это занимает слишком много времени и позволяет протестировать только один набор параметров, а мне нужно протестировать много.
Моя вторая идея заключалась в проведении бэктестинга с использованием исторических данных из CLOB API Polymarket. К сожалению, для рынка BTC 15-минутный РОСТ/ПАДЕНИЕ конечная точка исторических данных постоянно возвращала пустые наборы данных. Без исторических тиков (price ticks) бэктестинг не может обнаружить «резкое падение в течение примерно 3 секунд», чтобы запустить Leg 1, и, независимо от параметров, дает 0 циклов и 0% ROI (возврат на инвестиции).

После дальнейшего расследования я обнаружил, что другие пользователи столкнулись с той же проблемой при получении исторических данных для некоторых рынков. Я протестировал другие рынки, которые действительно возвращали исторические данные, и пришел к выводу, что для этого конкретного рынка исторические данные просто не сохраняются.
Из-за этого ограничения единственным надежным способом протестировать эту стратегию было создание собственного набора исторических данных путем записи лучших цен продажи (best-ask) в реальном времени во время работы бота.

Регистратор записывает на диск снимки, содержащие следующее:
· Временная метка
· Идентификатор раунда (round slug)
· Оставшиеся секунды
· ID токенов UP/DOWN
· Лучшая цена продажи UP/DOWN
Впоследствии «записанный бэктест (recorded backtest)» воспроизводит эти снимки и детерминированно применяет ту же автоматическую логику. Это гарантирует получение высокочастотных данных, необходимых для обнаружения обвалов и условий хеджирования.
В общей сложности я собрал 6 ГБ данных за 4 дня. Я мог бы записать больше, но посчитал, что этого достаточно для тестирования различных наборов параметров.

Я начал тестировать этот набор параметров:
· Начальный баланс: $1,000
· 20 акций за сделку
· sumTarget = 0.95
· Порог обвала = 15%
· windowMin = 2 минуты
Я также применил постоянную комиссию 0.5% и спред 2%, чтобы оставаться в консервативном сценарии.
Бэктест показал ROI 86%, за несколько дней $1,000 превратились в $1,869.

Затем я протестировал более агрессивный набор параметров:
· Начальный баланс: $1,000
· 20 акций за сделку
· sumTarget = 0.6
· Порог обвала = 1%
· windowMin = 15 минут
Результат: ROI -50% через 2 дня.

Это ясно показывает, что выбор параметров является наиболее важным фактором. Он может принести много денег или привести к значительным убыткам.
Ограничения бэктестинга
Даже с учетом комиссий и спреда, бэктестинг имеет свои ограничения.
· Во-первых, он использует данные всего за несколько дней, что может быть недостаточно для получения полного представления о рынке.
· Он relies on recorded best-ask snapshots; в реальности ордера могут исполняться частично или по разным ценам. Кроме того, глубина стакана и доступный объем не моделируются.
· Не улавливаются микроколебания на уровне ниже секунды (данные дискретизируются раз в секунду). Хотя в бэктесте есть временные метки с точностью до секунды, между секундами может произойти много всего.
· В бэктесте проскальзывание постоянно, не моделируется переменная задержка (например, 200–1500 мс) или сетевые пики.
· Каждая сделка считается исполненной «мгновенно» (нет очереди ордеров, нет ожидающих ордеров).
· Комиссии взимаются единообразно, в то время как в реальности они могут зависеть от: рынка / токена, мейкера или тейкера, уровня комиссий или условий.
Чтобы сохранять пессимистичный (осторожный) подход, я применил правило: если Leg 2 не выполняется до закрытия рынка, Leg 1 считается полным убытком (total loss).
Это сделано намеренно консервативно, но не всегда соответствует реальности:
· Иногда Leg 1 можно закрыть досрочно,
· Иногда он в итоге оказывается в деньгах (ITM) и выигрывает,
· Иногда убыток может быть частичным, а не полным.
Хотя убытки могут быть завышены, это обеспечивает практический сценарий «наихудшего случая».
Самое главное, бэктест не может смоделировать влияние ваших крупных ордеров на стакан или привлечение других трейдеров для охоты на вас. В реальности ваши ордера могут:
· Нарушать стакан,
· Привлекать или отпугивать других трейдеров,
· Вызывать нелинейное проскальзывание.
Бэктест предполагает, что вы纯粹 принимаете ликвидность (price taker) и не оказываете никакого влияния.
Наконец, он не моделирует лимиты частоты запросов (rate limits), ошибки API, отклоненные ордера, приостановки, тайм-ауты, переподключения или ситуации, когда бот занят и пропускает сигналы.
Бэктестинг чрезвычайно ценен для определения хорошего диапазона параметров, но это не 100% гарантия, поскольку некоторые эффекты реального мира невозможно смоделировать.
Инфраструктура
Я планирую запустить этого бота на Raspberry Pi, чтобы избежать потребления ресурсов моего основного компьютера и обеспечить круглосуточную работу 24/7.
Но здесь еще есть значительное пространство для улучшений:
· Использование Rust вместо JavaScript обеспечит гораздо более высокую производительность и время обработки.
· Запуск выделенного Polygon RPC узла further снизит задержку.
· Развертывание на VPS, близком к серверам Polymarket, также значительно снизит задержку.
Наверняка есть и другие методы оптимизации, которые я еще не обнаружил. В настоящее время я изучаю Rust, поскольку он становится неотъемлемым языком в разработке Web3.








