Browse Source

Instruction and workflow added

main
Asitav Sen 4 years ago
parent
commit
950399bbef
  1. 6
      .Rproj.user/178A6739/sources/prop/48F98022
  2. 4
      .Rproj.user/178A6739/sources/prop/9D91FFC1
  3. 4
      .Rproj.user/178A6739/sources/prop/A1AE5A83
  4. 2
      .Rproj.user/178A6739/sources/prop/INDEX
  5. 26
      .Rproj.user/178A6739/sources/session-99529da2/58AD392C
  6. 114
      .Rproj.user/178A6739/sources/session-99529da2/58AD392C-contents
  7. 141
      .Rproj.user/178A6739/sources/session-99529da2/AB2E26D4-contents
  8. 10
      .Rproj.user/178A6739/sources/session-99529da2/FE6BB309
  9. 873
      .Rproj.user/178A6739/sources/session-99529da2/FE6BB309-contents
  10. 1
      .Rproj.user/shared/notebooks/paths
  11. 873
      app.R
  12. 1631
      data/collateral.csv
  13. 257
      data/countries.csv
  14. 27433
      data/transactions.csv
  15. 5001
      data/x.csv
  16. 114
      panel.R

6
.Rproj.user/178A6739/sources/prop/48F98022

@ -0,0 +1,6 @@
{
"source_window_id": "",
"Source": "Source",
"cursorPosition": "50,5",
"scrollLine": "25"
}

4
.Rproj.user/178A6739/sources/prop/9D91FFC1

@ -0,0 +1,4 @@
{
"source_window_id": "",
"Source": "Source"
}

4
.Rproj.user/178A6739/sources/prop/A1AE5A83

@ -1,6 +1,6 @@
{
"source_window_id": "",
"Source": "Source",
"cursorPosition": "29,10",
"scrollLine": "4"
"cursorPosition": "36,2",
"scrollLine": "0"
}

2
.Rproj.user/178A6739/sources/prop/INDEX

@ -1 +1,3 @@
~%2FProjects%2FLoanRisk%2Fapp.R="A1AE5A83"
~%2FProjects%2FLoanRisk%2Fmod_basic.R="9D91FFC1"
~%2FProjects%2FLoanRisk%2Fpanel.R="48F98022"

26
.Rproj.user/178A6739/sources/session-99529da2/58AD392C

@ -0,0 +1,26 @@
{
"id": "58AD392C",
"path": "~/Projects/LoanRisk/panel.R",
"project_path": "panel.R",
"type": "r_source",
"hash": "814836357",
"contents": "",
"dirty": false,
"created": 1686047069391.0,
"source_on_save": false,
"relative_order": 2,
"properties": {
"source_window_id": "",
"Source": "Source",
"cursorPosition": "50,5",
"scrollLine": "25"
},
"folds": "",
"lastKnownWriteTime": 1686047216,
"encoding": "UTF-8",
"collab_server": "",
"source_window": "",
"last_content_update": 1686047216552,
"read_only": false,
"read_only_alternatives": []
}

114
.Rproj.user/178A6739/sources/session-99529da2/58AD392C-contents

