見出し画像

新NISA 投資期間について考える

サブテーマ:一括投資時の保有期間によるリターンの違いを調べてみる
                           S&P500 、NASDAQ100、日経225


1 初めに

 新NISAが始まって投資を始めた人が多いと思います。しかし、私自身もそうですが、買った投資信託をいつ売るべきか??迷われていると思います。
 そこで今回は、代表的な指数を保有期間を変更した場合のリターンについて過去実績を集計してみます。過去実績は、あくまで過去のこととはいえ、”歴史は繰り返す”という格言?の通り、統計的な集計結果は新NISAをはじめとする投資活動の参考になりますので、ぜひお付き合いください。

PYTYON入門者やプログラムに興味のある方へ

 PYTHONプログラムをつけております。パソコン+GoogleアカウントがあればGoogle Colabで誰でも簡単にコピペで実行できますので、ぜひ一度トライしてみてください。

今回のゴール①:超長期トレンドで代表的株価指数の比較チャート

株価指数(対数軸):S&P500(^GSPC),NASDAQ100(^NDX),日経225(^N225)

今回のゴール②:20年間一括投資のリターン実績

20年間後のリターン実績:S&P500(^GSPC),NASDAQ100(^NDX),日経225(^N225)

2 豆知識

1)株価指数と株価(同一指数)の違いについて

 株価指数は、特定の市場やセクターの代表的な株式の平均価格を示す指標であり、市場全体または特定のセクターのパフォーマンスを測るために使用されます。一方、その株価指数に連動するETF(上場投資信託)は、指数を模倣する一連の株式を実際に保有する投資商品です。ETFは証券取引所で株式と同様に取引され、投資家は指数全体に分散投資することができます。
 株価指数自体は直接投資の対象とならず、市場の動向を分析するためのツールとして機能します。一方、ETFは指数の動きを追跡することを目的としており、個別の株式に投資する代わりに、指数全体のパフォーマンスに投資することが可能です。これにより、投資家は低コストで簡単に広範な市場へのアクセスを得られ、分散投資の利点を享受することができます。
 なお今回の調査はYahoo Financeから取得しやすい指数を取得しています。実際には指数自体を購入するわけではなく、指数に連動した値動きをする投資信託もしくはETFに対し投資します。この違いに対し今回の調査で特に注意すべき点は、株価指数には維持費等の経費がないマイナス要素と、株式を保有する上で還元される配当のプラス要素が考慮されていないことです。そのため実際の投資リターンを厳密に検証するにはプラス/マイナス要素を考慮すべき内容であることをご承知ください。(次回以降、シミュレーションできる内容を検討してみますのでご期待ください。)

2)対数軸について

 対数軸を利用することで、データの比較が容易になり、長期的な傾向や相関関係を把握しやすくなります。
 対数は数学の概念で、ある数が別の数(底)を何乗したものかを表します。対数スケール(対数メモリ)は、値の範囲が非常に広いデータを表示する際に有効です。このスケールでは、数値の比率が等間隔で表示されるため、小さな変動と大きな変動を同時に視覚的に捉えやすくなります。例えば、株価や経済データなど、時間と共に指数関数的に増減する可能性があるデータを分析する際に対数スケールを使用すると、長期にわたる成長トレンドや変動パターンをより明瞭に理解することができます。

3 実践

1)調査対象について

今回の調査した株価指数とティッカーコード及び調査期間は下の通りです。
 
 調査期間:1985年10月1日から2024年3月初旬
 指数(ティッカー)   備考
  S&P500(^GSPC)    全米を代表する500社の米国株価指数
  NASDAQ100(^NDX)   NASDAQ市場を代表する100社
              (ハイテク&大型中心)
  日経225(^N225)    日本を代表する225社の株価指数

2)超長期トレンドを確認する

・データの取得&月1のデータに変更
前回までと同様にYahooFinanceからデータを取得し、月別データとします。なお、念のため日本株は米国株と祝日等が異なるため、あらかじめ欠損値対応するコード(前の値で穴埋め)を追加しています。

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 対象のティッカーシンボル
tickers = ['^GSPC', '^NDX','^N225']

