В последние пару лет меня достаточно сильно интересовал вопрос ценообразования в российских интернет-магазинах. Каждый раз при заявлении интернет-магазина о большой скидке в душу закрадывается сомнение… Действительно ли такая большая скидка? Была ли реальна цена которая сейчас зачеркнута?
Резкие изменения курса доллара в конце 2014г. подлили масла в огонь. Очень захотелось получить ответ на вопрос как зависят цены от курса доллара в реальности.
В итоге, я решил покончить с этими вопросами и собрать историю изменения цен по российским интернет-магазинам. По катом результаты работы + несколько интересных закономерностей.

Немного технический подробностей


На данный момент в системе работают несколько десятков парсеров написанных на python.
Хранить данные в лоб мне показалось очень расточительным, решил хранить только изменения цены. Если цена не меняется — записи в БД не создаются, такой подход позволяет очень хорошо экономить ресурсы. На данный момент в таблице всего 200 000 000 строк, что не так много для данных по ~100 000 товаров в >1000 магазинов за 8 месяцев.
В качестве хранилища используется MySQL 5.6. Недавно пришлось переехать на SSD, так как обычные HDD на Hetzner не очень справлялись с большой нагрузкой на запись.

В данной статье я хотел бы описать интересные закономерности найденные при анализе собранных данных:

1. Синхронное изменение цены


Собрав базу за несколько месяцев, я решил проанализировать коэффициент корреляции между предложениями одного и того же товара от разных магазинов. Для этого был быстренько набросан скрипт на python + pandas. Pandas в данном случае очень помог наличием функции resample.

sql = """
SELECT pr.date, pr.shopitemid, price from prices AS pr
JOIN shopitems AS si
ON pr.shopitemid = si.id
WHERE si.itemid = 1
AND si.shopid > 10
AND si.last_price IS NOT NULL
ORDER BY pr.date
""" 
df = pd.read_sql_query(sql, engine)
for item in df['shopitemid'].unique():
    x= df[df['shopitemid'] == item]
    nans = x.isnull().sum()['price']/float(len(x))
    if nans > 0.2 or len(x['price'].unique()) < 10 or     x['date'].min() >  (datetime.now() - relativedelta(months=3)):
        df = df.drop(df[df['shopitemid'] == item].index)
df = df.dropna()

df = df.pivot(index='date', columns='shopitemid', values='price')
df = df.fillna(method='pad')
df = df.dropna()
df = df.resample('24h', fill_method='pad', how='last', loffset='24h')
mtrx =  df.as_matrix().T
columns = df.columns.values

corr = np.corrcoef(mtrx)
z = np.where(corr > 0.90)
for x,y in zip(z[0],z[1]):
    if x<y:
        print columns[x],columns[y]
        myplot(mtrx[x])
        myplot(mtrx[y])
        
        plt.show()

Проанализируем историю изменения цен на примере холодильника Indesit SB 185.
На выходе получились достаточно интересные графики типа такого:


Ещё графики





Здесь можно посмотреть данный график в более удобном формате.
В данном примере видно что у трех магазинов цена изменяется абсолютно синхронно в течение 8 месяцев. Мне видятся такие вероятные причины такого явления:
  • В двух из трёх используются системы автоматического выставления цены на основе цен конкурентов.
  • Магазины как-то связаны организационно и имеют доступ к общей БД цен


2. Появление нового смартфона.
В момент анализа я наткнулся на график цен по Samsung Galaxy S6.



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

3. Самые дешевые интернет-магазины для каждой категории товаров


Собрав достаточно большую базу цен, появилась идея сформировать ТОП-10 самых дешевых магазинов для каждой категории товаров.
Разберем принципы формирования данного списка на примере категории Холодильники:
Пробегаемся по каждому товару категории.
Каждому магазину, продающему данный товар, начисляем баллы от 0-дорого, до 1-дешево.
Алгоритм расчета баллов score = (maxprice-price)/(maxprice-minprice)
Вычисляем среднее от баллов набранных каждым магазином.
Удаляем магазины продающие очень мало товаров данной категории.

