forked from AntoineSoetewey/mortgage-calculator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.R
More file actions
161 lines (146 loc) · 6.22 KB
/
Copy pathapp.R
File metadata and controls
161 lines (146 loc) · 6.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
library(dplyr)
library(DT)
library(ggplot2)
library(reshape2)
library(scales)
options(scipen = 999)
# Define UI for slider demo app ----
ui <- fluidPage(
# App title ----
titlePanel("Mortgage Calculator"),
h4(tags$a(href = "https://www.antoinesoetewey.com/", "Antoine Soetewey")),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar to demonstrate various slider options ----
sidebarPanel(
# Input: Simple integer interval ----
numericInput("principal", "Principal (loan amount)", 200000, min = 0, step = 1000),
hr(),
numericInput("interest", "Annual interest rate (in %)", 2, min = 0, max = 100, step = 0.01),
hr(),
sliderInput("length", "Duration of the loan (in years)",
min = 0,
max = 30,
value = 25,
step = 1
),
hr(),
checkboxInput("plot", "Display plot?", TRUE),
hr(),
HTML('<p>Report a <a href="https://github.com/AntoineSoetewey/mortgage-calculator/issues">bug</a> or view the <a href="https://github.com/AntoineSoetewey/mortgage-calculator">code</a>. See more information about this app in this <a href="https://statsandr.com/blog/mortgage-calculator-r-shiny">article</a>. Back to <a href="https://www.antoinesoetewey.com/">antoinesoetewey.com</a> or <a href="https://statsandr.com/">statsandr.com</a>.</p>')
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Table summarizing the values entered ----
uiOutput("text"),
br(),
plotOutput("distPlot"),
br(),
DT::dataTableOutput("tbl"),
br(),
p(em("Disclosure: Note that this application does not include investment advice or recommendations, nor a financial analysis. This application is intended for information only and you invest at your own risks. I cannot be held liable for any decision made based on the information contained in this application, nor for its use by third parties.")),
p(em("This R Shiny app is partially based on the R code of Prof. Thomas Girke.")),
br(),
br()
)
)
)
# Define server logic for slider examples ----
server <- function(input, output) {
mortgage <- function(P = 500000, I = 6, L = 30, amort = TRUE, plotData = TRUE) {
J <- I / (12 * 100)
N <- 12 * L
M <- P * J / (1 - (1 + J)^(-N))
monthPay <<- M
# Calculate Amortization for each Month
if (amort == TRUE) {
Pt <- P # current principal or amount of the loan
currP <- NULL
while (Pt >= 0) {
H <- Pt * J # this is the current monthly interest
C <- M - H # this is your monthly payment minus your monthly interest, so it is the amount of principal you pay for that month
Q <- Pt - C # this is the new balance of your principal of your loan
Pt <- Q # sets P equal to Q and goes back to step 1. The loop continues until the value Q (and hence P) goes to zero
currP <- c(currP, Pt)
}
monthP <- c(P, currP[1:(length(currP) - 1)]) - currP
aDFmonth <<- data.frame(
Month = 1:length(currP),
Year = sort(rep(1:ceiling(N / 12), 12))[1:length(monthP)],
Balance = c(currP[1:(length(currP))]),
Payment = monthP + c((monthPay - monthP)[1:(length(monthP))]),
Principal = monthP,
Interest = c((monthPay - monthP)[1:(length(monthP))])
)
aDFmonth <<- subset(aDFmonth, Year <= L * 12)
aDFyear <- data.frame(
Amortization = tapply(aDFmonth$Balance, aDFmonth$Year, max),
Annual_Payment = tapply(aDFmonth$Payment, aDFmonth$Year, sum),
Annual_Principal = tapply(aDFmonth$Principal, aDFmonth$Year, sum),
Annual_Interest = tapply(aDFmonth$Interest, aDFmonth$Year, sum),
Year = as.factor(na.omit(unique(aDFmonth$Year)))
)
aDFyear <<- aDFyear
}
if (plotData == TRUE) {
aDFyear2 <- aDFyear %>%
rename(
Interest = Annual_Interest,
Payment = Annual_Payment,
Principal = Annual_Principal
)
aDFyear2$Year <- as.factor(aDFyear2$Year)
aDFyear2 <- melt(aDFyear2[, c("Interest", "Principal", "Year")], id.vars = "Year")
ggplot(aDFyear2, aes(x = Year, y = value, fill = variable)) +
geom_bar(position = "fill", stat = "identity") +
labs(y = "Payment") +
scale_y_continuous(labels = percent) +
theme_minimal() +
theme(legend.title = element_blank(), legend.position = "top")
}
}
output$text <- renderUI({
mortgage(P = input$principal, I = input$interest, L = input$length, plotData = FALSE)
HTML(paste0(
"<h3>", "Summary", "</h3>",
"Principal (loan amount): ", format(round(input$principal, 2), big.mark = ","),
"<br>",
"Annual interest rate: ", input$interest, "%",
"<br>",
"Term: ", input$length, " years (", input$length * 12, " months)",
"<br>",
"<b>", "Monthly payment: ", format(round(monthPay, digits = 2), big.mark = ","), "</b>",
"<br>",
"<b>", "Total cost: ", "</b>", format(round(input$principal, 2), big.mark = ","), " (principal) + ", format(round(monthPay * 12 * input$length - input$principal, 2), big.mark = ","), " (interest) = ", "<b>", format(round(monthPay * 12 * input$length, digits = 2), big.mark = ","), "</b>"
))
})
output$distPlot <- renderPlot({
mortgage(P = input$principal, I = input$interest, L = input$length, plotData = input$plot)
})
# Data output
output$tbl <- DT::renderDataTable({
mortgage(P = input$principal, I = input$interest, L = input$length, plotData = FALSE)
df_month <- DT::datatable(data.frame(round(aDFmonth, 2)),
extensions = "Buttons",
options = list(
lengthChange = TRUE,
dom = "Blrtip",
buttons = c("copy", "csv", "excel", "pdf", "print"),
lengthMenu = list(c(-1, 10, 12, 15, 25, 50, 100), c("All", "10", "12", "15", "25", "50", "100"))
),
rownames = FALSE
) %>%
formatCurrency(c("Balance", "Payment", "Principal", "Interest"), currency = "", interval = 3, mark = ",")
})
}
# Run the application
shinyApp(ui = ui, server = server)