Гипотеза «новости двигают рынок» — самая интуитивная в трейдинге. Настолько интуитивная, что я потратил на её проверку недели GPU-часов, полный архив финансовых телеграм-каналов с 2021 года и пять принципиально разных постановок задачи — от простых счётчиков упоминаний до NLP-разметки и пер-минутного event study.

Результат: ноль из пяти. Ни одна постановка не улучшила боевую модель (с одной унизительной для NLP оговоркой — она в конце).

Но интересен не сам ноль — интересно, как именно проваливалась каждая попытка. Две из пяти сначала показали «улучшение» в бэктесте, и если бы я остановился на агрегатной цифре, сейчас бы искренне рассказывал вам, что нейронка с новостями торгует лучше. Эта статья — подробный разбор всех пяти механизмов: что строил, какие признаки считал, какие цифры получил и где именно каждая версия обманывала.

Это обещанное продолжение статьи про сидовый шум ±10 п.п. — протокол проверки оттуда, здесь он работает на живом сквозном примере.

Стенд, кратко

Для тех, кто не читал первую часть, минимальная рамка:

  • База: часовые свечи 20 ликвидных акций Мосбиржи, 2021–2026; рекуррентная сеть, бинарная метка «вырастет ли цена больше порога за несколько часов»; walk-forward с зазором на длину горизонта; комиссии в каждой цифре. Все Sharpe в статье — парные сравнения кандидата с бейзлайном в единой методике, а не обещания абсолютной доходности: сравнение переживает любые уточнения модели издержек, абсолютная цифра — нет.

  • Протокол против самообмана: (1) любая идея проверяется ансамблем из 5 сидов против ансамбля из 5 сидов — одиночный прогон нейронки на этих данных врёт на ±10 п.п.; (2) первый гейт — средний AUC пяти сидов: не сдвинулся — идея дальше не идёт; (3) пороги и параметры выбираются на первой половине out-of-sample периода, оценка — на второй, которую выбор «не видел»; (4) обязательная атрибуция: из каких бумаг пришла прибавка.

  • Бейзлайн: модель на цене + положении бумаги относительно корзины + микроструктуре часа. Важная деталь: бейзлайн — боевая модель на момент попытки, а она улучшалась по ходу кампании (счётчики проверялись против Sharpe 1.53, поздние попытки — против 2.16), поэтому у каждой попытки своя пара цифр.

Данные: как достать полмиллиона финансовых новостей

Сначала инженерная часть — она может пригодиться независимо от выводов.

Проблема: RSS финансовых СМИ не отдаёт историю. Подключив ленты сегодня, первую пригодную для обучения выборку вы соберёте через год.

Решение: Telegram. У крупных финансовых каналов история сообщений хранится с момента создания — и Telethon (MTProto-клиент) отдаёт её целиком, легально, через обычный аккаунт:

# суть; полный скрипт тривиален
from telethon import TelegramClient
client = TelegramClient("session", API_ID, API_HASH)
async for msg in client.iter_messages(channel, reverse=True,
                                      offset_date=START_DATE):
    save(channel, msg.date, msg.text)

Три канала (агрегатор рыночных новостей + два деловых СМИ) дали 476 тысяч постов с 2021 года — полное покрытие обучающего периода. Тикер-привязка — словарём ключевых слов (названия компаний, тикеры, продукты) с ручной чисткой ложных срабатываний. Поверх — живой RSS-коллектор, чтобы лента пополнялась в реальном времени.

Один нюанс, который сэкономит вам вечер: авторизацию Telethon делайте двухшаговой и неинтерактивной (отправка кода и ввод кода — отдельные вызовы), иначе она не переживёт запуск из демона.

Пять попыток: план кампании

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

#

Постановка

Возражение, на которое отвечает

1

Счётчики внимания

2

Сентимент (NLP)

«вы считали штуки, а важен знак»

3

Типы событий

«важен не тон, а ЧТО случилось»

4

Дивидендный календарь

«важны календарные события с датами»

5

Пер-минутная реакция цены

«важна не новость, а реакция рынка на неё»

