Open109

Google Apps Script / GAS でライフプランを作成してみる

ピン留めされたアイテム
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

その他の費用たち

  • 修繕費
  • 娯楽費 → 完了
  • 医療費 → 完了
  • 交際費 → 完了
  • 服飾費 → 完了
  • 保険料 → 完了
  • 交通費 → 完了
  • 水道光熱費 → 完了
  • 学費
  • 雑費
  • 固定資産税
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

このスクラップについて

このスクラップでは Google Apps Script でライフプラン(寿命までの 1 年ごとの収支状況)を作成して表やグラフ形式で出力するまでの過程を記録する。

Google Apps Script も仕事で少しだけ使ったことがあるが、改めて使い方を学んでいきたい。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

スプレッドシートの作成


新しいスプレッドシートを作成セクションの「空白」をクリックする。


無事にスプレッドシートが作成された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

はじめての関数

コード.gs
function myFunction() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
  const sheet = spreadsheet.getSheetByName("シート1")
  const range = sheet.getRange(1, 1)
  range.setValue("Hello World")
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

シートの追加と名前変更

入力用と出力用の 2 つのシートを作成しよう。


この 2 つのシートがあればしばらくは大丈夫かな?

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

西暦年を表示する

コード.gs
const スプレッドシート = SpreadsheetApp.getActiveSpreadsheet()
const 入力用シート = スプレッドシート.getSheetByName("入力用")
const 出力用シート = スプレッドシート.getSheetByName("出力用")
const 入力マップ = new Map(入力用シート.getSheetValues(1, 1, 入力用シート.getLastRow(), 2))

function 入力(項目名) {
  return 入力マップ.get(項目名)
}

function myFunction() {
  const 現在の余命 = 入力("寿命") - 入力("現在の年齢")
  const 西暦年 = [...Array(現在の余命)].map((_, i) => 入力("現在の西暦年") + i)
  const 出力する行 = [
    ['西暦年', ...西暦年],
  ]

  出力用シート.getRange(1, 1, 出力する行.length, 出力する行[0].length).setValues(出力する行)
}


出力用シートの 1 行目に西暦年が表示された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

年収

とりあえず 75 歳まで 600 万円を稼ぎ続けると仮定しよう。

コード.gs
const スプレッドシート = SpreadsheetApp.getActiveSpreadsheet()
const 入力用シート = スプレッドシート.getSheetByName("入力用")
const 出力用シート = スプレッドシート.getSheetByName("出力用")
const 入力マップ = new Map(入力用シート.getSheetValues(1, 1, 入力用シート.getLastRow(), 2))

function 入力(項目名) {
  return 入力マップ.get(項目名)
}

function 年齢At(西暦年) {
  return 入力("現在の年齢") + 西暦年 - 入力("現在の西暦年")
}

function 年収At(西暦年) {
  const 年齢 = 年齢At(西暦年)

  if (年齢 <= 入力("退職する年齢")) {
    return 入力("年収");
  } else {
    return 0;
  }
}