@ -0,0 +1,114 @@
countries <- read.csv("./data/countries.csv")
panel1<-
tabPanel(
"Home",
fluidRow(column(
width = 11,
fluidRow(
column(
width = 8,
tags$div(
tags$blockquote(
"LoanRisk is being built to provide convenience to Finance and Accounting consultants and SMEs in finance industry."
),
p(
"IFRS reporting, especially estimated loss calculation is a fairly complicated process involving Monte Carlo simulation, forecasting, survival modelling (or other predictive algorithm) and financial mathematics.
Naturally, it is time consuming and has its share of hassles. This app attempts to avoid all the hassles of setting up environment and tools to perform the multistep analysis.
This app will calculate the provisioning requirements in a few clicks and one can download the report with a single click!"
),
p("The basic steps are mentioned in the diagram on the left hand side. The app is not in its most evolved form yet.
There is a huge list of features and functions that I personally want to include and implement in future."),
h6("How to use?"),
p("Using the tool is very simple. You can upload two data sets. One that shows a certain number of transactions of each asset, along with some dates, parameters and event outcome.
And the other that contains value of collateral or estimated value of sales of the asset/hypothecated asset. Then proceed further with the clicks and in between select some parameters.
For e.g. the discount rate to be applied, the most probable, maximum possible and minimum possible depreciation of value of the collateral.
Once the simulation is done, you can download the report in pdf format.")#,
# "If you are a R coder, you are welcome to contribute and help improve. Please visit the ",
# tags$a(href = "https://github.com/asitav-sen/LoanRisk", "github page"),
# " or ",
# tags$a(href = "www.asitavsen.com", "contact me."),
# "Please use this ",
# tags$a(href = "https://github.com/asitav-sen/LoanRisk/issues", "link"),
# " to report issues and/or request new features/functions.", "For general discussions, please use this",tags$a(href = "https://github.com/asitav-sen/LoanRisk/discussions", "link"),
# tags$br(),
# tags$image(height=100, width=100,src="logo3.png")
)
),
column(
width = 4,
mermaid("
graph TB
A[Data Upload]-->B[Downloading macroeconomic data]
B[Downloading macroeconomic data from IMF]-->C[Forecasting macroeconomic parameters]
C[Forecasting macroeconomic parameters]-->D[Fit Survival Model]
D[Fit Survival Model]-->E[Monte Carlo Simulation]
E[Monte Carlo Simulation]-->F[Report]
")
)
),
))#,
# tags$hr(),
# fluidRow(
# column(
# width = 6,
# fluidRow(
# h3("Data"),
# br(),
# p("This section shows the data (uploaded or inbuilt sample).")
# ),
# br(),
# withSpinner(dataTableOutput("up_data"),type = 7,
# color = "black"),
# br(),
# actionButton("uploadnew", "Upload New Data", class="btn-light")
# ),
# column(width = 6,
# br(),
# basicstatUI("nofloans"))
#
# ),
# br(),
# br(),
# fluidRow(
# column(
# width = 6,
# h3("With Macroeconomic data"),
# p(
# "In this section, we add macroeconomic data. Please select the country of the asset and click on fetch button. If download fails, click again or try after sometime. Please note that GDP data has been discontinued by IMF recently. Hence, using Industrial output temporarily."
# ),
# column(
# width = 6,
# selectInput(
# "country",
# "Country",
# selected = "India",
# choices = countries$Country
# )
# ),
# column(
# width = 6,
# br(),
# actionButton("fetchimf", "Fetch IMF data", class = "glow")
# ),
# withSpinner(
# dataTableOutput("fulldata"),
# type = 7,
# color = "black"
# )
# ),
# column(width = 6,
# uiOutput("ac_button"),
# uiOutput("expcalcu"))
# ),
# br(),
# br(),
# fluidRow(column(width = 11,
# uiOutput("scenario_opts"))),
# br(),
# fluidRow(column(width = 11,
# uiOutput("credit_loss"))),
# fluidRow(column(width = 11,
# uiOutput("dlmanager")))
)

141
.Rproj.user/178A6739/sources/session-99529da2/AB2E26D4-contents

@ -0,0 +1,141 @@
# Module for a graph
# Module to show some stats
basicstatUI <- function(id) {
ns <- NS(id)
fluidRow(
h3("No of Assets"),
br(),
p(
"This section shows some basic information about the portfolio."
),
plotOutput(ns("statplot")),
verbatimTextOutput(ns("balancetext"))
)
}
basicstatServer <- function(id, dt) {
moduleServer(id,
function(input, output, session) {
df <- reactive({
dt %>%
ungroup() %>%
arrange(id, report_date) %>%
group_by(id) %>%
slice_max(report_date, n = 1) %>%
mutate(yr = lubridate::year(origination_date))
})
output$statplot <- renderPlot({
req(!is.null(df))
withProgress(message = "Plotting some graphs",
detail = "Won't take long",
value = 0,
{
setProgress(value = 1, message = "1 of 3..")
p1 <-
df() %>%
group_by(yr, loan_status) %>%
summarise(no_of_loans = n()) %>%
ungroup() %>%
ggplot(aes(
x = yr,
y = no_of_loans,
label = no_of_loans,
fill = factor(
loan_status,
levels = c("0", "1"),
labels = c("Good", "Bad")
)
)) +
geom_col(position = "dodge") +
geom_text(aes(y = no_of_loans + 20), position = position_dodge(width = 1)) +
labs(title = "No. of assets by year",
x = "Year",
y = "#") +
theme_bw() +
theme(legend.position = "none")
setProgress(value = 2, message = "2 of 3..")
p2 <-
df() %>%
group_by(asset_type, loan_status) %>%
summarise(no_of_loans = n()) %>%
ungroup() %>%
ggplot(aes(
x = asset_type,
y = no_of_loans,
label = no_of_loans,
fill = factor(
loan_status,
levels = c("0", "1"),
labels = c("Good", "Bad")
)
)) +
geom_col(position = "dodge") +
geom_text(aes(y = no_of_loans + 20), position = position_dodge(width = 1)) +
labs(title = "No. of assets by asset type",
x = "Asset Type",
y = "#") +
theme_bw() +
theme(legend.position = "none")
setProgress(value = 3, message = "3 of 3..")
p3 <-
df() %>%
group_by(customer_type, loan_status) %>%
summarise(no_of_loans = n()) %>%
ungroup() %>%
ggplot(
aes(
x = customer_type,
y = no_of_loans,
label = no_of_loans,
fill = factor(
loan_status,
levels = c("0", "1"),
labels = c("Good", "Bad")
)
)
) +
geom_col(position = "dodge") +
geom_text(aes(y = no_of_loans + 20), position = position_dodge(width = 1)) +
labs(title = "No. of assets by customer type",
x = "Customer Type",
y = "#") +
theme_bw() +
theme(legend.position = "bottom",
legend.title = element_blank())
setProgress(value = 4, message = "Patching..")
p4 <- p1 / (p2 | p3)
setProgress(value = 5, message = "Done..")
})
p4
})
output$balancetext <- renderText({
paste0(
"Total assets (no.): ",
length(unique(df()$id)) ,
"\n",
"Total balance outstanding: ",
round(sum(df()$balance) / 1000000, 2),
" M"
)
})
})
}

10
.Rproj.user/178A6739/sources/session-99529da2/FE6BB309

@ -3,7 +3,7 @@
"path": "~/Projects/LoanRisk/app.R",
"project_path": "app.R",
"type": "r_source",
"hash": "3883691992",
"hash": "0",
"contents": "",
"dirty": false,
"created": 1685718888828.0,
@ -12,15 +12,15 @@
"properties": {
"source_window_id": "",
"Source": "Source",
"cursorPosition": "29,10",
"scrollLine": "4"
"cursorPosition": "36,2",
"scrollLine": "0"
},
"folds": "",
"lastKnownWriteTime": 1686046542,
"lastKnownWriteTime": 1686047140,
"encoding": "UTF-8",
"collab_server": "",
"source_window": "",
"last_content_update": 1686046542053,
"last_content_update": 1686047140357,
"read_only": false,
"read_only_alternatives": []
}

873
.Rproj.user/178A6739/sources/session-99529da2/FE6BB309-contents

@ -17,30 +17,871 @@ library(triangle)
library(DiagrammeR)
library(stringr)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("LoanRisk"),
options(shiny.reactlog = TRUE, appDir = getwd())
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
source("panel.R")
# source("mod_basic.R")
# source("secretary.R")
# source("forplumber.R")
# source("modals.R")
),
# Adding initial data
# Show a plot of the generated distribution
mainPanel(
)
)
# Define UI for application
ui <- navbarPage(
theme = shinytheme("cosmo"),
title = "LoanRisk",
panel1
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# Data
# Some reactive values
collateral.dt<-reactiveVal()
transaction.dt<-reactiveVal()
# Adding initial data to reactive values
collateral.dt(read.csv("./data/collateral.csv") )
transaction.dt(read.csv("./data/transactions.csv") )
# Transforming Data
new.data <- reactive({
ndt<- transaction.dt()
withProgress(message = "Trying to read",
detail = "Hope the handwriting is legible!",
value = 0,
{
setProgress(value = 1, message = "Patience test 1 of 2")
ndt <-
ndt %>%
# Change format of some columns
mutate(
origination_date = ymd(origination_date),
maturity_date = ymd(maturity_date),
report_date = ymd(report_date)
) %>%
# Add age of loan, loan tenure in months, which are compulsory parameters
mutate(age_of_asset_months = round(as.numeric(
report_date - origination_date
) / 30)) %>%
mutate(loan_tenure_months = round(as.numeric(
maturity_date - origination_date
) / 30)) %>%
group_by(id) %>%
# Arranging to avoid mistakes in lag
arrange(report_date) %>%
# Add lag of bureau score and total number of defaults. Lag added for delta creation
mutate(
cum_default = cumsum(default_flag),
bureau_score_lag = ifelse(
is.na(lag(bureau_score_orig, 1)),
bureau_score_orig,
lag(bureau_score_orig, 1)
)
) %>%
# Adding delta of bureau score (ask me the reason if you do not know why)
mutate(bureau_score_delta = bureau_score_lag -
bureau_score_orig) %>%
# Adding quarter info for matching later with macroeconomic data
mutate(qtr = paste0(year(report_date), "-Q", quarter(report_date))) %>%
# Removing dummy
dplyr::select(-bureau_score_orig)
setProgress(value = 2, message = "Patience test 1 of 2")
})
ndt
})
# Show uploaded data
output$up_data <- renderDataTable({
DT::datatable(
new.data(),
extensions = c("Buttons"),
options = list(
pageLength = 5,
scrollX = TRUE,
dom = 'Bfrtip',
filter = list(position = 'top', clear = FALSE),
buttons = list(
list(extend = "csv", text = "Download Visible", filename = "page",
exportOptions = list(
modifier = list(page = "current")
)
),
list(extend = "csv", text = "Download All", filename = "data",
exportOptions = list(
modifier = list(page = "all")
)
)
)
)
)
})
maxdate <- reactive(max(new.data()$report_date))
# Show some stats
basicstatServer("nofloans", dt = new.data())
# IMF Data
imf.data <- reactive({
input$fetchimf
req(!is.null(new.data()), input$fetchimf)
# Defining database and other parameters for query of macroeconomic data
databaseID <- "IFS"
startdate = min(new.data()$report_date)
enddate = max(new.data()$report_date)
country = countries[countries$Country == input$country,]$Alpha.2.code
withProgress(message = "Extracting data from IMF",
detail = "Hope their server is up!",
value = 0,
{
setProgress(value = 1, message = "Trying to reach..")
print(country)
imf.data <- tryCatch(
expr={
imf_data(
databaseID,
c("NGDP_NSA_XDC",
"PCPI_IX"),
country = stringr::str_trim(country),
start = startdate,
end = enddate,
freq = "Q",
return_raw = FALSE,
print_url = T,
times = 3
)
},
error = function(e){ # Specifying error message
showModal(
modalDialog(
"Error in IMF database. Sorry for the inconvenience. Can you please try again later?"
)
)
message("Error with IMF database. This is usually temporary. Sorry for the inconvenience. Please try again later.")
},
finally = { # Specifying final message
message("Error with IMF database. Please try again later.")
}
)
setProgress(value = 2, message = "Done")
})
imf.data
})
# Adding macroeconomic data. Currently GDP and prices data are extracted
dataset_with_eco <- reactive({
req(!is.null(imf.data()))
withProgress(message = "Trying Hard",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
# New dataset by joining GDP and prices data
dataset_with_eco <-
new.data() %>%
left_join(imf.data(), by = c("qtr" = "year_quarter")) %>%
rename(gdp = NGDP_NSA_XDC, prices = PCPI_IX) %>%
select(-iso2c) %>%
group_by(id) %>%
mutate(gdp_lag = lag(gdp, 1),
prices_lag = lag(prices, 1)) %>%
dplyr::select(-qtr) %>%
dplyr::select(-c(gdp, prices))
# removing rows with no macroeconomic data
dataset_eco <-
dataset_with_eco[!is.na(dataset_with_eco$gdp_lag) &
!is.na(dataset_with_eco$prices_lag), ]
setProgress(value = 2, message = "working..")
})
return(dataset_eco)
})
# GDP Forecast
gdp.forecast <- reactive({
imf.data <- imf.data()
imf.data$year_quarter <-
zoo::as.yearqtr(imf.data$year_quarter, format = "%Y-Q%q")
ga <- imf.data[, c(2, 3)]
minqg <- min(imf.data$year_quarter)
gats <- ts(ga$NGDP_NSA_XDC, # AIP_IX,
start = minqg,
frequency = 4)
withProgress(message = "Forecasting GDP",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
fit.gdp <-
forecast::auto.arima(gats, seasonal = FALSE)
gdp.forecast <-
fit.gdp %>% forecast::forecast(h = 60)
setProgress(value = 2, message = "Done")
})
gdp.forecast
})
# Price forecast
pats.forecast <- reactive({
imf.data <- imf.data()
imf.data$year_quarter <-
zoo::as.yearqtr(imf.data$year_quarter, format = "%Y-Q%q")
gp <- imf.data[, c(2, 4)]
minqg <- min(imf.data$year_quarter)
pats <- ts(gp$PCPI_IX, start = minqg, frequency = 4)
withProgress(message = "Forecasting price",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
fit.pats <-
forecast::auto.arima(pats, seasonal = FALSE)
pats.forecast <-
fit.pats %>% forecast::forecast(h = 60)
setProgress(value = 2, message = "Done")
})
pats.forecast
})
# Show full data
output$fulldata <- renderDataTable({
validate(need(!is.null(dataset_with_eco()),
message = "Data Not ready yet"))
a <- dataset_with_eco()
DT::datatable(
a,
extensions = c("Buttons"),
options = list(
pageLength = 5,
scrollX = TRUE,
dom = 'Bfrtip',
filter = list(position = 'top', clear = FALSE),
buttons = list(
list(extend = "csv", text = "Download Visible", filename = "page",
exportOptions = list(
modifier = list(page = "current")
)
),
list(extend = "csv", text = "Download All", filename = "data",
exportOptions = list(
modifier = list(page = "all")
)
)
)
)
)
})
# Probability of default
output$expcalcu <- renderUI({
req(!is.null(dataset_with_eco()), input$fetchimf)
fluidRow(
h3("Probability of asset going bad"),
p(
"In this section you can see the distribution of probabilities of the assets going bad by year, upto 5 years from the last reporting date. Please click the button to proceed."
),
actionButton(
"start_model_selection",
"Initiate Model Selection",
class = "glow"
),
withSpinner(
plotOutput("probability_default"),
type = 7,
color = "black"
)
)
})
# Model Selection. Using functions. In production these are to be converted to APIs
selected_model <- reactive({
req(input$start_model_selection,!is.null(dataset_with_eco()))
model_sel(dff=dataset_with_eco())
})
# Preparing tables with predictions. Using functions. In production these are to be converted to APIs
predicted_table <- reactive({
input$start_model_selection
req(!is.null(selected_model()))
z<-predic_t(dff=dataset_with_eco(),
gdpfor=gdp.forecast(),
prfor=pats.forecast(),
maxdate=maxdate(),
final.model= selected_model())
z
})
# Plot Probability of default
output$probability_default <- renderPlot({
input$start_model_selection
req(predicted_table())
withProgress(message = "Plotting",
detail = "Just a moment",
value = 0,
{
setProgress(value = 1, message = "Rushing")
pl <- predicted_table() %>%
group_by(name) %>%
#summarise(pd.me=median(value), pd.min=quantile(value,0.05), pd.max=quantile(value, 0.95))%>%
slice_head(n = 6) %>%
mutate(name = factor(
name,
levels = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
)
)) %>%
filter(!is.na(name)) %>%
ggplot(aes(
x = name,
y = value,
fill = name
)) +
geom_violin() +
geom_boxplot(width = 0.1,
color = "black",
alpha = 0.2) +
labs(x = "",
y = "Probability",
title = "Probability of default") +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom")
setProgress(value = 2, message = "Done")
})
pl
})
# Show scenario creation options when exposures and risks are calculated
output$scenario_opts <- renderUI({
req(!is.null(predicted_table()),
input$start_model_selection)
fluidRow(
# remove class when btn clicked
br(),
h3("Possible Scenarios"),
p(
"In this section, the parameters for simulation will be selected. Please click on start simulation button to proceed"
),
)
fluidRow(
column(
width = 3,
h5("Select expected change in collateral value"),
p("-ve means reduction in value"),
sliderInput(
"mode_dep",
"Most Probable",
min = -1,
max = 1,
value = -0.7,
step = 0.1
),
sliderInput(
"min_dep",
"Minimum",
min = -1,
max = 1,
value = -1,
step = 0.1
),
sliderInput(
"max_dep",
"Max",
min = -1,
max = 1,
value = 1,
step = 0.1
)
),
column(
width = 3,
sliderInput(
"discount_rate",
"Select Discount rate / WACC",
min = 0.00,
max = 0.2,
value = 0.02,
step = 0.01
),
actionButton("update", "Start Simulation", class = "glow"),
h3("Please do not forget to click this button.")
),
column(
width = 6,
p(
"This section shows the possible exposure in case the asset goes bad."
),
plotOutput("exposure_on_default")
)
)
})
# Exposure on Default
output$exposure_on_default <- renderPlot({
input$update
req(nrow(predicted_table())>0)
discount_rate_pa <- input$discount_rate
withProgress(message = "Plotting",
detail = "Just a moment",
value = 0,
{
setProgress(value = 1, message = "Almost there")
pl <- predicted_table() %>%
mutate(pv.balance = balance / (1 + discount_rate_pa) ^
(r_n - 1)) %>%
mutate(exposure_on_default = pv.balance * value) %>%
group_by(name) %>%
summarise(
pv.balance = sum(pv.balance),
exposure_on_default = sum(exposure_on_default)
) %>%
mutate(name = factor(
name,
levels = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
)
)) %>%
pivot_longer(
cols = c("pv.balance", "exposure_on_default"),
names_to = "type",
values_to = "amount"
) %>%
ggplot(aes(
x = name,
y = amount / 1000000,
fill = type,
label = paste0(round(amount / 1000000), " M")
)) +
geom_col(position = "dodge") +
geom_text(aes(y = (amount / 1000000) + 5), position = position_dodge(width = 1)) +
labs(
x = "",
y = "Amount",
title = "Exposure on default",
subtitle = "Amounts discounted"
) +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom")
setProgress(value = 2, message = "Done")
})
pl
})
output$credit_loss <- renderUI({
req(!is.null(predicted_table()), input$update)
validate(
need(input$mode_dep <= input$max_dep, message = "Most probable value should be less than or equal to Max"),
need(input$min_dep <= input$mode_dep, message = "Min value should be less than or equal to Most probable value"),
need(input$min_dep <= input$mode_dep, message = "Min value should be less than or equal to Max value")
)
fluidRow(
# remove class when btn clicked
h3("Simulated Credit Loss with probability"),
p(
"This section shows the distribution of the simlated possible losses. Please select the time to check the corresponding distribution."
),
br(),
selectInput(
"riskperiod",
"Select time",
choices = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
),
selected = "risk_1yr"
),
br(),
column(
width = 6,
p(
"Please click an drag to check the probabilities between ranges of possible loss."
),
plotOutput("simres",
brush = brushOpts(
id = "sim_res_sel", direction = "x"
)),
verbatimTextOutput("cumprob")
),
column(
width = 6,
p(
"This section shows the overall estimated credit loss by year from last reporting date, upto 5 years"
),
plotOutput("exp_credit_loss")
)
)
})
# collateral<-reactive({
# collateral
# })
simdata <- reactive({
req(nrow(predicted_table())>0)
req(!is.null(input$discount_rate))
input$update
collateral<-collateral.dt()
discount_rate_pa <- input$discount_rate
withProgress(message = "Monte Carlo Simulation",
detail = "1000 simulations",
value = 0,
{
setProgress(value = 1, message = "preparing")
zz <-
predicted_table() %>%
ungroup() %>%
group_by(id) %>%
mutate(pv.balance = balance / (1 + discount_rate_pa) ^
(r_n - 1)) %>%
left_join(collateral, by = "id") %>%
ungroup() %>%
select(name, pv.balance, value, collateral)
setProgress(value = 2, message = "simulating")
sim.t <-
data.frame(matrix(ncol = 1000, nrow = nrow(zz)))
colnames(sim.t) <-
paste0("sim", seq(1:1000))
sim.col.prob <-
(1 + rtriangle(
1000,
a = input$min_dep,
b = input$max_dep,
c = input$mode_dep
))
for (i in 1:1000) {
sim.t[, i] <-
round(zz$value * (zz$pv.balance - zz$collateral * sim.col.prob[i]),
2)
}
sim.t[sim.t < 0] <- 0
sim.t <- cbind(zz, sim.t)
setProgress(value = 3, message = "Done")
})
sim.t
})
simresdata <- reactive({
dt <- simdata() %>%
filter(name == input$riskperiod) %>%
ungroup() %>%
select(matches("sim?"))
hist.pro <- density(colSums(dt))
hist.pro
})
output$simres <- renderPlot({
req(!is.null(simresdata()))
hist.pro <- simresdata()
pro_dens <- data.frame(hist.pro$x, hist.pro$y)
ggplot(pro_dens,
aes(x = hist.pro.x,
y = hist.pro.y)) + geom_area(aes(y = hist.pro.y)) +
labs(
x = "Amount",
y = "Chance",
title = "Simulated expected credit loss",
subtitle = "Amounts discounted"
) +
theme_bw()
})
output$cumprob <- renderText({
req(!is.null(input$sim_res_sel), !is.null(simresdata()))
hist.pro <- simresdata()
pro_dens <- data.frame(hist.pro$x, hist.pro$y)
res <- brushedPoints(pro_dens, input$sim_res_sel)
if (nrow(res) == 0) {
return()
}
paste0(
"Probability of the loss to be between ",
min(res$hist.pro.x),
" and ",
max(res$hist.pro.x),
" is " ,
sum(res$hist.pro.y)
)
})
finaldt <- reactive({
sim_fin(simdata())
})
output$exp_credit_loss <- renderPlot({
req(!is.null(finaldt()))
finaldt() %>%
mutate(amount = x * y) %>%
group_by(r) %>%
summarise(amount = sum(amount)) %>%
ggplot(aes(
x = r,
y = round(amount / 1000),
label = paste0(round(amount / 1000), " K")
)) +
geom_col() +
geom_text(aes(y = round(amount / 1000) + 1)) +
labs(
title = "Estimated Credit Loss",
subtitle = "Weighted sum of 1000 simulations",
x = "",
y = "Amount"
) +
theme_bw()
})
output$dlmanager <- renderUI({
input$update
req(!is.null(finaldt()))
fluidRow(
textInput("author", "Enter Your Name"),
downloadButton("report", "Generate report")
)
})
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "easyIFRSriskReport.pdf",
content = function(file) {
withProgress(message = "Monte Carlo Simulation",
detail = "1000 simulations",
value = 0,
{
setProgress(value = 1, message = "Copying to temp directory")
tempReport <-
file.path(tempdir(), "easyIFRSriskReport.Rmd")
file.copy("easyIFRSriskReport.Rmd", tempReport, overwrite = TRUE)
setProgress(value = 2, message = "Passing parameters")
ndata <- new.data()
edata <- dataset_with_eco()
predtable <- predicted_table()
simudata <- simdata()
fidata <- finaldt()
gfor <- gdp.forecast()
pfor <- pats.forecast()
params <- list(
user = input$author,
newdata = ndata,
predtabledata = predtable,
disrate = input$discount_rate,
simdata = simudata,
finaldata = fidata,
gdpf = gfor,
pf = pfor
)
setProgress(value = 3, message = "Knitting. Hang on.")
rmarkdown::render(
tempReport,
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
setProgress(value = 4, message = "Done.")
})
}
)
# File uploading Module
observeEvent(input$uploadnew, {
showModal(
modal1
)
})
observeEvent(input$closemodal1,{
removeModal()
})
observeEvent(input$closemodal2,{
removeModal()
})
# Uploading temp file and collecting info about the columns
observeEvent(input$uploadfiles,{
df.tr <- reactive({
inFile <- input$transaction
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df
})
df.c <- reactive({
inFile <- input$collaterals
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df
})
updateVarSelectInput("collateralid","Select id column", df.c(),session = getDefaultReactiveDomain())
updateVarSelectInput("collateralvalue","Select Collateral value column", df.c(),session = getDefaultReactiveDomain())
updateVarSelectInput("reportdate","Select report date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("origindate","Select origin date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("maturitydate","Select maturity date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("assettype","Select asset classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("customertype","Select customer classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("otherfact","Select any other classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("bureauscore","Select bureau score column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("balance","Select asset balance column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("status","Select loan status", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("defaultflag","Select default flag column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("transid","Select id column", df.tr(),session = getDefaultReactiveDomain())
})
# Modal 2
observeEvent(input$uploadfiles, {
showModal(
modal2
)
})
observeEvent(input$confirmupload,{
transaction.dt(
{
df <- read.csv(input$transaction$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
head(df)
df<-
df %>%
rename(report_date=input$reportdate,
origination_date=input$origindate,
maturity_date=input$maturitydate,
asset_type=input$assettype,
customer_type=input$customertype,
bureau_score_orig=input$bureauscore,
balance=input$balance,
loan_status=input$status,
default_flag=input$defaultflag,
id=input$transid)
if(input$dateformat=="ymd"){
df$report_date<-ymd(df$report_date)
df$origination_date<-ymd(df$origination_date)
df$maturity_date<-ymd(df$maturity_date)
} else {
df$report_date<-dmy(df$report_date)
df$origination_date<-dmy(df$origination_date)
df$maturity_date<-dmy(df$maturity_date)
}
df$loan_status<-as.integer(df$loan_status)
# Covert to factors
df$asset_type<-as.factor(df$asset_type)
df$customer_type<-as.factor(df$customer_type)
if(!is.null(input$otherfact)){
for(i in 1:length(input$otherfact)){
df$input$otherfact[i]<-as.factor(df$input$otherfact[i])
}
}
df
}
)
collateral.dt(
{
df <- read.csv(input$collaterals$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df<-
df %>%
rename(id=input$collateralid,
collateral=input$collateralvalue)
df
}
)
removeModal()
})
}
# Run the application
# Run the application
shinyApp(ui = ui, server = server)

1
.Rproj.user/shared/notebooks/paths

@ -0,0 +1 @@
/Users/asitav/Projects/LoanRisk/mod_basic.R="53362AD0"

873
app.R

@ -17,30 +17,871 @@ library(triangle)
library(DiagrammeR)
library(stringr)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("LoanRisk"),
options(shiny.reactlog = TRUE, appDir = getwd())
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
source("panel.R")
# source("mod_basic.R")
# source("secretary.R")
# source("forplumber.R")
# source("modals.R")
),
# Adding initial data
# Show a plot of the generated distribution
mainPanel(
)
)
# Define UI for application
ui <- navbarPage(
theme = shinytheme("cosmo"),
title = "LoanRisk",
panel1
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# Data
# Some reactive values
collateral.dt<-reactiveVal()
transaction.dt<-reactiveVal()
# Adding initial data to reactive values
collateral.dt(read.csv("./data/collateral.csv") )
transaction.dt(read.csv("./data/transactions.csv") )
# Transforming Data
new.data <- reactive({
ndt<- transaction.dt()
withProgress(message = "Trying to read",
detail = "Hope the handwriting is legible!",
value = 0,
{
setProgress(value = 1, message = "Patience test 1 of 2")
ndt <-
ndt %>%
# Change format of some columns
mutate(
origination_date = ymd(origination_date),
maturity_date = ymd(maturity_date),
report_date = ymd(report_date)
) %>%
# Add age of loan, loan tenure in months, which are compulsory parameters
mutate(age_of_asset_months = round(as.numeric(
report_date - origination_date
) / 30)) %>%
mutate(loan_tenure_months = round(as.numeric(
maturity_date - origination_date
) / 30)) %>%
group_by(id) %>%
# Arranging to avoid mistakes in lag
arrange(report_date) %>%
# Add lag of bureau score and total number of defaults. Lag added for delta creation
mutate(
cum_default = cumsum(default_flag),
bureau_score_lag = ifelse(
is.na(lag(bureau_score_orig, 1)),
bureau_score_orig,
lag(bureau_score_orig, 1)
)
) %>%
# Adding delta of bureau score (ask me the reason if you do not know why)
mutate(bureau_score_delta = bureau_score_lag -
bureau_score_orig) %>%
# Adding quarter info for matching later with macroeconomic data
mutate(qtr = paste0(year(report_date), "-Q", quarter(report_date))) %>%
# Removing dummy
dplyr::select(-bureau_score_orig)
setProgress(value = 2, message = "Patience test 1 of 2")
})
ndt
})
# Show uploaded data
output$up_data <- renderDataTable({
DT::datatable(
new.data(),
extensions = c("Buttons"),
options = list(
pageLength = 5,
scrollX = TRUE,
dom = 'Bfrtip',
filter = list(position = 'top', clear = FALSE),
buttons = list(
list(extend = "csv", text = "Download Visible", filename = "page",
exportOptions = list(
modifier = list(page = "current")
)
),
list(extend = "csv", text = "Download All", filename = "data",
exportOptions = list(
modifier = list(page = "all")
)
)
)
)
)
})
maxdate <- reactive(max(new.data()$report_date))
# Show some stats
basicstatServer("nofloans", dt = new.data())
# IMF Data
imf.data <- reactive({
input$fetchimf
req(!is.null(new.data()), input$fetchimf)
# Defining database and other parameters for query of macroeconomic data
databaseID <- "IFS"
startdate = min(new.data()$report_date)
enddate = max(new.data()$report_date)
country = countries[countries$Country == input$country,]$Alpha.2.code
withProgress(message = "Extracting data from IMF",
detail = "Hope their server is up!",
value = 0,
{
setProgress(value = 1, message = "Trying to reach..")
print(country)
imf.data <- tryCatch(
expr={
imf_data(
databaseID,
c("NGDP_NSA_XDC",
"PCPI_IX"),
country = stringr::str_trim(country),
start = startdate,
end = enddate,
freq = "Q",
return_raw = FALSE,
print_url = T,
times = 3
)
},
error = function(e){ # Specifying error message
showModal(
modalDialog(
"Error in IMF database. Sorry for the inconvenience. Can you please try again later?"
)
)
message("Error with IMF database. This is usually temporary. Sorry for the inconvenience. Please try again later.")
},
finally = { # Specifying final message
message("Error with IMF database. Please try again later.")
}
)
setProgress(value = 2, message = "Done")
})
imf.data
})
# Adding macroeconomic data. Currently GDP and prices data are extracted
dataset_with_eco <- reactive({
req(!is.null(imf.data()))
withProgress(message = "Trying Hard",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
# New dataset by joining GDP and prices data
dataset_with_eco <-
new.data() %>%
left_join(imf.data(), by = c("qtr" = "year_quarter")) %>%
rename(gdp = NGDP_NSA_XDC, prices = PCPI_IX) %>%
select(-iso2c) %>%
group_by(id) %>%
mutate(gdp_lag = lag(gdp, 1),
prices_lag = lag(prices, 1)) %>%
dplyr::select(-qtr) %>%
dplyr::select(-c(gdp, prices))
# removing rows with no macroeconomic data
dataset_eco <-
dataset_with_eco[!is.na(dataset_with_eco$gdp_lag) &
!is.na(dataset_with_eco$prices_lag), ]
setProgress(value = 2, message = "working..")
})
return(dataset_eco)
})
# GDP Forecast
gdp.forecast <- reactive({
imf.data <- imf.data()
imf.data$year_quarter <-
zoo::as.yearqtr(imf.data$year_quarter, format = "%Y-Q%q")
ga <- imf.data[, c(2, 3)]
minqg <- min(imf.data$year_quarter)
gats <- ts(ga$NGDP_NSA_XDC, # AIP_IX,
start = minqg,
frequency = 4)
withProgress(message = "Forecasting GDP",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
fit.gdp <-
forecast::auto.arima(gats, seasonal = FALSE)
gdp.forecast <-
fit.gdp %>% forecast::forecast(h = 60)
setProgress(value = 2, message = "Done")
})
gdp.forecast
})
# Price forecast
pats.forecast <- reactive({
imf.data <- imf.data()
imf.data$year_quarter <-
zoo::as.yearqtr(imf.data$year_quarter, format = "%Y-Q%q")
gp <- imf.data[, c(2, 4)]
minqg <- min(imf.data$year_quarter)
pats <- ts(gp$PCPI_IX, start = minqg, frequency = 4)
withProgress(message = "Forecasting price",
detail = "Hang on",
value = 0,
{
setProgress(value = 1, message = "working..")
fit.pats <-
forecast::auto.arima(pats, seasonal = FALSE)
pats.forecast <-
fit.pats %>% forecast::forecast(h = 60)
setProgress(value = 2, message = "Done")
})
pats.forecast
})
# Show full data
output$fulldata <- renderDataTable({
validate(need(!is.null(dataset_with_eco()),
message = "Data Not ready yet"))
a <- dataset_with_eco()
DT::datatable(
a,
extensions = c("Buttons"),
options = list(
pageLength = 5,
scrollX = TRUE,
dom = 'Bfrtip',
filter = list(position = 'top', clear = FALSE),
buttons = list(
list(extend = "csv", text = "Download Visible", filename = "page",
exportOptions = list(
modifier = list(page = "current")
)
),
list(extend = "csv", text = "Download All", filename = "data",
exportOptions = list(
modifier = list(page = "all")
)
)
)
)
)
})
# Probability of default
output$expcalcu <- renderUI({
req(!is.null(dataset_with_eco()), input$fetchimf)
fluidRow(
h3("Probability of asset going bad"),
p(
"In this section you can see the distribution of probabilities of the assets going bad by year, upto 5 years from the last reporting date. Please click the button to proceed."
),
actionButton(
"start_model_selection",
"Initiate Model Selection",
class = "glow"
),
withSpinner(
plotOutput("probability_default"),
type = 7,
color = "black"
)
)
})
# Model Selection. Using functions. In production these are to be converted to APIs
selected_model <- reactive({
req(input$start_model_selection,!is.null(dataset_with_eco()))
model_sel(dff=dataset_with_eco())
})
# Preparing tables with predictions. Using functions. In production these are to be converted to APIs
predicted_table <- reactive({
input$start_model_selection
req(!is.null(selected_model()))
z<-predic_t(dff=dataset_with_eco(),
gdpfor=gdp.forecast(),
prfor=pats.forecast(),
maxdate=maxdate(),
final.model= selected_model())
z
})
# Plot Probability of default
output$probability_default <- renderPlot({
input$start_model_selection
req(predicted_table())
withProgress(message = "Plotting",
detail = "Just a moment",
value = 0,
{
setProgress(value = 1, message = "Rushing")
pl <- predicted_table() %>%
group_by(name) %>%
#summarise(pd.me=median(value), pd.min=quantile(value,0.05), pd.max=quantile(value, 0.95))%>%
slice_head(n = 6) %>%
mutate(name = factor(
name,
levels = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
)
)) %>%
filter(!is.na(name)) %>%
ggplot(aes(
x = name,
y = value,
fill = name
)) +
geom_violin() +
geom_boxplot(width = 0.1,
color = "black",
alpha = 0.2) +
labs(x = "",
y = "Probability",
title = "Probability of default") +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom")
setProgress(value = 2, message = "Done")
})
pl
})
# Show scenario creation options when exposures and risks are calculated
output$scenario_opts <- renderUI({
req(!is.null(predicted_table()),
input$start_model_selection)
fluidRow(
# remove class when btn clicked
br(),
h3("Possible Scenarios"),
p(
"In this section, the parameters for simulation will be selected. Please click on start simulation button to proceed"
),
)
fluidRow(
column(
width = 3,
h5("Select expected change in collateral value"),
p("-ve means reduction in value"),
sliderInput(
"mode_dep",
"Most Probable",
min = -1,
max = 1,
value = -0.7,
step = 0.1
),
sliderInput(
"min_dep",
"Minimum",
min = -1,
max = 1,
value = -1,
step = 0.1
),
sliderInput(
"max_dep",
"Max",
min = -1,
max = 1,
value = 1,
step = 0.1
)
),
column(
width = 3,
sliderInput(
"discount_rate",
"Select Discount rate / WACC",
min = 0.00,
max = 0.2,
value = 0.02,
step = 0.01
),
actionButton("update", "Start Simulation", class = "glow"),
h3("Please do not forget to click this button.")
),
column(
width = 6,
p(
"This section shows the possible exposure in case the asset goes bad."
),
plotOutput("exposure_on_default")
)
)
})
# Exposure on Default
output$exposure_on_default <- renderPlot({
input$update
req(nrow(predicted_table())>0)
discount_rate_pa <- input$discount_rate
withProgress(message = "Plotting",
detail = "Just a moment",
value = 0,
{
setProgress(value = 1, message = "Almost there")
pl <- predicted_table() %>%
mutate(pv.balance = balance / (1 + discount_rate_pa) ^
(r_n - 1)) %>%
mutate(exposure_on_default = pv.balance * value) %>%
group_by(name) %>%
summarise(
pv.balance = sum(pv.balance),
exposure_on_default = sum(exposure_on_default)
) %>%
mutate(name = factor(
name,
levels = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
)
)) %>%
pivot_longer(
cols = c("pv.balance", "exposure_on_default"),
names_to = "type",
values_to = "amount"
) %>%
ggplot(aes(
x = name,
y = amount / 1000000,
fill = type,
label = paste0(round(amount / 1000000), " M")
)) +
geom_col(position = "dodge") +
geom_text(aes(y = (amount / 1000000) + 5), position = position_dodge(width = 1)) +
labs(
x = "",
y = "Amount",
title = "Exposure on default",
subtitle = "Amounts discounted"
) +
theme_bw() +
theme(legend.title = element_blank(),
legend.position = "bottom")
setProgress(value = 2, message = "Done")
})
pl
})
output$credit_loss <- renderUI({
req(!is.null(predicted_table()), input$update)
validate(
need(input$mode_dep <= input$max_dep, message = "Most probable value should be less than or equal to Max"),
need(input$min_dep <= input$mode_dep, message = "Min value should be less than or equal to Most probable value"),
need(input$min_dep <= input$mode_dep, message = "Min value should be less than or equal to Max value")
)
fluidRow(
# remove class when btn clicked
h3("Simulated Credit Loss with probability"),
p(
"This section shows the distribution of the simlated possible losses. Please select the time to check the corresponding distribution."
),
br(),
selectInput(
"riskperiod",
"Select time",
choices = c(
"risk_current",
"risk_1yr",
"risk_2yr",
"risk_3yr",
"risk_4yr",
"risk_5yr"
),
selected = "risk_1yr"
),
br(),
column(
width = 6,
p(
"Please click an drag to check the probabilities between ranges of possible loss."
),
plotOutput("simres",
brush = brushOpts(
id = "sim_res_sel", direction = "x"
)),
verbatimTextOutput("cumprob")
),
column(
width = 6,
p(
"This section shows the overall estimated credit loss by year from last reporting date, upto 5 years"
),
plotOutput("exp_credit_loss")
)
)
})
# collateral<-reactive({
# collateral
# })
simdata <- reactive({
req(nrow(predicted_table())>0)
req(!is.null(input$discount_rate))
input$update
collateral<-collateral.dt()
discount_rate_pa <- input$discount_rate
withProgress(message = "Monte Carlo Simulation",
detail = "1000 simulations",
value = 0,
{
setProgress(value = 1, message = "preparing")
zz <-
predicted_table() %>%
ungroup() %>%
group_by(id) %>%
mutate(pv.balance = balance / (1 + discount_rate_pa) ^
(r_n - 1)) %>%
left_join(collateral, by = "id") %>%
ungroup() %>%
select(name, pv.balance, value, collateral)
setProgress(value = 2, message = "simulating")
sim.t <-
data.frame(matrix(ncol = 1000, nrow = nrow(zz)))
colnames(sim.t) <-
paste0("sim", seq(1:1000))
sim.col.prob <-
(1 + rtriangle(
1000,
a = input$min_dep,
b = input$max_dep,
c = input$mode_dep
))
for (i in 1:1000) {
sim.t[, i] <-
round(zz$value * (zz$pv.balance - zz$collateral * sim.col.prob[i]),
2)
}
sim.t[sim.t < 0] <- 0
sim.t <- cbind(zz, sim.t)
setProgress(value = 3, message = "Done")
})
sim.t
})
simresdata <- reactive({
dt <- simdata() %>%
filter(name == input$riskperiod) %>%
ungroup() %>%
select(matches("sim?"))
hist.pro <- density(colSums(dt))
hist.pro
})
output$simres <- renderPlot({
req(!is.null(simresdata()))
hist.pro <- simresdata()
pro_dens <- data.frame(hist.pro$x, hist.pro$y)
ggplot(pro_dens,
aes(x = hist.pro.x,
y = hist.pro.y)) + geom_area(aes(y = hist.pro.y)) +
labs(
x = "Amount",
y = "Chance",
title = "Simulated expected credit loss",
subtitle = "Amounts discounted"
) +
theme_bw()
})
output$cumprob <- renderText({
req(!is.null(input$sim_res_sel), !is.null(simresdata()))
hist.pro <- simresdata()
pro_dens <- data.frame(hist.pro$x, hist.pro$y)
res <- brushedPoints(pro_dens, input$sim_res_sel)
if (nrow(res) == 0) {
return()
}
paste0(
"Probability of the loss to be between ",
min(res$hist.pro.x),
" and ",
max(res$hist.pro.x),
" is " ,
sum(res$hist.pro.y)
)
})
finaldt <- reactive({
sim_fin(simdata())
})
output$exp_credit_loss <- renderPlot({
req(!is.null(finaldt()))
finaldt() %>%
mutate(amount = x * y) %>%
group_by(r) %>%
summarise(amount = sum(amount)) %>%
ggplot(aes(
x = r,
y = round(amount / 1000),
label = paste0(round(amount / 1000), " K")
)) +
geom_col() +
geom_text(aes(y = round(amount / 1000) + 1)) +
labs(
title = "Estimated Credit Loss",
subtitle = "Weighted sum of 1000 simulations",
x = "",
y = "Amount"
) +
theme_bw()
})
output$dlmanager <- renderUI({
input$update
req(!is.null(finaldt()))
fluidRow(
textInput("author", "Enter Your Name"),
downloadButton("report", "Generate report")
)
})
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "easyIFRSriskReport.pdf",
content = function(file) {
withProgress(message = "Monte Carlo Simulation",
detail = "1000 simulations",
value = 0,
{
setProgress(value = 1, message = "Copying to temp directory")
tempReport <-
file.path(tempdir(), "easyIFRSriskReport.Rmd")
file.copy("easyIFRSriskReport.Rmd", tempReport, overwrite = TRUE)
setProgress(value = 2, message = "Passing parameters")
ndata <- new.data()
edata <- dataset_with_eco()
predtable <- predicted_table()
simudata <- simdata()
fidata <- finaldt()
gfor <- gdp.forecast()
pfor <- pats.forecast()
params <- list(
user = input$author,
newdata = ndata,
predtabledata = predtable,
disrate = input$discount_rate,
simdata = simudata,
finaldata = fidata,
gdpf = gfor,
pf = pfor
)
setProgress(value = 3, message = "Knitting. Hang on.")
rmarkdown::render(
tempReport,
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
setProgress(value = 4, message = "Done.")
})
}
)
# File uploading Module
observeEvent(input$uploadnew, {
showModal(
modal1
)
})
observeEvent(input$closemodal1,{
removeModal()
})
observeEvent(input$closemodal2,{
removeModal()
})
# Uploading temp file and collecting info about the columns
observeEvent(input$uploadfiles,{
df.tr <- reactive({
inFile <- input$transaction
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df
})
df.c <- reactive({
inFile <- input$collaterals
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df
})
updateVarSelectInput("collateralid","Select id column", df.c(),session = getDefaultReactiveDomain())
updateVarSelectInput("collateralvalue","Select Collateral value column", df.c(),session = getDefaultReactiveDomain())
updateVarSelectInput("reportdate","Select report date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("origindate","Select origin date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("maturitydate","Select maturity date column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("assettype","Select asset classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("customertype","Select customer classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("otherfact","Select any other classifier column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("bureauscore","Select bureau score column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("balance","Select asset balance column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("status","Select loan status", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("defaultflag","Select default flag column", df.tr(),session = getDefaultReactiveDomain())
updateVarSelectInput("transid","Select id column", df.tr(),session = getDefaultReactiveDomain())
})
# Modal 2
observeEvent(input$uploadfiles, {
showModal(
modal2
)
})
observeEvent(input$confirmupload,{
transaction.dt(
{
df <- read.csv(input$transaction$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
head(df)
df<-
df %>%
rename(report_date=input$reportdate,
origination_date=input$origindate,
maturity_date=input$maturitydate,
asset_type=input$assettype,
customer_type=input$customertype,
bureau_score_orig=input$bureauscore,
balance=input$balance,
loan_status=input$status,
default_flag=input$defaultflag,
id=input$transid)
if(input$dateformat=="ymd"){
df$report_date<-ymd(df$report_date)
df$origination_date<-ymd(df$origination_date)
df$maturity_date<-ymd(df$maturity_date)
} else {
df$report_date<-dmy(df$report_date)
df$origination_date<-dmy(df$origination_date)
df$maturity_date<-dmy(df$maturity_date)
}
df$loan_status<-as.integer(df$loan_status)
# Covert to factors
df$asset_type<-as.factor(df$asset_type)
df$customer_type<-as.factor(df$customer_type)
if(!is.null(input$otherfact)){
for(i in 1:length(input$otherfact)){
df$input$otherfact[i]<-as.factor(df$input$otherfact[i])
}
}
df
}
)
collateral.dt(
{
df <- read.csv(input$collaterals$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df<-
df %>%
rename(id=input$collateralid,
collateral=input$collateralvalue)
df
}
)
removeModal()
})
}
# Run the application
# Run the application
shinyApp(ui = ui, server = server)

1631
data/collateral.csv

File diff suppressed because it is too large

257
data/countries.csv

@ -0,0 +1,257 @@
"Country","Alpha-2 code","Alpha-3 code","Numeric code","Latitude (average)","Longitude (average)"
"Afghanistan", "AF", "AFG", "4", "33", "65"
"Albania", "AL", "ALB", "8", "41", "20"
"Algeria", "DZ", "DZA", "12", "28", "3"
"American Samoa", "AS", "ASM", "16", "-14.3333", "-170"
"Andorra", "AD", "AND", "20", "42.5", "1.6"
"Angola", "AO", "AGO", "24", "-12.5", "18.5"
"Anguilla", "AI", "AIA", "660", "18.25", "-63.1667"
"Antarctica", "AQ", "ATA", "10", "-90", "0"
"Antigua and Barbuda", "AG", "ATG", "28", "17.05", "-61.8"
"Argentina", "AR", "ARG", "32", "-34", "-64"
"Armenia", "AM", "ARM", "51", "40", "45"
"Aruba", "AW", "ABW", "533", "12.5", "-69.9667"
"Australia", "AU", "AUS", "36", "-27", "133"
"Austria", "AT", "AUT", "40", "47.3333", "13.3333"
"Azerbaijan", "AZ", "AZE", "31", "40.5", "47.5"
"Bahamas", "BS", "BHS", "44", "24.25", "-76"
"Bahrain", "BH", "BHR", "48", "26", "50.55"
"Bangladesh", "BD", "BGD", "50", "24", "90"
"Barbados", "BB", "BRB", "52", "13.1667", "-59.5333"
"Belarus", "BY", "BLR", "112", "53", "28"
"Belgium", "BE", "BEL", "56", "50.8333", "4"
"Belize", "BZ", "BLZ", "84", "17.25", "-88.75"
"Benin", "BJ", "BEN", "204", "9.5", "2.25"
"Bermuda", "BM", "BMU", "60", "32.3333", "-64.75"
"Bhutan", "BT", "BTN", "64", "27.5", "90.5"
"Bolivia, Plurinational State of", "BO", "BOL", "68", "-17", "-65"
"Bolivia", "BO", "BOL", "68", "-17", "-65"
"Bosnia and Herzegovina", "BA", "BIH", "70", "44", "18"
"Botswana", "BW", "BWA", "72", "-22", "24"
"Bouvet Island", "BV", "BVT", "74", "-54.4333", "3.4"
"Brazil", "BR", "BRA", "76", "-10", "-55"
"British Indian Ocean Territory", "IO", "IOT", "86", "-6", "71.5"
"Brunei Darussalam", "BN", "BRN", "96", "4.5", "114.6667"
"Brunei", "BN", "BRN", "96", "4.5", "114.6667"
"Bulgaria", "BG", "BGR", "100", "43", "25"
"Burkina Faso", "BF", "BFA", "854", "13", "-2"
"Burundi", "BI", "BDI", "108", "-3.5", "30"
"Cambodia", "KH", "KHM", "116", "13", "105"
"Cameroon", "CM", "CMR", "120", "6", "12"
"Canada", "CA", "CAN", "124", "60", "-95"
"Cape Verde", "CV", "CPV", "132", "16", "-24"
"Cayman Islands", "KY", "CYM", "136", "19.5", "-80.5"
"Central African Republic", "CF", "CAF", "140", "7", "21"
"Chad", "TD", "TCD", "148", "15", "19"
"Chile", "CL", "CHL", "152", "-30", "-71"
"China", "CN", "CHN", "156", "35", "105"
"Christmas Island", "CX", "CXR", "162", "-10.5", "105.6667"
"Cocos (Keeling) Islands", "CC", "CCK", "166", "-12.5", "96.8333"
"Colombia", "CO", "COL", "170", "4", "-72"
"Comoros", "KM", "COM", "174", "-12.1667", "44.25"
"Congo", "CG", "COG", "178", "-1", "15"
"Congo, the Democratic Republic of the", "CD", "COD", "180", "0", "25"
"Cook Islands", "CK", "COK", "184", "-21.2333", "-159.7667"
"Costa Rica", "CR", "CRI", "188", "10", "-84"
"Côte d'Ivoire", "CI", "CIV", "384", "8", "-5"
"Ivory Coast", "CI", "CIV", "384", "8", "-5"
"Croatia", "HR", "HRV", "191", "45.1667", "15.5"
"Cuba", "CU", "CUB", "192", "21.5", "-80"
"Cyprus", "CY", "CYP", "196", "35", "33"
"Czech Republic", "CZ", "CZE", "203", "49.75", "15.5"
"Denmark", "DK", "DNK", "208", "56", "10"
"Djibouti", "DJ", "DJI", "262", "11.5", "43"
"Dominica", "DM", "DMA", "212", "15.4167", "-61.3333"
"Dominican Republic", "DO", "DOM", "214", "19", "-70.6667"
"Ecuador", "EC", "ECU", "218", "-2", "-77.5"
"Egypt", "EG", "EGY", "818", "27", "30"
"El Salvador", "SV", "SLV", "222", "13.8333", "-88.9167"
"Equatorial Guinea", "GQ", "GNQ", "226", "2", "10"
"Eritrea", "ER", "ERI", "232", "15", "39"
"Estonia", "EE", "EST", "233", "59", "26"
"Ethiopia", "ET", "ETH", "231", "8", "38"
"Falkland Islands (Malvinas)", "FK", "FLK", "238", "-51.75", "-59"
"Faroe Islands", "FO", "FRO", "234", "62", "-7"
"Fiji", "FJ", "FJI", "242", "-18", "175"
"Finland", "FI", "FIN", "246", "64", "26"
"France", "FR", "FRA", "250", "46", "2"
"French Guiana", "GF", "GUF", "254", "4", "-53"
"French Polynesia", "PF", "PYF", "258", "-15", "-140"
"French Southern Territories", "TF", "ATF", "260", "-43", "67"
"Gabon", "GA", "GAB", "266", "-1", "11.75"
"Gambia", "GM", "GMB", "270", "13.4667", "-16.5667"
"Georgia", "GE", "GEO", "268", "42", "43.5"
"Germany", "DE", "DEU", "276", "51", "9"
"Ghana", "GH", "GHA", "288", "8", "-2"
"Gibraltar", "GI", "GIB", "292", "36.1833", "-5.3667"
"Greece", "GR", "GRC", "300", "39", "22"
"Greenland", "GL", "GRL", "304", "72", "-40"
"Grenada", "GD", "GRD", "308", "12.1167", "-61.6667"
"Guadeloupe", "GP", "GLP", "312", "16.25", "-61.5833"
"Guam", "GU", "GUM", "316", "13.4667", "144.7833"
"Guatemala", "GT", "GTM", "320", "15.5", "-90.25"
"Guernsey", "GG", "GGY", "831", "49.5", "-2.56"
"Guinea", "GN", "GIN", "324", "11", "-10"
"Guinea-Bissau", "GW", "GNB", "624", "12", "-15"
"Guyana", "GY", "GUY", "328", "5", "-59"
"Haiti", "HT", "HTI", "332", "19", "-72.4167"
"Heard Island and McDonald Islands", "HM", "HMD", "334", "-53.1", "72.5167"
"Holy See (Vatican City State)", "VA", "VAT", "336", "41.9", "12.45"
"Honduras", "HN", "HND", "340", "15", "-86.5"
"Hong Kong", "HK", "HKG", "344", "22.25", "114.1667"
"Hungary", "HU", "HUN", "348", "47", "20"
"Iceland", "IS", "ISL", "352", "65", "-18"
"India", "IN", "IND", "356", "20", "77"
"Indonesia", "ID", "IDN", "360", "-5", "120"
"Iran, Islamic Republic of", "IR", "IRN", "364", "32", "53"
"Iraq", "IQ", "IRQ", "368", "33", "44"
"Ireland", "IE", "IRL", "372", "53", "-8"
"Isle of Man", "IM", "IMN", "833", "54.23", "-4.55"
"Israel", "IL", "ISR", "376", "31.5", "34.75"
"Italy", "IT", "ITA", "380", "42.8333", "12.8333"
"Jamaica", "JM", "JAM", "388", "18.25", "-77.5"
"Japan", "JP", "JPN", "392", "36", "138"
"Jersey", "JE", "JEY", "832", "49.21", "-2.13"
"Jordan", "JO", "JOR", "400", "31", "36"
"Kazakhstan", "KZ", "KAZ", "398", "48", "68"
"Kenya", "KE", "KEN", "404", "1", "38"
"Kiribati", "KI", "KIR", "296", "1.4167", "173"
"Korea, Democratic People's Republic of", "KP", "PRK", "408", "40", "127"
"Korea, Republic of", "KR", "KOR", "410", "37", "127.5"
"South Korea", "KR", "KOR", "410", "37", "127.5"
"Kuwait", "KW", "KWT", "414", "29.3375", "47.6581"
"Kyrgyzstan", "KG", "KGZ", "417", "41", "75"
"Lao People's Democratic Republic", "LA", "LAO", "418", "18", "105"
"Latvia", "LV", "LVA", "428", "57", "25"
"Lebanon", "LB", "LBN", "422", "33.8333", "35.8333"
"Lesotho", "LS", "LSO", "426", "-29.5", "28.5"
"Liberia", "LR", "LBR", "430", "6.5", "-9.5"
"Libyan Arab Jamahiriya", "LY", "LBY", "434", "25", "17"
"Libya", "LY", "LBY", "434", "25", "17"
"Liechtenstein", "LI", "LIE", "438", "47.1667", "9.5333"
"Lithuania", "LT", "LTU", "440", "56", "24"
"Luxembourg", "LU", "LUX", "442", "49.75", "6.1667"
"Macao", "MO", "MAC", "446", "22.1667", "113.55"
"Macedonia, the former Yugoslav Republic of", "MK", "MKD", "807", "41.8333", "22"
"Madagascar", "MG", "MDG", "450", "-20", "47"
"Malawi", "MW", "MWI", "454", "-13.5", "34"
"Malaysia", "MY", "MYS", "458", "2.5", "112.5"
"Maldives", "MV", "MDV", "462", "3.25", "73"
"Mali", "ML", "MLI", "466", "17", "-4"
"Malta", "MT", "MLT", "470", "35.8333", "14.5833"
"Marshall Islands", "MH", "MHL", "584", "9", "168"
"Martinique", "MQ", "MTQ", "474", "14.6667", "-61"
"Mauritania", "MR", "MRT", "478", "20", "-12"
"Mauritius", "MU", "MUS", "480", "-20.2833", "57.55"
"Mayotte", "YT", "MYT", "175", "-12.8333", "45.1667"
"Mexico", "MX", "MEX", "484", "23", "-102"
"Micronesia, Federated States of", "FM", "FSM", "583", "6.9167", "158.25"
"Moldova, Republic of", "MD", "MDA", "498", "47", "29"
"Monaco", "MC", "MCO", "492", "43.7333", "7.4"
"Mongolia", "MN", "MNG", "496", "46", "105"
"Montenegro", "ME", "MNE", "499", "42", "19"
"Montserrat", "MS", "MSR", "500", "16.75", "-62.2"
"Morocco", "MA", "MAR", "504", "32", "-5"
"Mozambique", "MZ", "MOZ", "508", "-18.25", "35"
"Myanmar", "MM", "MMR", "104", "22", "98"
"Burma", "MM", "MMR", "104", "22", "98"
"Namibia", "NA", "NAM", "516", "-22", "17"
"Nauru", "NR", "NRU", "520", "-0.5333", "166.9167"
"Nepal", "NP", "NPL", "524", "28", "84"
"Netherlands", "NL", "NLD", "528", "52.5", "5.75"
"Netherlands Antilles", "AN", "ANT", "530", "12.25", "-68.75"
"New Caledonia", "NC", "NCL", "540", "-21.5", "165.5"
"New Zealand", "NZ", "NZL", "554", "-41", "174"
"Nicaragua", "NI", "NIC", "558", "13", "-85"
"Niger", "NE", "NER", "562", "16", "8"
"Nigeria", "NG", "NGA", "566", "10", "8"
"Niue", "NU", "NIU", "570", "-19.0333", "-169.8667"
"Norfolk Island", "NF", "NFK", "574", "-29.0333", "167.95"
"Northern Mariana Islands", "MP", "MNP", "580", "15.2", "145.75"
"Norway", "NO", "NOR", "578", "62", "10"
"Oman", "OM", "OMN", "512", "21", "57"
"Pakistan", "PK", "PAK", "586", "30", "70"
"Palau", "PW", "PLW", "585", "7.5", "134.5"
"Palestinian Territory, Occupied", "PS", "PSE", "275", "32", "35.25"
"Panama", "PA", "PAN", "591", "9", "-80"
"Papua New Guinea", "PG", "PNG", "598", "-6", "147"
"Paraguay", "PY", "PRY", "600", "-23", "-58"
"Peru", "PE", "PER", "604", "-10", "-76"
"Philippines", "PH", "PHL", "608", "13", "122"
"Pitcairn", "PN", "PCN", "612", "-24.7", "-127.4"
"Poland", "PL", "POL", "616", "52", "20"
"Portugal", "PT", "PRT", "620", "39.5", "-8"
"Puerto Rico", "PR", "PRI", "630", "18.25", "-66.5"
"Qatar", "QA", "QAT", "634", "25.5", "51.25"
"Réunion", "RE", "REU", "638", "-21.1", "55.6"
"Romania", "RO", "ROU", "642", "46", "25"
"Russian Federation", "RU", "RUS", "643", "60", "100"
"Russia", "RU", "RUS", "643", "60", "100"
"Rwanda", "RW", "RWA", "646", "-2", "30"
"Saint Helena, Ascension and Tristan da Cunha", "SH", "SHN", "654", "-15.9333", "-5.7"
"Saint Kitts and Nevis", "KN", "KNA", "659", "17.3333", "-62.75"
"Saint Lucia", "LC", "LCA", "662", "13.8833", "-61.1333"
"Saint Pierre and Miquelon", "PM", "SPM", "666", "46.8333", "-56.3333"
"Saint Vincent and the Grenadines", "VC", "VCT", "670", "13.25", "-61.2"
"Saint Vincent & the Grenadines", "VC", "VCT", "670", "13.25", "-61.2"
"St. Vincent and the Grenadines", "VC", "VCT", "670", "13.25", "-61.2"
"Samoa", "WS", "WSM", "882", "-13.5833", "-172.3333"
"San Marino", "SM", "SMR", "674", "43.7667", "12.4167"
"Sao Tome and Principe", "ST", "STP", "678", "1", "7"
"Saudi Arabia", "SA", "SAU", "682", "25", "45"
"Senegal", "SN", "SEN", "686", "14", "-14"
"Serbia", "RS", "SRB", "688", "44", "21"
"Seychelles", "SC", "SYC", "690", "-4.5833", "55.6667"
"Sierra Leone", "SL", "SLE", "694", "8.5", "-11.5"
"Singapore", "SG", "SGP", "702", "1.3667", "103.8"
"Slovakia", "SK", "SVK", "703", "48.6667", "19.5"
"Slovenia", "SI", "SVN", "705", "46", "15"
"Solomon Islands", "SB", "SLB", "90", "-8", "159"
"Somalia", "SO", "SOM", "706", "10", "49"
"South Africa", "ZA", "ZAF", "710", "-29", "24"
"South Georgia and the South Sandwich Islands", "GS", "SGS", "239", "-54.5", "-37"
"South Sudan", "SS", "SSD", "728", "8", "30"
"Spain", "ES", "ESP", "724", "40", "-4"
"Sri Lanka", "LK", "LKA", "144", "7", "81"
"Sudan", "SD", "SDN", "736", "15", "30"
"Suriname", "SR", "SUR", "740", "4", "-56"
"Svalbard and Jan Mayen", "SJ", "SJM", "744", "78", "20"
"Swaziland", "SZ", "SWZ", "748", "-26.5", "31.5"
"Sweden", "SE", "SWE", "752", "62", "15"
"Switzerland", "CH", "CHE", "756", "47", "8"
"Syrian Arab Republic", "SY", "SYR", "760", "35", "38"
"Taiwan, Province of China", "TW", "TWN", "158", "23.5", "121"
"Taiwan", "TW", "TWN", "158", "23.5", "121"
"Tajikistan", "TJ", "TJK", "762", "39", "71"
"Tanzania, United Republic of", "TZ", "TZA", "834", "-6", "35"
"Thailand", "TH", "THA", "764", "15", "100"
"Timor-Leste", "TL", "TLS", "626", "-8.55", "125.5167"
"Togo", "TG", "TGO", "768", "8", "1.1667"
"Tokelau", "TK", "TKL", "772", "-9", "-172"
"Tonga", "TO", "TON", "776", "-20", "-175"
"Trinidad and Tobago", "TT", "TTO", "780", "11", "-61"
"Tunisia", "TN", "TUN", "788", "34", "9"
"Turkey", "TR", "TUR", "792", "39", "35"
"Turkmenistan", "TM", "TKM", "795", "40", "60"
"Turks and Caicos Islands", "TC", "TCA", "796", "21.75", "-71.5833"
"Tuvalu", "TV", "TUV", "798", "-8", "178"
"Uganda", "UG", "UGA", "800", "1", "32"
"Ukraine", "UA", "UKR", "804", "49", "32"
"United Arab Emirates", "AE", "ARE", "784", "24", "54"
"United Kingdom", "GB", "GBR", "826", "54", "-2"
"United States", "US", "USA", "840", "38", "-97"
"United States Minor Outlying Islands", "UM", "UMI", "581", "19.2833", "166.6"
"Uruguay", "UY", "URY", "858", "-33", "-56"
"Uzbekistan", "UZ", "UZB", "860", "41", "64"
"Vanuatu", "VU", "VUT", "548", "-16", "167"
"Venezuela, Bolivarian Republic of", "VE", "VEN", "862", "8", "-66"
"Venezuela", "VE", "VEN", "862", "8", "-66"
"Viet Nam", "VN", "VNM", "704", "16", "106"
"Vietnam", "VN", "VNM", "704", "16", "106"
"Virgin Islands, British", "VG", "VGB", "92", "18.5", "-64.5"
"Virgin Islands, U.S.", "VI", "VIR", "850", "18.3333", "-64.8333"
"Wallis and Futuna", "WF", "WLF", "876", "-13.3", "-176.2"
"Western Sahara", "EH", "ESH", "732", "24.5", "-13"
"Yemen", "YE", "YEM", "887", "15", "48"
"Zambia", "ZM", "ZMB", "894", "-15", "30"
"Zimbabwe", "ZW", "ZWE", "716", "-20", "30"
1 Country Alpha-2 code Alpha-3 code Numeric code Latitude (average) Longitude (average)
2 Afghanistan AF AFG 4 33 65
3 Albania AL ALB 8 41 20
4 Algeria DZ DZA 12 28 3
5 American Samoa AS ASM 16 -14.3333 -170
6 Andorra AD AND 20 42.5 1.6
7 Angola AO AGO 24 -12.5 18.5
8 Anguilla AI AIA 660 18.25 -63.1667
9 Antarctica AQ ATA 10 -90 0
10 Antigua and Barbuda AG ATG 28 17.05 -61.8
11 Argentina AR ARG 32 -34 -64
12 Armenia AM ARM 51 40 45
13 Aruba AW ABW 533 12.5 -69.9667
14 Australia AU AUS 36 -27 133
15 Austria AT AUT 40 47.3333 13.3333
16 Azerbaijan AZ AZE 31 40.5 47.5
17 Bahamas BS BHS 44 24.25 -76
18 Bahrain BH BHR 48 26 50.55
19 Bangladesh BD BGD 50 24 90
20 Barbados BB BRB 52 13.1667 -59.5333
21 Belarus BY BLR 112 53 28
22 Belgium BE BEL 56 50.8333 4
23 Belize BZ BLZ 84 17.25 -88.75
24 Benin BJ BEN 204 9.5 2.25
25 Bermuda BM BMU 60 32.3333 -64.75
26 Bhutan BT BTN 64 27.5 90.5
27 Bolivia, Plurinational State of BO BOL 68 -17 -65
28 Bolivia BO BOL 68 -17 -65
29 Bosnia and Herzegovina BA BIH 70 44 18
30 Botswana BW BWA 72 -22 24
31 Bouvet Island BV BVT 74 -54.4333 3.4
32 Brazil BR BRA 76 -10 -55
33 British Indian Ocean Territory IO IOT 86 -6 71.5
34 Brunei Darussalam BN BRN 96 4.5 114.6667
35 Brunei BN BRN 96 4.5 114.6667
36 Bulgaria BG BGR 100 43 25
37 Burkina Faso BF BFA 854 13 -2
38 Burundi BI BDI 108 -3.5 30
39 Cambodia KH KHM 116 13 105
40 Cameroon CM CMR 120 6 12
41 Canada CA CAN 124 60 -95
42 Cape Verde CV CPV 132 16 -24
43 Cayman Islands KY CYM 136 19.5 -80.5
44 Central African Republic CF CAF 140 7 21
45 Chad TD TCD 148 15 19
46 Chile CL CHL 152 -30 -71
47 China CN CHN 156 35 105
48 Christmas Island CX CXR 162 -10.5 105.6667
49 Cocos (Keeling) Islands CC CCK 166 -12.5 96.8333
50 Colombia CO COL 170 4 -72
51 Comoros KM COM 174 -12.1667 44.25
52 Congo CG COG 178 -1 15
53 Congo, the Democratic Republic of the CD COD 180 0 25
54 Cook Islands CK COK 184 -21.2333 -159.7667
55 Costa Rica CR CRI 188 10 -84
56 Côte d'Ivoire CI CIV 384 8 -5
57 Ivory Coast CI CIV 384 8 -5
58 Croatia HR HRV 191 45.1667 15.5
59 Cuba CU CUB 192 21.5 -80
60 Cyprus CY CYP 196 35 33
61 Czech Republic CZ CZE 203 49.75 15.5
62 Denmark DK DNK 208 56 10
63 Djibouti DJ DJI 262 11.5 43
64 Dominica DM DMA 212 15.4167 -61.3333
65 Dominican Republic DO DOM 214 19 -70.6667
66 Ecuador EC ECU 218 -2 -77.5
67 Egypt EG EGY 818 27 30
68 El Salvador SV SLV 222 13.8333 -88.9167
69 Equatorial Guinea GQ GNQ 226 2 10
70 Eritrea ER ERI 232 15 39
71 Estonia EE EST 233 59 26
72 Ethiopia ET ETH 231 8 38
73 Falkland Islands (Malvinas) FK FLK 238 -51.75 -59
74 Faroe Islands FO FRO 234 62 -7
75 Fiji FJ FJI 242 -18 175
76 Finland FI FIN 246 64 26
77 France FR FRA 250 46 2
78 French Guiana GF GUF 254 4 -53
79 French Polynesia PF PYF 258 -15 -140
80 French Southern Territories TF ATF 260 -43 67
81 Gabon GA GAB 266 -1 11.75
82 Gambia GM GMB 270 13.4667 -16.5667
83 Georgia GE GEO 268 42 43.5
84 Germany DE DEU 276 51 9
85 Ghana GH GHA 288 8 -2
86 Gibraltar GI GIB 292 36.1833 -5.3667
87 Greece GR GRC 300 39 22
88 Greenland GL GRL 304 72 -40
89 Grenada GD GRD 308 12.1167 -61.6667
90 Guadeloupe GP GLP 312 16.25 -61.5833
91 Guam GU GUM 316 13.4667 144.7833
92 Guatemala GT GTM 320 15.5 -90.25
93 Guernsey GG GGY 831 49.5 -2.56
94 Guinea GN GIN 324 11 -10
95 Guinea-Bissau GW GNB 624 12 -15
96 Guyana GY GUY 328 5 -59
97 Haiti HT HTI 332 19 -72.4167
98 Heard Island and McDonald Islands HM HMD 334 -53.1 72.5167
99 Holy See (Vatican City State) VA VAT 336 41.9 12.45
100 Honduras HN HND 340 15 -86.5
101 Hong Kong HK HKG 344 22.25 114.1667
102 Hungary HU HUN 348 47 20
103 Iceland IS ISL 352 65 -18
104 India IN IND 356 20 77
105 Indonesia ID IDN 360 -5 120
106 Iran, Islamic Republic of IR IRN 364 32 53
107 Iraq IQ IRQ 368 33 44
108 Ireland IE IRL 372 53 -8
109 Isle of Man IM IMN 833 54.23 -4.55
110 Israel IL ISR 376 31.5 34.75
111 Italy IT ITA 380 42.8333 12.8333
112 Jamaica JM JAM 388 18.25 -77.5
113 Japan JP JPN 392 36 138
114 Jersey JE JEY 832 49.21 -2.13
115 Jordan JO JOR 400 31 36
116 Kazakhstan KZ KAZ 398 48 68
117 Kenya KE KEN 404 1 38
118 Kiribati KI KIR 296 1.4167 173
119 Korea, Democratic People's Republic of KP PRK 408 40 127
120 Korea, Republic of KR KOR 410 37 127.5
121 South Korea KR KOR 410 37 127.5
122 Kuwait KW KWT 414 29.3375 47.6581
123 Kyrgyzstan KG KGZ 417 41 75
124 Lao People's Democratic Republic LA LAO 418 18 105
125 Latvia LV LVA 428 57 25
126 Lebanon LB LBN 422 33.8333 35.8333
127 Lesotho LS LSO 426 -29.5 28.5
128 Liberia LR LBR 430 6.5 -9.5
129 Libyan Arab Jamahiriya LY LBY 434 25 17
130 Libya LY LBY 434 25 17
131 Liechtenstein LI LIE 438 47.1667 9.5333
132 Lithuania LT LTU 440 56 24
133 Luxembourg LU LUX 442 49.75 6.1667
134 Macao MO MAC 446 22.1667 113.55
135 Macedonia, the former Yugoslav Republic of MK MKD 807 41.8333 22
136 Madagascar MG MDG 450 -20 47
137 Malawi MW MWI 454 -13.5 34
138 Malaysia MY MYS 458 2.5 112.5
139 Maldives MV MDV 462 3.25 73
140 Mali ML MLI 466 17 -4
141 Malta MT MLT 470 35.8333 14.5833
142 Marshall Islands MH MHL 584 9 168
143 Martinique MQ MTQ 474 14.6667 -61
144 Mauritania MR MRT 478 20 -12
145 Mauritius MU MUS 480 -20.2833 57.55
146 Mayotte YT MYT 175 -12.8333 45.1667
147 Mexico MX MEX 484 23 -102
148 Micronesia, Federated States of FM FSM 583 6.9167 158.25
149 Moldova, Republic of MD MDA 498 47 29
150 Monaco MC MCO 492 43.7333 7.4
151 Mongolia MN MNG 496 46 105
152 Montenegro ME MNE 499 42 19
153 Montserrat MS MSR 500 16.75 -62.2
154 Morocco MA MAR 504 32 -5
155 Mozambique MZ MOZ 508 -18.25 35
156 Myanmar MM MMR 104 22 98
157 Burma MM MMR 104 22 98
158 Namibia NA NAM 516 -22 17
159 Nauru NR NRU 520 -0.5333 166.9167
160 Nepal NP NPL 524 28 84
161 Netherlands NL NLD 528 52.5 5.75
162 Netherlands Antilles AN ANT 530 12.25 -68.75
163 New Caledonia NC NCL 540 -21.5 165.5
164 New Zealand NZ NZL 554 -41 174
165 Nicaragua NI NIC 558 13 -85
166 Niger NE NER 562 16 8
167 Nigeria NG NGA 566 10 8
168 Niue NU NIU 570 -19.0333 -169.8667
169 Norfolk Island NF NFK 574 -29.0333 167.95
170 Northern Mariana Islands MP MNP 580 15.2 145.75
171 Norway NO NOR 578 62 10
172 Oman OM OMN 512 21 57
173 Pakistan PK PAK 586 30 70
174 Palau PW PLW 585 7.5 134.5
175 Palestinian Territory, Occupied PS PSE 275 32 35.25
176 Panama PA PAN 591 9 -80
177 Papua New Guinea PG PNG 598 -6 147
178 Paraguay PY PRY 600 -23 -58
179 Peru PE PER 604 -10 -76
180 Philippines PH PHL 608 13 122
181 Pitcairn PN PCN 612 -24.7 -127.4
182 Poland PL POL 616 52 20
183 Portugal PT PRT 620 39.5 -8
184 Puerto Rico PR PRI 630 18.25 -66.5
185 Qatar QA QAT 634 25.5 51.25
186 Réunion RE REU 638 -21.1 55.6
187 Romania RO ROU 642 46 25
188 Russian Federation RU RUS 643 60 100
189 Russia RU RUS 643 60 100
190 Rwanda RW RWA 646 -2 30
191 Saint Helena, Ascension and Tristan da Cunha SH SHN 654 -15.9333 -5.7
192 Saint Kitts and Nevis KN KNA 659 17.3333 -62.75
193 Saint Lucia LC LCA 662 13.8833 -61.1333
194 Saint Pierre and Miquelon PM SPM 666 46.8333 -56.3333
195 Saint Vincent and the Grenadines VC VCT 670 13.25 -61.2
196 Saint Vincent & the Grenadines VC VCT 670 13.25 -61.2
197 St. Vincent and the Grenadines VC VCT 670 13.25 -61.2
198 Samoa WS WSM 882 -13.5833 -172.3333
199 San Marino SM SMR 674 43.7667 12.4167
200 Sao Tome and Principe ST STP 678 1 7
201 Saudi Arabia SA SAU 682 25 45
202 Senegal SN SEN 686 14 -14
203 Serbia RS SRB 688 44 21
204 Seychelles SC SYC 690 -4.5833 55.6667
205 Sierra Leone SL SLE 694 8.5 -11.5
206 Singapore SG SGP 702 1.3667 103.8
207 Slovakia SK SVK 703 48.6667 19.5
208 Slovenia SI SVN 705 46 15
209 Solomon Islands SB SLB 90 -8 159
210 Somalia SO SOM 706 10 49
211 South Africa ZA ZAF 710 -29 24
212 South Georgia and the South Sandwich Islands GS SGS 239 -54.5 -37
213 South Sudan SS SSD 728 8 30
214 Spain ES ESP 724 40 -4
215 Sri Lanka LK LKA 144 7 81
216 Sudan SD SDN 736 15 30
217 Suriname SR SUR 740 4 -56
218 Svalbard and Jan Mayen SJ SJM 744 78 20
219 Swaziland SZ SWZ 748 -26.5 31.5
220 Sweden SE SWE 752 62 15
221 Switzerland CH CHE 756 47 8
222 Syrian Arab Republic SY SYR 760 35 38
223 Taiwan, Province of China TW TWN 158 23.5 121
224 Taiwan TW TWN 158 23.5 121
225 Tajikistan TJ TJK 762 39 71
226 Tanzania, United Republic of TZ TZA 834 -6 35
227 Thailand TH THA 764 15 100
228 Timor-Leste TL TLS 626 -8.55 125.5167
229 Togo TG TGO 768 8 1.1667
230 Tokelau TK TKL 772 -9 -172
231 Tonga TO TON 776 -20 -175
232 Trinidad and Tobago TT TTO 780 11 -61
233 Tunisia TN TUN 788 34 9
234 Turkey TR TUR 792 39 35
235 Turkmenistan TM TKM 795 40 60
236 Turks and Caicos Islands TC TCA 796 21.75 -71.5833
237 Tuvalu TV TUV 798 -8 178
238 Uganda UG UGA 800 1 32
239 Ukraine UA UKR 804 49 32
240 United Arab Emirates AE ARE 784 24 54
241 United Kingdom GB GBR 826 54 -2
242 United States US USA 840 38 -97
243 United States Minor Outlying Islands UM UMI 581 19.2833 166.6
244 Uruguay UY URY 858 -33 -56
245 Uzbekistan UZ UZB 860 41 64
246 Vanuatu VU VUT 548 -16 167
247 Venezuela, Bolivarian Republic of VE VEN 862 8 -66
248 Venezuela VE VEN 862 8 -66
249 Viet Nam VN VNM 704 16 106
250 Vietnam VN VNM 704 16 106
251 Virgin Islands, British VG VGB 92 18.5 -64.5
252 Virgin Islands, U.S. VI VIR 850 18.3333 -64.8333
253 Wallis and Futuna WF WLF 876 -13.3 -176.2
254 Western Sahara EH ESH 732 24.5 -13
255 Yemen YE YEM 887 15 48
256 Zambia ZM ZMB 894 -15 30
257 Zimbabwe ZW ZWE 716 -20 30

27433
data/transactions.csv

File diff suppressed because it is too large

5001
data/x.csv

File diff suppressed because it is too large

114
panel.R

@ -0,0 +1,114 @@
countries <- read.csv("./data/countries.csv")
panel1<-
tabPanel(
"Home",
fluidRow(column(
width = 11,
fluidRow(
column(
width = 8,
tags$div(
tags$blockquote(
"LoanRisk is being built to provide convenience to Finance and Accounting consultants and SMEs in finance industry."
),
p(
"IFRS reporting, especially estimated loss calculation is a fairly complicated process involving Monte Carlo simulation, forecasting, survival modelling (or other predictive algorithm) and financial mathematics.
Naturally, it is time consuming and has its share of hassles. This app attempts to avoid all the hassles of setting up environment and tools to perform the multistep analysis.
This app will calculate the provisioning requirements in a few clicks and one can download the report with a single click!"
),
p("The basic steps are mentioned in the diagram on the left hand side. The app is not in its most evolved form yet.
There is a huge list of features and functions that I personally want to include and implement in future."),
h6("How to use?"),
p("Using the tool is very simple. You can upload two data sets. One that shows a certain number of transactions of each asset, along with some dates, parameters and event outcome.
And the other that contains value of collateral or estimated value of sales of the asset/hypothecated asset. Then proceed further with the clicks and in between select some parameters.
For e.g. the discount rate to be applied, the most probable, maximum possible and minimum possible depreciation of value of the collateral.
Once the simulation is done, you can download the report in pdf format.")#,
# "If you are a R coder, you are welcome to contribute and help improve. Please visit the ",
# tags$a(href = "https://github.com/asitav-sen/LoanRisk", "github page"),
# " or ",
# tags$a(href = "www.asitavsen.com", "contact me."),
# "Please use this ",
# tags$a(href = "https://github.com/asitav-sen/LoanRisk/issues", "link"),
# " to report issues and/or request new features/functions.", "For general discussions, please use this",tags$a(href = "https://github.com/asitav-sen/LoanRisk/discussions", "link"),
# tags$br(),
# tags$image(height=100, width=100,src="logo3.png")
)
),
column(
width = 4,
mermaid("
graph TB
A[Data Upload]-->B[Downloading macroeconomic data]
B[Downloading macroeconomic data from IMF]-->C[Forecasting macroeconomic parameters]
C[Forecasting macroeconomic parameters]-->D[Fit Survival Model]
D[Fit Survival Model]-->E[Monte Carlo Simulation]
E[Monte Carlo Simulation]-->F[Report]
")
)
),
))#,
# tags$hr(),
# fluidRow(
# column(
# width = 6,
# fluidRow(
# h3("Data"),
# br(),
# p("This section shows the data (uploaded or inbuilt sample).")
# ),
# br(),
# withSpinner(dataTableOutput("up_data"),type = 7,
# color = "black"),
# br(),
# actionButton("uploadnew", "Upload New Data", class="btn-light")
# ),
# column(width = 6,
# br(),
# basicstatUI("nofloans"))
#
# ),
# br(),
# br(),
# fluidRow(
# column(
# width = 6,
# h3("With Macroeconomic data"),
# p(
# "In this section, we add macroeconomic data. Please select the country of the asset and click on fetch button. If download fails, click again or try after sometime. Please note that GDP data has been discontinued by IMF recently. Hence, using Industrial output temporarily."
# ),
# column(
# width = 6,
# selectInput(
# "country",
# "Country",
# selected = "India",
# choices = countries$Country
# )
# ),
# column(
# width = 6,
# br(),
# actionButton("fetchimf", "Fetch IMF data", class = "glow")
# ),
# withSpinner(
# dataTableOutput("fulldata"),
# type = 7,
# color = "black"
# )
# ),
# column(width = 6,
# uiOutput("ac_button"),
# uiOutput("expcalcu"))
# ),
# br(),
# br(),
# fluidRow(column(width = 11,
# uiOutput("scenario_opts"))),
# br(),
# fluidRow(column(width = 11,
# uiOutput("credit_loss"))),
# fluidRow(column(width = 11,
# uiOutput("dlmanager")))
)
Loading…
Cancel
Save