見出し画像

Pythonを用いた住宅ローンシミュレーション(金利上昇時の想定後編)

こんにちは。分析屋のFと申します。

前回の「Pythonを用いた住宅ローンシミュレーション(金利上昇時の想定前編)」に続き住宅ローンについて、今回は金利上昇による家計への負担を繰上げ返済で如何に逃げ切れるか(負担を最小限に留められるか)という内容でお伝えしていきます。
前回の記事はこちらになります。

前回からの繰り返しになりますが、現在は歴史的な低金利で推移しておりますため、この恩恵を最大限に享受しておくべきというのが個人的な考えとしてございます。そのため契約時は変動金利を選択し、繰上げ返済資金(軍資金と称します)を貯めながら返済を進めておくことが重要と考えます。今回は繰上げ返済のタイミングごとに軽減できる総利息額、短縮される返済期間に着目していきます。基本情報は前回と変わらず返済期間420ヶ月(35年)、借入額4000万とし、返済5年目より5年ごとに0.5%刻みで金利が上昇するケースを想定致します。

本記事の構成は以下の通りとなります。



1.金利上昇と繰上げ返済の処理概要

1.1 既存プログラムの組み合わせで動作しなかった点

繰上げ返済のプログラムは「繰上げ返済前編」で作成致しましたが、当時のプログラムは償還表から繰上げ返済開始月の翌月から月毎に(ユーザー入力の)概算額の超えない範囲で元金の和を算出の上レコード抽出し、別途テーブルを生成した後に軽減される総返済額、短縮される返済期間を算出しておりました。しかしここに金利上昇を想定する必要がありますため(具体的には繰上げ返済実施後の残債に対して金利を算出するetc…)償還表の表作成中に繰上げ返済の処理を行う必要があり、こちらの処理に大変悩みました。

1.2 金利上昇を踏まえた繰上げ返済の処理概要

例として3年目1ヶ月目に概算額50万円の繰上げ返済を実施したとします。indx=26(3年目1ヶ月目の翌月)のレコードよりprincipal(元金)の累積和を算出します。indx=31のレコードまで算出すると概算の50万を超えてしまうため、indx=30のレコードまでが繰上げ返済による総利息の軽減対象になります。

<償還表(一部抜粋)>

indx  repay_month  interest  principal early_sum early_cnt
21       101639     11941      89698          0          0
22       101639     11913      89726          0          0
23       101639     11885      89754          0          0    
24       101639     11857      89782          0          0
25       101639     11829      89810          0          0
26       101639     11800      89839      89839          1
27       101639     11772      89867     179706          2
28       101639     11744      89895     269601          3
29       101639     11716      89923     359524          4
30       101639     11688      89951     449475          5

ここでindx=30のレコードから算出された繰上げ返済額 ¥449,475 を繰上げ返済実施月である、indx=25のレコードに対してremain(残債)から引かれていなければいけない点が鬼門でした。(for文の処理の特性上、前のレコードを遡った処理が不可能なため)そこで償還表作成処理を2度実行することを考えました。1回目の償還表作成は繰上げ返済額、短縮期間の算出が目的であるため償還表自体は後工程で使用致しません。2回目は1回目で算出した繰上げ返済額、短縮期間を考慮の上で償還表を作成致します。
(データフレーム化後のソート処理等も考えられましたが、こちらは私のPandasの理解不足のため、ご容赦下さい。また、繰上げ返済も1度きりの実施と致します。)

1回目の償還表作成で生成する変数:

2回目の償還表作成で繰上げ返済の考慮の必要がある変数:


2.出力内容の設定

繰り返しになりますが、今回は金利が上昇したときに軍資金が如何に機能するかというテーマになります。まずは下記の表の②ー①を算出することによって金利上昇による負担が分かります。更に③ー②の算出によって、軍資金の投入が金利上昇の負担をどの程度軽減させるかについて一目で分かるように設定いたしました。

※繰上げ返済のタイミングごとに出力


3.金利上昇時のプログラム及び実行結果

<プログラム>

import numpy as np
import numpy_financial as npf
import pandas as pd
import math

##############################
#### 基本情報(元利均等返済) ####
##############################
# 金利
per = 0.375

# 返済期間
period = 12*35

# 借入額
repay_amount = 4000

########################
#### 金利上昇開始時期 ####
########################
riseyr = 5

# 金利上昇幅
width = 0.5

###########################################
#### 繰上げ返済情報(本プログラムでは一度きり) ####
###########################################
# 繰り上げ返済概算額(単位:万)
early_repay = 300

##### 入力ここまで #####

# 空のデータフレーム
kihon = pd.DataFrame()

