来源头条作者:Python小白分享师
逐步指南,旨在构建有用的Python仿真器,以帮助您更好地了解房屋净值及其潜在的未来增长。
抵押贷款不仅仅是在规定的付款期限内根据约定的金额每月还款。如果对抵押贷款的还款机制及其潜在风险没有很好的了解,抵押贷款很容易危及我们的财务。
在这里,我们通过一步步实践开发一个
Python的模拟器
,可以在长期模拟抵押贷款的偿还。该模拟器还将使我们能够实现可视化贷款摊销和房屋净值的未来增长。您可能会惊讶于看似略高的贷款利率会严重影响房屋净值。
必备的Python库
在开始开发过程之前,必须确保您有一下库:
Streamlit — https://www.streamlit.io/
Plotly — https://plotly.com/python/
Numpy — https://numpy.org/
本文预计阅读12分钟
如果您需要获得本篇文章的源代码,可以点赞本篇文章, 然后私信我
@Python小白分享师
获得完整的源代码,
1.导入库
首先,我们将所有必需的库都导入程序中。
import streamlit as st
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
2.设置页面标题
在这里,我们将开始使用Streamlit来构建我们的模拟器。Streamlit是用于开发数据应用程序的开源Python框架。
首先,让我们为浏览器选项卡和主页设置页面标题。
#使用Streamlit?set_page_config中的page_title定义浏览器选项卡的标题。
st.set_page_config(page_title=\”Mortgage Loan Simulator\”)
#创建模拟器的主标题。
st.title(\”Mortgage Loan Simulator\”)
此时,我们可以尝试运行Streamlit应用程序以可视化输出。为此,我们在终端/命令提示符下键入以下命令。
streamlit run YourPythonFileName.py
(注意:在运行应用程序之前,请确保已导航到保留脚本文件的目录。)
我们应该看到如下输出:
3.创建用于抵押详细信息的输入字段
为了模拟抵押付款,我们需要四项信息,分别是
房屋价值,预付定金百分比,贷款利率和还款期限
。
在本节中,我们将使用Streamlit构建四个数字输入字段,以获取用户对上述四条信息的输入。
#创建标题。
st.header(\”**Mortgage Details**\”)
#定义两列以放置我们的输入字段。
col1, col2 = st.beta_columns(2)
#在第一列中,创建相关的子标题,
#并使用Streamlit number_input方法创建房屋价值和利率的数字输入字段。
#我们将最小值设置为零,将输入格式设置为十进制数。
with col1:
st.subheader(\”Home Value\”)
home_value = st.number_input(\”Enter your home value($): \”, min_value=0.0, format=\’%f\’)
st.subheader(\”Loan Interest Rate\”)
interest_rate = st.number_input(\”Enter your home loan interest rate(%): \”, min_value=0.0, format=\’%f\’)
#在第二列中,重复上述类似的过程,
#以创建预付款百分比和付款年限的相关子标题和数字输入字段。
with col2:
st.subheader(\”Down Payment Percent\”)
down_payment_percent = st.number_input(\”Enter your down payment percent(%): \”, min_value=0.0, format=\’%f\’)
st.subheader(\”Target Payment Period (Years)\”)
payment_years = st.number_input(\”Enter your target payment period (years): \”, min_value=3, format=\’%d\’)
4.每月分期付款计算
准备好这四个信息之后,我们现在可以计算每月的分期付款了。这将使我们对按揭还款的每月承诺有一个大概的了解。
#通过从房屋价值中减去预付款来计算贷款金额。
#将付款年数乘以十二即可得出付款月总数。
#将利率转换为小数。
down_payment = home_value* (down_payment_percent / 100)
loan_amount = home_value – down_payment
payment_months = payment_years*12
interest_rate = interest_rate / 100
#根据输入的利率,我们使用公式计算定期利率
periodic_interest_rate = (1+interest_rate)**(1/12) – 1
monthly_installment = -1*np.pmt(periodic_interest_rate , payment_months, loan_amount)
#显示我们的模拟器的预付款,贷款额和每月分期付款。
st.subheader(\”**Down Payment:** #34; + str(round(down_payment,2)))
st.subheader(\”**Loan Amount:** #34; + str(round(loan_amount, 2)))
st.subheader(\”**Monthly Installment:** #34; + str(round(monthly_installment, 2)))
定期利率是在较短时期(例如1个月)内表示的年利率。由于抵押贷款是按月还款,因此我们的目标是获得每月定期利息,因此N = 12。最后,使用
Numpy pmt
方法根据定期利率,还款总月数和贷款额来计算每月分期付款额。
Numpy pmt
方法将封装计算逻辑,并自动产生每月的分期付款金额。
让我们尝试在抵押详细信息的那些数字输入字段上输入一组样本值:
房屋价值— 500000
首付款百分比— 10
贷款利率— 4.5
目标付款期限(年)— 30
模拟器处理我们的样本输入,每月分期付款2256.02。
5.抵押贷款摊销
在此阶段,我们的模拟器能够根据我们提供的抵押详细信息的输入值来估算每月的分期付款金额。但是,仅按月分期付款的数量并不能使我们知道我们的付款分别占贷款本金和贷款利息的多少。尽管每月的每月分期付款总额是相同的,但涵盖贷款本金和贷款利息的金额比例会随时间而有所不同。
在本节中,我们将为抵押贷款生成一个
摊销时间表
。摊销时间表是一个表,显示了每个月分期付款直到全部还清贷款之前的贷款本金和贷款利息额。此外,我们还将绘制一个图表,以直观地显示构成我们每月分期付款的贷款本金和贷款利息的每月变化。
st.markdown(\”—\”)
st.header(\”**抵押贷款摊销**\”)
#创建三个Numpy系列,以保存剩余本金,
#每月支付的本金和支付的利息的值。
#用零初始化每个Numpy系列。
principal_remaining = np.zeros(payment_months)
interest_pay_arr = np.zeros(payment_months)
principal_pay_arr = np.zeros(payment_months)
#创建一个循环来迭代计算构成当月分期付款的本金和利息。
#当前的利息支付是基于定期利率与先前剩余本金的乘积来计算的(第23行)。
#从每月的分期付款中减去所产生的利息,将得出该特定月份的本金(第24行)。
#将当前的利息支付,本金支付以及剩余的本金存储到之前创建的三个Numpy系列中(第29-31行)。
for i in range(0, payment_months):
if i == 0:
previous_principal_remaining = loan_amount
else:
previous_principal_remaining = principal_remaining[i-1]
interest_payment = round(previous_principal_remaining*periodic_interest_rate, 2)
principal_payment = round(monthly_installment – interest_payment, 2)
if previous_principal_remaining – principal_payment < 0:
principal_payment = previous_principal_remaining
interest_pay_arr[i] = interest_payment
principal_pay_arr[i] = principal_payment
principal_remaining[i] = previous_principal_remaining – principal_payment
month_num = np.arange(payment_months)
month_num = month_num + 1
principal_remaining = np.around(principal_remaining, decimals=2)
#使用Python Plotly make_subplots方法创建一个包含表格和图表的复合图形。
fig = make_subplots(
rows=2, cols=1,
vertical_spacing=0.03,
specs=[[{\"type\": \"table\"}],
[{\"type\": \"scatter\"}]
]
)
#使用Plotly go.Table对象创建一个表,该表显示每月本金支付,
#利息支付和剩余本金。将先前创建的Numpy系列插入单元格的值中(第44-46行)。
#使用add_trace方法将表添加到合成图形对象中。
fig.add_trace(
go.Table(
header=dict(
values=[\'Month\', \'Principal Payment($)\', \'Interest Payment($)\', \'Remaining Principal($)\']
),
cells = dict(
values =[month_num, principal_pay_arr, interest_pay_arr, principal_remaining]
)
),
row=1, col=1
)
#使用Plotly go.Scatter对象为几个月内的本金付款创建一个折线图。
#将Numpy系列的本金付款设置为y轴值。
#再次使用add_trace方法将图添加到合成图形对象中
fig.add_trace(
go.Scatter(
x=month_num,
y=principal_pay_arr,
name= \"Principal Payment\"
),
row=2, col=1
)
#以类似的方式,使用Plotly go.Scatter对象创建一个折线图,
#用于支付数月的利息。这次,我们使用append_trace方法添加折线图,
#以便在同一张图表中将其与本金支付的折线图重叠。
fig.append_trace(
go.Scatter(
x=month_num,
y=interest_pay_arr,
name=\"Interest Payment\"
),
row=2, col=1
)
#通过设置相关的标题,尺寸和图例来配置合成图形的布局。
fig.update_layout(title=\'Mortgage Installment Payment Over Months\',
xaxis_title=\'Month\',
yaxis_title=\'Amount($)\',
height= 800,
width = 1200,
legend= dict(
orientation=\"h\",
yanchor=\'top\',
y=0.47,
xanchor= \'left\',
x= 0.01
)
)
#使用Streamlit plotly_chart方法呈现合成图形。
st.plotly_chart(fig, use_container_width=True)
从摊销表和上面的线图可以看出,我们的每月分期付款大部分用于支付付款时间表的早期阶段的贷款利息。在最初的几年中,我们的分期付款中只有一小部分会支付本金。
但是,这种趋势会随着时间而改变。由于利息支付是根据先前剩余本金的定期利率计算的,因此,持续的还款将导致利息支付从一个月到另一个月稳步减少。在分期偿还时间表的后期,我们会发现每月分期付款的大部分用于支付我们的贷款本金。
6.房屋净值(具有恒定的市场价值)
持续偿还抵押贷款不仅会不时减少我们的利息支付,而且还会不断增加我们的房屋净值。基本上,
房屋
净值是我们在任何给定时间实际拥有的房屋当前价值的一部分。
假设我们以市场价格500,000购买,而我们的首付是10%。这意味着我们的初始房屋净值等于我们的定金50,000。当我们开始偿还抵押贷款时,只要分期付款,我们的房屋净值就会累积起来。例如,如果我们分三个月分期付款,累计本金总额为2700,那么我们最新的房屋净值为50,000 + 2700 = 52700。
通过假定房屋的市场价值在我们的还款期内保持不变,我们的房屋净值将等于抵押权期满时的500,000的市场价格。
让我们将图添加到模拟器中以显示更清晰的图片。
st.markdown(\”—\”)
st.header(\”**Home Equity (With Constant Market Value)**\”)
#使用Numpy cumsum方法获得本金付款和利息付款系列的累加总和。
#本金的累积总和等于累积房屋净值(假定该物业的市场价值保持不变)。
cumulative_home_equity = np.cumsum(principal_pay_arr)
cumulative_interest_paid = np.cumsum(interest_pay_arr)
#创建一个Plotly Fig对象以显示折线图。
fig = go.Figure()
#使用Plotly go.Scatter对象创建一个折线图,以显示几个月内的累计房屋净值。
#使用add_trace方法将线图添加到无花果对象。
fig.add_trace(
go.Scatter(
x=month_num,
y=cumulative_home_equity,
name=\”Cumulative Home Equity\”
)
)
#以类似的方式,使用Plotly go.Scatter对象创建另一个折线图,
#以显示几个月内支付的累计利息并将其添加到fig对象。
fig.add_trace(
go.Scatter(
x=month_num,
y=cumulative_interest_paid,
name=\”Cumulative Interest Paid\”
)
)
#通过设置图表图形的标题名称,x轴和y轴标题,尺寸和图例来配置布局。
fig.update_layout(title=\’Cumulative Home Equity Over Time\’,
xaxis_title=\’Month\’,
yaxis_title=\’Amount($)\’,
height= 500,
width = 1200,
legend= dict(
orientation=\”h\”,
yanchor=\’top\’,
y=0.98,
xanchor= \’left\’,
x= 0.01
)
)
st.plotly_chart(fig, use_container_width=True)
从上面的折线图中,我们可以看到我们的累计房屋净值逐月增加,直到在还款期末达到峰值。此外,我们还可以观察到,我们的累计房屋净值仅会在314个月之后(接近还款期末)超过累积的利息支付。
假设如果我们在模拟器中调整贷款的年利率并将其从4.5降低到4。一旦更改了值,我们的图将自动更新。
降低0.5%的年利率,我们可以看到最终支付的最终利息大大减少了。大约在278个月之后,我们的累计房屋净值将超过累计利息。这就是为什么我们一直在寻找能够为我们的抵押贷款提供最佳利率的金融机构的原因。
现在,如果我们将付款期限从30年调整为25年该怎么办?让我们看看随着时间的推移它将如何影响我们的累积房屋净值。
随着贷款还款期的缩短,累计支付的利息将大大减少。我们的累计房屋净值将高于抵押贷款到期后大致支付的累计利息。这表明,虽然我们可以为租期更长的每月支付较低的分期付款,但从长远来看,我们承担着沉重的利息成本。从长远来看,在控制我们当前的财务承诺和利润方面应该保持平衡。
7.预测房屋净值增长
最后,让我们向抵押贷款模拟器添加增长预测功能。在上一节中,房屋净值的演变完全基于我们在整个贷款期限内的本金支付,而没有考虑房屋市值的增长。
如果房屋的市场价值每年都在变化(这种情况经常发生),那么房屋净值将如何变化。重要的是要注意增长不一定是正数。也会出现负增长。
在这里,我们添加了另一个输入字段,以在模拟器中获得用户对预测增长率的输入,并且还创建了折线图以显示随时间推移的预测房屋价值和预测房屋净值。
st.markdown(\”—\”)
st.header(\”**预测增长**\”)
#为每年的国内市场价值增长率创建一个相关的子标题和一个新的数字输入字段
st.subheader(\”Forecast Growth (Per Year)\”)
forecast_growth = st.number_input(\”Enter your forecast growth rate(%): \”, format=\’%f\’)
#将年度预测增长率转换为月增长率。
#创建一个增长数组,并使用Numpy full方法用月增长率填充它
growth_per_month = (forecast_growth / 12.0) / 100
growth_array = np.full(payment_months, growth_per_month)
#使用Numpy cumprod方法来计算几个月内增长率的累积乘积。
#将所得的累积增长乘以原始房屋价值。这将导致预测房屋价值系列。
forecast_cumulative_growth = np.cumprod(1+growth_array)
forecast_home_value= home_value*forecast_cumulative_growth
#计算过去几个月中房屋所有权的累计百分比。
#将此累积百分比乘以预测房屋价值系列,将得出预测房屋净值系列。
cumulative_percent_owned = (down_payment_percent/100) + (cumulative_home_equity/home_value)
forecast_home_equity = cumulative_percent_owned*forecast_home_value
#重复前面部分中介绍的类似步骤,以创建折线图,
#以显示几个月内的预测房屋价值,几个月内的预测房屋净值和几个月内的剩余本金。
#使用Plotly add_trace方法将三个折线图添加到同一图表。
#通过设置相关标题,x轴和y轴标题,尺寸和图例来配置统计图布局。
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=month_num,
y=forecast_home_value,
name=\”Forecast Home Value\”
)
)
fig.add_trace(
go.Scatter(
x=month_num,
y=forecast_home_equity,
name=\”Forecast Home Equity Owned\”
)
)
fig.add_trace(
go.Scatter(
x=month_num,
y=principal_remaining,
name=\”Remaining Principal\”
)
)
fig.update_layout(title=\’Forecast Home Value Vs Forecast Home Equity Over Time\’,
xaxis_title=\’Month\’,
yaxis_title=\’Amount($)\’,
height= 500,
width = 1200,
legend= dict(
orientation=\”h\”,
yanchor=\’top\’,
y=1.14,
xanchor= \’left\’,
x= 0.01
)
)
#第53行:绘制图表。
st.plotly_chart(fig, use_container_width=True)
通过设置每年3%的增长率,我们将看到我们的国内市场价值在300个月(25年)后将翻倍。虽然我们仍按月分期还款,但我们的房屋净值在202个月后已超过原始房屋价值(500,000美元)。在还款期结束时,我们的房屋净值等于预测房屋价值,即原始房屋价值的200%。房屋净值的这种增加可以为我们提供机会,可以将房屋净值转换为现金的房屋净值贷款。
现在,让我们尝试再次将负值-5调整为增长率,并观察其对一段时间内我们房屋净值的影响。
从上面的线图中可以看出,在300个月(25年)后,房屋价值已大幅贬值至原始市场价值的30%左右。这也意味着我们的房屋净值也将在抵押期限结束时折旧。折旧财产使我们蒙受了巨大损失。
此外,还有相当长的一段时间(大约在第57个月至第169个月之间),我们的房屋价值低于剩余的本金金额。这种情况被称为
水下抵押贷款
。在此期间,除非我们有足够的现金来支付损失,否则我们将没有任何可用于信贷的权益,甚至可能阻止我们出售房屋。水下抵押贷款是
2008年金融危机
期间的一个普遍问题。
结论
房屋投资可能会非常有益,但这是一个充满风险的长期过程。在我们自己的财务计划中,需要仔细的市场分析和良好的自我控制。希望这里展示的Python模拟器可以为您提供有关抵押贷款的生动想法。任何投资都绝不会是一个随机的猜测活动,而是需要对未来情况进行一些可靠的预测,这将有助于我们做出更体面的决策。
祝您阅读本文愉快。