Перейти к содержимому
VC
Кейс 20 из 33 · Python · Оценка качества AI

Прогноз событий ансамблем моделей: калибровка и проверка по Брайеру

Собственная система прогнозирования исходов на рынках предсказаний (Polymarket): пять независимых агентов на языковой модели с поиском по открытым источникам, супервизор, калибровка, запись каждого прогноза в базу до исхода и проверка по показателю Брайера после. Кейс про измерение: как ставится планка качества, что она показала на 203 разрешившихся рынках и почему торговля реальными деньгами так и осталась выключенной.

Отрасль
Рынки предсказаний · собственная разработка
Стек
Python · DuckDB · Claude Sonnet + Opus · веб-поиск
Формат
Собственная система, без заказчика
Итог
Планка по Брайеру не взята: 13 замеров, 203 исхода
01 · Боль

Уверенный ответ модели проверить нечем

Языковая модель с доступом к поиску выдаёт связное рассуждение и число: «вероятность 0,82». Проверить это число на глаз невозможно. У одиночного прогноза про событие нет правильного ответа до исхода; после исхода один случай ничего не говорит о калибровке: уверенная ошибка и осторожное попадание выглядят одинаково. Нужна серия записанных прогнозов и метрика, которая наказывает и за самоуверенность, и за трусливые 50%.

Предыстория тоже про измерение. До этой системы на тех же площадках проверялись микроструктурные стратегии: реакция на движение котировок, зеркалирование крупных счетов. 12 мая 2026 года направление закрыто постмортемом: за 2,5 недели прогона без денег семь стратегий, и ни одна не прошла проверку. Три причины оказались общими. Подсчёт по снимкам стакана раздувал долю выигрышей: 51,9% по снимкам против 30,4% при агрегации по рынкам. Сигнал, прошедший проверку на истории с t = 4,79, за две недели ослаб до t = 1,73 и к 12 мая перестал срабатывать вовсе: ноль срабатываний за 11 часов при 27 тысячах сканов. Один удачный день маскировал семь убыточных из восьми.

Отсюда правила, с которыми строилась новая система: результат считается по рынкам, после исхода, на выборке заданного размера и с поправкой на распад найденного преимущества. И новый класс задач: медленные события в геополитике и политике, где цена держится днями, комиссия площадки для категории нулевая, и у модели есть время прочитать критерий разрешения. Гипотеза звучала так: цена ошибается там, где участники читают заголовки и пропускают критерий разрешения.

02 · Решение

Прогноз записывается до исхода и проверяется после

Контур из пяти шагов. Модель отвечает только за рассуждение; отбор рынков, база, калибровка, сверка исходов и показатель Брайера живут в Python и работают без модели. Рецепт ансамбля взят из статьи AIA Forecaster и с первого дня записывался так, чтобы каждый его элемент можно было пересчитать задним числом.

01
Отбор рынков

Публичный API площадки: бинарные рынки геополитики и политики, до разрешения 1–45 дней, цена 0,02–0,98, порог по суточному обороту. Повторный прогноз по рынку не чаще раза в 48 часов

02
Ансамбль

Пять независимых агентов на Claude Sonnet, у каждого до пяти поисков. Агент видит вопрос, критерий разрешения и горизонт; ответ заканчивается строкой PROBABILITY

03
Супервизор

Агент на Claude Opus читает рассуждения всех пяти, добирает поиском спорные факты и выдаёт сведённую вероятность

04
Калибровка и запись

Среднее по ансамблю, поправка Платта с α = 1,73, смесь с ценой рынка (вес 0,33), порог расхождения 0,03. В DuckDB пишутся сырая, калиброванная и смешанная вероятности, цена, согласие агентов, рассуждение

05
Исход и Брайер

Ежедневный таймер сверяет закрытые рынки по явному флагу победителя, пишет наш Брайер и рыночный, бумажный результат по цене покупки с полуспредом 0,015, отчёт в мессенджер

Планка задана до первого прогноза

