Разбор юнит экономики на реальных примерах. Часть первая.

Вводная часть

Начало 2020 года, вы - обычный продукт-мендежер, которому предложили развивать кредитный продукт в другой стране. Оффер принят, документы оформлены, пора за работу. Первое, что приходит в голову посмотреть, что там с экономикой продукта. И как вообще ведет себя продукт. Еще через пару дней совещание, на котором вас просят ответить на несколько вопросов:

1. Сейчас мы платим за привлечение клиента 695494. Какая стоимость привлечения для нас является приемлемой? Имеет ли смысл повысить стоимость привлечения на клиента, чтобы получить больший объем?
2. Насколько здоровой выглядит экономика портфеля и какая динамика здесь и сейчас?
3. Мы недавно изменили подход к размеру выдачи и стали в первые кредиты выдавать меньшие чеки. Как это сказалось на продукте?

В общем-то понятные вопросы, на которые стоит уметь отвечать любому владельцу продукта. Но есть проблема. Метрики, конечно, все посчитаны: LTV, СAC и прочее. Есть финансовая отчетность, где видны все расходы и доходы, и видно, что продукт в небольшом операционном плюсе. Но на вышеозначенные вопросы ответить сложно. Поиск ответов может занять кучу встреч и разговоров(которые еще и в меру субъективны), задач на аналитику(итерации чего занимают время) и попыток прокрутить дашборд(интерпретация которых может быть неверной).

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

Анализируй это

Пример взят из реальной практики. То есть вот прям все взаправду, данные подшумлены, но это реальный портфель. И анализируются данные примерно таким образом.

Для того, чтобы анализировать, понадобятся следующие инструменты: Rstudio, dbeaver(или аналог). Далее рассматривается реальный пример, как можгут выглядеть эти данные и что с ними можно сделать.

Итак, транзакции. Напишем в базу нечто вроде select * from transactions t и посмотрим результат. Также узнаем курс местной валюты к доллару(для примера возмьем, что курс без динамики и составляет 0.00003 доллара за местную валюту).

slice(lk, 1:20)

Видим всю историю транзакций по всем клиентами. Проанализируем состав полей(обычно можно посмотреть в документации, но кое-что понять можно и так). У нас есть идентификаторы заемщика, контракта, и тразнакции. Дата выдачи кредита (disbursment_date). Отметка о пролонгации кредита(prolongations_count) - перенос даты выплаты за отдельный платеж. Размер и дата транзакции. Отметка о “мягком” удалении. Главное - тип транзакции(ContractAdd- возврат денег заемщиком, DisburseTransaction - выплата денег заемщику).

Теперь поговорим об экономике продукта. Принципиально кредитиный бизнес работает просто(как и большинство бизнесов): заплатили, чтобы привести пользователя -> выдали кредит -> собрали деньги -> выдали еще кредит. Выручку по продукту формируют два финансовых потока: от нас к пользователю и от пользователя к нам. И в нашей табличке есть все данные, чтобы это посчитать.

Теперь посмотрим на структуру данных и займемся обработкой. Чуть обработаем их и приведем их в нужную форму. Назовем транзакции удобно и сделаем отрицательными транзакции выдачи кредитов(поля z_type и am):

lk %>% data.table()->lk1
lk1 %>% glimpse()
## Rows: 2,226,532
## Columns: 11
## $ X1                  <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
## $ borrower_id         <dbl> 2, 2, 2, 6, 6, 12, 12, 12, 12, 16, 20, 20, 20, 20…
## $ con_id              <dbl> 1, 1, 1, 2, 2, 4, 4, 4, 4, 5, 7, 7, 7, 7, 8, 9, 9…
## $ disbursement_date   <date> 2017-11-23, 2017-11-23, 2017-11-23, 2017-11-24, …
## $ prolongations_count <dbl> 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 3, 3, 3, 3, 0, 0, 0…
## $ loan_type           <chr> "pdl", "pdl", "pdl", "pdl", "pdl", "pdl", "pdl", …
## $ date                <date> 2017-12-15, 2017-11-23, 2017-12-06, 2017-11-24, …
## $ type                <chr> "Payments::Transaction::ContractAddTransaction", …
## $ amount              <dbl> 250000, 1000000, 1200000, 2500000, 3500000, 10400…
## $ id                  <dbl> 325, 2, 127, 5, 587, 557500, 557499, 557504, 5575…
## $ deleted_at          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
lk1[,':='(z_type=z_type<-fifelse(type=='Payments::Transaction::ContractAddTransaction','add','disb'),am=amount*fifelse(z_type=='add',1,-1))][1:20,c(-1,-11,-8,-6)]
lk1[disbursement_date<'2020-01-01' & date<='2020-03-01',c(-1,-11,-8,-6)]->lk1

