What is Mintos?

Mintos.com is a P2P lending platform. One can invest in loans offered by various loan organizers from various countries. Most loans are short-term and personal loans from FSU countries such as Georgia, Armenia, Russia, but also Spain or Indonesia etc. Many loans are very short term (1 month) but there’s also some with longer terms (several years). The majority of loans are denominated in Euro but the share of loans in other currencies is increasing. Typical interest rates for Euro-loans is 11 to 13%.

More than 13 million loans were issued on Mintos as of mid 2019. The loan amount offered is over 3 billion EUR (Euro loans only).

Mintos grants access to the full loan book of all loans issued since inception. For this head to Statistics and look for the link Download Loan Book (might require having an account and being logged in). One gets a ZIP with (as of today) 27 individual Excel sheets. Unzipped it’s abozut 1 Gb.

Let’s have a look.

Sidenote on data analytics

While Mintos hands out the data in several Excel sheets, Excel is not recommended for analysis. The maximum number of rows in Microsoft Excel is 1 048 576.

For using it in R, I recommend first converting and saving the sheets to csv’s. These csv’s can be loaded and row-bind. I use tidyR tibbles and dplyr but for performance reasons one could prefer to use data.table.

library(tidyverse)
library(readxl)

# converting xlsx to csv
files <- list.files("data/xlsx")

for (i in 1:length(files)) {
  print(i)
  data <- read_excel(paste0("data/", files[i]))
  data %>% write_csv(paste0("data/", str_replace(files[i], ".xlsx", ".csv")))
  print("done")
}
rm(data)

# read and bind together
csvfiles <- list.files("data/csv")

data <- tibble()
for (i in 1:length(csvfiles)) {
  print(i)
  data <- bind_rows(data, read_csv(paste0("data/csv/", csvfiles[i])))
  print("done")
}

# check the size
object.size(data) %>% format(units = "auto")

# save for later use
data %>% saveRDS("data/data.RDS")

# save in two RDS (both <100Mb because of Github's restiction on file size)
nrows <- nrow(data)
half  <- round(nrows/2)

data[1:half,]         %>% saveRDS("data/data1.RDS")
data[(half+1):nrows,] %>% saveRDS("data/data2.RDS")

Yet better would be to use Apache Spark, e.g. with sparklyr. I tried it and it works fine, but at the end I chose to use my usual workflow with dplyr anyway (instead of dplyr commands with sparklyr).

library(sparklyr)

for (i in 1:length(csvfiles)) {
  print(i)
  sparklyr::spark_read_csv(sc, 
                           name = paste0("data", i),
                           path = paste0("data/csv/", csvfiles[i]))
  assign(paste0("sparkdata", i), tbl(sc, paste0("data", i)))
  print("done")
}

data <- sdf_bind_rows(sparkdata1, sparkdata2, sparkdata3, sparkdata4, sparkdata5, sparkdata6, sparkdata7, sparkdata8, sparkdata9, sparkdata10,
                      sparkdata11, sparkdata12, sparkdata13, sparkdata14, sparkdata15, sparkdata16, sparkdata17, sparkdata18, sparkdata19, sparkdata20,
                      sparkdata21, sparkdata22, sparkdata23, sparkdata24, sparkdata25, sparkdata26, sparkdata27)

object.size(data) # should be tiny

A medium spec workstation is recommended (used here 16 Gb RAM + 16 Gb Swap, i7-4790 CPU @ 3.60GHz × 4). My laptop was not suited for the job.

Stylized facts

First, let’s look at the available columns.

library(tidyverse)
library(lubridate)
library(magrittr)

data <- bind_rows(readRDS("data/data1.RDS"), readRDS("data/data2.RDS"))