# 関数定義
def create_term(x):
	if x % 12 == 0:
		y = str(math.ceil(x/12))+'年目12ヶ月目'
	else:
		y = str(math.ceil(x/12))+'年目'+str(x%12)+'ヶ月目'
	return y
	
def short_term(x):
	if x % 12 == 0:
		y = str(math.floor(x/12))+'年'
	else:
		y = str(math.floor(x/12))+'年'+str(x%12)+'ヶ月'
	return y	
	
def get_lag(x, y, z):
	if x != 1:
		w = y + z
	return w

# 償還表作成
def rise(riseyr_ , st, conf, early_sum, early_cnt):
	
	# 毎月の返済額
	repay_month = math.floor(npf.pmt(0.01*per/12, period, -repay_amount*10000))
	risemonth = 12 * (riseyr_ - 1)
	risemonth_mod = np.mod(risemonth + 1, 60)
	per1 = per
	per2 = per

	# 返済済
	principal_acc = 0
	early_sum_ = 0
	early_cnt_ = 0
	early_fl = 0
	early_end = 0

	# 空のデータフレーム
	kihon = pd.DataFrame()

	for indx in range(1, period+1-early_cnt):
	
		if indx == 1: 
			remain = repay_amount * 10000
			
		# 毎月の利息
		if np.mod(indx, 60) == risemonth_mod and indx > risemonth:
			if (conf == 0 and indx < st + 1) or conf == 1:
				per2 = per2 + width
			
		interest = math.floor(npf.ipmt(0.01*per2/12, 1, period-indx+1-early_cnt, -remain))	
		
		# 毎月の返済額
		if np.mod(indx, 60) == 1 and indx > risemonth:
			if (conf == 0 and indx < st + 1) or conf == 1:
				per1 = per1 + width
				if indx > st:
					repay_month = math.floor(npf.pmt(0.01*per1/12, period-indx+1-early_cnt, -remain))
				else:
					repay_month = math.floor(npf.pmt(0.01*per1/12, period-indx+1, -remain))
																
		# 毎月の返済額中の元本部分
		principal = repay_month - interest
	
		# 返済済
		principal_acc += principal
		
		# 繰上げ返済元金
		if conf == 0:
			if indx == st + 1:
				early_fl = 1
				early_sum_ = principal
				early_cnt_ = 1
			elif st + 1 < indx and early_sum_ + principal < early_repay*10000:
				early_sum_ += principal
				early_cnt_ += 1
		elif conf == 1:
			if indx == st:
				principal_acc += early_sum
																																
		# 当該月時点の残債
		remain = repay_amount*10000 - principal_acc
			
		kihon_new = pd.DataFrame([[indx, repay_month, interest, principal, principal_acc, remain, per1, per2, early_sum_, early_cnt_]],
		columns=["indx", "repay_month", "interest", "principal", "principal_acc", "remain", "per1", "per2", "early_sum_", "early_cnt_"])
		kihon = pd.concat([kihon, kihon_new])
	
	kihon.loc[kihon["indx"]==period-early_cnt, "principal"] = kihon.loc[kihon["indx"]==period-1-early_cnt, "remain"]
	kihon.loc[kihon["indx"]==period-early_cnt, "repay_month"] = kihon.loc[kihon["indx"]==period-early_cnt, "principal"] + kihon.loc[kihon["indx"]==period-early_cnt, "interest"]
	kihon.loc[kihon["indx"]==period-early_cnt, "principal_acc"] = repay_amount*10000
	kihon.loc[kihon["indx"]==period-early_cnt, "remain"] = 0
	
	return kihon["repay_month"].sum(), kihon["interest"].sum(), kihon.loc[kihon["indx"]==period, "early_sum_"], kihon.loc[kihon["indx"]==period, "early_cnt_"], kihon

early_df0 = rise(riseyr, 500, 0, 0, 0)[0]	
early_df1 = rise(riseyr, 500, 2, 0, 0)[0]
early_df2 = early_df0 - early_df1

print("#### 返済期間:", period, "ヶ月、借入額:", repay_amount, "万円、借入当時の金利:", per ,"%の場合のシミュレーション結果 ####")
print("金利上昇を想定しない場合の総返済額は", '¥{:,.0f}'.format(early_df1), "になります。金利上昇開始が", riseyr , "年目で5年あたりの上昇幅が", width ,"%の場合、総返済額は", '¥{:,.0f}'.format(early_df0), "つまり、金利上昇による総返済額の増加幅は", '¥{:,.0f}'.format(early_df2), "となるところ、")