Например, для категории телевизоры, получился такой список:
Название
Кол-во баллов
Рейтинг на Yandex.Market
Кол-во оценок на Yandex.Market
КРАСНАЯ КНОПКА
0,877
5
697
Топтел
0,854
5
1358
Pleer.ru
0,853
4
52711
Greenbook
0,853
5
200
ОГО
0,832
5
4009
Technosteps.ru
0,832
5
294
Soundbreeze
0,812
5
662
ELECTROGOR
0,808
5
6445
ЦИФРОВИК
0,805
5
460
ЭЛЕКТРОЗОН
0,804
5
1664


4. Зачем же я всё это писал?


В качестве фидбэка от уважаемого сообщества мне очень хотелось бы получить ваши идеи по анализу данного датасета.
Что ещё можно проанализировать, какие интересные закономерности попробовать найти?
Чтобы предоставить возможность каждому посмотреть историю цен, тем более скоро черная пятница, я набросал простенькую веб-морду с возможностью поиска по товарам. Можете поиграться тут, надеюсь, не ляжет.

UPD 01.12.2015: Добавил возможность уведомления при снижении цены ниже определенного порога.

Комментарии (59)


  1. Tux
    26.11.2015 11:07

    Отличный сервис, весьма полезно. Только таблицы не сортируются, а жаль.


    1. ssh1
      26.11.2015 11:45

      Да, это первый вариант. Я думаю соберу фидбэк и что-то доработаю.


      1. foxyrus
        26.11.2015 15:25

        Нужно из графика выкидывать (может опционально) экстремум. Сейчас получился например такой график, ничего не разглядеть.


        1. ssh1
          26.11.2015 15:28

          Да, это косяки при сборе данных. Лучше обрабатывать при сборе, а не на выводе.
          Спасибо за пример.


  1. eaa
    26.11.2015 11:15
    +13

    В данном примере видно что у трех магазинов цена изменяется абсолютно синхронно в течение 8 месяцев. Мне видятся такие вероятные причины такого явления:

    В двух из трёх используются системы автоматического выставления цены на основе цен конкурентов.
    Магазины как-то связаны организационно и имеют доступ к общей БД цен


    Я вот буквально вчера на сайте МВидео читал, что они готовы продать товар по меньшей цене, если у конкурентов цена меньше. Так вот, оказывается, они учитывают только тех конкурентов — а там прям явно написан их список мелким шрифтом внизу, каких — у которых цены точно такие, как у них плюс-минут 100 рублей. А у кого цены меньше на несколько тысяч — «сорри, это неправильный конкурент».

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


    1. Artima
      27.11.2015 13:19
      +2

      Этот механизм называется РРЦ. А подобные функции типа «готовы продать товар по меньшей цене, если у конкурентов цена меньше» делаются в первую очередь для мониторинга цен конкурентов усилиями клиентов, в не самого магазина. Все немного иначе с другой стороны. ;)


      1. eaa
        27.11.2015 16:40

        Вот только если у кого-то реально цены ниже — то они не готовы по такой цене продать


        1. KriMs
          27.11.2015 22:59

          Готовы. Покупал объектив за 5к вместо 6


          1. icoz
            28.11.2015 11:18

            А сколько вы времени потратили в поисках у кого дешевле?


            1. KriMs
              28.11.2015 11:50

              Минуты 2


              1. icoz
                28.11.2015 11:54
                +1

                С другой стороны, вы сказали, что есть дешевле, и вам отдали за 5к. Через 10 минут пришёл другой покупатель, он не знал, что есть дешевле, и взял за 6к. Тоже вполне себе модель бизнеса.


                1. Artima
                  29.11.2015 13:48

                  Все верно, а параллельно они включают определенные рычаги и цена конкурента становится не 5 тыс, а те же 6 тыс.


        1. Artima
          29.11.2015 13:46

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


  1. DancingOnWater
    26.11.2015 11:28
    +2

    А еще они могут иметь одного поставщика.


    1. FractalizeR
      26.11.2015 14:45
      +1

      И фиксированные наценки.


  1. rPman
    26.11.2015 11:35
    +1

    Некоторые (многие?) магазины могут играть ценой за счет изменения цены доставки, специально или так получается, но это тоже важно, особенно если товар категории до 5т.р. даже 500р доставка уже ощутима.
    Можно парсить их предложение по доставке в пару тройку регионов страны пары-тройки товаров разной категории (мини — сотовый, средний — ноутбук/монитор,… большой — холодильник), соответственно визуализация может быть либо учтена в графиках при выборе особенности стоимости доставки выше либо отдельные графики по каждой категории товаров.


  1. alexkuku
    26.11.2015 12:51
    +2

    Вообще, очень крутая тема:
    1. Можно пробовать ловить демпинг. На некоторые товары есть минимальная цена. Производитель обычно строго следит, чтобы она не нарушалась, можно ему помочь
    2. Пробовать определять успешность продукта по тому, как быстро падает его цена. Например, сравнить Айфоны
    3. Пробовать предсказать по первым неделям продаж, какая будет цена через несколько месяцев. Поможет определиться покупать сейчас или подождать
    4. Проверять действительно ли магазин делает скидку или сначала повешает, а потом понижает цену
    5. Посмотреть с какой задержкой и как влияют курсы на цены и предсказывать цены исходя из курсов


    1. Aclz
      26.11.2015 13:19
      +3

      Только часто бывает цена на сайте одна, а звонишь — и там она, оказывается, совсем другая, такая же как у конкурентов («не успели обновить сайт»).


      1. areht
        04.12.2015 01:44

        Не часто, но первые 3-5 строчек на прайсру действительно мошенниками забиты. Наверное, они статистически должны выявляться провалом в 5% от всех конкурентов.


    1. ssh1
      26.11.2015 13:26

      Спасибо за идеи.
      1. Вопрос где её взять, да, и интересно ли это производителю.
      2. А является ли падение цены критерием успешности?
      3. Интересно, но отсмотрев вручную около сотни графиков закономерностей не нашёл.
      4. Спасибо, надо подумать как достать предложение о скидке. Бывает приходит рассылка: «Вот купон, он дает ссылку 10% на эти товары» и т.д.
      5. Тоже думал. Доллар вырос в 2 раза. У многих товаров цена вообще не зависит от него. Хотя возможно она бы падала в случае неизменного курса.

      Вообще я думал попробовать предсказать цену товара на основе прошлых цен + цен на товары в других категориях. Есть надежда что цены на стиралки, например, могут являться хорошими фичами для предсказания цен на холодильники. Пока не дошли руки.


  1. DmitryO
    26.11.2015 13:13

    Замечательный сервис, спасибо. Праздный вопрос — повествование ведется от первого лица, ниужели это все сделано «в одни руки»?


    1. ssh1
      26.11.2015 13:17
      +1

      Спасибо. Да, долго, нудно, но в одни )


      1. DmitryO
        26.11.2015 13:19
        +1

        Снимаю шляпу )


      1. Pashkevich
        26.11.2015 21:10

        Вы цены откуда берете?
        Из xml-выгрузок?
        Или парсите сайты? Все >1000?
        И почему магазинов больше 1000, а товаров всего то 100 000?


        1. ssh1
          26.11.2015 21:17

          Парсинг магазинов/аггрегаторов
          100 000 имеется в виду уникальных товаров, а не пар товар-магазин.
          Да, кстати, как поживает ваш аналогичный проект? Планируется какое-либо развитие?


          1. Pashkevich
            26.11.2015 21:25

            Спасибо, что спросили.
            Сам сервис живет нормально.
            Всё работает, цены каждый день я скачиваю и отображаю на сайте. С этим нет проблем.
            С развитием пока не делаю ничего.
            Скоро приступлю, я думаю к доработкам.
            И первое, что сделаю, это нормальный удобный интерфейс. )))


            1. icoz
              28.11.2015 11:57

              А что за проект?


              1. Pashkevich
                28.11.2015 12:51

                В профиле есть, historyprice.ru


  1. Anisotropic
    26.11.2015 13:28

    Поиск несколько странный. Sony z5 не находит, выдаёт кучу товаров и ни одного телефона.


    1. ssh1
      26.11.2015 13:41
      +1

      Согласен, поиск не очень хорош. Думаю прикрутить sphinx как дойдут руки.


      1. icoz
        28.11.2015 11:59

        Может на хабре опишете как реализован ваш проект? Какие технологии, языки, библиотеки…


        1. ssh1
          28.11.2015 13:29

          Парсеры python + urllib
          База MySQL 5.6 недавно перешел на SSD
          Пришлось немного повозиться чтобы научиться писать данные без избыточности
          WEB — python + Django + bootstrap + highcharts
          Memcached
          Среднее время ответа сервера, судя по ньюрелик, 20-30мс. Учитывая что в кэше явно есть не всё, считаю это вполне достойным результатом)


  1. DmitryO
    26.11.2015 13:30
    +1

    В копилку «дурацких идей» — вполне очевидная секция «Latest Deals». Навеяно «Черной пятницей».
    Список TOP X товаров, цена на которые опусилась [в магазине N] ниже медианы на YY% за какой-то период.


  1. Styxx
    26.11.2015 13:33

    Хотелось бы копию проекта, натравить на магазины своего региона! А то перед покупкой много работы приходится делать в поисках…
    И то находишь цену, уточняешь, а она не актуальна или нет в наличии и т.д…


  1. tonick
    26.11.2015 14:11

    Как строится монетизация проекта?


    1. ssh1
      26.11.2015 15:09

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


  1. sonor
    26.11.2015 15:01
    +1

    Замечательная работа проделана. Спасибо.
    Может быть стоит добавить к графику кривую курса $, добавило бы наглядности скачков цен, а точнее их обоснованности курсом или подготовкой к «распродаже».


    1. ssh1
      26.11.2015 15:07

      Спасибо. Скорее всего действительно добавим.


  1. BupycNet
    26.11.2015 15:45
    -4

    А вы ведь данные собираете какими то ботами?
    Можете сделать канал у нас в сервисе PushAll, чтобы можно было подписываться на определенные товары? Ну т.е. например если цена на какой то товар упадет ниже определенной цены — уведомить меня об этом push-уведомлением.
    Даже можно сделать эту фичу платной, чем собственно окупить в итоге ваш проект.
    PS. у нас в сервисе будут платные каналы, можно на основе этой платформы сделать платный канал с оповещениями о изменении цен.
    Например я хочу купить Nexus 9 где нить в районе 20-21к, вроде цена много где падает, причем интересно. что цена уже сейчас ниже чем зарубежом в $, интересно упадет ли еще.


  1. 26.11.2015 15:49
    +4

    А как вы связывали товары между собой?
    В магазинах же может быть разное название у одного и того же товара.


    1. silenzushka
      26.11.2015 21:53

      Это делает API Яндекс.Маркета, на сколько я понял принцип сервиса.


      1. ssh1
        26.11.2015 22:01

        Связки достаточно сделать один раз.
        Тут работает свой алгоритм определения близости по цене и названию + парсинг агрегаторов. В общем есть куда развиваться.


        1. silenzushka
          26.11.2015 22:05
          +1

          Раз не из Маркета берёте, то за алгоритм (и его ручную доводка) отдельный респект. Огромная работа.


          1. ssh1
            26.11.2015 22:10

            Скажем так: часть там, часть там.
            Бывает такое в названиях накрутят)


  1. ragman
    27.11.2015 08:58

    Здравствуйте. Заинтересовался сервисом и решил проверить на личном опыте.
    На днях подбирал смартфон и, в частности, смотрел на модель Prestigio Muze C3. Один такой уже купил жене, теперь заказал дочке.
    Так вот, оба телефона приобрел в Юлмарте.
    Ваш сервис сообщает что на сегодня (27.11.15г.) его нет в наличии в данном магазине. Иду в магазин — есть. Возможно его нет в каком-либо другом городе. Но тогда нужно и это учитывать в Вашем сервисе. Либо Вы не смогли получить данные с сайта (вчера в 19:00, например, сайт Юлмарта лежал глухо).
    И да, они, видимо как и все другие, перед «черной пятницей» подняли на него цену, а затем сделали скидку. Скидка здесь без кавычек, так как скинули все-таки больше, чем добавили. «Но осадочек остался».
    Ваш сервис показывает что вчера (26.11.15) цена на него была 7490руб., но я его приобрел вчера же со скидкой за 5990руб.
    А вообще приятный сервис. Лишний раз убедился что честных скидок не бывает.


    1. ssh1
      27.11.2015 09:52

      Спасибо за комментарий. Данные на графиках выводятся после ресэмплинга, соответственно, если на графике точка в 18:00, это не значит, что именно в 18:00 была такая цена. Плюс к этому магазины скорее всего очень часто меняют цены в период чёрной пятницы.
      Спасибо за фидбэк, попробую изучить подробнее что происходило.


      1. ragman
        27.11.2015 09:59

        Возможно проблема в том, что нет цены на этот телефон в магазине Юлмарт на Яндекс.Маркете.


        1. ssh1
          27.11.2015 10:00

          Как вариант. Спасибо, посмотрю подробнее.


  1. pro100olga
    27.11.2015 09:52

    Впечатляет! Очень интересно, спасибо. Помимо курса доллара, о котором говорили выше, еще хотелось бы на графиках видеть собственно даты (месяцы), чтобы понять наличие сезонных колебаний цен (есть ли смысл покупать под Новый Год, например)


    1. ssh1
      29.11.2015 13:51

      Спасибо. Какие даты вы имеете в виду? Снизу вроде есть даты?


      1. pro100olga
        29.11.2015 14:49

        Да, вы правы. Это я сфокусировалась на графиках по холодильникам — там по оси Х только числа (номера наблюдений, видимо).
        Получается, вы где-то с весны начали собирать данные (смотрю опять же холодильники на сайте), то есть про Новый год можно будет в следующем году сказать. И кстати про 8 марта тоже будет интересно, по каким категориям цены меняются, если меняются вообще.
        Интересно, что максимальная цена меняется чаще и больше, чем минимальная — почему так может быть? Возможно, минимальная установлена на уровне близком к нулевой рентабельности?


        1. ssh1
          29.11.2015 15:26

          Да, все праздники в следующем году можно будет отследить в реальном времени.
          Мне кажется, максимальная цена меняется чаще, так как в районе максимальной цены плотность магазинов намного меньше чем в районе минимальной. Соответственно пропадание товара в магазине с максимальной ценой ведёт к более резкому скачку.


  1. pro100olga
    27.11.2015 13:38

    А еще вопрос: сколько человекочасов заняла организация парсинга (написание, отладка)? А сколько написание этого материала, включая анализ? Мне кажется, это огромная работа, хочется оценить ее как-то количественно )


    1. ssh1
      29.11.2015 13:58
      +2

      Проект делался в свободное время, в качестве хобби.
      Если пересчитать:
      Парсинг + отладка + игра «успей за изменениями на источнике» — 5 недель
      Веб морда — 3 недели
      Анализ — 5 часов
      Статья — 1 час

      Могу ошибаться в 2-3 раза в любую сторону)


  1. negodnik
    27.11.2015 23:17

    Сколько магазинов подключено вручную? Ведь довольно много магазинов, которых нет на маркете.


  1. DjOnline
    30.11.2015 21:22

    Есть ли API или выгрузка для интернет-магазинов?
    Учитываются ли разные цены на разные цвета в одной карточке товара?
    Сюда ещё бы интеграцию с я.маркетом, чтобы помечалось «эта позиция в этом магазине рекламируется в я.маркете». Ведь не все магазины там размещаются, поэтому не всегда там лучшие цены.
    Максимальная цена возможно считается неправильно в этом товаре http://priceanalytic.com/item/3612/, цифра 88800 пишется, но магазинов с такой ценой нет.
    Ну и актуальный фичареквест — переключатель рубли/USD/Euro для исторических данных.
    Также хотелось бы обновления таблицы магазинов при нажатии на дату на графики, например непонятно кто это устроил аттракцион невиданной щедрости 3го августа здесь http://priceanalytic.com/item/40352/


  1. ssh1
    30.11.2015 22:29

    API и интеграции пока нет.
    По ошибкам и предложениям спасибо, подумаю.


  1. ssh1
    01.12.2015 17:43

    Всем спасибо за обратную связь.
    Добавлены уведомления при снижении цены ниже определенного порога.


  1. melon
    02.12.2015 15:36
    +2

    Круто! Народ, зацените график для цен на айфоны priceanalytic.com/item/73558. Видны два отчётливых пика перед 4 и 11 ноября, которые были днями распродажи) Очередное доказательство, что чёрная пятница в РФ не более чем утка!