Показатель Брайера — квадрат разности между названной вероятностью и исходом (1 или 0). Ноль означает безошибочный прогноз, вечные 50% дают ровно 0,25, уверенная ошибка стоит почти единицу. Та же величина считается для цены рынка на момент прогноза, и это даёт естественный эталон: рынок тоже прогнозист. Планка сформулирована в коде отчёта раньше, чем записан первый прогноз:

  • не меньше 30 разрешившихся рынков и наш Брайер ниже рыночного
  • до выполнения обоих условий торговля реальными деньгами запрещена; система живёт в режиме прогона без денег
  • бумажный результат считается по цене покупки с полуспредом 0,015, чтобы прогон без денег не льстил
  • категория геополитики выбрана в том числе потому, что комиссия площадки для неё нулевая: спред остаётся единственной издержкой в модели

Два пути к прогнозу: модель по API и модель-оператор

Полный конвейер на Python вызывает модель по API: пять агентов параллельно, потом супервизор. На сервере ключа к API не оказалось, поэтому рабочим стал второй путь: сессия Claude Code с веб-поиском проводит исследование по описанному в навыке рецепту; скрипт записи получает от неё сырую вероятность, сам берёт живую цену рынка, применяет калибровку, считает расхождение и пишет строку. Ежедневный прогон выглядит так: очередь из 13–14 рынков, 8–14 подагентов на Claude Sonnet через рабочий процесс, затем арбитраж оператора перед записью.

Разделение ролей принципиальное. Модель владеет рассуждением и поиском. Python владеет тем, что должно переживать смену моделей и промптов: отбором рынков, базой, калибровкой, сверкой исходов и отчётом.

Счётчик исходов молчал семь недель

Первый настоящий сбой случился в самом важном месте. Публичный API площадки перестал отдавать закрытые рынки по адресу, через который система сверяла исходы: ответ приходил пустым и без ошибки. Таблица исходов оставалась пустой с конца мая по 16 июля, отчёт честно писал «разрешившихся пока нет», и выглядело это как медленные рынки. Класс отказа тот же, что в кейсе про надёжность фоновых служб: процесс жив, данные не приходят, никто не жалуется.

Исправление: сверка переведена на эндпоинт биржевого ядра по идентификатору условия, где у каждого исхода стоит явный флаг победителя; запрос по адресу рынка остался запасным путём. Первый же запуск записал 4 исхода: наш Брайер 0,499 против рыночного 0,235. Рынок впереди с первой строки, и с этого момента измерение стало ежедневным.

В строке хранится всё, что нужно для пересчёта

У каждого прогноза сохраняются сырая вероятность ансамбля, калиброванная, смешанная с ценой, сама цена, число агентов, мера их согласия, сторона сигнала, рассуждение и версия модели. Это решило судьбу проекта позже: когда возник вопрос, помогает ли поправка Платта, ответ считался по уже накопленным строкам, без повторных прогонов. Отдельные правила гигиены очереди появились по инцидентам:

  • рынок попадает в очередь, только если отбор видел его в последние 48 часов: майские рынки с застывшим сроком «1,6 дня» висели в очереди в июле
  • расхождение считается только по живой цене: цена в очереди отставала от реальной в 10 раз (0,04 против 0,389)
  • горизонт отбора сокращён со 120 до 45 дней: короткие рынки быстрее дают разрешившиеся пары
03 · Стек

Кода мало — вся сложность в измерении

Python 3 · httpx

Клиенты публичных API площадки без авторизации: отбор рынков, живые цены, сверка исходов

DuckDB

Три таблицы: рынки, прогнозы, исходы. Сырая и калиброванная вероятности лежат рядом, пересчёт доступен задним числом

Claude Sonnet ×5 + Claude Opus

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

Claude Code + рабочий процесс подагентов

Операторский путь: 8–14 подагентов на пакет, проходы скептика и арбитра, запись через скрипт

Поправка Платта · смесь с ценой

Экстремизация в логит-пространстве с α = 1,73 и смесь с ценой (вес 0,33) по рецепту статьи; оба слоя измерены отдельно

systemd-таймеры на сервере

Сверка исходов и отчёт раз в сутки без участия модели. Пакет прогнозов по API подготовлен отдельным таймером (08:45 UTC, до 12 рынков за прогон) и включается одной командой, когда на сервере появится ключ

Отчёт в мессенджер

Число рынков, прогнозов и исходов, Брайер против рынка, очередь на прогноз — ежедневная сводка в Discord