for tming in range(1, period+1, 12):		
	early_sum = rise(riseyr, tming, 0, 0, 0)[2]
	early_no = rise(riseyr, tming, 1, 0, 0)[0]
	early_ttl = rise(riseyr, tming, 1,
		int(rise(riseyr, tming, 0, 0, 0)[2]),
		int(rise(riseyr, tming, 0, 0, 0)[3]))[0]
	early_cnt = int(rise(riseyr, tming, 0, 0, 0)[3])
	if period - early_cnt <= tming:
			early_sum = 0
	early_df3 = int(early_ttl + early_sum - early_df1)

	print(create_term(tming), "に", early_repay ,"万円の繰上げ返済を行うことによって", '¥{:,.0f}'.format(early_df3), "となり、総返済額は", '¥{:,.0f}'.format(early_df2-early_df3) ,"軽減でき、返済期間は", short_term(early_cnt) ,"短縮できます。")

<実行結果>

#### 返済期間: 420 ヶ月、借入額: 4000 万円、借入当時の金利: 0.375 %の場合のシミュレーション結果 ####
金利上昇を想定しない場合の総返済額は ¥42,688,443 になります。金利上昇開始が 5 年目で5年あたりの上昇幅が 0.5 %の場合、総返済額は ¥50,917,315 つまり、金利上昇による総返済額の増加幅は ¥8,228,872 となるところ、
1年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,889,979 となり、総返済額は ¥2,338,893 軽減でき、返済期間は 2年9ヶ月 短縮できます。
2年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,901,089 となり、総返済額は ¥2,327,783 軽減でき、返済期間は 2年9ヶ月 短縮できます。
3年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,912,243 となり、総返済額は ¥2,316,629 軽減でき、返済期間は 2年9ヶ月 短縮できます。
4年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,923,434 となり、総返済額は ¥2,305,438 軽減でき、返済期間は 2年9ヶ月 短縮できます。
5年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,698,334 となり、総返済額は ¥2,530,538 軽減でき、返済期間は 3年3ヶ月 短縮できます。
6年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,889,552 となり、総返済額は ¥2,339,320 軽減でき、返済期間は 2年11ヶ月 短縮できます。
7年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,976,431 となり、総返済額は ¥2,252,441 軽減でき、返済期間は 2年10ヶ月 短縮できます。
8年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,002,224 となり、総返済額は ¥2,226,648 軽減でき、返済期間は 2年10ヶ月 短縮できます。
9年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,028,242 となり、総返済額は ¥2,200,630 軽減でき、返済期間は 2年10ヶ月 短縮できます。
10年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥5,886,955 となり、総返済額は ¥2,341,917 軽減でき、返済期間は 3年3ヶ月 短縮できます。
11年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,082,138 となり、総返済額は ¥2,146,734 軽減でき、返済期間は 2年11ヶ月 短縮できます。
12年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,178,151 となり、総返済額は ¥2,050,721 軽減でき、返済期間は 2年10ヶ月 短縮できます。
13年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,218,617 となり、総返済額は ¥2,010,255 軽減でき、返済期間は 2年10ヶ月 短縮できます。
14年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,312,391 となり、総返済額は ¥1,916,481 軽減でき、返済期間は 2年9ヶ月 短縮できます。
15年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,237,768 となり、総返済額は ¥1,991,104 軽減でき、返済期間は 3年1ヶ月 短縮できます。
16年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,389,236 となり、総返済額は ¥1,839,636 軽減でき、返済期間は 2年10ヶ月 短縮できます。
17年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,492,876 となり、総返済額は ¥1,735,996 軽減でき、返済期間は 2年9ヶ月 短縮できます。
18年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,548,356 となり、総返済額は ¥1,680,516 軽減でき、返済期間は 2年9ヶ月 短縮できます。
19年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,649,202 となり、総返済額は ¥1,579,670 軽減でき、返済期間は 2年8ヶ月 短縮できます。
20年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,676,237 となり、総返済額は ¥1,552,635 軽減でき、返済期間は 2年10ヶ月 短縮できます。
21年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,795,325 となり、総返済額は ¥1,433,547 軽減でき、返済期間は 2年8ヶ月 短縮できます。
22年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥6,904,776 となり、総返済額は ¥1,324,096 軽減でき、返済期間は 2年7ヶ月 短縮できます。
23年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,011,538 となり、総返済額は ¥1,217,334 軽減でき、返済期間は 2年6ヶ月 短縮できます。
24年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,081,779 となり、総返済額は ¥1,147,093 軽減でき、返済期間は 2年6ヶ月 短縮できます。
25年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,150,421 となり、総返済額は ¥1,078,451 軽減でき、返済期間は 2年7ヶ月 短縮できます。
26年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,279,411 となり、総返済額は ¥949,461 軽減でき、返済期間は 2年5ヶ月 短縮できます。
27年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,391,785 となり、総返済額は ¥837,087 軽減でき、返済期間は 2年4ヶ月 短縮できます。
28年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,500,619 となり、総返済額は ¥728,253 軽減でき、返済期間は 2年3ヶ月 短縮できます。
29年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,605,741 となり、総返済額は ¥623,131 軽減でき、返済期間は 2年2ヶ月 短縮できます。
30年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,698,682 となり、総返済額は ¥530,190 軽減でき、返済期間は 2年2ヶ月 短縮できます。
31年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,807,848 となり、総返済額は ¥421,024 軽減でき、返済期間は 2年1ヶ月 短縮できます。
32年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥7,917,655 となり、総返済額は ¥311,217 軽減でき、返済期間は 2年 短縮できます。
33年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥8,022,628 となり、総返済額は ¥206,244 軽減でき、返済期間は 1年11ヶ月 短縮できます。
34年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥8,122,480 となり、総返済額は ¥106,392 軽減でき、返済期間は 1年10ヶ月 短縮できます。
35年目1ヶ月目 に 300 万円の繰上げ返済を行うことによって ¥8,200,358 となり、総返済額は ¥28,514 軽減でき、返済期間は 0年11ヶ月 短縮できます。