function myFunction() {
  const 現在の余命 = 入力("寿命") - 入力("現在の年齢")
  const 西暦年 = [...Array(現在の余命)].map((_, i) => 入力("現在の西暦年") + i)
  const 出力する行 = [
    ['西暦年', ...西暦年],
    ['年齢', ...西暦年.map((西暦年) => 年齢At(西暦年))],
    ['年収', ...西暦年.map((西暦年) => 年収At(西暦年))],
  ]

  出力用シート.getRange(1, 1, 出力する行.length, 出力する行[0].length).setValues(出力する行)
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

10/27 (金) はここまで

作業時間は 1.5 時間、累計 1.5 時間。

次は社会保険料について考えよう。

前はかなりざっくりだったの今度はもう少しマジメに考えよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

社会保険料

https://zenn.dev/link/comments/26179799030bb2

コード.gs(追加分)
function 厚生年金保険料At(西暦年) {
  const 年齢 = 年齢At(西暦年)
  const 年収 = 年収At(西暦年)

  if (年齢 <= 70) {
    return 年収 * 18.3e-2 / 2
  }

  return 0
}

function 健康保険料At(西暦年) {
  const 年齢 = 年齢At(西暦年)
  const 年収 = 年収At(西暦年)

  if (年齢 <= 39) {
    return 年収 * 9.51e-2 / 2
  } else if (40 <= 年齢 && 年齢 <= 75) {
    return 年収 * 11.15e-2 / 2
  }

  return 0
}

function 社会保険料At(西暦年) {
  return 厚生年金保険料At(西暦年) + 健康保険料At(西暦年)
}


社会保険料関係の行 3 つが追加された。

以前の計算結果と同じなので大丈夫そうだ。

https://zenn.dev/link/comments/a5e3cd2550a52a

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

所得税

https://zenn.dev/link/comments/69455892df3550

コード.gs(追加分)
// 所得税

function 給与所得控除At(西暦年) {
  return 年収At(西暦年) * 20e-2 + 440000
}

function 小規模企業共済等掛金控除At(西暦年) {
  const 年齢 = 年齢At(西暦年)
  const 退職する年齢 = 入力('退職する年齢')
  const 小規模企業共済掛金 = 入力('小規模企業共済掛金')
  const iDeCo掛金 = 入力('iDeCo掛金')

  if (年齢 <= 65) {
    return 小規模企業共済掛金 + iDeCo掛金
  } else if (年齢 <= 75) {
    return 小規模企業共済掛金
  } else {
    return 0;
  }
}

function 所得税の生命保険料控除At(西暦年) {
  return 120000
}

function 所得税の地震保険料控除At(西暦年) {
  return +入力('地震保険料')
}

function 所得税の配偶者控除At(西暦年) {
  if (配偶者の年齢At(西暦年) < 70) {
    return 380000
  } else {
    return 480000
  }
}

function 所得税の扶養控除At(西暦年) {
  let 合計金額 = 0

  for (const 子供の年齢 of 子供たちの年齢At(西暦年)) {
    if (16 <= 子供の年齢 && 子供の年齢 <= 24) {
      合計金額 += 380000
    }
  }

  return 合計金額
}

function 所得税の基礎控除At(西暦年) {
  return 480000
}

function 所得税の所得控除At(西暦年) {
  return [
    給与所得控除At(西暦年),
    社会保険料At(西暦年),
    小規模企業共済等掛金控除At(西暦年),
    所得税の生命保険料控除At(西暦年),
    所得税の地震保険料控除At(西暦年),
    所得税の配偶者控除At(西暦年),
    所得税の扶養控除At(西暦年),
    所得税の基礎控除At(西暦年),
  ].reduce((合計, 金額) => 合計 + 金額, 0)
}

function 所得税の所得金額At(西暦年) {
  return Math.max(0, 年収At(西暦年) - 所得税の所得控除At(西暦年))
}

function 所得税At(西暦年) {
  const 所得金額 = 所得税の所得金額At(西暦年)

  if (所得金額 < 1950000) {
    return 所得金額 * 5e-2
  } else {
    return 所得金額 * 10e-2 - 97500
  }
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

住民税

https://zenn.dev/link/comments/30add8fbf5ee11

コード.gs(追加分)
// 住民税

function 住民税の生命保険料控除At(西暦年) {
  return 70000
}

function 住民税の地震保険料控除At(西暦年) {
  return +入力('地震保険料') / 2
}

function 住民税の配偶者控除At(西暦年) {
  if (配偶者の年齢At(西暦年) < 70) {
    return 330000
  } else {
    return 480000
  }
}

function 住民税の扶養控除At(西暦年) {
  let 合計金額 = 0

  for (const 子供の年齢 of 子供たちの年齢At(西暦年)) {
    if (16 <= 子供の年齢 && 子供の年齢 <= 18) {
      合計金額 += 330000
    } else if (19 <= 子供の年齢 && 子供の年齢 <= 22) {
      合計金額 += 450000
    } else if (23 <= 子供の年齢 && 子供の年齢 <= 入力("子供が独立する年齢")) {
      合計金額 += 330000
    }
  }

  return 合計金額
}

function 住民税の基礎控除At(西暦年) {
  return 430000
}

function 住民税の所得控除At(西暦年) {
  return [
    給与所得控除At(西暦年),
    社会保険料At(西暦年),
    小規模企業共済等掛金控除At(西暦年),
    住民税の生命保険料控除At(西暦年),
    住民税の地震保険料控除At(西暦年),
    住民税の配偶者控除At(西暦年),
    住民税の扶養控除At(西暦年),
    住民税の基礎控除At(西暦年),
  ].reduce((合計, 金額) => 合計 + 金額, 0)
}

function 住民税の所得金額At(西暦年) {
  return Math.max(0, 年収At(西暦年) - 住民税の所得控除At(西暦年))
}

function 住民税の税額控除前所得割At(西暦年) {
  return 住民税の所得金額At(西暦年) * 10e-2
}

function 住民税の調整控除At(西暦年) {
  const 配偶者の年齢 = 配偶者の年齢At(西暦年)
  const 子供たちの年齢 = 子供たちの年齢At(西暦年)

  let 合計金額 = 50000

  if (配偶者の年齢 < 70) {
    合計金額 += 50000
  } else {
    合計金額 += 100000
  }

  for (const 子供の年齢 of 子供たちの年齢) {
    if (16 <= 子供の年齢 && 子供の年齢 <= 18) {
      合計金額 += 50000
    } else if (19 <= 子供の年齢 && 子供の年齢 <= 22) {
      合計金額 += 180000
    } else if (22 <= 子供の年齢 && 子供の年齢 <= 入力("子供が独立する年齢")) {
      合計金額 += 50000
    }
  }

  return 合計金額 * 5e-2
}

function 住民税At(西暦年) {
  return Math.max(0, 住民税の税額控除前所得割At(西暦年) - 住民税の調整控除At(西暦年))
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

住宅ローン控除

https://zenn.dev/link/comments/9c92222b59a2a4

コード.gs(追加分)
// 住宅ローン控除

function 入居年数At(西暦年) {
  return 西暦年 - 入力('入居年')
}

function 住宅ローン残高At(西暦年) {
  return Math.max(0, 入力('住宅ローン借入金') - 入居年数At(西暦年) * 入力('年間返済額'))
}

function 住宅ローン控除At(西暦年) {
  const 入居年数 = 入居年数At(西暦年)
  let 候補金額 = 0

  if (0 <= 入居年数 && 入居年数 < 10) {
    候補金額 = 住宅ローン残高At(西暦年) * 1e-2
  } else if (10 <= 入居年数 && 入居年数 < 13) {
    候補金額 = Math.min(住宅ローン残高At(西暦年) * 1e-2, 入力('建物購入価格') * 2e-2 / 3)
  }

  return Math.floor(Math.min(候補金額, 所得税At(西暦年) + 住民税At(西暦年)) / 100) * 100
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

児童手当

https://zenn.dev/link/comments/2a82621841a2fe

コード.gs(追加分)
// 児童手当

function 児童手当支給月額At(子供の年齢, 第n子) {
  if (子供の年齢 < 3) {
    return 15000
  } else if (子供の年齢 < 13) {
    if (第n子 < 3) {
      return 10000
    } else {
      return 15000
    }
  } else if (子供の年齢 < 16) {
    return 10000;
  } else {
    return 0;
  }
}

function 第n子の児童手当At(西暦年, 第n子) {
  return 児童手当支給月額At(子供の年齢At(西暦年, 第n子), 第n子) * 12
}

function 児童手当At(西暦年) {
  let 合計金額 = 0

  for (const [i] of 子供たちの年齢At(西暦年).entries()) {
    合計金額 += 第n子の児童手当At(西暦年, i + 1)
  }

  return 合計金額
}

function 可処分所得At(西暦年) {
  return 年収At(西暦年)
    - 社会保険料At(西暦年)
    - 所得税At(西暦年)
    - 住民税At(西暦年)
    + 住宅ローン控除At(西暦年)
    + 児童手当At(西暦年)
}


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

住宅ローン金利

コード.gs(追加分)
// 住宅ローン金利

function 住宅ローン金利At(西暦年) {
  const 入居年数 = 入居年数At(西暦年)
  
  if (0 <= 入居年数 && 入居年数 < 10) {
    return Math.round(住宅ローン残高At(西暦年) * 入力('住宅ローン金利(1〜10年)') / 100)
  } else {
    return Math.round(住宅ローン残高At(西暦年) * 入力('住宅ローン金利(11年目移行)') / 100)
  }
}


入力用シート


出力用シート

住宅ローン控除が無くなってからの負担が大きそう。

それ以降の金利負担は累計 200 万円くらいになるようだ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

食費

4 人家族の我が家だと2022 年の食費は年間で 67 万円くらい。

2021 年は 70 万円くらいだったので 70〜80万円かかりそう。

子供が大きくなると食べる量が増えるので増える。

子供は 7 歳までは大人の 50%、7〜12 歳は 75%、それ以降は 100 % としよう。

また人数が増えてくるとスケールメリットが働くので 95 %、90% と 5 % ずつ減らしていこう。

そして独立したら家を出ていくと仮定する。

そうすると大人 1 人の 1 年間の食費あ 250,000 円くらいと考えれば良さそうだ。

コード.gs(追加分)
function 食費At(西暦年) {
  const 子供たちの年齢 = 子供たちの年齢At(西暦年)
  const 大人1人の食費 = +入力('大人1人の食費')
  let 合計金額 = 大人1人の食費 * 2

  for (const 子供の年齢 of 子供たちの年齢) {
    if (0 <= 子供の年齢 && 子供の年齢 < 7) {
      合計金額 += 大人1人の食費 * 50e-2
    } else if (7 <= 子供の年齢 && 子供の年齢 < 12) {
      合計金額 += 大人1人の食費 * 75e-2
    } else if (12 <= 子供の年齢 && 子供の年齢 <= 入力('子供が独立する年齢')) {
      合計金額 += 大人1人の食費
    }
  }

  return 合計金額 * (1 - 5e-2 * 同居家族の人数At(西暦年))
}


入力用シート


出力用シート

我ながらうまくモデリングできたのでは無いかと思うが高齢になってからの食費は検討の余地があるかもしれない。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

食材費のリファクタリング

このままでも良いがもう少し改良しよう。

コード.gs(食費関連)
// 食費

function 同居家族の人数At(西暦年) {
  const 子供たちの年齢 = 子供たちの年齢At(西暦年)
  let 同居家族の人数 = 2

  for (const 子供の年齢 of 子供たちの年齢) {
    if (子供の年齢 <= 入力('子供が独立する年齢')) {
      同居家族の人数 += 1
    }
  }

  return 同居家族の人数
}

function 夫婦の食費At(西暦年) {
  return 2 * 入力('大人1人の食費')
}

function 第n子の食費At(西暦年, 第n子) {
  const 子供の年齢 = 子供の年齢At(西暦年, 第n子)

  if (0 <= 子供の年齢 && 子供の年齢 < 1) {
    return +入力('乳児1人の食費')
  } else if (1 <= 子供の年齢 && 子供の年齢 < 7) {
    return +入力('幼児1人の食費')
  } else if (7 <= 子供の年齢 && 子供の年齢 < 12) {
    return +入力('小学生1人の食費')
  } else if (12 <= 子供の年齢 && 子供の年齢 <= 入力('子供が独立する年齢')) {
    return +入力('大人1人の食費')
  } else {
    return 0
  }
}

function 子供たちの食費At(西暦年) {
  const 子供たちの年齢 = 子供たちの年齢At(西暦年)
  let 合計金額 = 0

  for (const [i] of 子供たちの年齢.entries()) {
    合計金額 += 第n子の食費At(西暦年, i + 1)
  }

  return 合計金額
}

function 食費合計At(西暦年) {
  const 夫婦の食費 = 夫婦の食費At(西暦年)
  const 子供たちの食費 = 子供たちの食費At(西暦年)

  return 夫婦の食費 + 子供たちの食費
}

function 食費のスケールメリットAt(西暦年) {
  return 1 - +入力('食費の低減率') * (同居家族の人数At(西暦年) - 1)
}

function 食費At(西暦年) {
  return 食費合計At(西暦年) * 食費のスケールメリットAt(西暦年);
}


入力用シート


出力用シート

より細かく設定できるようになった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

消耗品費

我が家の直近 5 年間の実績だと 2022 年は 30 万円、2021 年は 15 万円、2020 年は 25 万円、2019 年は 25 万円、2018 年は 15 万円と年によってだいぶバラついている。

ちなみに 2023 年は 10 カ月経過時点で 23 万円、月数に比例すると仮定すると 28 万円と予想される。

中央値は 25 万円、平均値は 22 万円、1 カ月 2 万円くらいと考えると良さそう。

ボディーソープなど家族が増えると使用量が増えるものもある。

シンプルに固定費 + 変動費 × 同居人数 で計算しようかな。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

年金を忘れていた

収入の部は終わったかと思ったが年金を忘れていた。

年金は複雑なので頑張って勉強しよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

年金の繰下げ支給

https://www.nenkin.go.jp/service/jukyu/roureinenkin/kuriage-kurisage/20140421-02.html

下記の式で計算して良さそうだ、受給開始年齢の最大値は 75 歳。

増額率 = 0.7 \% \times (受給開始年齢 - 65 歳) \times 12カ月

75 歳まで繰り下げると 84.0% になり、損益分岐点は 87 歳になるそうだ。

増額されるのは老齢基礎年金だけではなく、老齢厚生年金も対象になる。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

老齢厚生年金

https://www.nenkin.go.jp/service/jukyu/roureinenkin/jukyu-yoken/20140421-01.html

特別支給や経過的加算や加給年金などが複雑だが、平成 15 年(2003 年)以降に加入した場合の比例報酬部分だけを考えると下記のように計算できるようだ。

比例報酬部分 = 平均標準報酬額 \times \frac{5.481}{1000} \times 加入月数

https://www.nenkin.go.jp/service/yougo/hagyo/hoshuhirei.html

平均標準報酬額が 50 万円、加入月数が 600 カ月(50 年間)の場合は 1,644,300 円になる。

老齢基礎年金の満額と合わせると 2,439,300 円、75 歳まで繰下げ支給すると 4,488,312 円。

地方なら年金だけで暮らして行けそうな金額だ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

本人の公的年金受給額

コード.gs(追加分)
// 年金

function 経過年数At(西暦年) {
  return 西暦年 - 入力('現在の西暦年')
}

function 厚生年金加入年数At(西暦年) {
  if (年齢At(西暦年) > 入力('退職する年齢')) {
    return 入力('退職する年齢') - 入力('現在の年齢') + 入力('現在の厚生年金加入年数')
  } else {
    return 入力('現在の厚生年金加入年数') + 経過年数At(西暦年)
  }
}

function 老齢基礎年金At(西暦年) {
  if (年齢At(西暦年) >= 入力('公的年金の受給開始年齢')) {
    return 795000 * Math.min(40, 厚生年金加入年数At(西暦年)) / 40
  } else {
    return 0;
  }
}

function 年収の累計At(西暦年) {
  const 現在までの年収の累計 = 西暦年 === parseInt(入力('現在の西暦年'), 10)
    ? +入力('現在までの年収の累計')
    : 年収の累計At(西暦年 - 1)

  return 現在までの年収の累計 + 年収At(西暦年)
}

function 老齢厚生年金At(西暦年) {
  if (年齢At(西暦年) >= 入力('公的年金の受給開始年齢')) {
    return 年収の累計At(西暦年) * 5.481 / 1000
  } else {
    return 0;
  }
}

function 繰下げ支給の増額率At(西暦年) {
  const 年齢 = 年齢At(西暦年)

  if (年齢 <= 65) {
    return 0
  } else {
    return 1 + (Math.min(年齢, 入力('公的年金の受給開始年齢')) - 66) * 12 * 0.7e-2
  }
}

function 公的年金の支給額At(西暦年) {
  return Math.round((老齢基礎年金At(西暦年) + 老齢厚生年金At(西暦年)) * 繰下げ支給の増額率At(西暦年))
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

配偶者の公的年金

コード.gs
// 配偶者の年金

function 配偶者の公的年金加入年数At(西暦年) {
  if (年齢At(西暦年) > 入力('退職する年齢')) {
    return 入力('退職する年齢') - 入力('現在の年齢') + 入力('配偶者の現在の公的年金加入年数')
  } else {
    return 入力('配偶者の現在の公的年金加入年数') + 経過年数At(西暦年)
  }
}

function 配偶者の老齢基礎年金At(西暦年) {
  if (年齢At(西暦年) >= 入力('公的年金の受給開始年齢')) {
    return 795000 * Math.min(40, 配偶者の公的年金加入年数At(西暦年)) / 40
  } else {
    return 0;
  }
}

function 配偶者の年収の累計At(西暦年) {
  return +入力('配偶者の現在までの年収の累計')
}

function 配偶者の老齢厚生年金At(西暦年) {
  if (配偶者の年齢At(西暦年) >= 入力('公的年金の受給開始年齢')) {
    return Math.round(配偶者の年収の累計At(西暦年) * 5.481 / 1000)
  } else {
    return 0;
  }
}

function 配偶者の繰下げ支給の増額率At(西暦年) {
  const 配偶者の年齢 = 配偶者の年齢At(西暦年)

  if (配偶者の年齢 <= 65) {
    return 0
  } else {
    return 1 + (Math.min(配偶者の年齢, 入力('公的年金の受給開始年齢')) - 66) * 12 * 0.7e-2
  }
}

function 配偶者の公的年金の支給額At(西暦年) {
  return Math.round((配偶者の老齢基礎年金At(西暦年) + 配偶者の老齢厚生年金At(西暦年)) * 配偶者の繰下げ支給の増額率At(西暦年))
}

function 夫婦の公的年金の支給額合計At(西暦年) {
  return 公的年金の支給額At(西暦年) + 配偶者の公的年金の支給額At(西暦年)
}


入力用シート


出力用シート

生涯の平均年収 600 万円の 1 馬力で年金を 75 才までの繰下げ支給すると 584 万円でほぼ現役並みの収入がもらえる。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

消耗品費

消耗品費については下記のように簡易的に計算しよう。

消耗品費 = 固定部分 + 変動部分
変動部分 = 1人当たりの変動費 \times 同居人数
コード.gs(追加分)
// 消耗品費

function 消耗品費の固定部分At(西暦年) {
  return +入力('固定の消耗品費')
}

function 消耗品費の変動部分At(西暦年) {
  return +入力('1人当たりの消耗品費') * 同居家族の人数At(西暦年)
}

function 消耗品費At(西暦年) {
  return 消耗品費の固定部分At(西暦年) + 消耗品費の変動部分At(西暦年)
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

娯楽費

過去 5 年間の実績は 30 万円、24 万円、11 万円、5 万円、4 万円

2018 年の 30 万円のうち 29 万円は新婚旅行なので、それを省けば 1 万円になる、少ない!

2019 年は特にこれと言ったものは無かった。

娯楽費は年々変動するのでどうモデル化するかが悩ましい。

今のところ子供が小さいうちや大きくなったらどこかに旅行に行きたいとかも無いので年間 12 万円で固定しておこう。

コード.gs(追加分)
// 娯楽費

function 娯楽費At(西暦年) {
  return +入力('1年間の娯楽費')
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

医療費

5年間の実績は下記の通り。

西暦年 医療費
2018 228,899
2019 57,398
2020 42,800
2021 84,320
2022 32,250

平均値は 99,133.4 円、中央値は 57,398 円。

2018 年は出産費用 184,980 円があったので、それを除けば 43,919 円になる。

2021 年は卵白アレルギーの発生で検査費用 34,010 円があったので、それを除けば 52,070 円になる。

これらを省くと平均値は 45,687 円、中央値は 43,919 円になる。

ちょっと多めに見積もって 1 年間は 60,000 円にしておこうかな。

年齢が高くなると増加していくことが予想される。

高額医療費制度があり、600 万円の場合は 1 月あたりの自己負担限度額は下記の式で計算される。

自己負担限度額 = 80,100円+(総医療費-267,000円)×1 %

例えば手術で 100 万円かかっても 87,430 円までしか負担しなくても良い。

さらに過去 1 年間に 3 カ月以上制度を利用した場合は多数該当で 44,400 円になるようだ。

そうなると人工透析とかで毎月高額医療費が発生しても 532,800 円が年間の上限になるようだ。

さて知識は深まったがどうやってモデル化しようか。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

医療費

医療費をモデル化していこう。


フィデリティ証券の Web ページより引用

下記のようにまとめられそう。

年齢 自己負担額
0〜4 3 万円
5〜29 2 万円
30〜39 2.5 万円
40〜69 3〜8 万円
70〜 8 万円

ただ、長岡市は 18 才まで 1 回 530 円までの医療費助成があるのでほとんどお金がかからない。

https://www.city.nagaoka.niigata.jp/kosodate/cate01/nyuyouji.html

毎月病院に行っても 6,360 円、わかりやすく 6,000 円にしておこう。

ただ 0〜3 才は予防接種とかあるな、この辺は妻に確認してからモデル化してみよう。

コード.gs(追加分)
// 医療費

function n歳での医療費自己負担額(年齢) {
  if (年齢 < 18) {
     return +入力('0〜18歳の医療費')
  } else if (18 <= 年齢 && 年齢 < 30) {
     return +入力('18〜30歳の医療費')
  } else if (30 <= 年齢 && 年齢 < 40) {
     return +入力('30〜40歳の医療費')
  } else if (40 <= 年齢 && 年齢 < 69) {
     const スタートの金額 = +入力('40歳の医療費')
     const ゴールの金額 = +入力('70歳以降の医療費')
     const 差額 = ゴールの金額 - スタートの金額

     return Math.round(スタートの金額 + 差額 / 30 * (年齢 - 40))
  } else {
     return +入力('70歳以降の医療費')
  }
}

function 本人の医療費自己負担額At(西暦年) {
  return n歳での医療費自己負担額(年齢At(西暦年))
}

function 配偶者の医療費自己負担額At(西暦年) {
  return n歳での医療費自己負担額(配偶者の年齢At(西暦年))
}

function 第n子の医療費自己負担額At(西暦年, 第n子) {
  const 子供の年齢 = 子供たちの年齢At(西暦年)[第n子 - 1]

  if (子供の年齢 < 入力('子供が独立する年齢')) {
    return n歳での医療費自己負担額(子供の年齢)
  } else {
    return 0;
  }
}

function 医療費自己負担額の合計At(西暦年) {
  let 合計金額 = 0

  合計金額 += 本人の医療費自己負担額At(西暦年)
  合計金額 += 配偶者の医療費自己負担額At(西暦年)

  for (const [i] of 子供たちの年齢At(西暦年).entries()) {
    合計金額 += 第n子の医療費自己負担額At(西暦年, i + 1)
  }

  return 合計金額
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

交際費

過去 5 年間の実績は下記の通り。

西暦年 交際費
2022 年 20,000 円
2021 年 88,980 円
2020 年 9,000 円
2019 年 169,807 円
2018 年 317,669 円

平均値は 121,091 円、中央値は 88,980 円。

あまりプライベートで飲みに行ったりしなくなったのでだいぶ少ない。

それでも年間 12 万円くらいは下限として考えておいた方が良いだろう。

子供が小学生の時は倍くらいになりそう。

また 50 歳から引退する 75 歳までも倍くらいになりそうだ。

これらを踏まえてモデル化してみよう。

コード.gs(追加分)
// 交際費

function 交際費At(西暦年) {
  const 年齢 = 年齢At(西暦年)

  if (入力('交際が増える年齢') <= 年齢 && 年齢 <= 入力('退職する年齢')) {
    return +入力('交際が増える年齢の交際費')
  }

  const 子供たちの年齢 = 子供たちの年齢At(西暦年)
  const 子供が小中学生である = 子供たちの年齢.some((子供の年齢) => {
    return 7 <= 子供の年齢 && 子供の年齢 < 16
  })

  if (子供が小中学生である) {
    return +入力('子供が小中学生の場合の交際費')
  }

  return +入力('下限の交際費')
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

5 分くらい服飾費について考えてみよう

過去 5 年間の実績は下記の通り。

西暦年 交際費
2022 年 277,251 円
2021 年 135,247 円
2020 年 124,843 円
2019 年 99,354 円
2018 年 76,620 円

平均値は 142,663 円、中央値は 124,843 円。

綺麗に右肩上がりになっている、特に去年は倍増している。

去年はスーツを新調して 189,695 円がかかったので、それを引けば 87,556 円となる。

どうモデルかしていくか悩ましいが子供が中高生になったらオシャレに気を使うので高くなりそうだ。

ちなみに今年は 10 月末時点で 416,506 円と大変高額。

今年もスーツを追加したのでその費用が 259,490 円かかっており、靴も 104,360 円と結構買ったのでこれらが大きい。

これらを抜くと 52,656 円とそれほどでも無い。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

服飾費

美容室

中学生以上は 1 人あたり年間 30,000〜60,000 円はかかりそう。

平均をとって 45,000 円にしておこう。

小学生は年間 30,000 円、それ以前は年間 15,000 円くらい見ておけば良いかな?

洋服や化粧品

去年くらいから美容に目覚めて身なりを整えるようになったので 1 人あたり年間 120,000 円くらいは見ておきたい。

年齢が上がるにつれて色々とコストがかかるようになると思うので 60 歳までに 240,000 円くらいまで増やしていきたい。

ありがたいことにじーちゃんばーちゃんが里帰りする度に子供の服を買ってくれるので、自分たちで買うことがほとんどない。

ただ中学生以降になったらそういう訳にもいかないだろう。

子供 1 人あたり 60,000 円を見ておけば良いかな?

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

11/7 (火) はここまで

作業時間は 0.75 時間、累計 10.5 時間。

美容料が終わったので次回は洋服や化粧品を実装しよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

服飾費が完成

コード.gs(追加分)
// 服飾費

function n歳の美容料(年齢) {
  if (年齢 < 7) {
    return +入力('乳幼児の美容料')
  } else if (7 <= 年齢 && 年齢 < 13) {
    return +入力('小学生の美容料')
  } else {
    return +入力('中学生以上の美容料')
  }
}

function 美容料At(西暦年) {
  const 年齢 = 年齢At(西暦年)
  return n歳の美容料(年齢)
}

function 配偶者の美容料At(西暦年) {
  const 年齢 = 配偶者の年齢At(西暦年)
  return n歳の美容料(年齢)
}

function 第n子の美容料At(西暦年, 第n子) {
  const 年齢 = 子供の年齢At(西暦年, 第n子)

  if (年齢 <= 入力('子供が独立する年齢')) {
    return n歳の美容料(年齢)
  } else {
    return 0
  }
}

function 美容料の合計At(西暦年) {
  let 合計金額 = 0

  合計金額 += 美容料At(西暦年)
  合計金額 += 配偶者の美容料At(西暦年)

  for (const [i] of 子供たちの年齢At(西暦年).entries()) {
    合計金額 += 第n子の美容料At(西暦年, i + 1)
  }

  return 合計金額
}

function 大人の洋服代(年齢) {
  const 洋服代の下限 = +入力('洋服代の下限')
  const 洋服代の上限 = +入力('洋服代の上限')
  const 洋服代が増え始める年齢 = +入力('洋服代が増え始める年齢')
  const 洋服代が増え終わる年齢 = +入力('洋服代が増え終わる年齢')

  if (年齢 <= 洋服代が増え始める年齢) {
    return 洋服代の下限
  } else if (洋服代が増え始める年齢 < 年齢 && 年齢 < 洋服代が増え終わる年齢) {
    const 傾き = (洋服代の上限 - 洋服代の下限) / (洋服代が増え終わる年齢 - 洋服代が増え始める年齢)
    return Math.round(洋服代の下限 + 傾き * (年齢 - 洋服代が増え始める年齢))
  } else {
    return 洋服代の上限
  }
}

function 子供の洋服代(年齢) {
  if (13 <= 年齢 && 年齢 <= 入力('子供が独立する年齢')) {
    return +入力('子供の中学生以降の洋服代')
  } else {
    return 0
  }
}

function 洋服代At(西暦年) {
  return 大人の洋服代(年齢At(西暦年))
}

function 配偶者の洋服代At(西暦年) {
  return 大人の洋服代(配偶者の年齢At(西暦年))
}

function 第n子の洋服代At(西暦年, 第n子) {
  return 子供の洋服代(子供の年齢At(西暦年, 第n子))
}

function 洋服代の合計At(西暦年) {
  let 合計 = 0

  合計 += 洋服代At(西暦年)
  合計 += 配偶者の洋服代At(西暦年)

  for (const [i] of 子供たちの年齢At(西暦年).entries()) {
    合計 += 第n子の洋服代At(西暦年, i + 1)
  }

  return 合計
}

function 服飾費At(西暦年) {
  return 美容料の合計At(西暦年) + 洋服代の合計At(西暦年)
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

11/8 (水) はここまで

作業時間は 0.5 時間、累計 11 時間。

美容料が終わったので次回は保険料について考えてみよう。

保険料はなかなか手強そうだ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

今支払っている保険料

  • 火災保険:5 年単位、ずっと
  • 地震保険:5 年単位、ずっと
  • 生命・医療保険:毎月、ずっと
  • 年金保険:毎年、65 歳まで
  • 学資保険:毎年、18 年間と 15 年間の 2 つ

保険料

火災保険は 5 年で 20 万円、地震保険は 5 年で 8 万円、生命・医療保険は掛捨てで毎月 1.5 万円、年金保険は毎年 8 万円、学資保険は 10 + 20 万円としておこう。

年金保険

66 歳から 75 歳まで 10 年間にわたって 27 万円の給付がある。

学資保険

18 年間の方は第 1 子が 18〜23 歳までの 5 年間にわたって 36 万円ほど給付がある。

15 年間の方は好きなタイミングで好きな金額を引き出すことができるが第 2 子が進学するタイミングで 5 年間にわたって引き出すことにしよう、そうすると 1 年間に 60 万円くらいになる。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

11/10 (金) はここまで

作業時間は 0.75 時間、累計 11.75 時間。

今日は保険料について考えるだけで終わったしまった。

次回は実装していこう

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

火災保険料

コード.gs(追加分)
function 火災保険料At(西暦年) {
  if (西暦年 % 5 === 0) {
    return 200000
  }

  return 0;
}

細かい部分は後から直そう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

12/11 (月) はここまで

作業時間は 10 分、累計 11.75 時間 + 10 分。

次は火災保険料をパラメータで変えられるようにしよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

火災保険と地震保険

コード.gs(追加分)
function 火災保険料At(西暦年) {
  if ((西暦年 - 入力('火災保険料の初回西暦年')) % 入力('火災保険料の年数') === 0) {
    return +入力('火災保険料の金額')
  }

  return 0;
}

function 地震保険料At(西暦年) {
  if ((西暦年 - 入力('火災保険料の初回西暦年')) % 入力('火災保険料の年数') === 0) {
    return +入力('火災保険料の金額')
  }

  return 0;
}

function 地震保険料At(西暦年) {
  if ((西暦年 - 入力('地震保険料の初回西暦年')) % 入力('地震保険料の年数') === 0) {
    return 入力('地震保険料') * 入力('地震保険料の年数')
  }

  return 0;
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

生命保険と医療保険

生命保険は 75 才までだったが医療保険は終身だった。

生命保険で一括りにするのではなく別々に考えた方が良さそうだ。

生命保険は 1 万円、医療保険は 5 千円としよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

12/12 (火) はここまで

作業時間は 20 分、累計 11.75 時間 + 30 分、735 分。

次は生命保険と医療保険について実装しよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

12/26 (火) はここから

また不測の事態で 2 週間も止まってしまった。

今日は生命保険と医療保険を終わらせよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

生命保険と医療保険

コード.gs(追加分)
function 生命保険料At(西暦年) {
  if (年齢At(西暦年) <= 入力('生命保険料の払い込み年齢')) {
    return +入力('生命保険料の年額')
  } else {
    return 0
  }
}

function 医療保険料At(西暦年) {
  return +入力('医療保険料の年額')
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

年金保険の実装

コード.gs(追加分)
function 年金保険料At(西暦年) {
  if (年齢At(西暦年) <= 入力('年金保険料の払い込み年齢')) {
    return +入力('年金保険料の年額')
  } else {
    return 0
  }
}

function 年金保険収入At(西暦年) {
  const 年齢 = 年齢At(西暦年)
  const 開始年齢 = 入力('年金保険収入の開始年齢')
  const 終了年齢 = 入力('年金保険収入の終了年齢')

  if (開始年齢 <= 年齢 && 年齢 <= 終了年齢) {
    return +入力('年金保険収入の年額')
  } else {
    return 0
  }
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

1 つ目の学資保険

保険料は年間 11 万円、支払い回数は 17 回、2019 年に契約しているので 2035 年まで支払いがある。

給付は 2036〜2040 年までの 5 年間で毎年 40 万円のようだ。

コード.gs(追加分)
function 学資保険Jの年間保険料At(西暦年) {
  if (西暦年 <= 入力('学資保険Jの払い込み西暦年')) {
    return +入力('学資保険Jの年間保険料')
  }
  
  return 0
}

function 学資保険Jの年間給付金At(西暦年) {
  if (入力('学資保険Jの給付開始西暦年') <= 西暦年 && 西暦年 <= 入力('学資保険Jの給付終了西暦年')) {
    return +入力('学資保険Jの給付年額')
  }

  return 0
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

学資保険 G

年間保険料は 20 万円、払い込み期間は 15 年間、2019 年契約なので 2033 年まで支払いがある。

解約返戻金は第 2 子が 18〜22 才までの 5 年間(2039〜2043)に 60 万円ずつ受け取るとする。

コード.gs(追加分)
function 学資保険Gの年間保険料At(西暦年) {
  if (西暦年 <= 入力('学資保険Gの払い込み西暦年')) {
    return +入力('学資保険Gの年間保険料')
  }
  
  return 0
}

function 学資保険Gの年間給付金At(西暦年) {
  if (入力('学資保険Gの給付開始西暦年') <= 西暦年 && 西暦年 <= 入力('学資保険Gの給付終了西暦年')) {
    return +入力('学資保険Gの給付年額')
  }

  return 0
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

保険料合計

コード.gs(追加分)
/**
 * @param {number[]} array
 * @return {number}
 */
function 合計(array) {
  return array.reduce((memo, value) => memo + value, 0)
}

function 保険料合計At(西暦年) {
  return 合計([
    火災保険料At(西暦年),
    地震保険料At(西暦年),
    生命保険料At(西暦年),
    医療保険料At(西暦年),
    年金保険料At(西暦年),
    学資保険Jの年間保険料At(西暦年),
    学資保険Gの年間保険料At(西暦年),
  ])
}


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

交通費の分析

過去 5 年間の実績は下記の通り。

西暦年 金額
2023 52,875
2022 58,464
2021 54,667
2020 49,235
2019 111,968

2019 年は少し例外だがほぼ 5 万円台で来ている。

少し多めに見積もって 60,000 円で固定にしておこう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

交通費の実装

コード.gs(追加分)
function 交通費At(西暦年) {
  return +入力('年間交通費')
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

水道光熱費の分析

過去 5 年間の実績は下記の通り。

西暦年 電気料 水道料
2023 60,000 22,656
2022 110,000 25,648
2021 69,593 26,510
2020 117,471 26,133
2019 134,443 42,918

2019 と 2020 はガスや灯油もあるが電気料にまとめた。

2022 年は電気をバンバン使っていたこともあって高かったが引っ越した 2021 年からはおおむね 60,000 円で来ているので 60,000 円ということにしておこう。

水道料も 1 カ月 2,500 円くらいなので 30,000 円で固定にしておこう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

水道光熱費の実装

コード.gs(追加分)
function 水道料At(西暦年) {
  return +入力('年間水道料')
}

function 電気料At(西暦年) {
  return +入力('年間電気料')
}

function 水道光熱費At(西暦年) {
  return 水道料At(西暦年) + 電気料At(西暦年)
}


入力用シート


出力用シート

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

保育料の続き

子供が 0 才の時は保育料 0 円、1〜3 才(になる年)の時、4 才(になる年)の時、5〜6 才(になる年)の時で別々に保育料を設定できるようにしておこう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

保育料の実装

コード.gs(追加分)
function 第n子の保育料At(西暦年, 第n子) {
  const 年齢 = 子供の年齢At(西暦年, 第n子)

  if (0 <= 年齢 && 年齢 <= 0) {
    return 入力('0歳の保育料月額') * 12
  } else if (1 <= 年齢 && 年齢 <= 3) {
    return 入力('1〜3歳の保育料月額') * 12
  } else if (4 <= 年齢 && 年齢 <= 4) {
    return 入力('4歳の保育料月額') * 12
  } else if (5 <= 年齢 && 年齢 <= 6) {
    return 入力('5〜6歳の保育料月額') * 12
  } else {
    return 0
  }
}

function 子供たちの保育料At(西暦年) {
  const 子供たちの年齢 = 子供たちの年齢At(西暦年)
  let 合計金額 = 0

  for (const [i] of 子供たちの年齢.entries()) {
    合計金額 += 第n子の保育料At(西暦年, i + 1)
  }

  return 合計金額
}


入力用シート


出力用シート