<jupyter_start><jupyter_text>Pythonで国民年金シミュレーション（その２）〜７０歳超も？〜 公的年金は3階建ての年金と言われます．1階部分は国民年金です．現役世代は全て国民年金の被保険者となり，高齢期となれば，基礎年金の給付を受けます．([厚生労働省「公的年金制度の概要」](http://www.mhlw.go.jp/stf/seisakunitsuite/bunya/nenkin/nenkin/zaisei01/index.html))  2018/1/17日本経済新聞に[「年金受給開始　70歳超も　 政府検討　選択制、額は上乗せ　高齢者に就労促す」](https://www.nikkei.com/article/DGKKZO25752900W8A110C1MM8000/)との記事がありました．そこで，以前の投稿[Pythonで国民年金をシミュレーションする](https://qiita.com/ryoshi81/items/a312d404e480469d0a22)を少し修正し，Pythonを使った国民年金の保険料の支払いと年金の給付のシミュレーションを70歳超の繰り下げ受給にも対応させてみました．  重要：免責事項など- 本投稿での計算及び計算した数値は仮定のものであり，その数値に一切責任は負いません．- 本投稿での年金制度の内容は簡略化した説明なので正確な内容は必ず厚生労働省または日本年金機構のHPで確認してください．- また本内容は2018年1月20日時点のものです．最新の情報は厚生労働省または日本年金機構のHPでご確認ください．- 本内容は個人の見解であり，所属組織とは一切関係ありません．- もし誤った記載がありましたら，修正・削除しますので，ご指摘ください．公的年金の仕組みや支払い・受給額は厚生労働省や日本年金機構のHPで説明されています．  準備 今回使用するライブラリをインポートします．<jupyter_code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline<jupyter_output><empty_output><jupyter_text>国民年金の損益分岐点 国民年金の保険料は日本年金機構のHPで調べることができます．→[日本年金機構「国民年金保険料」](http://www.nenkin.go.jp/service/kokunen/hokenryo/20150313-02.html)国民年金の受け取りにあたる老齢基礎年金の受給額も同じく日本年金機構のHPで調べることができます．→[日本年金機構「老齢基礎年金の受給要件・支給開始時期・計算方法」](http://www.nenkin.go.jp/service/jukyu/roureinenkin/jukyu-yoken/20150401-02.html)HPには「20歳から60歳になるまでの40年間の全期間保険料を納めた方は，65歳から満額の老齢基礎年金が支給されます．」と書かれています．以下の，Pythonのコードの変数「premium_monthly」と「pension_yearly」に日本年金機構のHPに記載の月額保険料と年金額(年額)を入力すると，20歳から60歳までの保険料の支払い，65歳以降の老齢基礎年金の受け取り，保険料と年金の累積額をシミュレーションすることができます．(保険料，年金額は受給開始年度によって若干変わるので，必ず日本年金機構のHPを確認してください．また，マクロ経済スライドなどによる改定率は今回のシミュレーションでは考慮していません．)<jupyter_code>premium_monthly =  # ここに月額保険料を入力
pension_yearly =  # ここに年金額(年額)を入力
revision_rate = 1.0  # 必要に応じて保険料改定率を入力
year = range(20, 100)
cashflow = pd.DataFrame(index=year, columns=['premium','pension'])
cashflow['premium'] = 0
cashflow['premium'] = cashflow['premium'].mask(cashflow.index<60, -premium_monthly*revision_rate*12)
cashflow['pension'] = 0
cashflow['pension'] = cashflow['pension'].mask(cashflow.index>=65, pension_yearly)
cashflow['cashflow'] = cashflow['premium'] + cashflow['pension']
cashflow['accumlation'] = cashflow['cashflow'].cumsum()<jupyter_output><empty_output><jupyter_text>シミュレーションを可視化します．横軸が年齢，左の縦軸が支払保険料または受け取り年金の毎年の金額，赤のバーが支払う保険料，青のバーが受け取る老齢年金額，緑の線が保険料と年金の累積額の推移で，右の縦軸が累積額の金額になっています．<jupyter_code>from matplotlib import rcParams
rcParams['font.sans-serif'] = 'Source Han Code JP'
rcParams['font.weight'] = 'regular'
rcParams['axes.titlesize'] = 16
rcParams['ytick.labelsize'] = 14
rcParams['xtick.labelsize'] = 14
plt.style.use('ggplot')
fig = plt.figure(figsize=(12, 6))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.bar(cashflow.index, cashflow['pension'], label='年金')
ax1.bar(cashflow.index, cashflow['premium'], label='保険料')
ax1.set_xlabel('年齢')
ax1.set_ylabel('収支')
ax1.set_title('国民年金保険料と老齢基礎年金')
ax1.legend(prop={'size': 15})
ax1.set_ylim(-400000, 800000)
ax2.plot(cashflow.index, cashflow['accumlation'], color='g', label='accumlation')
ax2.set_ylim(-10000000, 20000000)
plt.show()<jupyter_output><empty_output><jupyter_text>国民年金の繰り上げ受給と繰り下げ受給 老齢基礎年金は，原則として65歳から受け取ることができますが，希望すれば60歳から65歳になるまでの間でも繰り上げて受けることができます．しかし，繰上げ支給の請求をした時点に応じて年金が減額され，その減額率は一生変わりません．([日本年金機構「年金の繰上げ受給」](http://www.nenkin.go.jp/service/jukyu/roureinenkin/kuriage-kurisage/20140421-01.html))一方，65歳で請求せずに66歳以降70歳までの間で申し出た時から老齢年金を繰下げて請求できます．繰下げ率は，繰下げの請求をした時点に応じて年金額が増額されます．([日本年金機構「年金の繰下げ受給」](http://www.nenkin.go.jp/service/jukyu/roureinenkin/kuriage-kurisage/20140421-02.html))つまり，国民年金には繰り上げ受給と繰り下げ受給，そして繰り上げ(下げ)を何ヶ月にするかという選択肢があります．  2018/1/17日本経済新聞に[「年金受給開始　70歳超も　 政府検討　選択制、額は上乗せ　高齢者に就労促す」](https://www.nikkei.com/article/DGKKZO25752900W8A110C1MM8000/)との記事がありました．では，何ヶ月の繰り上げ受給，または繰り下げ受給を選択するのが良いのでしょうか．Pythonで60歳から75歳まで（据え置き1パターンと繰り上げ60パターンと繰り下げ60＋60パターン）をシミュレーションして比較してみます．<jupyter_code>pension_monthly = pension_yearly // 12
months = range(-60, 121)  # 61から121に修正
age = pd.MultiIndex.from_product([range(60, 100), range(1, 13)], names=['年', '月'])<jupyter_output><empty_output><jupyter_text>繰り上げ受給の場合と繰り下げ受給の場合の繰り上げ(下げ)月数に応じた受給額月額を計算します．<jupyter_code>benefit = pd.Series(pension_monthly, index=months)
benefit = benefit.mask(benefit.index < 0, pension_monthly * (1.0 + 0.005*benefit.index))
benefit = benefit.mask(benefit.index > 0, pension_monthly * (1.0 + 0.007*benefit.index))  # 未定のため仮で0.7％据え置き
#benefit = benefit.mask(benefit.index > 60, pension_monthly * (1.0 + 0.009*benefit.index))  # 仮で他の値に設定する場合
benefit = benefit.round(0)<jupyter_output><empty_output><jupyter_text>年齢ごとの年金受給額の累積を計算します．上で計算した繰り上げ(下げ)月数ごと受給額を対角化して，pandasのcumsum()を2回使うことで簡単に計算できます．<jupyter_code>benefit = pd.DataFrame(np.diag(benefit.values), index=age[:len(months)], columns=months)
benefit = pd.DataFrame(index=age).merge(benefit, how='left', left_index=True, right_index=True).fillna(0)
pension = benefit.cumsum().cumsum()<jupyter_output><empty_output><jupyter_text>各年齢ごとに最も受給額の大きい選択肢（繰り上げか繰り下げか）を調べます．<jupyter_code>pension['最大受給額'] = pension.max(axis=1)
pension['最良繰り下げ月数'] = pension.idxmax(axis=1)
pension<jupyter_output><empty_output><jupyter_text>CSVに書き出します．<jupyter_code>pension.to_csv('pension_simulation.csv')<jupyter_output><empty_output><jupyter_text>Excelに書き出す場合はこちら．<jupyter_code>writer = pd.ExcelWriter('pension_simulation.xlsx', engine='xlsxwriter')
pension.to_excel(writer, sheet_name='国民年金シミュレーション')
# フォーマットを整える
workbook  = writer.book
worksheet = writer.sheets['国民年金シミュレーション']
header_format = workbook.add_format({
    'bold': True,
    'text_wrap': True,
    'fg_color': '#D7E4BC',
    'border': 1})
index_format = workbook.add_format({
    'bold': True,
    'valign': 'top',
    'fg_color': '#FFCC99',
    'border': 1})
values_format = workbook.add_format({
    'border': 1})
result_format = workbook.add_format({
    'fg_color': '#FFFFCC',
    'border': 1})
for col_num, value in enumerate(list(pension.index.names)+list(pension.columns)):
    worksheet.write(0, col_num, value, header_format)
from itertools import product
for row_num, (y_val, m_val) in enumerate(product(pension.index.levels[0], pension.index.levels[1])):
    worksheet.write(row_num+1, 0, y_val, index_format)
    worksheet.write(row_num+1, 1, m_val, index_format)
for row_num, _row_val in enumerate(pension.index):
    for col_num, _col_val in enumerate(pension.columns):
        worksheet.write(row_num+1, col_num+2, 
                        pension.iloc[row_num, col_num], values_format)
for row_num, (_y_val, _m_val) in enumerate(pension.index):
    worksheet.write(row_num+1, pension.shape[1]+len(pension.index.names)-2,
                    pension.iloc[row_num, -2], result_format)
    worksheet.write(row_num+1, pension.shape[1]+len(pension.index.names)-1, 
                    pension.iloc[row_num, -1], result_format)
# Excelファイルを保存
writer.save()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14124962984897838, 'fraction_numerical': 0.045158424637252, 'mean_word_length': 9.067064083457526, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 40, 'https://': 3, 'lorem ipsum': 0, 'www.': 7, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '567081', 'license': 'MIT', 'n_tokens_mistral': 4374, 'n_tokens_neox': 4032, 'n_words': 257, 'path': 'pension_simulation2.ipynb', 'repo_name': 'ryoshii8/finpy', 'size': '6754'}