Спойлер траектории: 1 — честная ничья, 2 — честный лёгкий минус, 3 — громкий провал, 4 и 5 — ложные победы, разоблачённые атрибуцией. Чем изощрённее постановка, тем коварнее провал.

Попытка 1. Счётчики внимания: ничья

Самая простая гипотеза: всплеск внимания к бумаге предвещает движение. Признаки на каждый бар:

  • число постов о бумаге за последние 24 часа и за неделю;

  • давность последнего поста (часов назад);

  • общерыночный поток постов за 4 часа и за сутки (прокси «на рынке что-то происходит»).

Итог: AUC пяти сидов не сдвинулся (0.542 против 0.543), честная вторая половина — Sharpe 1.49 против 1.53 у бейзлайна. Статистическая ничья.

Механизм: всплеск внимания не существует в вакууме — он приходит вместе со всплеском объёма и волатильности, которые модель уже видит в свече напрямую. Счётчик постов — это запаздывающий пересказ колонки volume. Информация не добавилась, добавился шум измерения той же информации.

Попытка 2. Сентимент: лёгкий минус

Возражение принято: считаем не «сколько», а «с каким знаком». Все 476 тысяч постов размечены компактной русскоязычной sentiment-моделью (rubert-tiny2-based) за одну ночь на GPU: sent = P(positive) − P(negative) для каждого поста.

Занятная деталь разметки: позитивными модель посчитала лишь 11% финансовых постов, негативными — 33%. Общедоменная sentiment-модель осторожна с финансовым позитивом — «компания увеличила выручку на 40%» для неё нейтральна, а любое упоминание санкций — негатив. Для наших целей это не фатально: признаку нужна не абсолютная точность, а стабильный сигнал в относительных изменениях.

Признаки: средний тон постов о бумаге за 24 часа и за неделю, тон последнего поста, среднерыночный тон за 4 и 24 часа.

Итог: AUC ниже бейзлайна у всех пяти сидов (0.540 против 0.544), честная половина 1.78 против 2.16. Не ничья — устойчивый лёгкий минус: признаки заняли ёмкость модели и ничего не заплатили за постой.

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

Попытка 3. Типы событий: громкий провал

Возражение принято: тон — примитив, важна семантика события. Дивиденды двигают цену не так, как санкции; отчётность — не так, как ставка ЦБ. Размечаем регэкспами пять событийных типов (на полмиллионе постов регэкспы честнее и в тысячу раз дешевле LLM):

  • дивиденды — 8.5 тыс. постов;

  • отчётность — 30 тыс.;

  • санкции — 20 тыс.;

  • ставка ЦБ — 6 тыс.;

  • M&A — 7 тыс.

Признаки: события каждого типа по бумаге в скользящих окнах, санкционный и ставочный фон по рынку, направление последней дивидендной новости (через сентимент из попытки 2).

Итог — худший в серии, с большим отрывом: AUC 0.519 против 0.544 у всех пяти сидов, честная половина Sharpe 0.38 против 2.16. Модель с событийными признаками разучилась торговать вообще.

Механизм — самый поучительный из пяти: медленные фоновые признаки. Признак «на рынке санкционная неделя» константен часами и сутками и одинаков для всех 20 бумаг. Для сети это идеальный идентификатор эпохи: вместо «санкции → продавай» она выучивает «в кварталах с таким фоном рынок вёл себя так-то» — то есть запоминает конкретные исторические отрезки train-выборки. На out-of-sample эта память не просто бесполезна — она активно вредна, потому что уверенно применяет чужой контекст. Я называю это ловушкой slow features; она у меня срабатывала на шести разных семействах признаков, событийные типы — самый чистый случай.

Практическое следствие: если ваш признак почти не меняется внутри дня и одинаков для всех инструментов — он кандидат не в фичи, а в идентификаторы эпохи. Обращайтесь осторожно.

Попытка 4. Дивидендный календарь: первая ложная победа

Возражение принято: фон — зло, возьмём точечные календарные события с датами и величинами. Биржевой API отдаёт историю дивидендных отсечек (280 выплат по нашим бумагам): близость отсечки (≤14 дней), дивидендная доходность выплаты, пост-гэповое окно (≤10 дней после отсечки — там, по фольклору, «закрывают гэп»).

