用Python分析房屋抵押贷款 —— 带着Python玩金融(3)

你打算买房了,可是你对抵押贷款却是一头雾水。每月该还多少呢?利息占多少?房子几成属于自己呢?房价上涨或下跌时怎么估算房产价值?别担心,本文将通过Python带你一步步算清这其中的门道。

每月还款额

抵押贷款是指购房者将所购房屋作为抵押,从银行获得贷款,并且按照一定的利率分期还款给银行。
假如你打算按揭贷款一套500万的房子,首付三成,我们先来计算首付和贷款的金额。

import numpy as np

# 设置房屋总价值
home_value = 5000000
# 设置首付比例
down_payment_percent = 0.3

# 计算首付金额
down_payment = home_value * down_payment_percent
print("首付金额: " + str(down_payment))
# 计算贷款额度
mortgage_loan = home_value - down_payment
print("贷款金额: " + str(mortgage_loan))
首付金额: 1500000.0
贷款金额: 3500000.0

假设商业贷款的年利率是5.6%,那么在计算每月还款额之前,我们需要先将年利率换算成月利率。注意这里采用的是复利,12个月累计的复利等价于1年的年利率,表述成数学公式如下:

(1 + R_{Month})^{12} = 1 + R_{Annual}

其中 R_{Month} 是月利率, R_{Annual} 是年利率。将上述等式变换一下,我们就得到月利率的计算公式。

R_{Month} = (1 + R_{Annual})^\frac{1}{12} - 1

使用该公式,在python中计算贷款的月利率。

# 设置年利率
annual_rate = 0.056
# 计算月利率
month_rate = (1 + annual_rate) ** (1/12) -1
print("贷款的月利率:", round(month_rate,6))
贷款的月利率: 0.004551

假设贷款30年,那么贷款的总期数是:

# 计算贷款期数
payment_periods = 12 * 30
print("贷款总期数:", payment_periods)
贷款总期数: 360

接下来就可以计算每月的按揭还款额了,这里采用等额本息的还款方式,即每月的还款额固定。我们可使用Numpy包中的.pmt() 函数来计算,该函数说明如下:

numpy.pmt(rate, nper, pv)

  • rate:定期利率
  • nper:总的支付期数
  • pv:抵押贷款的总额度
# 计算每月还款额
periodic_payment = -np.pmt(rate=month_rate, nper=payment_periods, pv=mortgage_loan)
print("每月的按揭还款额: " + str(round(periodic_payment, 2)))
每月的按揭还款额: 19787.51

每期偿还的本金和利息

我们采用等额本息还款,每月还款的额度固定,先支付剩余本金产生的利息,然后才归还本金。由于贷款的额度很高,在贷款初期,主要支付的是利息部分;随着时间的推移,利息在还款额中所占的比例将越来低,而本金部分的比例越来越高。为了说明这一点,接下来我们将具体计算利息和本金部分,并绘制其曲线图。

首先来看第一期还款的情况,先支付贷款利息。

initial_interest = mortgage_loan * month_rate
print("第一期支付的利息: " + str(round(initial_interest, 2)))
第一期支付的利息: 15928.52

每期的还款额减去利息,剩下的才是对本金部分的还款。

initial_principal = periodic_payment - initial_interest
print("第一期支付的本金: " + str(round(initial_principal, 2)))
第一期支付的本金: 3858.99

第一期还款中利息部分占了大头。下面我们将使用循环来计算每一期还款的利息和本金部分,并将这些数值存储到NumPy数组中。

# 初始化numpy数组,长度等于总支付期数,初始值设为0.0
principal_remaining = np.repeat(0., payment_periods)  # 剩余本金
interest_paid = np.repeat(0., payment_periods)        # 每期支付的利息部分
principal_paid = np.repeat(0., payment_periods)       # 每期支付的本金部分