data %>% glimpse()
## Observations: 13,314,969
## Variables: 19
## $ Id                      <chr> "8210540-02", "9657926-03", "13425646-01…
## $ `Issue Date`            <dttm> 2019-04-14, 2019-04-04, 2019-04-10, 201…
## $ `Closing Date`          <dttm> 2019-04-28, 2019-05-04, 2019-05-10, 201…
## $ `Listing Date`          <dttm> 2019-04-14 19:26:03, 2019-04-14 19:26:0…
## $ Country                 <chr> "Ukraine", "Russian Federation", "Russia…
## $ `Loan Originator`       <chr> "Dinero", "Dozarplati", "Dozarplati", "D…
## $ `Mintos Rating`         <chr> "C+", "B-", "B-", "B-", "B-", "B-", "B-"…
## $ `Loan Type`             <chr> "Short-Term Loan", "Short-Term Loan", "S…
## $ `Loan Rate Percent`     <dbl> 14.0, 17.5, 17.5, 17.5, 17.5, 17.5, 17.5…
## $ Term                    <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ Collateral              <chr> "No", "No", "No", "No", "No", "No", "No"…
## $ `Initial LTV`           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ LTV                     <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ `Loan Status`           <chr> "Finished prematurely", "Finished premat…
## $ `Buyback reason`        <chr> "Agreement prolongation", "Agreement pro…
## $ `Initial Loan Amount`   <dbl> 77.58, 8000.00, 4000.00, 10000.00, 1000.…
## $ `Remaining Loan Amount` <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Currency                <chr> "EUR", "RUB", "RUB", "RUB", "RUB", "RUB"…
## $ Buyback                 <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes"…

One loan at random:

set.seed(2)

data %>% 
  sample_n(1) %>% 
  glimpse()
## Observations: 1
## Variables: 19
## $ Id                      <chr> "2089899-06"
## $ `Issue Date`            <dttm> 2018-03-28
## $ `Closing Date`          <dttm> 2018-04-27
## $ `Listing Date`          <dttm> 2018-03-31 19:32:03
## $ Country                 <chr> "Latvia"
## $ `Loan Originator`       <chr> "Bino"
## $ `Mintos Rating`         <chr> "B-"
## $ `Loan Type`             <chr> "Short-Term Loan"
## $ `Loan Rate Percent`     <dbl> 13.1
## $ Term                    <dbl> 1
## $ Collateral              <chr> "No"
## $ `Initial LTV`           <dbl> 0
## $ LTV                     <dbl> 0
## $ `Loan Status`           <chr> "Finished prematurely"
## $ `Buyback reason`        <chr> "Agreement prolongation"
## $ `Initial Loan Amount`   <dbl> 420.86
## $ `Remaining Loan Amount` <dbl> 0
## $ Currency                <chr> "EUR"
## $ Buyback                 <chr> "Yes"

Due to the number of observations we resort to samples of 1 000 to 10 000 for some calculations.

Correlation matrix

# library(ggcorrplot)
library(GGally)

topcountries <- data %>%
  group_by(Country) %>%
  count() %>%
  ungroup() %>%
  arrange(-n) %>%
  top_n(3) %>%
  pull(Country)

toporigin <- data %>%
  group_by(`Loan Originator`) %>%
  count() %>%
  ungroup() %>%
  arrange(-n) %>%
  top_n(3) %>%
  pull(`Loan Originator`)

set.seed(15)

data %>% 
  select(Rate = `Loan Rate Percent`, Term, LTV0 = `Initial LTV`, Amount1000 =`Initial Loan Amount`, Currency, `Listing Date`, Buyback,
         Country, Origin = `Loan Originator`, Collateral) %>% 
  mutate(Currency = recode_factor(Currency, "EUR" = "EUR", .default = "Other"),
         Buyback = as.factor(Buyback),
         Collateral = as.factor(Collateral),
         Country = fct_other(Country, keep = topcountries, other_level = "Other"),
         Origin = fct_other(Origin, keep = toporigin, other_level = "Other"),
         ListingYear = year(`Listing Date`)) %>% 
  select(-`Listing Date`) %>% 
  select(-Country, -Origin) %>% 
  sample_n(10000) %>% 
  filter(!is.na(ListingYear)) -> quants_fct