Диагностика по таблице исходов

Разбивка потерь по диапазонам цены и семейные базовые частоты по шаблону вопроса

PythonDuckDBhttpxClaude SonnetClaude Opusweb_searchPlatt scalingBrier scoresystemd timercronDiscord
04 · Результат

Планка не взята — и это измерено

Разрешившихся рынков в серии
30 203

первый замер 31 июля, тринадцатый — 5 сентября 2026; свыше 600 записанных прогнозов

Брайер: наш / рыночный, n = 203
0,104 / 0,075

13 замеров подряд планка не взята; на первом замере было 0,119 против 0,080

Рынков, где мы точнее цены
80,8%

164 из 203; отставание по сумме целиком делают редкие уверенные промахи

Где именно теряется точность

Подпись результата устойчива от замера к замеру: по большинству рынков мы точнее цены, по сумме проигрываем. На n = 66 четыре промаха давали 84% всего отставания (3,646 из 4,322); без них 0,068 против 0,057 на 62 парах, почти вровень. Три из четырёх — уверенные расхождения с ценой больше чем на 75 п.п., и во всех четырёх рынок оказался прав. Два промаха — один и тот же шаблон вопроса про проход военных кораблей через пролив: сырые 0,98 и 0,82 против цены 0,010 и 0,037, оба исхода «нет». Ещё один — подмена одного конфликта другим: 0,03 против 0,895, исход «да». Разбивка по диапазонам цены на n = 203 показала, что течь не размазана:

  • цена ниже 0,10 — n = 132, наш Брайер 0,042 против 0,022 при реальной частоте таких исходов 2,3%: редкие события мы переоценивали
  • середина 0,25–0,75 — n = 20, 0,297 против 0,220: единственный диапазон, где наше несогласие с ценой вредит статистически
  • цена выше 0,90 — n = 21, 0,048 против 0,047: здесь мы равны рынку, ломать нечего

Поправка из статьи ухудшала показатель

Поправка Платта растягивает вероятности к краям: логит умножается на 1,73. В статье она улучшала Брайер, потому что модели склонны жаться к 50%. На нашей серии эффект обратный, и это видно по тем же строкам, где сырая вероятность хранится отдельно: на n = 53 сырой Брайер 0,108, с поправкой 0,115, рыночный 0,048. На хвостах поправка переворачивает знак расхождения: сырые 0,13 при цене 0,07 означают «мы выше рынка», после растяжения получается 0,036 и сигнал в противоположную сторону. В одном пакете из 13 рынков знак перевернулся у 9.

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

Что изменили по итогам замеров

Каждое изменение рецепта записывалось датой и проверялось на следующих замерах по той же таблице:

  • Агенту не показывают цену рынка. Несмотря на прямой запрет в промпте, все пять прогнозов одной лестницы легли в пределах 1,5 п.п. от цены, и в рассуждении так и было написано. С 23 августа агент получает только вопрос, критерий и горизонт
  • Одно семейство рынков — один агент. Независимые агенты выдавали логически невозможные пары на лестницах дат: 0,25 на «до 31 августа» и 0,15 на «до 15 сентября». Теперь лестница считается одной моделью выживания, монотонность проверяет арбитр
  • Проход скептика и проход арбитра. При расхождении с ценой от 15 п.п. второй агент опровергает несущие факты: 29 августа переписаны 5 из 14 прогнозов. При расхождении от 20 п.п. третий агент в роли «того, кто будет разрешать рынок» проходит критерий по пунктам: 1 сентября перевернул 3 хвоста из 5 (0,94 → 0,33; 0,93 → 0,32; 0,78 → 0,55) и два подтвердил
  • Базовые частоты по семействам из таблицы исходов. «Перемирие продержится до даты» — 14 из 14 «да» при нашем среднем 0,847; «захват населённого пункта к дате» — 0 из 4 при нашем 0,268 и цене 0,095; «снятие блокады к дате» — 10 из 10 «нет», наш 0,011 против цены 0,101, Брайер 0,0003 против 0,0161 — единственное семейство, где мы уверенно точнее рынка

