К содержимому
MoranaLabs.
Инженерные гайды5 мин чтения0 просмотров

Динамическое ценообразование в реальном времени: цена, которая подстраивается под спрос 

Забыли обновить цены — потеряли маржу, завысили — убили конверсию. Разбираем, как построить потоковую систему, которая меняет ценники на лету, не уходит в демпинг и не бесит покупателей.

0xReality

В 2021 году один крупный ритейлер решил поиграть в алгоритмы. Они выкатили скрипт, который снижал цену на технику, если у конкурента было дешевле, и ушли спать. Утром выяснилось, что бот конкурента делал то же самое: алгоритмы сцепились в спирали смерти и за четыре часа распродали партию премиальных пылесосов по 150 рублей за штуку. В MoranaLabs мы делаем индустриальный ИИ, edge-вычисления и высоконагруженный инференс на железе клиента, и к нам регулярно приходят разгребать последствия таких экспериментов. Когда на столе лежит задача «Динамическое ценообразование в реальном времени: цена, которая подстраивается под спрос», большинство видит в этом лишь парсинг чужих витрин. На практике это суровая инженерия на стыке потоковых данных и reinforcement learning.

«Да какое там RL? Вся ваша динамика — это просто грабить Яндекс.Маркет и ставить минус рубль. Зачем тут городить ИИ и реалтайм?»

В 90% случаев e-commerce так и делает. И это прямой путь к потере маржи.

Вы меняете цены вручную или раз в сутки с гигантским опозданием. Снижаете — теряете прибыль на товарах, которые и так бы купили. Завышаете — гробите конверсию. Реальный real-time прайсинг смотрит не только на соседей. Сигналы для адекватного пересчета цены — это ваши текущие складские остатки (burn rate), эластичность спроса по каждому конкретному SKU, всплески трафика в категории и даже погода за окном пользователя. Если у вас на складе осталось три кондиционера, а на улице аномальная жара, плевать, что там у конкурентов. Цена должна автоматически расти до потолка эластичности.

«Хорошо, сигналы понятны. Но зачем потоковая архитектура? Запустили крон-джобу ночью, пересчитали табличку на миллион строк, залили в базу. Работает же».

Работает. Ровно до тех пор, пока не случается внезапный всплеск спроса.

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

Архитектура: динамическое ценообразование в реальном времени под капотом

Как это выглядит в проде, когда мы говорим про жесткий high-load? У вас есть шина данных — обычно Kafka. Туда льются кликстрим, транзакции, добавления в корзину и обновления остатков из ERP. Дальше стоит потоковый движок, например, Flink. Он на лету собирает окна агрегации: сколько просмотров карточки товара за последние 5 минут, какова конверсия в добавление в корзину.

Эти фичи улетают в инференс-сервис. Модель оценивает вероятность покупки при разных уровнях цены. Но голая нейронка или RL-агент в вакууме смертельно опасны. Они алгоритмически склонны к демпингу в ноль, если их функция потерь завязана только на максимизацию конверсии.

Поэтому перед отправкой цены в продакшен работает фильтр бизнес-правил (guardrails). Жесткие ограничения: не опускаться ниже себестоимости + X%, не демпинговать больше чем на Y% от рынка, не менять цену чаще одного раза в 10 минут для конкретной сессии.

def calculate_dynamic_price(sku_events, current_stock, competitor_price):
    # Модель предсказывает кривую эластичности (спрос в зависимости от цены)
    demand_curve = model.predict_elasticity(sku_events)
    
    # Ищем цену, максимизирующую: (цена - себестоимость) * ожидаемый_спрос
    optimal_price = optimize_margin(demand_curve, cost=current_stock.cogs)
    
    # Жесткий слой бизнес-правил для защиты от демпинга и багов
    MIN_MARGIN_MULTIPLIER = 1.15
    MAX_PRICE_JUMP = 1.25
    
    # Ниже себестоимости + 15% не падаем никогда
    price = max(optimal_price, current_stock.cogs * MIN_MARGIN_MULTIPLIER)
    # Резко цену не задираем, чтобы не отпугнуть лояльных клиентов
    price = min(price, current_stock.base_price * MAX_PRICE_JUMP)
    # Учитываем рынок, но не слепо падаем на дно
    price = min(price, competitor_price * 0.98) 
    
    return round(price)
«А как же репутация? Люди ненавидят, когда билеты на такси дорожают в дождь. Амазон за это тоже пинали. Ценовые войны убьют лояльность».

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

Ответ здесь — управление ожиданиями и техническая сегментация. Нельзя менять цену в корзине, когда человек уже ввел номер кредитки. Нельзя делать разброс цен для одного и того же пользователя при F5 страницы. Вы обязаны фиксировать цену на сессию или использовать токен идемпотентности. Грамотные системы скрывают резкие скачки за счет персонализированных промокодов или автоматического списания баллов лояльности, а не просто переписывая базовый ценник в лоб.

Как доказать эффект на маржу: A/B оценка

«Выкатили мы вашу потоковую магию. Продажи выросли. А может, это просто зарплатный день и сезонность? Как доказать, что алгоритм приносит деньги, а не просто перекладывает их из кармана в карман?»

Классическое A/B тестирование с разделением пользователей по кукам здесь не работает. Если половине пользователей вы показываете цену 1000 рублей, а половине 1200, они заметят это, пойдут в соцсети и разорвут ваш бренд. Кроме того, спрос перетечет в более дешевую группу, математически искажая оценку эластичности.

Оценивать эффект нужно иначе:

  • Switchback-тестирование (чередование по времени). Вы переключаете алгоритмы целыми интервалами. Понедельник с 10:00 до 11:00 работает статика, с 11:00 до 12:00 — динамика. Окна сглаживаются, чтобы нивелировать внутридневную сезонность.
  • Пространственное разделение (Geo-split). Берете разные, но статистически похожие по профилю регионы. В одном городе включаете алгоритм, в другом оставляете статику. Эффект замеряете через Difference-in-Differences.
  • Сплит по кластерам SKU. Разбиваете каталог на корзины товаров со схожей оборачиваемостью и эластичностью. Для группы А включаете динамику, для B оставляете правила ручного ценообразования.

Ценообразование — это не интуиция и не рулетка. Если p99 ответа вашей системы пересчета цены больше 200 миллисекунд — клиент уйдет. Если нет жестких ограничений по марже — алгоритм продаст весь склад в минус. Либо вы управляете ценой на основе данных в реалтайме, либо рынок управляет вашими убытками.

  • #a/b testing
  • #dynamic pricing
  • #high-load
  • #real-time
  • #streaming
ПоделитьсяTelegramX
рассылка

Новые статьи — на почту

Лонгриды про ML в проде, edge и компьютерное зрение — сразу после выхода.

Канал в Telegram: morana.log

Без спама. Нажимая «Подписаться», соглашаетесь с обработкой персональных данных

бесплатный pdf-гайд

Edge AI или облако: когда тащить нейросеть на железо

Признаки, фреймворк выбора и прикидка экономии — короткий PDF-гайд на почту.

PDF · 5 страниц · без спама. Нажимая «Получить», соглашаетесь с обработкой персональных данных

Читать дальше
— заявка

Опишите задачу  ответим как инженеры. 

Оставьте имя и Telegram — остальное обсудим. Без брифов на 40 слайдов и звонков по три раза.

Отвечаем за пару часовотвечает инженер, а не отдел продажNDA по запросу

Сюда напишем — это быстрее всего

Или сразу написать в Telegram

Без спама и звонков-роботов. Нажимая кнопку, вы соглашаетесь с политикой конфиденциальности и обработкой персональных данных.