mintoscolor <- "#78c8c7"

quants_fct %>% 
  # drop_na() %>% 
  mutate(ListYr = as.factor(ListingYear),
         Amount1000 = Amount1000/1000) %>%
  select(-ListingYear) %>% 
  ggpairs(
    lower = list(
      continuous = wrap("smooth_loess", alpha = 0.5, color = mintoscolor),
      combo = wrap("box_no_facet", alpha = 0.5, fill = mintoscolor), #"facetdensity",
      discrete = wrap("ratio", alpha = 0.5, fill = mintoscolor)
      # mapping = aes(color = ListYr)
      ),
    upper = list(
      combo = wrap("facetdensity", color = mintoscolor),
      discrete = wrap("ratio", alpha = 0.5, fill = mintoscolor)
    ),
    diag = list(
      continuous = wrap("densityDiag", alpha = 0.5),
      discrete = "barDiag",
      mapping = aes(color = ListYr)
    ),
  switch = "y",
  title = "Correlation of Mintos.com loan characteristics") -> cp

cp

Loan interest rates

What we see is that rates have droped since 2015 but most recently in 2019 have risen again. This might be partially caused by a higher share of non-EUR loans which generally offer higher interest rates.

# library(ggbeeswarm)

set.seed(12)

data %>% 
  filter(Currency == "EUR", !is.na(`Listing Date`)) %>% 
  mutate(ListYr = factor(year(`Listing Date`))) -> d

d %>% sample_n(30000) %>% 
  ggplot(aes(x = ListYr, y = `Loan Rate Percent`)) +
  geom_boxplot() +
  # geom_beeswarm(data = (d %>% sample_n(1000)), alpha = 0.1, color = mintoscolor)
  geom_jitter(data = (d %>% sample_n(1000)), alpha = 0.2, color = mintoscolor) +
  scale_y_continuous(breaks = seq(0,25,1)) +
  labs(title = "Distribution of interest rate of newly listed loans") +
  theme_bw()

Let’s compare the interest rates over originator, country, and currency.

topn <- 5

topcurrencies <- data %>%
  group_by(Currency) %>%
  count() %>%
  ungroup() %>%
  arrange(-n) %>%
  top_n(topn) %>%
  pull(Currency)

topcountries <- data %>%
  group_by(Country) %>%
  count() %>%
  ungroup() %>%
  arrange(-n) %>%
  top_n(topn) %>%
  pull(Country)

toporigin <- data %>%
  group_by(`Loan Originator`) %>%
  count() %>%
  ungroup() %>%
  arrange(-n) %>%
  top_n(topn) %>%
  pull(`Loan Originator`)

data %>% 
   mutate(Currency = fct_other(Currency, keep = topcurrencies, other_level = "Other"),
         # Buyback = as.factor(Buyback),
         # Collateral = as.factor(Collateral),
         Country = fct_other(Country, keep = topcountries, other_level = "Other"),
         Origin = fct_other(`Loan Originator`, keep = toporigin, other_level = "Other"),
         ListingYear = year(`Listing Date`)) %>% 
    select(Rate = `Loan Rate Percent`, Country, Origin, Currency) %>% 
  sample_n(3000) %>% 
  drop_na() %>% 
    ggpairs(
    lower = list(
      continuous = wrap("smooth_loess", alpha = 0.5, color = mintoscolor),
      combo = wrap("box_no_facet", alpha = 0.5, fill = mintoscolor), #"facetdensity",
      discrete = wrap("ratio", alpha = 0.5, fill = mintoscolor)
      # mapping = aes(color = ListYr)
      ),
    upper = list(
      combo = wrap("facetdensity", color = mintoscolor),
      discrete = wrap("ratio", alpha = 0.5, fill = mintoscolor)
    ),
    diag = list(
      continuous = wrap("densityDiag", alpha = 0.5),
      discrete = "barDiag"
    ),
  switch = "y",
  title = "Correlation of Mintos.com loan characteristics") -> cp

cp +
  theme_bw()