Давайте посмотрим на главное и посчитаем, прибыльный ли портфель. Для этого посмотрим тразнакции за все время. И так как цифры крупные, посмотрим сразу в миллионах:

lk1[,.(total_in_blns=sum(am*for_ex)/1e6),.(z_type)]

Видим ясный и понятный результат: транзакции от заемщиков(add) значительно превышают транзакции от выдачи кредита(disb). А ведь часть кредитов наверняка только выдана и по ним даже не подошла дата выплаты.

И здесь же разберемся с темпом, с которым выдавали кредиты:

lk1[!is.na(disbursement_date)&z_type=='disb',.(sum=sum(am*for_ex*-1,na.rm = T)/1e6),.(date=floor_date(disbursement_date,'month',))][,
ggplot(.SD,aes(date,sum,label=round(sum,2)))+
geom_col(fill=polar_night[2])+ff+tt+
  geom_text(aes(y=sum+0.1),col=aurora[1])+
  labs(x='месяц выдачи',y='выдача в миллионах долларов',title='Выдача кредитов в месяц')
  

]

Аналитически видно, что масштабирование продукта в последние несколько месяцев остановилось. Выдаем столько же сколько и выдавали.

Вернемся к Юнит экономике

Глобально мы занимаемся масштабированием пользователей, ведь кредит без человека выдать сложно. А юнит экономика в таком - это сколько мы зарабатываем или теряем на одном пользоватале, заплатив за его привлечение.

Давайте посчитаем доходную часть. Чтобы это сделать, нужно для среднего пользовталеля взять кумулятивный баланс его доходов и расходов(сумму транзакций выдач и возвратов кредитов) и наложить на время его жизни. Удобнее работать с относительным временем, так сможем сравнивать пользователей, пришедших в разное время:

lk1[][,':='( min_date=min(disbursement_date)),.(borrower_id)][,c("gen",'dif'):=.(floor_date(min_date,'1 month'),as.numeric(date-min_date))][,n:=uniqueN(borrower_id),][,
  .(sum=sum(am*for_ex),n=unique(n)),
  .(dif)
][order(dif)][,":="(bal=bal<-sum/n,cum=cumsum(bal))][,
                           ggplot(.SD,aes(dif,cum))+
                             geom_line()+
                             tt+ff+
                                  labs(x='дни жизни заемщика',y='доход в USD',col='поколение',title='LTV клиента по поколениям и по годам')+
                             scale_y_continuous(breaks = seq(-200,200,20),labels =paste0('$',seq(-200,200,20),'k' ))+
                             scale_x_continuous(breaks = seq(0,1000,20))
                           
                           ]

Получившаяся кривая показывает его LTV c динамикой по времени. И это уже близко к ответу на первый вопрос о стоимости привлечения пользователя.

Но перед тем как пустится в эти рассуждения, стоит вспомнить, кто такой, этот средний пользователь. Мало ли, может, лучшие времена продукта давно позади. Поэтому стоит посмотреть этот же график, но разбив по поколениям и посмотрев последние 24 поколения. Сразу же наложим сюда стоимость привлечения и разобьем по годам(чисто для удобства сравнения):

lk1[][,':='( min_date=min(disbursement_date)),.(borrower_id)][,c("gen",'dif'):=.(floor_date(min_date,'1 month'),as.numeric(date-min_date))][,n:=uniqueN(borrower_id),.(gen)][,
  .(sum=sum(am*0.00003),n=unique(n)),
  .(gen,dif)
][order(gen,dif)][,":="(bal=bal<-sum/n)][,':='(cum=cumsum(bal),m_dif=max(dif)),.(gen)][dif<=m_dif-30 & gen %between% c('2018-01-01','2021-03-31')][,
                           ggplot(.SD,aes(dif,cum,col=factor(gen)))+
                             geom_line()+
                             facet_wrap(~factor(year(gen),levels = c(2019,2018)),nrow=2)+tt+ff+
                             labs(x='дни жизни заемщика',y='доход в USD',col='поколение',title = 'LTV клиента по поколениям и по годам')+
                             scale_y_continuous(breaks = seq(-200,200,20),labels =paste0('$',seq(-200,200,20),'k' ))+
                             scale_x_continuous(breaks = seq(0,1000,20))+
                             geom_hline(yintercept = 695494*for_ex,color='red',size=1)+
                             geom_hline(yintercept = 0,color='dark red',linetype='dashed')+
                             geom_text(inherit.aes = F,aes(x=as.Date(600),y=695494*for_ex+3,group=1),label='Стоимость привлечения клиента = $20.86',col='red',size=6)+tt+ff+
                             theme(legend.text = element_text(size=20),
                                   legend.title = element_text(size=25))+
                              guides(colour = guide_legend(override.aes = list(size=10)))
                             # geom_vline(xintercept = c(140,180),col='red')
                      
                           
                           ]

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