Эффект виден в тех же корзинах. Дешёвый хвост перестал расти: с n = 183 до n = 203 прибавилось 12 исходов, при этом суммарный разрыв в нём изменился с 2,605 до 2,579; переоценка редких событий сократилась с 2,3 до 1,7 раза от реальной частоты. Середина 0,25–0,75 продолжает течь: два новых исхода добавили 0,371 разрыва. Именно туда сейчас направлена дисциплина записи: прогноз, попавший по цене в середину, ставится консервативнее вывода агентов.

Соседняя линия: численный ансамбль на погодных рынках

Параллельно та же дисциплина применялась к рынкам на дневную температуру, где вероятность считалась по ансамблю численных прогнозов (30–50 членов). Первый урок оттуда: доля выигрышей сама по себе ничего не значит. Бот с долей выигрышей 91,6% на 1089 рынках оставался в минусе: при покупке фаворитов по высокой цене один проигрыш съедает много выигрышей. Крайний диапазон показал это в чистом виде: при средней цене 0,995 точка безубыточности — 99,5%, и фактические 97,54% на 285 рынках до неё не дотягивали. Второй урок: бот выбирал фаворитов по цене и вообще не смотрел на прогноз; порог по ансамблю подключили 31 мая сначала в режиме наблюдения, где он только логировал своё решение. Рынки на минимальную температуру исключены после доли выигрышей 61%, в бумажный расчёт добавлена найденная комиссия площадки. 28 июля линия закрыта по собственному A/B-порогу: ожидание в проверенных вариантах отрицательное.

Общий итог без деталей: система не заработала права торговать реальными деньгами, и таблица исходов говорит это за 13 замеров одинаково. Ценность в измерительном контуре: у каждого прогноза есть дата, сырая и калиброванная вероятность, цена и исход, поэтому любой спор о качестве решается запросом к базе.

05 · Применимость

Та же проверка нужна любому AI, который отвечает числом или решением

За кейсом стоит типовая задача «модель отвечает уверенно, и проверить её можно только по накопленным исходам». Это ядро услуги оценки и настройки качества AI-ответов: записать ответ до того, как известен результат, сравнить с эталоном, найти диапазон, где модель ошибается. Контур переносится почти без изменений:

  • AI-чаты и поиск по документам, где качество ответов оценивает вторая модель — её оценки сверяются с оценками людей той же метрикой, что здесь сверялись с исходами
  • Скоринг и оценка рисков, где модель выдаёт вероятность — разбивка по диапазонам показывает, в каком именно диапазоне она переоценивает себя
  • Классификация документов и обращений, где уверенная ошибка на редком классе стоит дороже десятка осторожных попаданий
  • Прогноз спроса и сроков — базовые частоты по семействам случаев из собственной истории точнее любого априорного коэффициента
  • Агенты с поиском, которые строят связную цепочку из живого новостного сюжета — проход скептика и проход арбитра по критерию нужны им до того, как ответ ушёл дальше
  • Любая методика из статьи — коэффициенты калибровки, веса, пороги — получает право на существование только после пересчёта на собственных исходах
Что переиспользуется на следующих проектах
  • Схема хранения: ответ записывается до исхода, величина до поправки и после лежат рядом, пересчёт любого слоя доступен задним числом
  • Планка качества, сформулированная до первого запуска: размер выборки, метрика, эталон и запрет на следующий шаг до её выполнения
  • Диагностика по диапазонам: разбивка показателя по корзинам ответа и запрос базовых частот по семействам случаев
  • Проходы скептика и арбитра: опровержение несущих фактов и разбор по пунктам критерия для ответов с большим расхождением от эталона
  • Контроль якорения: модели не показывают эталонный ответ на этапе исследования; связность семейства ответов проверяет отдельный агент
  • Сверка исходов как отдельный автономный процесс с проверкой на тихий отказ: пустой ответ источника отличается от отсутствия исходов
Похожая задача?

Если модель отвечает уверенно, вопрос в том, записаны ли исходы

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

Готовы начать?

Аудит за 9 900 ₽ — с конкретным отчётом и сметой

Расскажу что внедрить в вашем бизнесе в первую очередь, какая будет окупаемость, и нужен ли вообще AI для вашей задачи (иногда — нет).

Или просто напишите свой вопрос — отвечу в течение 2 часов