Default rates

Mintos’ default rating D

library(kableExtra)

data %>% 
  filter(`Closing Date` < (Sys.Date() - days(60))) %>% 
  mutate(Default = recode(`Mintos Rating`, "D" = "D", .default = "notD")) %>% 
  group_by(Default, ClYr = year(`Closing Date`)) %>% 
  count() %>% 
  spread(Default, n) %>% 
  ungroup() %>% 
  mutate(ClYr = as.character(ClYr)) %>%
  knitr::kable(format = "html", format.args = list(big.mark = "'")) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
ClYr D notD <NA>
2015 NA 10’589 NA
2016 NA 300’037 859
2017 380 1’176’765 24
2018 1’012 3’800’260 45
2019 NA 3’526’038 1
data %>% 
  filter(`Closing Date` < (Sys.Date() - days(60))) %>% 
  # mutate(Default = recode(`Mintos Rating`, "D" = "D", .default = "notD")) %>% 
  group_by(`Loan Status`, ClYr = year(`Closing Date`)) %>% 
  count() %>% 
  spread(`Loan Status`, n) %>% 
  ungroup() %>% 
  mutate(ClYr = as.character(ClYr)) %>% 
  knitr::kable(format = "html", format.args = list(big.mark = "'")) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
ClYr Current Default Finished as scheduled Finished - Bad Debt Finished prematurely Late 16-30 Late 31-60 Late 60+ <NA>
2015 NA NA 6’968 NA 3’621 NA NA NA NA
2016 NA 7 97’935 3 202’950 NA NA 1 NA
2017 1 22 139’526 15 1’037’320 NA NA 285 NA
2018 174 22 433’766 30 3’366’739 NA NA 581 5
2019 52 9 341’630 8 3’150’406 1 33’892 35 6

Euro loans

Let’s define default as loans that have not repaid at least 95% and are already past at least 60 days after their closing date.

data %>% 
  filter(Currency == "EUR",
         `Closing Date` < (Sys.Date() - days(60))) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(ClYr = year(`Closing Date`)) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  mutate(ClYr = as.character(ClYr)) %>%
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
ClYr Count CountLoss Amount AmountLost lostPerc lossPercCount
2015 10’589 2 2’588’797 692.30 0.03 0.02
2016 300’896 12 60’779’178 45’057.93 0.07 0.00
2017 1’086’214 296 198’827’294 237’980.96 0.12 0.03
2018 3’482’709 599 768’336’118 317’565.96 0.04 0.02
2019 3’321’869 26’311 679’377’978 3’894’735.41 0.57 0.79

By originator (2019):

