Rのローンポートフォリオの構造の評価

議論の中で、「小さな」タスクが発生しました。それは、ローンポートフォリオの構造のダイナミクス(たとえば、クレジットカードのダイナミクス)を構築することです。重要な特異性があります-ローンを返済するためにFIFO法を適用する必要があります。それら。返済するときは、最も早いローンを最初に返済する必要があります。これは、個々のローンのステータスを計算し、その満期日を決定する際に特定の要件を課します。







それをオリンピックの問題と考えてください。血まみれのエネルギー賞」やコードペダリングはなく、アプローチはもっぱら「最初に考える」ことです。プロトタイプごとに1画面のコードのみで、ループはありません(パフォーマンスと読みやすさのために埋め込まれています)。以下は、プロトタイプアプローチを使用したRコードです。







これは、以前の一連の出版物の続きです







分解



すべてをゼロから行うため、タスクを3つのステップに分割します。







  1. テストデータの形成。
  2. 各ローンの満期日の計算。
  3. 特定の時間枠のダイナミクスの計算と視覚化。


プロトタイプの前提条件と規定:







  1. 最新の粒度。1つの日付に1つのトランザクションのみ。1日に複数のトランザクションがある場合は、それらの順序を確立する必要があります(FIFOの原則に準拠するため)。addを使用できます。インデックス、unixtimestampを使用でき、他の何かを思い付くことができます。これはプロトタイプには関係ありません。
  2. 明示的なループがあってfor



    はなりません。不要なコピーがあってはなりません。最小のメモリ消費と最大のパフォーマンスに焦点を合わせます。
  3. 次の遅延グループを検討します:「<0」、「0-30」、「31-60」、「61-90」、「90+」。


ステップ1.データセットを生成する



単なるテストデータセットであり、すべての一致はランダムです。ユーザーごとに、最大10個のレコードを生成します。計算では、ローンは正の値であり、返済は負の値であると想定しています。そして、各ユーザーのライフサイクル全体はローンから始める必要があります。







データセットの生成
library(tidyverse)
library(lubridate)
library(magrittr)
library(tictoc)
library(data.table)

total_users <- 100

events_dt <- tibble(
  date = sample(
    seq.Date(as.Date("2021-01-01"), as.Date("2021-04-30"), by = "1 day"),
    total_users * 10,
    replace = TRUE)
  ) %>%
  #    50 .
  mutate(amount = (runif(n(), -2000, 1000)) %/% 50 * 50) %>%
  #   
  mutate(user_id = sample(!!total_users, n(), replace = TRUE)) %>%
  setDT(key = "date") %>%
  #     
  .[.[, .I[1L], by = user_id]$V1, amount := abs(amount)] %>%
  #        , 
  #          
  #       
  unique(by = c("user_id", "date"))
      
      





ステップ2.各ローンの満期日を計算します



data.table



関数内でも参照によりオブジェクトを変更できるので、積極的に活用していきます。







満期日の計算
#  
accu_dt <- events_dt[amount < 0, .(accu = cumsum(amount), date), by = user_id]

ff <- function(dt){
  #           
  #   
  accu_dt[dt, amount := i.amount, on = "user_id"]
  accu_dt[is.na(amount) == FALSE, accu := accu + amount][accu > 0, accu := NA, by = user_id]
  calc_dt <- accu_dt[!is.na(accu), head(date, 1), by = user_id]

  #     data.frame,   
  calc_dt[dt, on = "user_id"]$V1
}

repay_dt <- events_dt[amount > 0] %>%
  .[, repayment_date := ff(.SD), by = date] %>%
  .[order(user_id, date)]
      
      





ステップ3.期間中の構造のダイナミクスの計算



ダイナミクス計算
calcDebt <- function(report_date){
  as_tibble(repay_dt) %>%
    #  ,      
    filter(is.na(repayment_date) | repayment_date > !! report_date) %>%
    mutate(delay = as.numeric(!!report_date - date)) %>%
    #  
    mutate(tag = santoku::chop(delay, breaks = c(0, 31, 61, 90),
                               labels = c("< 0", "0-30", "31-60", "61-90", "90+"),
                               extend = TRUE, drop = FALSE)) %>%
    #  
    group_by(tag) %>%
    summarise(amount = sum(amount)) %>%
    mutate_at("tag", as.character)
}

#   
df <- seq.Date(as.Date("2021-04-01"), as.Date("2021-04-30"), by = "1 day") %>%
  tibble(date = ., tbl = purrr::map(., calcDebt)) %>%
  unnest(tbl)

#  
ggplot(df, aes(date, amount, colour = tag)) +
  geom_point(alpha = 0.5, size = 3) +
  geom_line() +
  ggthemes::scale_colour_tableau("Tableau 10") +
  theme_minimal()
      
      





このようなものを手に入れることができます。







必要に応じて、1画面のコード。







前の投稿- 「BI対読み聞かせR報告書、実用的なアプローチ








All Articles