見出し画像

資産運用ストレステスト・シミュレーター in Python

このPythonスクリプトは、様々な経済シナリオ下での資産運用ポートフォリオのパフォーマンスをシミュレートし、分析するためのツールです。ユーザーが設定したパラメータに基づいて、通常のシナリオとストレスシナリオでのポートフォリオの挙動を比較します。


特徴

  • ユーザー入力によるポートフォリオ構成とシミュレーションパラメータの設定

  • 複数の資産クラス(株式、債券、現金)を含むポートフォリオのシミュレーションが可能

  • 各資産クラスの想定リターンとボラティリティをカスタマイズ可能

  • 3つのリスク許容度(保守的、中庸、積極的)に基づくシミュレーション

  • 3つのストレスシナリオ:

    • 市場急落

    • 長期不況

    • 高インフレ

  • 以下の主要なパフォーマンス指標を計算:

    • 最終ポートフォリオ価値(通常シナリオとストレスシナリオ)

  • matplotlibを使用してシミュレーション結果を可視化

要件

  • Python 3.7以上

  • 必要なPythonパッケージ:

    • numpy

    • matplotlib

必要なパッケージは以下のコマンドでインストールできます。

pip install numpy matplotlib

使用方法

1. コマンドプロンプトからプログラムを実行します。

python asset_management_simulator.py

2. プロンプトに従って、以下の情報を入力します:

  • 初期投資額(ドル)

  • 投資期間(年)

  • リスク許容度(保守的、中庸、積極的)

  • ポートフォリオの構成(株式、債券、現金の配分比率)

  • 各資産クラスの想定リターンとボラティリティ

  • 想定インフレ率

  • ストレスシナリオの選択

  • リバランス頻度(月)

3. プログラムが自動的にシミュレーションを実行します。

4. 結果が表示され、グラフが生成されます。

スクリプト詳細

import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass

@dataclass
class SimulationParams:
    initial_investment: float
    investment_period: int
    risk_tolerance: str
    asset_allocation: dict
    asset_returns: dict
    asset_volatilities: dict
    inflation_rate: float
    stress_scenario: str
    rebalance_frequency: int

def run_simulation(params):
    # リスク許容度に基づいてリターンとボラティリティを調整
    risk_multipliers = {'conservative': 0.8, 'moderate': 1.0, 'aggressive': 1.2}
    risk_multiplier = risk_multipliers[params.risk_tolerance]
    adjusted_returns = {k: v * risk_multiplier for k, v in params.asset_returns.items()}
    adjusted_volatilities = {k: v * risk_multiplier for k, v in params.asset_volatilities.items()}

    # ポートフォリオのリターンとボラティリティを計算
    portfolio_return = sum(params.asset_allocation[asset] * adjusted_returns[asset] for asset in params.asset_allocation)
    portfolio_volatility = np.sqrt(sum((params.asset_allocation[asset] * adjusted_volatilities[asset])**2 for asset in params.asset_allocation))

    # シナリオをシミュレート
    normal_scenario = simulate_scenario(params, portfolio_return, portfolio_volatility, 'normal')
    stress_scenario = simulate_scenario(params, portfolio_return, portfolio_volatility, params.stress_scenario)

    return normal_scenario, stress_scenario

def simulate_scenario(params, base_return, base_volatility, scenario_type):
    # 各シミュレーションでシードをリセット
    np.random.seed()
    scenario = [params.initial_investment]
    
    if scenario_type == 'market_crash':
        scenario[0] *= 0.6  # 40%の初期下落
        return_multiplier, volatility_multiplier = 0.5, 1.5
    elif scenario_type == 'prolonged_recession':
        return_multiplier, volatility_multiplier = 0.3, 1.2
    elif scenario_type == 'high_inflation':
        return_multiplier, volatility_multiplier = 1.0, 1.0
        base_return -= params.inflation_rate / 100
    else:  # 通常のシナリオ
        return_multiplier, volatility_multiplier = 1.0, 1.0
    
    scenario_return = base_return * return_multiplier
    scenario_volatility = base_volatility * volatility_multiplier

    for month in range(params.investment_period * 12):
        monthly_return = np.random.normal(scenario_return / 12, scenario_volatility / np.sqrt(12))
        real_return = monthly_return - params.inflation_rate / 1200  # インフレ調整
        scenario.append(scenario[-1] * (1 + real_return))
        
        if (month + 1) % params.rebalance_frequency == 0:
            target_allocation = {asset: value * scenario[-1] for asset, value in params.asset_allocation.items()}
            scenario[-1] = sum(target_allocation.values())

    return scenario

def plot_results(normal_scenario, stress_scenario, params):
    years = range(0, params.investment_period + 1)
    normal_annual = [normal_scenario[i*12] for i in years]
    stress_annual = [stress_scenario[i*12] for i in years]

    plt.figure(figsize=(10, 6))
    plt.plot(years, normal_annual, label='Normal Scenario')
    plt.plot(years, stress_annual, label='Stress Scenario')
    plt.xlabel('Years')
    plt.ylabel('Portfolio Value ($)')
    plt.title('Asset Management Stress Test Simulation')
    plt.legend()
    plt.grid(True)
    plt.xticks(years)
    plt.show()