Итог скрининга: Sharpe 2.49 против 2.16. Улучшение! Первое за четыре попытки. Признаюсь: рука уже тянулась записать победу и обновить прод.

Протокол потребовал атрибуцию, и она перевернула картину:

  • дивидендные плательщики суммарно: −22 тыс. ₽ к PnL против бейзлайна;

  • весь прирост — +21.7 тыс. ₽ на одной бумаге, у которой в тот период дивидендного признака не было вовсе (нули в этих колонках).

Улучшение пришло ровно оттуда, куда механизм признака указывать не может. Это не сигнал — это перетасовка сидового шума: дивидендный признак ненулевой лишь на ~3% баров, но само его добавление меняет размерность входа сети, а значит — всю раскладку случайной инициализации. Пять новых сидов — новый билет в лотерею из первой статьи, и в этот раз билет оказался выигрышным. На следующем еженедельном переобучении «прибавка» испарилась бы вместе с удачей.

Правило, которое я после этого сформулировал: если улучшение пришло не оттуда, куда указывает механизм признака — это не улучшение, а шум. Агрегатный Sharpe не является доказательством в принципе.

Попытка 5. Пер-минутная реакция: ложная победа, версия «про»

Последнее и самое сильное возражение: сама новость не важна — важно, как рынок на неё отреагировал. Это уже почти классический event study: если за 15 минут после поста цена пошла вверх на повышенном объёме — рынок «проголосовал», и это знание свежее любого текста.

Постановка самая трудоёмкая из пяти: минутные свечи, для каждого поста — окно 15 минут после публикации, доходность и всплеск объёма в окне (объём нормирован на собственную историю бумаги в это время суток). Получилось 34 тысячи размеченных реакций. Признаки на бар: подписанная реакция на последний пост, её давность, величина всплеска объёма, сумма реакций за сутки.

Итог скрининга: Sharpe 2.39 против 2.16, и просадка лучше. Опять победа? Атрибуция:

  • суммарный PnL против бейзлайна: −49 тыс. ₽ (Sharpe вырос, денег стало меньше — за счёт упавшего оборота);

  • бумаги, богатые новостями — те, где механизм обязан работать лучше всего — стали хуже: первый по капитализации банк −12.3 тыс., сама биржа −8 тыс.;

  • «выигрыш» пришёл на бумагу с 214 реакциями за пять лет — там, где признак практически пуст.

Паттерн, обратный механизму, в квадрате. Плюс новый симптом в коллекцию: рост Sharpe при падении PnL и оборота — артефакт, а не улучшение (отфильтровались и убыточные, и прибыльные сделки; знаменатель сжался быстрее числителя).

Почему текст всегда опаздывает

Пять постановок, пять разных провалов, один корень.

На часовом горизонте новостной текст — это запаздывающий пересказ ценового ряда. Цепочка событий на реальном рынке: инсайдеры и связанные стороны действуют до публикации; алгоритмы и профессиональные ленты — в первые секунды-минуты; текст в телеграм-канале появляется, когда движение уже идёт; к закрытию часового бара оно уже в свече — в доходности, объёме, волатильности, положении бумаги относительно рынка. Всё, что «знает» новость, модель уже прочитала из цены, причём без ошибок парсинга и тикер-привязки.

Отсюда честная карта того, что я не проверял и почему:

  • Субсекундная реакция на новость — там текст ещё может опережать часть участников, но это HFT-ниша: колокация, комиссии маркетмейкера, война за микросекунды. На retail-инфраструктуре с комиссией 0.05% за сторону экономика мертва до всякого ML.

  • LLM-понимание текста вместо регэкспов и лёгкого сентимента. Дорого, но проверяемо; мой скептицизм структурный: LLM извлечёт смысл точнее, но не раньше — а хоронит новостные признаки именно запаздывание, не качество извлечения. Улучшать точность пересказа того, что уже в цене, можно бесконечно.

  • Длинные горизонты (недели), где фундаментальные новости могли бы работать, — у моей системы другой горизонт, а смена горизонта — отдельная большая история (спойлер: часовые признаки на горизонте недели не предсказывают ничего).

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

