【Python】外貨定期預金のシュミレーション(積立なし)

## Pythonを使って、外貨定期預金のシュミレーションをしてみる

- 目的はまとまった金額(円)を外貨定期預金(豪ドル)で運用する際のリスクを把握
- 定期、非定期に関わらず積立はしない前提
- 終価係数ベースでのシュミレーション
- 源泉分離課税 20.315% =（国税 15％ + 地方税 5％ + 復興特別所得税 0.315）の税率が適用
- 為替差益に対する課税は未処理
- 三井住友信託銀行の[外貨定期預金シュミレーション](https://www.smtb.jp/personal/saving/foreign/tool/simulation)と同じ結果になることを確認
- 基本上記サイトで事足りてしまう。が、為替シュミレーションが±5円の幅までしか確認できない。このコードであれば自由に幅を設定出来るので、より為替損益のリスクが把握しやすい
- 5年で運用していれば、10円、20円変動することは十分あり得る

::: note info
__環境__
- MacOS : Sonoma 14.4.1
- python : 3.12.0
:::

::: note info
__ポイント__
- 後でモジュールとして使えるようにクラス化
- if_name__ = 'main' を使ってスクリプトファイルとして実行できるようにした
- python的には難しいことは何もやってない😅
- __お金の計算なので、Decimalモジュールを使用__
- こういうものを簡単に自作できちゃうPythonってめっちゃステキ！❤️
:::

### 実行結果

![simulation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699739/0a38dbab-3816-a390-c354-ac3e39652660.png)


### コード

``` gaika_teiki_yokin.py
# -*- coding: utf-8 -*-

from decimal import *


class GaikaTeikiYokin:
    def __init__(self):
        self.present_value = None
        self.interest_rate = None
        self.tts_rate = None
        self.ttb_simulation = None
        self.term = None
        self.tax_kokuzei = None
        self.tax_chihouzei = None

    def terminal_value_coefficient(self):
        """終価係数"""
        return Decimal(
               (Decimal("1") + Decimal(self.interest_rate)) ** Decimal(self.term)
               ).quantize(Decimal(".001"), rounding=ROUND_HALF_UP)

    def aud_current_value(self):
        """現在価値（豪ドル）"""
        return Decimal(
               Decimal(self.present_value) / Decimal(self.tts_rate)
               ).quantize(Decimal(".01"), rounding=ROUND_UP)

    def aud_future_value(self, aud_current_value, terminal_value_coefficient):
        """将来価値（豪ドル）"""
        return Decimal(aud_current_value) * Decimal(terminal_value_coefficient)

    def aud_interest_amout(self, aud_future_value, aud_current_value):
        """利息（税引前） = 将来価値 - 現在価値"""
        return Decimal(
               Decimal(aud_future_value) - Decimal(aud_current_value)
               ).quantize(Decimal(".01"), rounding=ROUND_DOWN)

    def aud_interest_kokuzei(self, aud_interest_amout):
        """国税（豪ドル） = 利息（税引前）* 国税"""
        return Decimal(
               Decimal(aud_interest_amout) * (Decimal(self.tax_kokuzei))
               ).quantize(Decimal(".01"), rounding=ROUND_DOWN)

    def aud_interest_chihozei(self, aud_interest_amout):
        """地方税（豪ドル） = 利息（税引前）* 地方税"""
        return Decimal(
               Decimal(aud_interest_amout) * (Decimal(self.tax_chihouzei))
               ).quantize(Decimal(".01"), rounding=ROUND_DOWN)

    def aud_interest_amout_tax(self, aud_interest_amout, kokuzei, chihouzei):
        """利息（税引後） = 利息（税引前）- 国税 - 地方税"""
        return Decimal(aud_interest_amout) - Decimal(kokuzei) - Decimal(chihouzei)

    def aud_future_value_tax(self, aud_current_value, aud_interest_amout_tax):
        """将来価値(税引後) = 現在価値 + 利息(税引後)"""
        return Decimal(aud_current_value) + Decimal(aud_interest_amout_tax)

    # メイン関数
    def operation_simulation(self):
        """ 運用シュミレーション """
        tvc = self.terminal_value_coefficient()
        acv = self.aud_current_value()
        afv = self.aud_future_value(acv, tvc)
        aia = self.aud_interest_amout(afv, acv)
        kokuzei = self.aud_interest_kokuzei(aia)
        chihouzei = self.aud_interest_chihozei(aia)
        aiat = self.aud_interest_amout_tax(aia, kokuzei, chihouzei)
        afvt = self.aud_future_value_tax(acv, aiat)
        # pass
        print(
        f"""

【外貨定期預金】
運用シュミレーション結果

預入金          : {self.present_value:,} 円
利率            : {self.interest_rate:.2%}
期間            : {self.term} 年
TTS             : {self.tts_rate} 円

終価係数        : {tvc}
現在価値        : {acv:>11,.2f} AUD
将来価値(税引前): {afv:>11,.2f} AUD
利息(税引前)    : {aia:>11,.2f} AUD
国税(15.315%)  : {kokuzei:>11,.2f} AUD
地方税(5%)     : {chihouzei:>11,.2f} AUD
利息(税引後)    : {aiat:>11,.2f} AUD
将来価値(税引後): {afvt:>11,.2f} AUD

        """
        )


    def ttb_ex_simulation(self):
        """TTBのシュミレーション"""
        ttb_rate_list = []
        for i in self.ttb_simulation:
            ttb_rate_list.append(Decimal(self.tts_rate) + Decimal(i))
        return ttb_rate_list

    def jpn_future_value_list(self, ttb_rate_list, aud_future_value_tax):
        """TTBシュミレーションをベースにした税引後将来価値（円）"""
        jpn_fv_list = []
        for i in ttb_rate_list:
            jpn_fv_list.append(Decimal(aud_future_value_tax) * Decimal(i))
        return jpn_fv_list

    def jpn_diff_list(self, jpn_fv_list):
        """差額（税引後の為替損益）"""
        jpn_diff_list = []
        for i in jpn_fv_list:
            jpn_diff_list.append(Decimal(i) - Decimal(self.present_value))
        return jpn_diff_list

    def case_simulation(self, ttb_rate_list, jpn_fv_list, jpn_diff_list):
        """損益シュミレーション"""

        print("損益シュミレーション結果")
        print("")
        print(
            f"税引後将来価値(満期[{self.term}]年後) と 全体損益(為替差益に対する課税は未処理)"
        )
        for r, s, a, d in zip(
            ttb_rate_list, self.ttb_simulation, jpn_fv_list, jpn_diff_list
        ):
            print(
                f" ・TTB {r:>6.2f}({s:>3.0f})円の場合：{Decimal(Decimal(a).quantize(Decimal("1."), rounding=ROUND_DOWN)):>10,.0f}円, 損益：{Decimal(Decimal(d).quantize(Decimal("1."), rounding=ROUND_DOWN)):>10,.0f}円"
            )
        print("")

    def pl_simulation(self):
        """損益シュミレーション"""
        tvc = self.terminal_value_coefficient()
        acv = self.aud_current_value()
        afv = self.aud_future_value(acv, tvc)
        aia = self.aud_interest_amout(afv, acv)
        kokuzei = self.aud_interest_kokuzei(aia)
        chihouzei = self.aud_interest_chihozei(aia)
        aiat = self.aud_interest_amout_tax(aia, kokuzei, chihouzei)
        afvt = self.aud_future_value_tax(acv, aiat)
        tes = self.ttb_ex_simulation()
        jfvl = self.jpn_future_value_list(tes, afvt)
        jdl = self.jpn_diff_list(jfvl)
        self.case_simulation(tes, jfvl, jdl)

if __name__ == ("__main__"):

    # 変数の定義
    gty = GaikaTeikiYokin()
    gty.present_value = 5_000_000
    gty.interest_rate = 0.037
    gty.tts_rate = 102.50
    gty.term = 4.68  # 三井住友信託銀行の外貨定期預金の5年定期の設定
    # gty.term = 5
    gty.tax_kokuzei = 0.15315
    gty.tax_chihouzei = 0.05
    gty.ttb_simulation = [-20.0, -15.0, -10.0, -5.0, 0.0, 5.0, 10.0, 15.0, 20.0]

    #　関数の実行
    gty.operation_simulation()
    gty.pl_simulation()

```