TLDR; https://github.com/alterfo/moex-trader

Здравствуйте, меня зовут Олег. 11+ лет опыта в архитектуре и управлении разработкой.

Я как кузнец — не могу не куя, и сейчас, в меж-работье, занимаюсь своими проектами. Среди них — интерактивный нотный тренажер для игры на пианино, шифрованный личный дневник, игра по мотивам Космических Рейнджеров - Вакуумные Пройдохи и ещё штук 6, включая движок базы знаний по коду, чатам, докам и таскам и редактор IDEF0.

Сейчас в фокусе проект AI-трейдинга.

Мысль о заработке с помощью ИИ не даёт мне покоя уже три года. Когда слово “агентные” можно было услышать только в интервью Сергея Брина, а опенсорсные модели годились только для adult-ботов, я создал своего первого агента с помощью nerve-cli. Это утилита, которая запускает запросы модели в цикле с доступом к утилитам и промптом-целью.

Агент сам писал себе тулу для сбора новостей на заданную тему, проводил анализ настроений и выдавал рекомендации по инвестициям. По сути, это был прототип News Sentiment Trading. Дело было в начале 2024-го. Эта система выдавала конечный результат 1 раз из 10, и лишь один из 10 конечных результатов я брал в работу. Под капотом была первая опенсорсная gemma.

Система сгенерировала мне значительную прибыль, которую я потратил на двухнедельный отпуск в пятизвездочном отеле на Хайнане. Но счастье длилось недолго. Где как не в Китае осознать непостоянную природу бытия.

Сентимент, который перестал работать.

В 2025-м году с рынком что-то случилось. Новостной анализ перестал приносить желаемый результат. Вооруженный нейросетями (Claude, DeepSeek, Qwen, и бесплатные от Opencode) я принялся искать рабочий подход.

Первым делом я начал искать корелляции между новостями и стоимостью бумаг. Каждый день система собирала новости, считала сентимент, писала отчёт с калибровкой. За месяц таких отчётов накопилось несколько десятков — я честно пытался подкрутить веса источников, отсеять шум, разбить на категории, добавить доверие проверенным изданиям и штрафовать желтизну.

Появился зачаточный бэктест — анализ влияния новостей на котировки на горизонте 1/3/5/10 дней. Все попытки откалибровать (не только сентимент) и найти корелляцию находили только шум и 50/50. Из интересного — обнаружилось что PR/маркетинговые новости приводили к росту на горизонте 5 дней с вероятностью 80% тогда как и за негативными новостями, вроде выпиливания Озон из стора — следовал рост акций. Получил несколько полезных инсайтов для долгих ставок и прогнозов.

В это время Google выложила в опенсорс продвинутую модель для анализа временных рядов  — TimesFM 3, она была обучена на сезонных данных и могала находить корелляцию между разными данными. Она обнаружила корелляцию между Полюсом (золотодобыча) и МТС, и между МТС и Сбером с лагом в 3 дня за последние 90 дней, но это не подтвердилось анализом других таймфреймов, поэтому эту идею я выбросил. Для сезонного пронозирования очень хорошая модель, но для моих нужд не подошла.

Движок

Испробовав идею на python, я переписываю её на Go. Просто меньше проблем при доработках. И в этот раз мне не хотелось снова собирать особенности Python-среды и я создал модульный Go-монолит, который:

  • каждые 5 минут забирает котировки и стакан по MOEX IIS,

  • торгует в песочнице,

  • тянет новости из проверенных на прошлом этапе источников,

  • считает FeatureContext (моментум, RSI, отклонение от скользящей, реализованная волатильность, z-score объема, дисбаланс стакана, новостной сентимент),

  • проверяет заявки по набору правил (не съест ли комиссия прибыль, не много ли заявок, нет ли новостных блокеров, и тд),

  • реализует простейший кластер доступности — если вдруг макбук выключится, приложение, запущенное на ai-box переходит в режим трейдера, а когда макбук оживает — он становится основной системой,

  • шлёт исполненные заявки в телеграм бота и в аудит лог,

  • при запуске делает бэктест на свежих данных, и если тот показывает минус - не запускается.

LLM я исключил из системы, мне был нужен детерминизм и быстрый бэктест, а модель могла отвечать по-разному на одни и те же входные данные, а бэктест занимал 8 часов.

Дальше пошёл перебор моделей, настроек торговли и данных. Логистическую регрессию я собрал в ансамбль вместе с LightGBM и XGBoost (через инференс в Go) — три модели голосуют, финальный сигнал усредняется. Для анализа новостей я обучил собственный bag-of-words классификатор на чистом Go, который размечает заголовок по восьми категориям событий (дивиденды, байбэк, санкции и т. п.) вместо расплывчатого “сентимента”. Это было продолжением активностей по поиску корелляций.

Чтобы собственный классификатор показывал честный результат, я обучил его на старых новостях и данных, до таймфрейма бэктеста (90 дней).

Результаты

Итоговые результаты прогона бэктеста на свежих MOEX данных (2026-06-19 — 2026-09-16). 18 тикеров, депозит 1 000 000 ₽, комиссия 0,05 %, kill-switch включён:

Вариант

Сделок

Net P&L

Hit rate

Просадка

Sharpe

rule (правило по порогу)

599

−3 458 ₽

45,9 %

0,39 %

−2,13

model (логрегрессия, 1 лот)

3

+2 668 ₽

100 %

0,27 %

1,44

ensemble, 1 лот

45

+5 583 ₽

84,4 %

0,07 %

5,70

ensemble, notional 3 000 ₽

91

+14 890 ₽

72,5 %

0,20 %

6,10

ensemble, notional 10 000 ₽

114

+48 932 ₽

68,4 %

0,57 %

6,29

ensemble, notional 15 000 ₽ (боевой рецепт)

136

+75 029 ₽

64,0 %

0,84 %

6,38

ensemble, notional 20 000 ₽

143

+99 016 ₽

61,5 %

1,10 %

6,38

Вы спросите почему боевой вариант не последний? Потому что на окне в 6 кварталов (18 месяцев) у него была большая просадка, которая не пролезла в kill-switch (он срабатывает при просадке портфеля на 3%)

Для меня это инженерная задача. Все цифры — результат тестирования на исторических данных MOEX и той же защитой, что в живой системе. Это не инвестиционная рекомендация и не обещание доходности.

Выводы

Несмотря на волатильность рынка в последние годы, ансамбль из трёх нейросетей, двух специализированных (LightGBM и XGBoost) и одной самостоятельно обученной показали возможность дохода.

Процесс обучения классификатора, бэктесты и другие детали реализации предлагаю вынести в комментарии чтобы не нагружать статью.