(история одной разработки)
Постановка задачиКогда товар в избытке на центральном складе, а в магазинах его разбирают как горячие пирожки - довольно просто собрать статистику и спрогнозировать дальнейшую динамику спроса в каждом магазине. А вы попробуйте проделать то же самое, когда у вас 50 магазинов, в каждом товар покупается в среднем по 1-2 шт в неделю, а на центральном складе запас всего в 10 единиц. Кому выделить товар в первую очередь?Итак, имеем на входе:
РешениеДовольно долго мы изучали текущую схему работы отдела товароведения, пытаясь понять алгоритм, по которому человек распределяет товар по магазинам, и автоматизировать его. Решение никак не складывалось: программа то переоценивала спрос для конкретного магазина, то недооценивала его. Все встало на место, когда кто-то из товароведов обронил гениальную фразу: "Товар надо дать тому, кто быстрее его продаст". Это, казалось бы, очевидное правило, сотрудники выполняли интуитивно, уменьшая или увеличивая количество товара, рассчитанное в Excel в поставке, но никак не могли описать в виде формулы. Начальные действияПервым шагом на пути создания программы для распределения было формирование дерева Групп распределения. Весь ассортимент товаров был разделен на группы, приблизительно одинаковые с точки зрения распределения. Если для товара почему-либо невозможно было спрогнозировать продажи, то прогноз рассчитывался по группе в целом и делился на количество активных (продававшихся в течение последней недели) товаров в группе. Таким образом решалось сразу две задачи: ввод в систему новых товаров (для которых отсутствовала статистика) и замена товара его аналогами. (рисунок: Дерево групп распределения) Норма запаса для группы распределения (НЗГ) устанавливалась как количество дней (по умолчанию 14), в течение которых магазин мог бы торговать данных товаром без поставок с центрального склада. Данный параметр влиял на все товары в группе и дополнительно регулировался специальным множителем для учета динамики спроса в предпраздничные дни. Вес группы распределения (ВГР) определял приоритет (артикул/группа) при расчете среднего времени продажи для группы. Больше вес – выше приоритет группы. Вес артикула равен (1 – вес группы распределения). По умолчанию вес группы равен 0,5, т.е. группа и артикул вносили приблизительно равный вклад в расчет динамики продаж. Все склады были выстроены в Дерево поставок. Корнем дерева являлся Центральный склад, его подчиненными были объекты, на которые шли непосредственные поставки (центральные магазины и "главные" магазины регионов), далее шли магазины регионов, получающие товар с "главных" магазинов. Большей глубины в нашем случае не было. (рисунок: Дерево поставок) Для каждого склада задавался определенный "вес распределения" (по умолчанию =1), корректирующий потребность по всем товарам для данного магазина в сторону повышения или понижения. Вес распределения равный 0 означал запрет распределения всех товаров на данный склад. Так учитывалось расширение, или наоборот, планируемое закрытие магазина. Важным параметром для склада являлся срок поставки - количество дней доставки (ДД) товара до регионального распределительного склада от времени создания регионом заявки на поставку. Блокировки распределенияПоскольку не все магазины торговали полным ассортиментом товаров (например, телефонные карты московского региона продавались только в Москве), то необходимо было запретить распределение таких товаров на остальные магазины. Было введено два вида блокировок: Блокировки группы и Блокировки товара. Суть их одинакова, только в первом случае блокировалась вся группа распределения, а во втором - конкретный товар. График поставок, поставки под заказСуществовало еще два фактора, усложнявших задачу:
(рисунок: График поставок) Прогнозирование спросаИнформация о продажах поступала в систему из программы учета Storehouse Explorer. Были настроены определенные фильтры импорта. Например, не учитывались продажи со складов уценки, списания на определенных "технических клиентов" и т.д.Все товары были разделены на три группы в зависимости от продаж за предыдущие четыре недели (названия были предложены руководством):
Алгоритм расчета потребности был своим для каждой группы. Типовые склады распределения («Mаячковые» склады) Список складов по продажам, которых возможно прогнозировать продажи по другим складам. Алгоритм распределенияВсе расчеты проводились по-артикульно. Исключения составляли товары "Бренд", для которых расчет велся по "Коду модели", однако сам принцип расчета был тот же. Поскольку часть товара требуется оставить "на завтра", необходимо было рассчитать, сколько из имеющегося товара мы можем отдать в магазины сегодня. Если обозначить:
То количество товара, распределяемое сегодня пропорционально отношению потребности магазинов распределяемых сегодня к общей потребности с учетом веса дня недели: Sсегодня = Sрозн / [Сумма (Nсегодня )*Pдня + (Сумма (Nзавтра ) - Доставки )* (1–Pдня)] * Сумма (Nсегодня *Pдня) Замечание: если сумма в […] равна нулю, распределение не требуется. Если (Сумма (Nзавтра )* (1–Pдня) - Доставки) < 0, то (Сумма (Nзавтра )* (1–Pдня) - Доставки) = 0Борьба с "пиковыми продажами"Что такое "пиковая продажа"? Это случайная крупная покупка, вероятность повторения которой очень низка. Например, покупатель приобрел в одном заказе сразу 10 телевизоров для своей новой дачи. Появится ли еще когда-нибудь такой покупатель? Кто знает...В системе прогнозирования данная покупка приводит к сильной переоценке покупательского спроса. Если ранее продажи товара прогнозировались, например, на уровне 1-2 штук в неделю, то теперь система оценивает спрос в 5-10 единиц товара. Происходит перенасыщение склада и падение оборачиваемости. Бороться с такими пиками можно только нелинейными математическими методами. На практике, при малом количестве данных, эффективным оказался следующий подход: за длительный период (например, за год) анализируем количество каждого товара в чеках и используем метод квартилей для нахождения "уровня отсечки": сколько штук обычно покупают в одном заказе. Выстраиваем полученные числа по возрастанию и отбрасываем четверть данных с максимальными значениями (можно взять не четверть, а другое количество, например, одну десятую, но существенно на результат это не влияет). Полученную цифру увеличиваем на единицу, чтобы создать некоторый буферный запас. Допустим, график зависимости количества чеков от количества товара в чеке выглядит следующим образом: Третий квартиль в нашем примере = 4 штуки товара в одном чеке, т.е. уровень отсечки устанавливаем = 5 штук. Записываем это число в параметры товара, и все продажи, где в чеке больше 5 штук данной номенклатуры, считаем пиковыми. Для сети магазинов компьютерной техники значение "уровня отсечки" оказалось равным 2 для 90% товаров. Что делать с пиковыми продажами? Хорошие результаты дала замена пиковых продаж значением "уровня отсечки". Таким образом, мы учитываем эти продажи в статистике и не слишком искажаем прогноз. В рассматриваемой системе уровень отсечки вычислялся не только для каждой номенклатуры, но и для группы номенклатур. В результате все новые номенклатуры на старте получали "уровень отсечки" равный групповому значению.
|
Программирование > Прочее >