feat(generator): день-функция — трафик, визиты и просмотры страниц
Зачем: план состава отдаёт дневную аудиторию, но событий у мира ещё не было. День-функция превращает аудиторию в поток просмотров — на нём стоят лабы про сборку визитов и про витрины, а следующий этап вешает на него торговые события. Что: - `day.py` — день как чистая функция зерна и номера дня: суточная волна в местном времени посетителя, визиты по документированным правилам нарезки, все 47 колонок выгрузки; шов для торговых событий — ряды `page` и `product`; - `reference.py` — справочники-литералы: профили устройств, города Поволжья с настоящими гео-id Яндекса, источники трафика, карта сайта; - `catalog.py` и `data/catalog/products.csv` — каталог на 180 позиций, общий у генератора и будущего словаря ClickHouse; - `weights.py` — выбор по целым весам, один на план и на день; - паспорт куки (устройство и город) переехал в план состава; броски приписаны последними, поэтому измеренные числа канонического мира не сдвинулись; - словарь: «визит» закреплён за сессией, одноимённое понятие плана стало «днём активности»; статьи в `CONTEXT.md`; - решения по ходу — в спеку генератора, раздел 9; наполнение `ParsedParamsKey1` отложено тикетом #47. Проверка: `make lint`, `make typecheck`, `make test` — 353 passed (было 297). Счётчики плана после правки те же: приток 3827,64/день, дневная аудитория 6235–7124, 68 119 посетителей за 14 дней, 170 двухкуковых пар. День 0 — 45 810 событий за 0,6 с, снимок 14 дней — 5,9 с при пороге 30 с на день. Две слепые линии ревью, десять находок, все закрыты и перепроверены. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,16 @@
|
||||
|
||||
from datetime import date
|
||||
|
||||
# Счётчик стенда: сайт один, номер — константа мира.
|
||||
COUNTER_ID = 42150607
|
||||
|
||||
# Часовой пояс счётчика, минуты от UTC: Самара, UTC+4. Модельные сутки
|
||||
# считаются в этом поясе, как в выгрузке Метрики: `EventDate` — дата в поясе
|
||||
# счётчика, `UTCEventTime` — абсолютная метка. Отсюда следствие, о котором
|
||||
# сторона хранилища должна знать заранее: `toDate(UTCEventTime)` ≠ `EventDate`
|
||||
# у ночных событий (спека генератора, раздел 9).
|
||||
COUNTER_TIMEZONE_MINUTES = 240
|
||||
|
||||
# D0 — первый день оси модельного времени, понедельник. Реальный календарь в
|
||||
# модели не участвует: дата нужна лишь затем, чтобы дни оси легли в
|
||||
# `EventDate`/`UTCEventTime` конкретными числами. От даты запуска мир не
|
||||
@@ -25,9 +35,11 @@ ORIGIN = date(2026, 6, 1)
|
||||
DAILY_INFLUX = 3_800
|
||||
|
||||
# Недельная волна мира, проценты от среднего: понедельник … воскресенье.
|
||||
# Профиль один на весь мир: по нему идёт приток, по нему же пойдёт трафик
|
||||
# дня-функции — иначе доля новичков скакала бы по дням недели. В сумме ровно
|
||||
# 700: за неделю средний день остаётся средним.
|
||||
# Волна задана притоку — по ней в мир приходят новые люди. Трафик наследует
|
||||
# её через дневную аудиторию, а не вторым умножением (довод — у суточной
|
||||
# волны выходного дня), поэтому доля новичков по дням недели ровная, а
|
||||
# недельный размах трафика выходит мягче притока: ±7% против ±10%. В сумме
|
||||
# ровно 700: за неделю средний день остаётся средним.
|
||||
WEEKLY_PROFILE_PERCENT = (105, 108, 107, 105, 95, 88, 92)
|
||||
|
||||
# Разброс притока изо дня в день, проценты: ровный приток выдал бы себя в
|
||||
@@ -43,13 +55,13 @@ ONE_SHOT_PERCENT = 75
|
||||
# притоке 3 800 (спека, разделы 5 и 9).
|
||||
RETURN_COUNT_WEIGHTS = (25, 20, 15, 12, 9, 7, 5, 4, 2, 1)
|
||||
|
||||
# Хвост возвратов: окно активности человека от его первого визита, общее на
|
||||
# Хвост возвратов: окно активности человека от его первого дня, общее на
|
||||
# обе его куки. За краем окна кука не возвращается. Оно же — глубина
|
||||
# предыстории: столько когорт живёт до D0, чтобы дневная аудитория была на
|
||||
# полке с самого первого дня.
|
||||
RETURN_TAIL_DAYS = 90
|
||||
|
||||
# Профиль возвратов по дням от первого визита: почти всё в первую неделю,
|
||||
# Профиль возвратов по дням от первого дня куки: почти всё в первую неделю,
|
||||
# дальше тонкий хвост до края окна — повторные покупки в магазине случаются
|
||||
# и через месяцы. Профиль затухает к краю, поэтому обрыв на нём в данных не
|
||||
# виден. Читается по парам «сколько дней — с каким весом»; дней в сумме
|
||||
@@ -69,3 +81,56 @@ BUYER_PERCENT = 5
|
||||
# Такой паре план назначает по гарантированному заказу с каждой куки — на
|
||||
# этом стоит лаба про склейку личности.
|
||||
PAIRED_BUYER_PERCENT = 15
|
||||
|
||||
# --- Числа дня: суточная волна, визиты, воронка ---------------------------
|
||||
|
||||
# Суточная волна буднего дня: проценты от среднего часа, от 00 до 23 часов
|
||||
# местного времени посетителя. Ночной провал, обеденный и вечерний пики до
|
||||
# ~2× среднего (спека генератора, раздел 2). В сумме ровно 2400: средний час
|
||||
# остаётся средним, и суточный объём от формы волны не зависит.
|
||||
WEEKDAY_HOURS_PERCENT = (
|
||||
35, 20, 12, 8, 8, 12, 25, 45, 70, 105, 115, 130,
|
||||
170, 165, 140, 130, 130, 140, 160, 185, 210, 180, 130, 75,
|
||||
) # fmt: skip
|
||||
|
||||
# Выходной день: подъём позже, обеденного пика нет — день ровнее, вечер
|
||||
# ниже буднего. Здесь только форма, поэтому сумма та же — 2400: объём
|
||||
# выходного день-функция не трогает, он приходит сам, потому что дневная
|
||||
# аудитория уже дышит недельной волной через приток. Умножить на неё
|
||||
# второй раз значило бы удвоить недельный размах.
|
||||
WEEKEND_HOURS_PERCENT = (
|
||||
45, 30, 20, 12, 10, 10, 14, 22, 40, 70, 105, 140,
|
||||
165, 160, 175, 175, 170, 165, 165, 175, 180, 165, 120, 67,
|
||||
) # fmt: skip
|
||||
|
||||
# Сколько визитов у куки в её день активности: веса для 1, 2 и 3 визитов.
|
||||
# В среднем ≈1,4 — при дневной аудитории 6–7 тыс. это 8–10 тыс. визитов
|
||||
# (спека, раздел 5).
|
||||
VISITS_PER_ACTIVE_DAY_WEIGHTS = (70, 22, 8)
|
||||
|
||||
# Длина визита в страницах: веса для 1, 2, 3 … страниц. Первая доля — отказы
|
||||
# (посмотрел одну страницу и ушёл), дальше затухающий хвост. В среднем ≈4,8
|
||||
# страницы: вместе с числом визитов это ~45 тыс. pageview в средний день,
|
||||
# и до ~50 тыс. добирают торговые события (#40).
|
||||
VISIT_PAGES_WEIGHTS = (250, 150, 120, 100, 88, 78, 68, 58, 50, 42, 35, 28, 22, 16)
|
||||
|
||||
# Таймаут визита: пауза дольше этой рвёт визит надвое. Правило резки, по
|
||||
# которому лаба сессий сверяет свою сборку с `VisitID` (мастер-спека,
|
||||
# раздел 1.2), поэтому паузы внутри визита всегда короче, а соседние визиты
|
||||
# одной куки всегда разведены дальше.
|
||||
VISIT_TIMEOUT_SECONDS = 1800
|
||||
|
||||
# Пауза между соседними страницами визита, секунды: обычная и «задумался».
|
||||
# Обе целиком внутри таймаута — иначе визит распался бы там, где генератор
|
||||
# этого не обещал.
|
||||
PAGE_PAUSE_SECONDS = (8, 300)
|
||||
LONG_PAUSE_SECONDS = (300, 1500)
|
||||
LONG_PAUSE_PERCENT = 12
|
||||
|
||||
# Воронка: доля визитов, дошедших до корзины, и доли следующих шагов от
|
||||
# предыдущего. Произведение — конверсия визита в оформленный заказ: 2%
|
||||
# (спека генератора, раздел 9). Гарантированные планом заказы двухкуковых
|
||||
# пар проходят воронку целиком независимо от этих долей.
|
||||
CART_PERCENT = 8
|
||||
CHECKOUT_OF_CART_PERCENT = 45
|
||||
CONFIRMATION_OF_CHECKOUT_PERCENT = 55
|
||||
|
||||
Reference in New Issue
Block a user