data %>% 
  filter(Currency == "EUR",
         `Closing Date` < (Sys.Date() - days(60)),
         year(`Closing Date`) == 2019) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(`Loan Originator`) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  # mutate(ClYr = as.character(ClYr)) %>%
  
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
Loan Originator Count CountLoss Amount AmountLost lostPerc lossPercCount
Aasa 1’650 0 1’292’636.93 0.30 0.00 0.00
Aforti 115 0 2’132’483.51 130.03 0.01 0.00
Akulaku 72’812 53 4’738’875.70 3’637.95 0.08 0.07
Alfakredyt 4’542 20 2’598’914.57 14’043.87 0.54 0.44
Banknote 89’906 428 20’011’769.29 41’411.24 0.21 0.48
BB Finance Group 8’134 4 2’241’850.00 392.86 0.02 0.05
Bino 133’369 319 41’433’267.24 93’066.72 0.22 0.24
Capitalia 378 7 3’262’270.34 20’666.21 0.63 1.85
Capital Service 7’747 4 3’450’530.31 240.20 0.01 0.05
CashCredit 7’045 3 2’533’764.41 201.92 0.01 0.04
Cashwagon 165’398 3’338 15’819’175.90 303’436.42 1.92 2.02
Creamfinance 7’835 6 4’879’834.66 3’459.62 0.07 0.08
Credissimo 1’681 3 602’599.57 148.04 0.02 0.18
Creditstar 28’300 107 12’171’291.06 38’236.58 0.31 0.38
Credius 1’288 36 687’961.46 2’343.08 0.34 2.80
Debifo 316 6 2’219’242.00 10’613.18 0.48 1.90
Dindin 73 0 26’218.39 0.00 0.00 0.00
Dineo Credito 5’913 122 1’620’380.00 36’440.00 2.25 2.06
Dinero 405’664 2’430 52’225’033.01 362’876.16 0.69 0.60
Dozarplati 136’898 1’751 9’710’667.78 121’620.83 1.25 1.28
EBV Finance 25’018 0 30’985’218.45 0.00 0.00 0.00
EcoFinance 15’830 62 2’732’277.12 13’655.76 0.50 0.39
ExpressCredit 112 0 53’686.02 0.00 0.00 0.00
ExpressCredit Zambia 44’327 960 8’386’069.35 176’887.72 2.11 2.17
Extra Finance 4 0 71’238.91 0.02 0.00 0.00
Fireof 3 0 100’200.00 0.00 0.00 0.00
Getbucks 1’182 0 352’503.04 4.07 0.00 0.00
GetBucks 12’489 65 3’504’240.46 11’295.42 0.32 0.52
Hipocredit 27 0 321’483.57 0.00 0.00 0.00
ID Finance 76’792 967 30’581’409.20 242’181.27 0.79 1.26
ITF Group 7’810 45 1’818’455.20 7’322.22 0.40 0.58
IuteCredit 20’390 10 5’645’257.36 747.10 0.01 0.05
Kredit24 2’864 31 450’171.92 7’400.38 1.64 1.08
Kredito garantas 1 0 2’260.38 0.00 0.00 0.00
Kredit Pintar 12’431 1’029 780’792.30 57’065.39 7.31 8.28
Kredo 54’568 149 6’802’618.19 20’041.26 0.29 0.27
Kuki 113’187 1’836 49’198’282.86 821’745.25 1.67 1.62
Kviku 84’842 11 1’561’973.96 138.24 0.01 0.01
Leaselink 137 0 230’353.62 0.00 0.00 0.00
Lendo 250’963 235 42’113’626.90 34’503.31 0.08 0.09
LF TECH 6’936 0 853’001.40 0.00 0.00 0.00
Lime Zaim 55’125 2’042 6’334’809.48 106’073.85 1.67 3.70
Metrokredit 217’556 2’155 25’942’811.35 283’811.29 1.09 0.99
Mogo 15’522 19 27’126’223.54 16’735.71 0.06 0.12
Monego 18’125 122 2’415’047.23 18’853.85 0.78 0.67
Moneyman 1’900 286 444’411.70 63’226.81 14.23 15.05
Mozipo Group 5’628 0 2’614’658.14 0.06 0.00 0.00
Peachy 12’137 47 3’295’439.67 6’437.90 0.20 0.39
Placet 2’404 0 1’064’337.16 0.00 0.00 0.00
Rapicredit 29’640 982 1’988’400.00 66’175.88 3.33 3.31
Rapido Finance 19’506 213 9’561’971.63 102’959.75 1.08 1.09
Sebo 128’940 240 19’429’508.58 31’502.65 0.16 0.19
Simbo 68’636 9 40’494’950.06 5’180.22 0.01 0.01
Tengo 332’512 4’928 38’997’671.69 440’220.38 1.13 1.48
Tigo 32’436 104 4’494’373.66 12’308.61 0.27 0.32
Varks 570’299 1’124 123’484’185.92 295’080.11 0.24 0.20
VIZIA 1’480 3 620’589.00 175.99 0.03 0.20
Watu Credit 1’046 0 864’702.35 39.73 0.00 0.00

By country (2019):