# データの取得
data = yf.download(tickers, start="1985-10-01", end=pd.Timestamp.now().strftime('%Y-%m-%d'))
# 必要な列のみ抽出
data = data[['Adj Close']]
data['Adj Close']['^N225'] = data['Adj Close']['^N225'].fillna(method='ffill')

# 月別にリサンプリングして、月の初めのデータを取得
monthly_data = data.resample('MS').first()
monthly_data
1985年10月から2024年3月までの株価指数

次に取得したデータをプロットします。
 今回3つのパターンのグラフが一度に出力するコードとしてます。
 1つ目は価格そのままのグラフです。時系列の変化はわかりますが、比較は難しいです。
 2はスタート月(1985年10月)を100としたグラフですが、米国株の値上がりと日本株の低迷差が際立っていて差が見えないです。
 3は2のグラフを対数軸にしてます。対数軸にすることで比較がしやすくなっています。

#1 時系列の線グラフを描画
plt.figure(figsize=(14, 7))  # グラフのサイズを設定
# 各ティッカーについて線グラフをプロット
for ticker in tickers:
    plt.plot(monthly_data['Adj Close'][ticker], label=ticker)
# グラフのタイトルと軸ラベルを設定
plt.title('Monthly Adjusted Close Prices Over Time')
plt.xlabel('Date')
plt.ylabel('Adjusted Close Price')
plt.legend()  # 凡例を表示

# 基準日の価格で各ティッカーの価格を割り、100をかけてインデックス化
normalized_data = monthly_data['Adj Close'].apply(lambda x: x / x.iloc[0] * 100)

#2 インデックス化されたデータの時系列グラフを描画
plt.figure(figsize=(14, 7))  # グラフのサイズを設定
# 各ティッカーについて線グラフをプロット
for ticker in tickers:
    plt.plot(normalized_data[ticker], label=ticker)
# 初期線(100)を追加
plt.axhline(y=100, color='red', linestyle='--', linewidth=1)
# グラフのタイトルと軸ラベルを設定
plt.title('Normalized Monthly Adjusted Close Prices Over Time')
plt.xlabel('Date')
plt.ylabel('Normalized Price (Base=100 on 1985-10-01)')
plt.legend()


#3 対数軸のグラフの描写
plt.figure(figsize=(14, 7)) 
# 各ティッカーについて線グラフをプロット
for ticker in tickers:
    plt.plot(normalized_data[ticker], label=ticker)
# 初期線(100)を追加
plt.axhline(y=100, color='red', linestyle='--', linewidth=1)
# グラフのタイトルと軸ラベルを設定
plt.title('LogPlot Normalized Monthly Adjusted Close Prices Over Time')
plt.xlabel('Date')
plt.ylabel('Log Normalized Price (Base=100 on 1985-10-01)')
plt.legend()
# y軸を対数スケールに設定
plt.yscale('log')


# グラフを表示
plt.show()
1 価格そのままの時系列グラフ
2 スタート月(1985年10月)を100にインデックス化したグラフ
3 スタート月(1985年10月)を100にインデックス化したグラフ(対数軸)

3)保有期間によるリターン実績を集計する(一括投資)

・一括投資実績の計算
 今回、1000ドル一括した各指数を、1ヶ月、3ヶ月、6ヶ月、1年(12ヶ月)、3年(36ヶ月)、5年(60ヶ月)、10年(120ヶ月)、20年(240ヶ月)保有した実績を計算します。それぞれ、1月単位でずらして計算させますが、月が多いのでFor文を使って一括で計算させるコードにしています。
 次に得られた結果(results)を箱ひげ図を表示します。こちらも期間が多いためfor文を使って一度に全ての期間を表示します。また初期投資額1000ドルを赤の点線で表示させることで、初期投資からの値上がり代が見やすくなっています。

# 投資期間を月で指定(複数)
investment_periods_months = [1, 3, 6, 12, 36, 60, 120, 240]

