Instruction and workflow added
This commit is contained in:
6
.Rproj.user/178A6739/sources/prop/48F98022
Normal file
6
.Rproj.user/178A6739/sources/prop/48F98022
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"source_window_id": "",
|
||||
"Source": "Source",
|
||||
"cursorPosition": "50,5",
|
||||
"scrollLine": "25"
|
||||
}
|
||||
4
.Rproj.user/178A6739/sources/prop/9D91FFC1
Normal file
4
.Rproj.user/178A6739/sources/prop/9D91FFC1
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"source_window_id": "",
|
||||
"Source": "Source"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"source_window_id": "",
|
||||
"Source": "Source",
|
||||
"cursorPosition": "29,10",
|
||||
"scrollLine": "4"
|
||||
"cursorPosition": "36,2",
|
||||
"scrollLine": "0"
|
||||
}
|
||||
@@ -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
Normal file
26
.Rproj.user/178A6739/sources/session-99529da2/58AD392C
Normal file
@@ -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
Normal file
114
.Rproj.user/178A6739/sources/session-99529da2/58AD392C-contents
Normal file
@@ -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
Normal file
141
.Rproj.user/178A6739/sources/session-99529da2/AB2E26D4-contents
Normal file
@@ -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"
|
||||
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
@@ -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
Normal file
1
.Rproj.user/shared/notebooks/paths
Normal file
@@ -0,0 +1 @@
|
||||
/Users/asitav/Projects/LoanRisk/mod_basic.R="53362AD0"
|
||||
873
app.R
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
Normal file
1631
data/collateral.csv
Normal file
File diff suppressed because it is too large
Load Diff
257
data/countries.csv
Normal file
257
data/countries.csv
Normal file
@@ -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"
|
||||
|
27433
data/transactions.csv
Normal file
27433
data/transactions.csv
Normal file
File diff suppressed because it is too large
Load Diff
5001
data/x.csv
Normal file
5001
data/x.csv
Normal file
File diff suppressed because it is too large
Load Diff
114
panel.R
Normal file
114
panel.R
Normal file
@@ -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")))
|
||||
)
|
||||
Reference in New Issue
Block a user