口下手エンジニアの悪あがき

自動車エンジニアのつぶやき

かゆい所に手が届く積立シミュレーションをpythonで#2

前回、基本的な情報から積立シミュレーションをできるプログラムを作成しました。

ganbaruengineer.hatenablog.com

でもこれだけだったら巷にある他のWebサービスでも全く問題なくつかえるわけで、巷にあるものが何が不満かというと、人のライフステージに合わせた積立計画を立てられないということです。

具体的には、例えば子どもがいてまだお金がかかるうちは少額の積み立てをするが、子どもが社会人になってお金がかからなくなったら、増額していく、など。人によって人生の途中で必ず変化があるものなので、そういうものに対応するシミュレーションがしたいわけで・・・

計算の前提

前回は、以下の4つのパラメータを入力して計算するプログラムでした。
「初期投資金額」「毎月の積立額」「年利」「積立年数」

今回は、「積立年数」と「毎月の積立額」をそれぞれ2つ指定して、途中で積立金額を変更できるようにします。

つまり、

変数 内容
seed_money 初期投資金額
amount_accum1 毎月の積立額1
amount_accum2 毎月の積立額2
num_years1 積立年数1
num_years2 積立年数2
annual_rate 年利

とし、「毎月の積立額1」の金額を初年~「積立年数1」の期間積み立てて、次に「毎月の積立額2」を「積立年数2」の期間積み立てた場合の資産推移を計算していこうと思います。

コードの変更点とアウトプットグラフ

変数の設定
今回は、初期資金100万円、初めの10年間は毎月5万円積み立てて、次の5年では毎月10万円を積み立てるシミュレーションをしてみようと思います。

seed_money = 100
amount_accum1 = 5
amount_accum2 = 10
num_years1 = 10
num_years2 = 5
annual_rate = 5

リストの初期化

 lst_seed = [seed_money]*(num_years1+num_years2+1)  # 2つの期間を合わせた長さでリスト作成

積立年数2の期間についてのループ計算の追加

deposit1 = amount_accum1*12*num_years1  # 積立期間1での積み立て額総計

for i in range(num_years2):
    asset_now = npf.fv(annual_rate/12/100, 12, -amount_accum2, -asset_now)
    lst_total.append(int(asset_now))
    lst_gain.append(lst_total[-1] - seed_money - deposit1 - (i+1)*amount_accum2*12)
    lst_deposit.append(deposit1 + (i+1)*amount_accum2*12)

そういう感じで修正していって、完成です。
途中から積立額がぐぐっと増えているのがグラフから見て取れます。ただし、投資とは「市場にいる期間」×「投資資金」なわけで、それを考えると若いうちになるべく入金した方がいいに決まっているんですけどね。詳しくは以下の本で書かれています。


本当の自由を手に入れる お金の大学 [ 両@リベ大学長 ]

図1.途中で積立額を切り替えた積立シミュレーション

全コード

import numpy as np
import numpy_financial as npf
import matplotlib.pyplot as plt

def calc(seed_money, amount_accum1=5, amount_accum2=0, num_years1=15, num_years2=0, annual_rate=5):
    asset_now = seed_money
    lst_seed = [seed_money]*(num_years1+num_years2+1)
    lst_gain = [0]
    lst_deposit = [0]
    lst_total = [seed_money]
    
    for i in range(num_years1):
        asset_now = npf.fv(annual_rate/12/100, 12, -amount_accum1, -asset_now)
        lst_total.append(int(asset_now))
        lst_gain.append(lst_total[-1] - seed_money - (i+1)*amount_accum1*12)
        lst_deposit.append((i+1)*amount_accum1*12)

    deposit1 = amount_accum1*12*num_years1

    for i in range(num_years2):
        asset_now = npf.fv(annual_rate/12/100, 12, -amount_accum2, -asset_now)
        lst_total.append(int(asset_now))
        lst_gain.append(lst_total[-1] - seed_money - deposit1 - (i+1)*amount_accum2*12)
        lst_deposit.append(deposit1 + (i+1)*amount_accum2*12)

    t = [i for i in range(num_years1+num_years2 + 1)]
    fig, ax = plt.subplots(figsize=(10,5), sharey=True)
    ax.bar(t, lst_seed,label="initial investment")
    ax.bar(t, lst_deposit,bottom=lst_seed,label="amount of deposit")
    ax.bar(t,lst_gain,bottom=[i+j for i,j in zip(lst_seed,lst_deposit)],label="gain")
    text_y1 = [0.4 * i+seed_money for i in lst_deposit]
    text_y2 = [0.3 * j + i + seed_money for i,j in zip(lst_deposit,lst_gain)]
    for i in range(len(lst_deposit)):
        ax.text(t[i],seed_money*0.4,seed_money, ha="center",size=9)
        ax.text(t[i],text_y1[i],lst_deposit[i], ha="center", size=9)
        ax.text(t[i],text_y2[i],lst_gain[i], ha="center", size=9)
        ax.text(t[i],lst_total[i]+lst_total[-1]/50,lst_total[i],ha="center", size=10, color="k")
    plt.grid(axis='y')
    plt.xlabel("Number of Years")
    plt.ylabel("Amount of money(10,000yen)")
    plt.legend()
    plt.show()

seed_money = 100
amount_accum1 = 5
amount_accum2 = 10
num_years1 = 10
num_years2 = 5
annual_rate = 5

calc(seed_money, amount_accum1, amount_accum2, num_years1, num_years2,annual_rate)