Если каждая траектория - это поколение пользователей (месяц в котором выдан первый кредит), то мы можем сделать несколько важных выводов исходя из следующего:

  1. Точка, из которой начинаются линии - размер первого кредита.
  2. Чем выше траектория, тем больше денег на одного пользователя мы заработали в этом поколении.
  3. Чем раньше траектория поколения пересекает 0, тем быстрее мы начинаем зарабатывать на привлеченном пользователе.
  4. Чем раньше линия пересекает линию стоимости привлечения, тем раньше мы зарабатываем достаточно, чтобы окупать его в данном поколении.

Выводы

  1. Продукт становится лучше. Траектории более поздних поколений пересекают ноль и стоимость привлечения раньше, чем траектории старых поколений (150 дней против 180).
  2. Разница в темпах окупаемости объясняется скорее стартовой точкой и первой парой кредитов. Например, поколения конца 2018 года окупались лучше, имея меньшую сумму первого кредита и большую сумму второго. Это можно понять по “провалу” на траектории на 10-40 днях. Так же в 2019 году: поколения с меньшей средней суммой первого кредита окупали себя намного быстрее.
  3. На дистанции в один год мы заработаем на одном пользователе от 40 до 60 долларов. Максимальный размер заработка неизвестен. Ни одно поколение пока не вышло на плато, но экстраполируя, оценка в 120-150 долларов на дистанции в 3 года выглядит разумной
  4. Наиболее существенное влияние на траекторию оказывают события первых 90 дней, после этого темп роста плюс минус одинаковый.

Мы тут ради ответов, а не картинки смотреть

Воспользуемся полученными знаниями и поррасуждаем об ответах на вопросы к предстоящему совещанию

1. Сейчас мы платим 695494. Какая стоимость привлечения для нас является приемлемой? Имеет ли смысл повысить стоимость привлечения на клиента, чтобы получить больший объем?

Ситуация выглядит следующим образом - у нас есть успешный продукт, который мы не масштабируем - и это проблема. Ожидания по доходности от клиента на дистанции год - 40-60 долларов. Текущие затраты на привлечение $20.8 (695494* 0.00003) В приницпе - увеличение стоимости привлечения наша экономика выдержит, портфель не станет убыточным. Но в продукте - длинный срок окупаемости клиента. Если мы можем позволить себе тратить сейчас - что бы заработать потом - эксперименты оправданы.

2. Насколько здоровой выглядит экономика портфеля и какая динамика здесь и сейчас?

Портфель устойчиво положительный, с динамикой к росту за счет практик развития клиентов в первые дни жизни. Главное пространство для идей - механика работы с клиентами возраста 100+ дней. Там существенных прорывов пока не было.

3. Мы недавно изменили подход к размеру выдачи и стали в первые кредиты выдавать меньшие чеки. Как это сказалось на продукте?

Вообще - видно что поколения в которых первый кредит был меньшим по размерам окупали себя чуть лучше. Четкий ответ - только через АБ тест.

Итог и всякое такое

Помните про скорость принятия решений? 2.2 млн строк рассказали о том, что происходит. Такой анализ занимает от 30 минут до пары часов. В зависимости от знания предметной области и грязи в данных. Для такого анализа не нужно ничего, кроме сырых данных и открытого ПО. Несколько десятков строк кода, чуть здравых размышлений и экономика продукта ясна, посчитана и выводы сделаны.

Из этих же данных несложно собирается еще несколько важных оценок и выводов , но о них в другой раз.

To be continued


Отдельное спасибо Наталье Ионовой. Идея, структура, редактура.