# 投資結果を格納するための辞書を初期化
results_dict = {period: pd.DataFrame() for period in investment_periods_months}

# 各投資期間に対して計算
for investment_period_months in investment_periods_months:
    start_dates = monthly_data.index[:-investment_period_months]
    results = pd.DataFrame(index=start_dates, columns=tickers)
    for ticker in tickers:
        for start_date in start_dates:
            end_date = start_date + pd.DateOffset(months=investment_period_months)
            if end_date not in monthly_data.index:
                continue
            initial_price = monthly_data['Adj Close'][ticker][start_date]
            final_price = monthly_data['Adj Close'][ticker][end_date]
            shares_bought = 1000 / initial_price
            value_after_period = shares_bought * final_price
            results.loc[start_date, ticker] = value_after_period
    results = results.astype(float)
    results_dict[investment_period_months] = results

# ボックスプロットの表示
plt.figure(figsize=(15, 8))
lines = []  # 凡例用のラインオブジェクトを保存するリスト
labels = []  # 凡例用のラベルを保存するリスト
for i, (period, results) in enumerate(results_dict.items(), 1):
    plt.subplot(2, 4, i)
    plt.boxplot([results[ticker].dropna() for ticker in tickers], labels=tickers)
    line = plt.axhline(y=1000, color='r', linestyle='--')
    if i == 1:  # 凡例用のラベルとラインを初回のループでのみ追加
        lines.append(line)
        labels.append('Initial Investment Value')
    plt.title(f'{period}-Month Investment Outcomes')
    plt.ylabel('Value after Period')

# 全体の凡例をグラフの上に表示
plt.figlegend(lines, labels, loc='upper center', ncol=3, bbox_to_anchor=(0.5, 1.05))

plt.tight_layout(rect=[0, 0, 1, 0.95])  # 上部に凡例のためのスペースを確保
plt.show()
各投資期間におけるリターンの分布(S&P500,NASDAQ100,日経225)

4)結論:調査結果から言えること

 20年間のグラフ(右下より)
 ・S&P500は3〜4倍で、損失の可能性は極めて低い。
 ・NASDAQ100は6〜10倍
 ・日経225は儲からない*

 全てのチャート(時系列で眺めて)
 ・米国株の指数で損をしたくなければ、20年程度保有が必要

チャートの見方:20年後(240ヶ月:右下)チャートより、S&P500(^GSPC)の四角の幅で3000〜4000でありオレンジの中央値は3500程度です。これは、20年で50%の確率で3〜4倍であり中央値は3.5倍であったことを示してます。また下ヒゲも赤線を越えていて、投資した人全てが利益があったことを示してます。(もっとも運が悪いタイミングでも2倍になってます。)
 さらに、米国株は全ての期間で増える方向であり、長期で保有している方が儲かる確率が高いことが示せています。逆に日経225は全く儲からない。

 *注意 今回は指数として調査したため全く儲からない結果となったが、
  豆知識の補足の通り、実際に投資信託やETFを保有していると年率数
  %の配当金があるため、配当+配当に対する複利効果分は増えること
  になりますので、ご注意ください。

4 最後に

1)プログラムで実施したこと

 今回対数軸の時系列グラフと、For文を使って、複数の調査期間を短いコードで沢山の処理と箱ひげ図のプロットを実施しました。コード自体は複雑に見えるかもしれませんが、初めはコピペで十分ですので、ぜひトライしてみてください。

2)調査結果で得られたこと

 統計的に集計比較することで、一括投資の場合、日本株に比べて米国株の優位性と、長期になればなるほど投資リターンの向上確率が上がることが示されました。
 今後、積立投資の場合や、配当や手数料の影響等も調査していきます。今後もぜひお付き合いください。


過去の掲載記事:興味があればぜひ読んでください。
グラフ化集計の基礎:S &P500と金や米国債を比較してます。

移動平均を使った時系列予測

Kota@Python&米国株投資チャンネル


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