def get_user_input(prompt, default=None):
    if default is not None:
        user_input = input(f"{prompt} (デフォルト: {default}): ").strip()
        return default if user_input == "" else float(user_input)
    else:
        return float(input(prompt))

def main():
    print("資産運用ストレステストシミュレーター")

    initial_investment = get_user_input("初期投資額($)")
    investment_period = int(get_user_input("投資期間(年)"))
    
    risk_tolerance_options = {
        '1': ('保守的', 'conservative'),
        '2': ('中庸', 'moderate'),
        '3': ('積極的', 'aggressive')
    }
    print("\nリスク許容度を選択してください:")
    print("1. 保守的 - リスクを最小限に抑え、安定した運用を目指します。")
    print("2. 中庸 - バランスの取れたリスクと収益を目指します。")
    print("3. 積極的 - 高いリターンを目指し、より大きなリスクを取ります。")
    risk_choice = input("番号を入力してください (1/2/3): ")
    risk_tolerance = risk_tolerance_options[risk_choice][1]

    print("\n資産配分を入力してください(合計が100%になるようにしてください)")
    stocks = get_user_input("株式の割合(%)")
    bonds = get_user_input("債券の割合(%)")
    cash = 100 - stocks - bonds
    print(f"現金の割合(%): {cash:.1f}")
    asset_allocation = {'stocks': stocks/100, 'bonds': bonds/100, 'cash': cash/100}

    print("\n各資産クラスの想定リターンとボラティリティを入力してください")
    asset_returns = {
        'stocks': get_user_input("株式の想定リターン(%)", 8.0) / 100,
        'bonds': get_user_input("債券の想定リターン(%)", 3.0) / 100,
        'cash': get_user_input("現金の想定リターン(%)", 1.0) / 100
    }
    asset_volatilities = {
        'stocks': get_user_input("株式のボラティリティ(%)", 20.0) / 100,
        'bonds': get_user_input("債券のボラティリティ(%)", 8.0) / 100,
        'cash': get_user_input("現金のボラティリティ(%)", 1.0) / 100
    }

    inflation_rate = get_user_input("想定インフレ率(%)")

    stress_scenario_options = {
        '1': ('市場急落', 'market_crash'),
        '2': ('長期不況', 'prolonged_recession'),
        '3': ('高インフレ', 'high_inflation')
    }
    print("\nストレスシナリオを選択してください:")
    print("1. 市場急落 - 株式市場が急激に下落し、その後緩やかに回復するシナリオ")
    print("2. 長期不況 - 経済が長期間停滞し、全体的なリターンが低下するシナリオ")
    print("3. 高インフレ - インフレ率が急上昇し、実質リターンが大きく低下するシナリオ")
    scenario_choice = input("番号を入力してください (1/2/3): ")
    stress_scenario = stress_scenario_options[scenario_choice][1]

    rebalance_frequency = int(get_user_input("リバランス頻度(月)"))

    params = SimulationParams(
        initial_investment=initial_investment,
        investment_period=investment_period,
        risk_tolerance=risk_tolerance,
        asset_allocation=asset_allocation,
        asset_returns=asset_returns,
        asset_volatilities=asset_volatilities,
        inflation_rate=inflation_rate,
        stress_scenario=stress_scenario,
        rebalance_frequency=rebalance_frequency
    )

    normal_scenario, stress_scenario = run_simulation(params)

    print(f"\n通常シナリオの最終ポートフォリオ価値: ${normal_scenario[-1]:,.0f}")
    print(f"ストレスシナリオの最終ポートフォリオ価値: ${stress_scenario[-1]:,.0f}")

    plot_results(normal_scenario, stress_scenario, params)

if __name__ == "__main__":
    main()

出力例

初期投資額:$10,000
投資期間:10年
リスク許容度:中庸
ポートフォリオ構成:
  株式: 60.00%
  債券: 30.00%
  現金: 10.00%
想定インフレ率:2.00%
ストレスシナリオ:市場急落
リバランス頻度:6ヶ月

通常シナリオの最終ポートフォリオ価値: $12,233
ストレスシナリオの最終ポートフォリオ価値: $9,478

スクリプトは、通常シナリオとストレスシナリオでのポートフォリオ価値推移を比較するグラフも生成します。

カスタマイズ

このスクリプトは、実行時にユーザー入力を受け付けるため、以下の項目を簡単にカスタマイズできます。

  • 初期投資額

  • 投資期間

  • リスク許容度

  • ポートフォリオの資産構成(株式、債券、現金の配分)

  • 各資産クラスの想定リターンとボラティリティ

  • 想定インフレ率

  • ストレスシナリオの種類

  • リバランス頻度

注意点

  • ポートフォリオの配分比率の合計が100%になるように入力してください。

  • 各資産クラスの想定リターンとボラティリティにはデフォルト値が設定されていますが、必要に応じて変更できます。

注意事項

このスクリプトは情報提供の目的でのみ作成されています。金融アドバイスを構成するものではありません。シミュレーション結果は将来の実際のパフォーマンスを保証するものではありません。

この記事が気に入ったらサポートをしてみませんか?