
На закате массового использования Gemini 2.5 Pro хочу поделиться опытом использования этой модели для тестирования продуктовой идеи: от формирования общей продуктовой концепции до работающего прототипа. Уровень проработки прототипа должен был получиться MVP - не меньше. А если исследование получилось бы крайне удачным, то далее его можно было бы уже развить в полноценный тиражируемый и масштабируемый продукт.
Disclaimer: Я строгий противник того, чтобы называть лендинг‑страницу с окошком чата или корзиной для товаров «MVP IT‑продукта», когда на самом деле результаты взаимодействия перекидываются куче людей «за кулисами», которые бегут ножками в магазины и покупают товар для клиента или передают ТЗ в разработку куче низкооплачиваемых программистов вместо использования нейронки, о которой заявляют. В моем понимании MVP должен быть на самом деле «жизнеспособным», хоть и не очень функциональным, а не быть маской, под которой скрывается ручное исполнение задач.
Постановка задачи
Собственно, в чем состояла задача: создать MVP HFT-бота, который должен выискивать возможности внутри биржевых арбитражных сделок и непосредственно их исполнять. Для удобства оператора сразу же были заложены базовые аспекты по созданию web-страницы для запуска/остановки торговли, мониторинга успехов и небольших кастомизаций торговых сессий. Ничего объемного и сложного, просто упрощение наглядности, чтобы не смотреть в голую консоль сервера.
Такая задача приводит к необходимости детальной проработки Backend-логики с минимальными требованиями к UI - самое то, чтобы проверить, на что способна нейронка без потребности детально разбираться в разработке Frontend, в котором я мало что смыслю. Заранее скажу, что в моем случае это была единственно верная стратегия. Как показала практика, любые доработки UI почти не несли исследовательского значения, но отвлекали колоссальное количество внимания от реально критичных архитектурных задач. Поэтому на середине исследования я почти перестал дорабатывать Frontend, оставив его в зачаточном состоянии, а весь ресурс вложил в детализацию и понятность логов движка. Настоящая магия происходила именно там, в глубине алгоритмов, и ей надо было управлять прозрачно и точно.
Планирование и работа с требованиями
Когда цель исследования была сформирована, я подключил к работам нейронку. Первично были поставлены задачи сформировать целевое описание продукта как с бизнесовой, так и с технической стороны. Но не все за раз, а постепенно, увеличивая детализацию и с разделением на прорабатываемые разделы. Причиной тому был типичный формат ответов нейронки: она старается сжать передаваемую информацию максимально кратко. Даже если внутри окна рассуждений она хранит важные аспекты реализации и детализации, то может посчитать их несущественными для отражения в документе.
В ходе детализации ставились ограничения на реализацию, вот базовые из них:
Быстрый движок со скоростью обнаружения исполнения до 150 мс (это я думал быстро, ха-ха).
Программный код должен быть на Python (да, я знаю, что Python не вариант для итогового решения, об этом будет ниже).
Только вертикальное масштабирование, т.к. сетевые задержки уничтожили бы всю идею.
3-х и 4-х ногие трейды.
Запись в БД только необходимых данных о торговой сессии, совершенных трейдах и ордерах внутри них.
Базовые аспекты UI я упомянул выше.
Завязка на возможность переключения между биржами.
Итоговый продукт должен разворачиваться в контейнерах.
Для MVP никаких встроенных инструментов для авторизации не заложено, т.к. вопрос закрывается внешними инструментами.
Что было приятно видеть, так это то, что Gemini 2.5 Pro достаточно часто предлагала дельные советы: что еще стоит отразить в документе (даже если я этого не просил) или в каких аспектах мои требования слишком мягкие, а где - слишком жесткие для MVP. В конечном итоге сформировался документ на более чем 1200 строк (это актуальное состояние, которое неоднократно обновлялось в связи с переработкой проекта) с вводной частью, целями и метриками, объемом работ и границами релизов (чтобы нейронка понимала, что делаем сейчас, но с акцентом, куда целимся, дабы минимизировать создание техдолга), базовым набором пользовательских сценариев и путей использования, use cases, функциональных и нефункциональных требований, рисков принимаемых решений, техстеком, архитектурными принципами и фактической архитектурой, аспектами запуска приложения и структурой проекта.
Скажу так, что «рыбу» данного документа я мог бы составить в одиночку и наполнить его процентов на 60-70% после скрупулезного изучения проблематики, но это заняло бы у меня значительно больше времени. А если учесть оставшиеся 30-40% аспектов, которые не менее важны, но по которым я мог только дать заключения в формате «звучит разумно» или «чушь какая-то, давай думать еще», то без участия нейронки я бы закопался на недели только для составления данного документа. Конечно, в ходе реализации многие архитектурные аспекты претерпели изменения и не совпадают в точности с исходной постановкой, но заложенные принципы бизнес- и тех-архитектуры продукта позволяли придерживаться направления, а не начинать каждую итерацию сначала.
Технический стек и инфраструктура
Чуть детальнее про моменты о техстеке и hardware, которые относятся к опыту с нейронками лишь косвенно.
Выбран был Python, т.к. я его неплохо помню из более раннего опыта дата-анализа, а также нейронки его очень любят, а значит, есть надежда, что будут подсказывать дельные советы в направлении solution-оптимизаций. Также для Python есть отличные C-native библиотеки для работы с математикой, что также давало надежду, что для прототипа проблемы чистого Python не будут критичными. А еще у меня были опасения, что на других языках результаты (скорость реализации исследования) будут значительно хуже.
Первичные запуски приложения проводились локально на ноутбуке с AMD Ryzen 6600H и 16Gb RAM, этих ресурсов на Windows 11 не хватало для полноценного тестирования. OS + IDE + Браузер + Docker сжирают всю RAM просто катастрофически. В этот момент очень жалел, что временно пришлось переключиться с Fedora из-за проблем у Wi-Fi адаптера в диапазоне 2.4GHz - ОС на Linux гораздо более отзывчивы. Поэтому сначала перенес проект на локальный сервер с LXC-образом серверной Ubuntu. Уже это дало определенный буст - можно больше выдавать RAM и ядер для работы приложения. Следующим этапом было арендовать VPS в соседнем ЦОД от биржи - это позволило изучить влияние сетевых задержек на результаты работы. И в конечном итоге использовались VDS в Google Cloud для оценки точного значения необходимых ресурсов сервера. Возможность арендовать сервер поминутно очень помогла исследовать потребность в масштабировании. В целом считаю, что с этого сразу надо было начинать, а не возиться с локальным сервером и VPS.
Этапы реализации и преодоление трудностей
О этапах реализации MVP: Нейронка очень опасалась сразу лезть в многопоточность (concurrency issues, race conditions), а я боялся за нее и сложность отладки. Поэтому на первом этапе мы сознательно выбрали упрощенную модель: асинхронные вызовы (asyncio) в рамках одного потока. На этом этапе была отработана базовая логика: создание и закрытие торговой сессии, надежное подключение к основной БД и ее реплике, подключение к API биржи, прослушивание Websockets (WS), их первичный анализ и создание ордеров. В целом опыт взаимодействия с нейронкой был положительный: мы поэтапно прорабатывали проект, инкапсулировали то, что положено (выносили логику биржи в адаптеры), и не перебарщивали с абстракциями там, где они были некритичны.
Но вот при детальной проработке модуля создания и менеджмента ордеров всплыла серьезная проблема: массовые отказы исполнения со стороны биржи. Были то одни ошибки (неверная точность цены), то другие (нарушение лимитов, неверный шаг объема). Нейронка каждый раз зацикливалась в своих рассуждениях: предлагала исправление, которое чинило одну ошибку, но тут же ломало логику в другом месте, вызывая новую ошибку. Удалось реализовать данный функционал, только скормив ей документ с полной спецификацией API биржи и тянув ее за руку к правильному решению.
В дальнейшем такие ситуации стали возникать неоднократно, поэтому я завел отдельный документ с «выученными уроками» разработки приложения, что позволило превентивно подсовывать его нейронке и сообщать, какие решения неприемлемы, и что реально сработало успешно. Вторым решением было в моменты возникновения зацикливания нейронки полностью обновлять контекст, снова рассказывать о возникшей проблеме, логах и т.д., но без предыдущего обсуждения проекта. И, как ни удивительно, в новом контексте нейронка чаще всего давала рабочее решение сразу же или после нескольких уточняющих вопросов.
Масштабирование и оптимизация
Все пробы проводились сначала на тестовом контуре биржи, а затем на боевом. Это приводило к тому, что нагрузка на движок отличалась кардинально, а также менялись рыночные условия: количество тактов на Проде выше в среднем в 15 раз. Это все же потребовало использования честной многопоточности - одно ядро Python, даже с asyncio, просто задыхалось от обработки входящего потока JSON-ов. Нейронка не была уверена в своих возможностях правильно распараллелить Python-код (из-за GIL) и боялась возникающих рисков (дедлоки, гонки данных), но вместе мы сформировали план с минимальным архитектурным вмешательством в движок. Для межпроцессного взаимодействия (IPC) стали использовать Redis, который надолго прописался в архитектуре как шина данных. Для ускорения IO были настроены Linux sockets. План по пользованию Linux sockets также был причиной обязательного мигрирования на Linux.
Как итог, самая нагруженная часть приложения - математический модуль расчета сотен тысяч путей арбитража - обрела многопоточность (через multiprocessing), и это дало надежду на возможность масштабирования в рамках одной мощной машины.
Далее последовало большое число итераций по стабилизации приложения и бизнес-логики:
детальное планирование размеров ордеров с учетом сложной структуры комиссий (мейкер/тейкер);
наглядная и быстрая обработка проблем на исполнение ордеров на стороне биржи (частичное исполнение, отмена);
формирование оптимальных процессов и путей по экстренному освобождению капитала, застрявшего на промежуточных "ногах" арбитражных трейдов;
процессы избавления от «пыли» - формируемых незначительных сумм на промежуточных символах из-за обязательных округлений при формировании ордера (минимальный шаг цены и минимальный размер ордера часто оставляют "хвосты", которые копятся);
мониторинг качества трейда в реальном времени в ходе его исполнения и прерывание цепочки, если продолжение только усугубит ситуацию.
Эти и многие другие оптимизации логики позволили избавиться от тупого, механистического следования плану и сделать реально умный движок, который оценивает риски каждую миллисекунду и совершает наиболее оптимальные действия, исходя из текущего состояния рынка. В этой части вопросов почти все идеи формировал я сам, исходя из наблюдений за рынком, а нейронка выступала кодером, формируя solution в коде, т.к. ей самой не удавалось увидеть за деревьями лес и понять рыночную механику.
Но и этого оказалось мало. Сложная логика и дополнительные проверки безопасности привели к задержкам трейдов во внутренних очередях приложения, медленным расчетам и исполнению. На Проде соединения WS обрывались по тайм-ауту, т.к. CPU был занят расчетами и не успевал отвечать на ping/pong запросы биржи. Четко прослеживались большие просадки производительности из-за очередей IO (сериализация/десериализация данных для Redis). Необходимы были радикальные оптимизации скорости и дальнейшие оптимизации solution при сохранении действующей функциональности.
Что было сделано:
Математика была полноценно переведена на векторные вычисления NumPy.
Стандартный интерпретатор Python был заменен на JIT-компилируемый PyPy, что дало прирост на чистой логике.
Подключена библиотека uvloop - сверхбыстрая замена стандартному циклу событий asyncio.
Сервисы подписки к WS и отслеживания тиков также были переведены на честную многопоточность.
Redis полностью был убран из контура "горячих" расчетных взаимодействий. Мы перешли на Shared Memory (разделяемую память) для прямого доступа процессов к данным стакана. Это позволило сильно ускорить расчеты, снизить IO и разгрузить CPU от лишней работы по перекладке байтов.
Стал использоваться выделенный приватный WS-канал исключительно для отправки ордеров (сильно снизилось latency трейдов).
Все эти трансформации проходили под моим жестким контролем, но справедливости ради - наибольшая часть технических идей (как Shared Memory или uvloop) озвучивалась самой нейронкой, если проблемы скармливались ей дозированно. При слишком широких и объемных вопросах нейронка начинала "плыть" и сыпаться в рассуждениях.
Если в целом оценивать проработку упомянутых этапов, то фактически они тесно переплетались, а не происходили строго в порядке, изложенном здесь. Уточнение функциональности приводило к ошибкам в других местах. Оптимизации скорости приводили к потере мелких, но важных функциональных аспектов. Чем детальнее прорабатывалось решение, тем меньше было прямого исполнения предложений нейронки. В связи с поверхностным знанием ЯП я просил нейронку пояснять детально изменения и принимаемые решения и озвучивать риски их принятия. Это позволяло превентивно отклонять участки изменений, которые звучали очень разумно, но были абсолютно неприемлемы.
Порой долго приходилось убеждать нейронку в правоте своего мнения, меняя аргументы и предоставляя новые доказательства своей правоты, и только когда критическая масса доводов перевешивала, нейронка соглашалась делать то, что мне было нужно.
Особенности работы с Gemini 2.5 Pro
Несколько слов о формате взаимодействия с Google Gemini 2.5 Pro. Для себя нашел оптимальным форматом работу именно в AI Studio. Причины просты: огромное контекстное окно (до миллиона токенов), наглядные метрики его текущего использования (ты видишь, когда "память" кончается) и более удобный интерфейс с возможностью кастомизации системного промпта. Обычный чат в Gemini (даже с подпиской Pro) понравился гораздо меньше: отслеживать остатки контекстного окна можно только интуитивно, нет тонких настроек температуры генерации и прочих нюансов. Плагин Gemini Code для IDE вообще показался полной лажей - годится только для автодополнений пары строк, потыкался с ним час и перестал использовать вообще, он просто не видит всей картины проекта.
Также должен сказать, что качество работы нейронки после 500–600 тыс. токенов стремительно падает, поэтому при приближении к данному лимиту слишком серьезные и сложные аспекты вообще переставал обсуждать, а чаще всего переходил в новый чат. К слову, в новых чатах нейронка часто делает отсылки к тем моментам, которые в чате не обсуждались, т.е. какой-то контекст остается общесистемным, что где-то упрощает работу, а где-то ухудшает, т.к. нельзя выдать информацию как с чистого листа.
Еще один момент: сам проект состоит из множества файлов в различных каталогах, но во всех чатах есть ограничение на количество загружаемых файлов. Так вот, чтобы решить данную проблему с помощью той же нейронки, был написан скрипт, который склеивал файлы с исходниками в один с четким разделением, где какой файл начинается и где заканчивается, и упоминанием его точного местоположения в проекте.
Результаты и выводы
Как вы понимаете, получившийся исследовательский проект не перерос во что-то большее коммерческое. Причина прозаична: настоящие co-location HFT-трейдеры работают в рамках наносекунд, используют FPGA, тесно связаны с управлением крупных бирж и арендуют стойки непосредственно в самих ЦОД бирж, подключаясь к ядру напрямую. Конкурировать с ними на Python и VDS - утопия. Но было очень занятно и полезно изучить, что возможно реализовать сложную систему с помощью нейронки без собственных глубоких знаний ЯП, но с четким пониманием архитектуры: что и как нужно реализовать.
Чтобы добавить финальной конкретики: итоговый трейдинговый движок стал способен обрабатывать 15 тыс. рыночных тиков в секунду, анализировать в режиме онлайн до 300 тыс. возможных арбитражных путей (графов) на основе этих тиков. Общее время реакции (latency) в цепочке «получение тика - расчет - принятие решения - запуск исполнения трейда» уложилось в интервал 7–30 мс. Само исполнение трейдов (обмен на бирже) занимало 20–35 мс в среднем. Эти цифры даны для всего лишь одного балансового ассета и при запуске приложения на VDS с 8 vCPU и 16 Gb RAM (AMD Milan) со средней нагрузкой на CPU около 50–60% и почти пустой RAM (благодаря Shared Memory). Как понимаете, такие результаты на распределенной типовой инфраструктуре (микросервисы + REST API) были бы физически невозможны, но даже на арендованном VDS они оказались вполне реализуемыми.
Так какие выводы из всего этого можно сделать? Что нейронные сети уже достаточно умны, чтобы очень сильно помогать в реализации мелких продуктов или в поверхностных задачах: там, где нужна была research-команда разноплановых специалистов, теперь может справиться один человек с нейродвижком. Но я все еще считаю, что на крупных взаимосвязанных продуктах и проектах требуются глубокие специалисты, особенно в вопросах реализации development-аспектов продуктов - они банально обгонят вайб-кодеров на дистанции; пока вайб-кодеры нарисуют интерфейс и глючный backend, high-qualified команда уже займет рыночную нишу.
Но также это означает, что просадки компетенций в команде на временной основе все же с горем пополам можно пробовать затыкать нейропомощниками. А также не стоит полностью доверять нейронкам, они очень убедительно строят свои доводы, даже если несут несусветную чушь. Посмотрим, что сегодня Google выкатил в Gemini 3.0 Pro.
P.S. Eсли есть у кого-то интерес к полученным исходникам, то напишите мне в личку - я чутка их причешу и выложу на GitHub. Сейчас просто нет особого желания в это вкладываться, т.к. результаты исследования получены, зафиксированы и вполне наглядны.