Перейти к основному содержимому

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)​

  1. Прямая установка — bid = targetCpc * 100 копеек при каждом запуске. Плюсы: просто. Минусы: игнорирует реальный аукцион; ставка может расходиться с оптимальной при изменении конкуренции.

  2. Пропорциональный 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).