Чек-лист: если проверяете новостные признаки сами

  1. Бейзлайн обязан видеть цену и объём полностью — иначе новости «сработают», просто пересказав их.

  2. AUC-гейт до денег: средний AUC нескольких сидов не сдвинулся — дальше не считать.

  3. Атрибуция по бумагам: прибавка обязана жить там, где признак есть. Прибавка на бумагах с нулями признака = перетасовка шума.

  4. Атрибуция по богатству признака: у бумаг с самыми частыми новостями эффект должен быть самым сильным. Обратный градиент — приговор.

  5. Sharpe при падающем PnL и обороте — артефакт фильтрации, а не улучшение.

  6. Осторожно с фоновыми признаками (константными внутри дней и общими для всех бумаг) — это идентификаторы эпохи, модель запомнит по ним историю.

  7. Редкий признак (единицы процентов баров) меняет размерность входа и перезапускает сидовую лотерею — сравнивайте только ансамбль против ансамбля.

Что в итоге

Ноль из пяти — это результат, купленный неделями GPU-часов, и я считаю покупку выгодной. Дешевле было бы поверить в любую из двух «побед» — но тогда бы я сейчас торговал шумом и рассказывал вам, как нейронка читает новости. Отрицательный результат с протоколом стоит больше положительного без него.

Полная честность требует сноски: самые тупые счётчики внимания в комбинации с микроструктурными признаками позже дали микроскопическую, но подтверждённую по полному протоколу прибавку — и в этом виде сидят в боевой модели. А весь NLP — сентимент, семантика, типы событий — проиграл счётчику постов. Это, пожалуй, самый унизительный для нейросетей вывод всей серии.

Система тем временем торгует виртуально в реальном времени, на очереди — реальные деньги с публичным трек-рекордом. Следующей статьёй планирую разбор главного страха любой обученной на истории системы — смены рыночного режима: что из измеренных страховок работает (еженедельное переобучение, автоматический выключатель), а что проваливается (почти всё остальное). Но очередь гибкая: если интереснее экономика издержек и исполнения, устройство live-инфраструктуры на дешёвом VPS или пошаговый разбор протокола проверки — скажите в комментариях, следующую тему могу выбрать из предложенных, либо пойду по уже намеченному плану.


Не является индивидуальной инвестиционной рекомендацией.

Комментарии (6)


  1. kuza2000
    20.08.2026 08:52

    Вы используете нейронки? Какая архитектура сети - полносвязная, сверточная, RNN, трансформер?


    1. svtoroi Автор
      20.08.2026 08:52

      рекуррентная, компактная GRU, сигнал снимается с последнего состояния
      гонял прости нее attantion-пуллинг, трансформер и вариант с учетверенным контекстом - все проиграли по деньгам


  1. VsBirdEye
    20.08.2026 08:52

    Интересно будет почитать про вашу реализацию rolling re-overfit weekly, измеряли ли инерцию режима, на какие параметры завязали стоп-кран и т.д.


    1. svtoroi Автор
      20.08.2026 08:52

      все перечисленное как раз будет в следующей статье, плюс недавно нашел дыру в стресс тесте и она заметно поменяла часть выводов - так что статья выйдет честнее
      но сначала опубликую короткий разбор по этой находке


  1. tester37
    20.08.2026 08:52

    Такие темы надо начинать с основ тервера. Сто раз читал умнейшие разборы, где авторы даже не удосуживались подумать о том, что такое дисперсия и какой реально объем данных нужен, чтобы быть уверенным, что не она дала полученный результат


    1. svtoroi Автор
      20.08.2026 08:52

      статья ровно об этом) Сидовый шум ±10 п.п. из первой части - это и есть прямое измерение дисперсии оценки
      один прогон нейронки не значит ничего, поэтому все сравнивается ансамблями по 5 сидов и первый гейт - сдвиг среднего AUC, а не красивый эквити
      в ней под похожим комментарием считал deflated Sharp с поправкой на число перебранных гипотез
      если видите где подход дырявый статистически - ткните пальцем, посчитаю и вернусь с цифрами