
Гипотеза «новости двигают рынок» — самая интуитивная в трейдинге. Настолько интуитивная, что я потратил на её проверку недели 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 извлечёт смысл точнее, но не раньше — а хоронит новостные признаки именно запаздывание, не качество извлечения. Улучшать точность пересказа того, что уже в цене, можно бесконечно.
Длинные горизонты (недели), где фундаментальные новости могли бы работать, — у моей системы другой горизонт, а смена горизонта — отдельная большая история (спойлер: часовые признаки на горизонте недели не предсказывают ничего).
Если видите постановку, которую я упустил, — напишите в комментариях: стенд и протокол под рукой, осмысленную гипотезу могу прогнать и вернуться с цифрами. После прошлой статьи один такой расчёт по мотивам комментария уже случился.
Чек-лист: если проверяете новостные признаки сами
Бейзлайн обязан видеть цену и объём полностью — иначе новости «сработают», просто пересказав их.
AUC-гейт до денег: средний AUC нескольких сидов не сдвинулся — дальше не считать.
Атрибуция по бумагам: прибавка обязана жить там, где признак есть. Прибавка на бумагах с нулями признака = перетасовка шума.
Атрибуция по богатству признака: у бумаг с самыми частыми новостями эффект должен быть самым сильным. Обратный градиент — приговор.
Sharpe при падающем PnL и обороте — артефакт фильтрации, а не улучшение.
Осторожно с фоновыми признаками (константными внутри дней и общими для всех бумаг) — это идентификаторы эпохи, модель запомнит по ним историю.
Редкий признак (единицы процентов баров) меняет размерность входа и перезапускает сидовую лотерею — сравнивайте только ансамбль против ансамбля.
Что в итоге
Ноль из пяти — это результат, купленный неделями GPU-часов, и я считаю покупку выгодной. Дешевле было бы поверить в любую из двух «побед» — но тогда бы я сейчас торговал шумом и рассказывал вам, как нейронка читает новости. Отрицательный результат с протоколом стоит больше положительного без него.
Полная честность требует сноски: самые тупые счётчики внимания в комбинации с микроструктурными признаками позже дали микроскопическую, но подтверждённую по полному протоколу прибавку — и в этом виде сидят в боевой модели. А весь NLP — сентимент, семантика, типы событий — проиграл счётчику постов. Это, пожалуй, самый унизительный для нейросетей вывод всей серии.
Система тем временем торгует виртуально в реальном времени, на очереди — реальные деньги с публичным трек-рекордом. Следующей статьёй планирую разбор главного страха любой обученной на истории системы — смены рыночного режима: что из измеренных страховок работает (еженедельное переобучение, автоматический выключатель), а что проваливается (почти всё остальное). Но очередь гибкая: если интереснее экономика издержек и исполнения, устройство live-инфраструктуры на дешёвом VPS или пошаговый разбор протокола проверки — скажите в комментариях, следующую тему могу выбрать из предложенных, либо пойду по уже намеченному плану.
Не является индивидуальной инвестиционной рекомендацией.
Комментарии (6)

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

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

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

svtoroi Автор
20.08.2026 08:52статья ровно об этом) Сидовый шум ±10 п.п. из первой части - это и есть прямое измерение дисперсии оценки
один прогон нейронки не значит ничего, поэтому все сравнивается ансамблями по 5 сидов и первый гейт - сдвиг среднего AUC, а не красивый эквити
в ней под похожим комментарием считал deflated Sharp с поправкой на число перебранных гипотез
если видите где подход дырявый статистически - ткните пальцем, посчитаю и вернусь с цифрами
kuza2000
Вы используете нейронки? Какая архитектура сети - полносвязная, сверточная, RNN, трансформер?
svtoroi Автор
рекуррентная, компактная GRU, сигнал снимается с последнего состояния
гонял прости нее attantion-пуллинг, трансформер и вариант с учетверенным контекстом - все проиграли по деньгам