# 计算每一期还款的利息和本金部分
for i in range(0, payment_periods):
    
    # 将上一期还款后剩余的本金存储在变量previous_principal_remaining中
    # 如果是第一期,previous_principal_remaining的值等于总的贷款额度
    if i == 0:
        previous_principal_remaining = mortgage_loan
    else:
        previous_principal_remaining = principal_remaining[i-1]
        
    # 根据前一次还款后剩余的本金,计算本次还款的利息和本金部分
    interest_payment = previous_principal_remaining * month_rate
    principal_payment = periodic_payment - interest_payment

    # 在最后一次还款时,如果剩余本金小于上面计算的还款本金,
    # 则还款本金将等于剩余本金
    if previous_principal_remaining < principal_payment:
        principal_payment = previous_principal_remaining
        
    # 将本期还款的利息、本金和剩余本金存储到数组中
    interest_paid[i] = interest_payment
    principal_paid[i] = principal_payment
    principal_remaining[i] = previous_principal_remaining - principal_payment

    # 输出前5次还款的情况
    if i < 5 :
        print("第"+str(i+1)+"期--利息:" \
              + str(round(interest_payment,2)) + "  本金:" \
              + str(round(principal_payment,2)) + "  剩余本金" \
              + str(round(principal_remaining[i],2)))
第1期--利息:15928.52  本金:3858.99  剩余本金3496141.01
第2期--利息:15910.96  本金:3876.55  剩余本金3492264.46
第3期--利息:15893.32  本金:3894.19  剩余本金3488370.26
第4期--利息:15875.6  本金:3911.92  剩余本金3484458.35
第5期--利息:15857.79  本金:3929.72  剩余本金3480528.63

我们将用图表更直观的表现每期还款中利息和本金的变化。

from matplotlib import pyplot as plt  # 使用matplotlib绘图库
%config InlineBackend.figure_format = 'retina' # 设置图片清晰度
plt.rcParams['font.sans-serif']=['SimHei'] #设置中文字体

# 绘图
plt.plot(interest_paid, color="red", label="利息")
plt.plot(principal_paid, color="blue", label="本金")
plt.legend(loc=2)
plt.xlabel("贷款期数")
plt.ylabel("金额")
plt.show()

从上图中可以明显看出,随着时间的流逝,还款额中利息的比例越来越少,而本金的比例越来越多,这两者的总额不变,即每期支付的还款额。这就是等额本息还款的特点。

累计的本金和利息

随着还款时间的推移,总共还了多少本金,多少利息呢?我们可以使用numpy.cumsum()函数来进行累积求和,它返回的是一系列迭代的和,而不是一个数字。

比如对数组[1,2,3,4,5]进行累积求和,返回的是数组[1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5]。

np.cumsum(np.array([1,2,3,4,5]))
array([ 1,  3,  6, 10, 15])

下面就使用numpy.cumsum()计算累积的本金和利息,并绘制成图表。

# 计算累计的本金
cumulative_principle = np.cumsum(principal_paid)

# 计算累积的利息
cumulative_interest = np.cumsum(interest_paid)

# 绘图
plt.plot(cumulative_interest, color='red', label="累计的利息")
plt.plot(cumulative_principle, color='blue', label="累计的本金")
plt.legend(loc=2)
plt.xlabel("贷款期数")
plt.ylabel("金额")
plt.show()

从图中我们看出,支付的总利息甚至比贷款额度还高,这是由于贷款期限较长,金额较高,一开始都在还利息了。

还款中累计的本金部分才对房屋所有权有贡献,你实际拥有的房产等于首付加上累计的本金,计算如下:

# 计算所占房屋产权的比例
house_owned = down_payment_percent + (cumulative_principle/home_value)
print("10年后占有的房产:", round(house_owned[10*12],4))
print("20年后占有的房产:", round(house_owned[20*12],4))

# 绘图
plt.plot(house_owned)
plt.xlabel("期数")
plt.ylabel("拥有房屋产权的比例")
plt.show()
10年后占有的房产: 0.4242
20年后占有的房产: 0.637