「2.出力内容の設定」に沿うと以下のような内容になります。
① = ¥42,688,443
② = ¥50,917,315(②ー① = ¥8,228,872)
③ = ¥8,228,872(③ー① = ¥5,889,979 ※1年目1ヶ月目)
③ー② = ¥2,338,893 ※1年目1ヶ月目
この結果において着目すべきは軽減額及び短縮期間が最大になるのが5年目であり、「繰上げ返済後編」でお伝えした早期の繰上げ返済が必ずしも正解とは言えないことが分かります。これは金利が上昇することで毎月の返済額における元金の割合が小さくなるため(利息の割合が大きくなるため)同じ繰上げ返済額であっても金利の高い時が効果が大きいことを意味しております。そのため、少額をこつこつ返済することよりも金利上昇のタイミングまで軍資金を貯金しておくことも戦術かもしれません。ただし、金利の上昇幅が一定未満の場合は繰上げ返済のタイミングは早いに越したことないため(金利上昇の手前で残債を減らしておけば金利上昇時の利息の負担が少なくなる)この現象は起きません。0.5%刻みの金利上昇が本当に現実的なのか、国内外の経済情勢と照らし合わせて吟味しても良いと思います。


4.結言

金利上昇に関してお伝え致しましたが如何でしたでしょうか。個人的には今回の金利上昇を踏まえた繰上げ返済のシミュレーションはPythonの実装能力が問われるものでして、収穫は大きかったと考えております。
住宅ローンに関する持ちネタとしては以上になりますが、ここまでのボリュームも盛り沢山でして、お伝えし切れなかった部分も多々あるかと存じます。それらに関しましては今後は補遺編としてお伝えできればと存じます。

尚、本プログラムはご自身の責任においてご利用頂けますようお願いいたします。当社はいかなる損害についても一切の責任を負いかねます。

免責事項は以下の記事に記載しております。




ここまでお読みいただき、ありがとうございました!
この記事が少しでも参考になりましたら「スキ」を押していただけると幸いです!

これまでの記事はこちら!

株式会社分析屋について

弊社が作成を行いました分析レポートを、鎌倉市観光協会様HPに掲載いただきました。

ホームページはこちら。

noteでの会社紹介記事はこちら。

【データ分析で日本を豊かに】
分析屋はシステム分野・ライフサイエンス分野・マーケティング分野の知見を生かし、多種多様な分野の企業様のデータ分析のご支援をさせていただいております。 「あなたの問題解決をする」をモットーに、お客様の抱える課題にあわせた解析・分析手法を用いて、問題解決へのお手伝いをいたします!
【マーケティング】
マーケティング戦略上の目的に向けて、各種のデータ統合及び加工ならびにPDCAサイクル運用全般を支援や高度なデータ分析技術により複雑な課題解決に向けての分析サービスを提供いたします。
【システム】
アプリケーション開発やデータベース構築、WEBサイト構築、運用保守業務などお客様の問題やご要望に沿ってご支援いたします。
【ライフサイエンス】
機械学習や各種アルゴリズムなどの解析アルゴリズム開発サービスを提供いたします。過去には医療系のバイタルデータを扱った解析が主でしたが、今後はそれらで培った経験・技術を工業など他の分野の企業様の問題解決にも役立てていく方針です。
【SES】
SESサービスも行っております。



この記事が参加している募集

やってみた