data %>% 
  filter(Currency == "EUR",
         `Closing Date` < (Sys.Date() - days(60)),
         year(`Closing Date`) == 2019) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(Country) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  # mutate(ClYr = as.character(ClYr)) %>%
  
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
Country Count CountLoss Amount AmountLost lostPerc lossPercCount
Albania 67’362 152 10’763’618.04 20’352.39 0.19 0.23
Armenia 570’299 1’124 123’484’185.92 295’080.11 0.24 0.20
Botswana 7’363 48 1’502’845.05 7’706.55 0.51 0.65
Bulgaria 16’868 51 5’852’580.61 7’708.58 0.13 0.30
Colombia 29’640 982 1’988’400.00 66’175.88 3.33 3.31
Denmark 74’947 15 43’975’252.41 8’634.54 0.02 0.02
Estonia 1’941 9 6’813’949.87 12’194.65 0.18 0.46
Finland 10’173 5 5’185’580.73 2’230.58 0.04 0.05
Georgia 262’754 235 50’357’533.98 34’508.61 0.07 0.09
Indonesia 135’442 2’445 10’245’255.18 175’278.09 1.71 1.81
Kazakhstan 343’278 4’959 40’931’399.01 447’620.76 1.09 1.44
Kenya 2’628 14 1’328’825.08 3’354.99 0.25 0.53
Kosovo 19’629 128 2’677’680.73 19’253.85 0.72 0.65
Latvia 233’075 759 74’484’436.85 149’356.40 0.20 0.33
Lithuania 34’513 14 44’142’228.80 21’081.66 0.05 0.04
Mexico 1’900 286 444’411.70 63’226.81 14.23 15.05
Moldova 134’663 241 20’910’295.57 31’538.57 0.15 0.18
North Macedonia 32’845 104 4’553’558.14 12’308.66 0.27 0.32
Philippines 115’199 1’975 11’093’588.72 188’861.67 1.70 1.71
Poland 140’699 1’905 63’745’326.96 852’222.26 1.34 1.35
Romania 2’479 36 1’426’945.63 2’343.10 0.16 1.45
Russian Federation 510’251 6’021 46’282’539.69 525’299.97 1.13 1.18
South Africa 820 0 133’764.12 4.07 0.00 0.00
Spain 107’090 1’363 41’363’182.79 401’917.27 0.97 1.27
Sweden 2 0 4’688.99 0.00 0.00 0.00
Ukraine 405’664 2’430 52’225’033.01 362’876.16 0.69 0.60
United Kingdom 12’137 47 3’295’439.67 6’437.90 0.20 0.39
Zambia 48’208 963 10’165’430.26 177’161.33 1.74 2.00

Non-EUR loans

data %>% 
  filter(Currency != "EUR",
         `Closing Date` < (Sys.Date() - days(60))) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(ClYr = year(`Closing Date`)) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  mutate(ClYr = as.character(ClYr)) %>%
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
ClYr Count CountLoss Amount AmountLost lostPerc lossPercCount
2017 90’955 0 76’672’462 12.32 0.00 0.00
2018 318’608 1 2’265’239’076 722.37 0.00 0.00
2019 204’170 2’097 3’706’148’038 34’409’861.17 0.93 1.03

Seems like here we have slightly higher defaults in 2019. Let’s examine:

data %>% 
  filter(Currency != "EUR",
         `Closing Date` < (Sys.Date() - days(60)),
         year(`Closing Date`) == 2019) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(Currency) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  # mutate(ClYr = as.character(ClYr)) %>%
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
Currency Count CountLoss Amount AmountLost lostPerc lossPercCount
CZK 7’591 49 45’811’562.0 380’173.18 0.83 0.65
DKK 2’336 0 10’418’500.0 0.00 0.00 0.00
GBP 121 0 263’361.5 0.00 0.00 0.00
GEL 8’662 1 7’132’936.5 202.62 0.00 0.01
KZT 51’641 585 2’918’810’929.6 28’369’426.07 0.97 1.13
MXN 1’623 107 7’138’687.7 473’155.37 6.63 6.59
PLN 42’857 772 81’332’022.2 1’570’436.01 1.93 1.80
RUB 89’277 583 635’204’316.1 3’616’467.92 0.57 0.65
USD 62 0 35’722.5 0.00 0.00 0.00
data %>% 
  filter(Currency != "EUR",
         `Closing Date` < (Sys.Date() - days(60)),
         year(`Closing Date`) == 2019) %>% 
  # sample_n(1) %>% glimpse()
  mutate(Lost95 = (`Remaining Loan Amount`/`Initial Loan Amount`)>=0.05) %>% 
  group_by(`Loan Originator`, Currency) %>%
  summarise(Count = n(), CountLoss = sum(Lost95), 
            Amount = sum(`Initial Loan Amount`), 
            AmountLost = sum(`Remaining Loan Amount`)) %>% 
  mutate(lostPerc = (AmountLost/Amount)*100,
         lossPercCount = (CountLoss/Count)*100) %>% 
  ungroup() %>% 
  # mutate(ClYr = as.character(ClYr)) %>%
  knitr::kable(format = "html", format.args = list(big.mark = "'"), digits = 2) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>% 
  row_spec(0, bold = T)
Loan Originator Currency Count CountLoss Amount AmountLost lostPerc lossPercCount
1pm GBP 5 0 1.758450e+05 0.00 0.00 0.00
Aasa PLN 151 0 5.489000e+05 1.89 0.00 0.00
Aforti PLN 34 0 1.125233e+06 0.00 0.00 0.00
Alfakredyt PLN 2’396 13 4.632150e+06 26’500.00 0.57 0.54
BIG GEL 387 0 8.625554e+05 0.00 0.00 0.00
Capital Service PLN 1’395 11 2.269750e+06 6’033.35 0.27 0.79
Creamfinance CZK 5’161 18 2.782831e+07 178’404.43 0.64 0.35
Creamfinance GEL 648 1 8.012000e+05 197.58 0.02 0.15
Credilikeme MXN 313 1 1.396688e+06 6’192.71 0.44 0.32
Creditstar CZK 2’430 31 1.798325e+07 201’768.75 1.12 1.28
Creditstar PLN 3’080 26 5.318030e+06 46’189.64 0.87 0.84
Dozarplati RUB 46’881 492 2.504827e+08 2’365’967.92 0.94 1.05
EcoFinance RUB 20’309 91 2.451075e+08 1’250’500.00 0.51 0.45
Efaktor PLN 46 1 5.594339e+05 3’585.46 0.64 2.17
GetBucks USD 62 0 3.572250e+04 0.00 0.00 0.00
ID Finance GEL 1’991 0 3.391050e+06 0.00 0.00 0.00
ID Finance KZT 220 0 6.121542e+07 0.00 0.00 0.00
Kredit24 KZT 21’167 124 1.259374e+09 8’737’684.18 0.69 0.59
Kuki PLN 35’653 721 6.613712e+07 1’488’125.67 2.25 2.02
Kviku RUB 20’879 0 9.494811e+07 0.00 0.00 0.00
Leaselink PLN 67 0 4.747804e+05 0.00 0.00 0.00
Lendo GEL 5’507 0 1.759044e+06 5.04 0.00 0.00
LF TECH KZT 8’673 0 4.675385e+08 0.00 0.00 0.00
Metrokredit RUB 1’134 0 8.416375e+06 0.00 0.00 0.00
Mikro Kapital RUB 1 0 5.000000e+05 0.00 0.00 0.00
Mogo GBP 116 0 8.751649e+04 0.00 0.00 0.00
Mogo GEL 129 0 3.190874e+05 0.00 0.00 0.00
Mogo PLN 35 0 2.666257e+05 0.00 0.00 0.00
Moneyman MXN 1’310 106 5.742000e+06 466’962.66 8.13 8.09
PimPay RUB 73 0 3.574958e+07 0.00 0.00 0.00
Simbo DKK 2’336 0 1.041850e+07 0.00 0.00 0.00
Tengo KZT 21’581 461 1.130683e+09 19’631’741.89 1.74 2.14