首付后,你拥有房产的30%;10年后才占有42.42%;20年后占有63.7%;直到30年后还完房贷才对房屋有100%的所有权。

房价变化的影响

我们知道,房价是会随着时间变化的。如果房价上升,那你拥有的房产也会升值。现在假设房价以每月0.25%的速度稳步上升,让我们来绘制你所拥有的房产随时间的变化曲线。

首先来计算增长的房价,这里需要使用 numpy.cumprod() 函数来进行累积求乘积,类似于上节中使用的累积求和函数。比如对数组[1,2,3,4,5]进行累积求乘积,返回的是数组[1, 1x2, 1x2x3, 1x2x3x4, 1x2x3x4x5]。

np.cumprod(np.array([1,2,3,4,5]))
array([  1,   2,   6,  24, 120])

使用 numpy.cumprod() 函数计算累积的增长率,然后乘上原先的房价,就能预测房价随时间的变化了。

# 计算累积的增长率
growth_array = np.repeat(0.0025, payment_periods)
cumulative_growth = np.cumprod(1 + growth_array)

# 预测房价
home_value_forecast = home_value * cumulative_growth

将预测的房价乘上你对房屋所有权拥有的比例,就得到你实际拥有的房产价值。

# 预测你拥有的房产
home_value_owned = home_value_forecast * house_owned

# 绘图
plt.plot(home_value_forecast, color='red', label="房价")
plt.plot(home_value_owned, color='blue', label="拥有的房屋产权价值")
plt.legend(loc=2)
plt.xlabel("期数")
plt.ylabel("金额")
plt.show()

从图中看出,由于不断增长的房价,即使没有完成还款,大概在还款18年后,你拥有的房屋价值也超过了当初的500万房价。这将是一项成功的投资。

先不要太过乐观,房价并不是永远上升的,你也需要警惕房价下跌。假设房价以每月0.45%的速度持续下跌,我们使用上述类似的方法来分析未来的房价和你所拥有房产的价值。

# 计算累积的增长率,负数表示下跌
decline_array = np.repeat(-0.0045, payment_periods)
cumulative_decline = np.cumprod(1+decline_array)

# 预测房价
home_value_forecast = home_value * cumulative_decline

# 预测你拥有的房产
home_value_owned = home_value_forecast * house_owned

# 绘图
plt.plot(home_value_forecast, color='red', label="房价")
plt.plot(home_value_owned, color='blue', label="拥有的房屋产权价值")
plt.legend(loc=1)
plt.xlabel("期数")
plt.ylabel("金额")
plt.show()

可见即使按期还款,你所拥有的房产价值也是在不断下跌的,这是一项失败的投资。
这时卖掉房子也许是更好的选择,但更差的情况是,即便你卖了房子还是还不了贷款。为了更直观的看清这一点,我们来绘制房价和剩余应还本金的曲线图。

plt.plot(home_value_forecast, color='red', label="房价")
plt.plot(principal_remaining, color='blue', label="剩余本金")
plt.legend(loc=1)
plt.xlabel("期数")
plt.ylabel("金额")
plt.show()

上图中有一段时间剩余的贷款金额(蓝线)高于房屋的实际价值(红线),出现了资不抵债的情况,也就是说即使卖了房子你也还不起贷款。这也是2008年美国金融危机时发生的情况。

小结

本文对抵押贷款进行了剖析,计算了房贷每期的还款额、每期还款中本金和利息部分,以及累计还款的本金和利息,并且分析了房价上涨和下跌时的房产投资情况。

另外还学习了三个 NumPy 函数:

# 计算按揭还款额
numpy.pmt(rate, nper,pv) 

# 累计求和
numpy.cumsum(array)

# 累计求乘积
numpy.cumprod(array)

注:本文是DataCamp课程Intro to Financial Concepts using Python的学习笔记。
更多该课程的笔记:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容