0025. Алгоритм движка управления ставками автобиддера
Копия ADR из репозитория:
backend/docs/adr/0025-bid-engine.md. Канонический текст — в репозитории; портал обновляется командойnpm run sync:adr.
- Статус: accepted
- Дата: 2026-06-25
- Связанные задачи: OP-67
Контекст и проблема
Нужен алгоритм автоматической корректировки ставок рекламных кампаний WB по
заданной стратегии (OP-67 · 5.4). Доступные данные в БД: текущие ставки
(bidsJson в AdCampaignEntity) и статистика кампаний (AdCampaignStatEntity
— расход, клики, показы, заказы). Данные о выручке с заказов и позиции в поиске
в текущей схеме отсутствуют.
Рассмотренные варианты
Тип cpc (целевой CPC)
-
Прямая установка —
bid = targetCpc * 100 копеекпри каждом запуске. Плюсы: просто. Минусы: игнорирует реальный аукцион; ставка может расходиться с оптимальной при изменении конкуренции. -
Пропорциональный feedback (выбрано) —
newBid = currentBid × (targetCpc / observedCpc), зажато до ±50% за цикл.observedCpc = totalSpendRub / totalClicksза последние 7 дней. Bootstrap (ставка =targetCpc * 100) — только когда нет исторических данных (stats=null). Если данные есть, но кликов 0 — hold. Плюсы: адаптивно; не сбрасывает ставку на 0-кликовых кампаниях. Минусы: медленная сходимость при больших отклонениях (намеренное ограничение ±50%).
Тип drr (доля рекламных расходов)
Без данных о выручке (revenue) в AdCampaignStatEntity невозможно рассчитать
DRR = spend / revenue * 100. Альтернатива — прокси-метрика через заказы —
требует среднего чека, которого тоже нет.
Решение: пассивный режим (hold) до реализации отдельного трекинга выручки.
Тип position (позиция в поиске)
Позиция в результатах поиска WB требует отдельного API /adv/v0/normquery/stats,
который не интегрирован в текущей итерации.
Решение: пассивный режим (hold) до интеграции normquery/stats.
Решение
cpc— пропорциональный feedback с зажатием ±50%/цикл; bootstrap приstats=null.drr,position— пассивный режим с явным hold.- HTTP-эндпоинт
POST /autobidder/runс RBAC-проверкой черезaccounts.getById(actor). - Системный путь
runSystem(wbAccountId)для будущего планировщика (аналогично repricer). - WB API:
PATCH /api/advert/v1/bids, чанки по 50 кампаний за запрос. - После успешного push — обновление
bidsJsonв БД и аудит-запись (F6).
Последствия
- Положительные: алгоритм детерминирован, тестируем, не меняет ставки резко.
- Отрицательные / компромиссы:
drrиpositionработают в пассивном режиме (стратегии этих типов не производят изменений до следующего OP). - Что нужно дальше: интеграция
normquery/stats(position), трекинг выручки (drr).