Pythonで投資信託のバックテスト!ライブラリ選びと運用シミュレーションを解説

  • URLをコピーしました!

「もし5年前にこの投資信託を買っていたら、今ごろいくらになっていたんだろう?」

そんな疑問を抱いたとき、多くの人は証券会社のシミュレーターを使います。しかし、一般的なツールでは、手数料の細かい計算や、複数の銘柄を組み合わせた際のリスクまではなかなか見えてきません。

自分の大切なお金を預ける先だからこそ、納得感のあるデータが欲しいはず。そこで役立つのがPythonです。難しそうに感じるかもしれませんが、基本的な型さえ覚えれば、プログラミングは強力な武器になります。この記事では、初心者でも迷わず運用シミュレーションができるよう、具体的なコードと共に手順を解説します。

目次

投資信託のバックテストをPythonで自作するメリット

投資信託のバックテストを自分で行う最大の魅力は、ブラックボックスをなくせることです。既存のサイトでは「なぜその結果になったのか」の計算過程が見えませんが、Pythonなら1円単位の動きまで自分の目で追うことができます。

ここでは、自作することで得られる3つの大きな利点について見ていきましょう。

既存のシミュレーターにはない自由度

ネット上のシミュレーターは、あらかじめ用意された項目を入力するだけなので手軽ですが、自由度は低いです。例えば「暴落したときだけ追加購入する」とか「特定の指数と組み合わせてリバランスする」といった特殊な動きを検証することはできません。

Pythonを使えば、こうした独自のルール(アルゴリズム)を自由自在に組み込めます。

例えば、単純な積立だけでなく、「利益が10%出たら一部を売却して現金化する」といった利益確定のルールを試すことも可能です。これにより、自分の性格やリスク許容度に合わせた、より現実的な運用プランを練ることができます。

ただし、自由度が高い分、計算式を間違えると全くデタラメな結果が出てしまう点には注意が必要です。まずはシンプルな計算から始め、少しずつ条件を増やしていくのが失敗しないコツです。

複数の銘柄を組み合わせた相関分析ができる

投資の基本は分散ですが、似たような動きをする銘柄ばかりを持っていてもリスクは分散されません。Pythonなら、複数の銘柄のデータを並べて、それらがどれくらい同じ方向に動いているか(相関)を瞬時に計算できます。

「米国株と全世界株を両方持っているけれど、実はほとんど同じ動きをしていた」といった事実は、グラフや数値で比較して初めて気づくものです。

以下の表は、自作シミュレーションで比較・分析できる主な要素をまとめたものです。

分析項目シミュレーター(一般的)Python(自作)
銘柄の組み合わせ1〜3個程度制限なし
相関関係の算出できないことが多いグラフと数値で可視化
リバランス設定固定比率のみ条件に応じた自動計算
データの保存できないCSVや画像で保存可能

このように、ポートフォリオ全体の健康診断ができるのは自作ならではの強みと言えます。

手数料や税金の条件を細かく設定できる

投資信託の運用成績を大きく左右するのが、信託報酬(手数料)と税金です。多くのツールでは「年利○%」とざっくり計算されますが、実際の手数料は毎日少しずつ引かれています。

Pythonのコード内に信託報酬のレートを組み込めば、長期運用でどれほど利益が削られるかをリアルに再現できます。

例えば、新NISA枠内での運用なら非課税ですが、特定口座であれば利益に対して約20%の税金がかかります。この「税引き後」のリアルな手残りを計算できるかどうかが、将来の資金計画の精度を左右します。

もちろん、手数料の安さだけで銘柄を選ぶのが正解とは限りませんが、コストが利益に与えるインパクトを数字で直視しておくことは、運用を長く続けるための防衛策になります。

Pythonで解析を始めるための準備

プログラムを書く前に、まずは道具を揃えましょう。とはいえ、高価なソフトを買う必要はありません。すべて無料で、しかもブラウザだけで完結する環境を整えることができます。

まずは、最低限必要となるツールとデータの入手先について整理します。

Google Colabなら環境構築が不要

Pythonを始める際の最大の壁は「環境構築」です。自分のパソコンにソフトをインストールして設定するのは、初心者にはかなりハードルが高い作業になります。

そこでおすすめなのが、Googleが提供している「Google Colab(コラボ)」です。

Googleアカウントさえあれば、ブラウザ上でコードを書いて実行できます。難しい設定は一切不要で、データ分析に必要なライブラリも最初から揃っています。

作業内容はGoogleドライブに保存されるため、別のパソコンから続きを行うことも簡単です。まずはGoogle Colabを開いて、新しいノートブックを作成するところから始めてみましょう。

必須となる3つのライブラリをインストールしよう

Pythonには、特定の作業を楽にしてくれる「ライブラリ」という道具箱があります。投資信託の分析で必ず使うのは、以下の3つです。

これらはデータ分析の世界では標準的なツールで、使いこなせると分析の幅がぐっと広がります。

  1. Pandas(パンダス):表形式のデータを扱うためのライブラリです。株価や基準価額の計算はほとんどこれで行います。
  2. Matplotlib(マットプロットリブ):計算結果をグラフにするための道具です。資産の推移を視覚的に理解するのに欠かせません。
  3. yfinance(ワイファイナンス):Yahoo Financeから市場データを取得するための便利なツールです。

Google Colabでは、以下のコマンドを入力するだけで準備が完了します。

!pip install yfinance
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf

まずはこの4行を実行して、エラーが出ないことを確認してください。これが分析の第一歩です。

投資信託のデータを入手するルートを確認

バックテストには、過去の基準価額データが必要です。日本の投資信託のデータを入手する方法は、主に以下の2パターンあります。

初心者の方は、まずは「yfinance」を使って、投資信託と同じ動きをするETF(上場投資信託)のデータを取得するのが一番簡単です。

例えば、eMAXIS Slim 米国株式(S&P500)の代わりに、S&P500に連動するETF「IVV」や、日本市場の「1545」というコードを使う方法です。

取得方法メリットデメリット
yfinanceコード数行で最新データが手に入る投資信託そのものの番号では探せない
投信会社のCSV実際の投資信託の正確なデータ手動でダウンロードが必要
Webスクレイピング自動化が可能サイトの仕様変更に弱い

最初はyfinanceでETFのデータを使い、慣れてきたら実際の投資信託のCSVを読み込む形に移行するのがスムーズです。

投資信託のデータを取得するコードを書く

準備ができたら、実際にデータを手元に持ってくるコードを書いてみましょう。ここでは、世界的に有名な指数に連動するETFのデータを例に進めます。

データが正しく取得できているか、1行ずつ確認しながら進めるのがポイントです。

yfinanceを使って基準価額データを取得する

まずは、米国株(S&P500)に連動するETFのデータを取得してみましょう。ここでは「1545(NF・米国株S&P500ヘッジ無)」という、東証に上場しているETFのデータを使います。

以下のコードをコピーして実行してみてください。

# 銘柄コードを指定(東証の場合は末尾に .T をつける)
ticker = "1545.T"

# 過去5年分のデータを取得
data = yf.download(ticker, start="2019-01-01", end="2023-12-31")

# 最初の5行を表示して確認
print(data.head())

実行すると、日付ごとに始値や終値が並んだ表が表示されます。このうち、分析で主に使うのは「Adj Close(調整後終値)」です。これは分配金などを考慮した価格なので、バックテストに最適です。

データが取得できない場合は、インターネット接続やティッカーシンボル(銘柄コード)の間違いがないか確認しましょう。

日本の投資信託データをCSVから読み込む方法

特定の投資信託(非上場)を分析したい場合は、運用会社のホームページからダウンロードできるCSVファイルを使います。Google Colabにファイルをアップロードすれば、Pandasで簡単に読み込めます。

# CSVファイルを読み込む(ファイル名は適宜変更してください)
df = pd.read_csv('fund_data.csv', encoding='shift-jis')

# 日付列を日付型に変換
df['日付'] = pd.to_datetime(df['日付'])
df.set_index('日付', inplace=True)

print(df.head())

CSVデータは、会社によって列の名前や日付の形式が異なります。読み込んだ後にdf.info()を実行して、データが正しく「数値」や「日付」として認識されているかチェックする癖をつけましょう。

文字化けする場合は、encoding='utf-8'encoding='cp932'を試してみてください。

取得したデータの欠損値を処理しよう

取得したデータには、土日祝日のデータが抜けていたり、エラーで数値が入っていなかったり(欠損値)することがよくあります。そのまま計算するとエラーの原因になるため、きれいに整える必要があります。

これを「データクレンジング」と呼びます。

# 欠損値がある行を確認
print(data.isnull().sum())

# 前の日のデータで埋める(投資信託の評価額計算では一般的)
data = data.fillna(method='ffill')

特にCSVから読み込んだデータは、一番下の行に「注釈」などの不要なテキストが入っていることがあり、それが原因でエラーになるケースが多いです。

「データは汚れているもの」という前提で、計算前に必ず中身を覗き見るのが、スムーズなバックテストの秘訣です。

一括投資した場合の運用成績をシミュレーション

データが整ったら、いよいよ運用シミュレーションです。まずは、ある時点でまとめて購入し、そのまま持ち続けた(ガチホした)場合の成績を計算してみましょう。

シンプルですが、複利の効果や下落時のダメージを理解するのに最適な分析です。

累積リターンを算出する基本のロジック

一括投資の成績を知るには、初日の価格を「1」としたときに、最終日にいくらになっているかを計算します。

# 初日の価格を取得
start_price = data['Adj Close'].iloc[0]

# 全データを初日の価格で割って、リターンを計算
data['Cumulative Return'] = data['Adj Close'] / start_price

例えば、結果が「1.5」であれば、資産が1.5倍(+50%)になったことを意味します。この計算の利点は、投資金額が10万円でも100万円でも、増減の比率は同じように確認できることです。

ただし、これはあくまで「価格の推移」です。実際には購入時の手数料(買付手数料)がかかる場合もあるので、必要に応じて初日の資産から手数料分を差し引く処理を加えるとより正確になります。

投資元本の推移を計算する方法

比率だけではイメージが湧きにくいので、実際の投資金額を掛けて「評価額」の推移を出してみましょう。

100万円を投資したと仮定して計算します。

initial_investment = 1000000 # 100万円
data['Asset Value'] = data['Cumulative Return'] * initial_investment

こうすることで、「2020年のコロナショックのとき、100万円がいくらまで減ったのか」が具体的な金額で見えてきます。

数字の列を眺めるだけでなく、data['Asset Value'].tail(1)を確認して、最終的な金額がいくらになったかを見てみましょう。増えているのを見ると嬉しいものですが、その過程でどれくらいのマイナスに耐えたのかも同時に意識することが重要です。

1行のコードで変化率を把握する

「前日に比べて何%動いたか」という日次リターンも、リスクを把握するために重要です。Pandasにはこれを1行で計算できる便利な機能があります。

data['Daily Return'] = data['Adj Close'].pct_change()

この「日次リターン」を分析すると、その銘柄の激しさがわかります。例えば、1日で5%以上動く日が多い銘柄は、リターンも大きいかもしれませんが、精神的な負担も大きくなります。

自分が耐えられる「変動の幅」を知ることは、投資を挫折しないための第一歩です。日次リターンの平均や最大値を調べることで、その銘柄の「性格」を深く理解しましょう。

毎月積立(ドル・コスト平均法)の計算を実装する

多くの人が実践しているのが、毎月決まった金額を購入する「積立投資」です。一括投資に比べて計算は少し複雑になりますが、Pythonを使えば正確にシミュレーションできます。

毎月買うことで、高いときには少なく、安いときには多く買うという「ドル・コスト平均法」の効果を可視化してみましょう。

毎月の購入タイミングを定義しよう

まずは、データを「月単位」にまとめ直します。毎日購入するシミュレーションも可能ですが、月1回の方が現実的で計算も軽くなります。

# 各月末のデータだけを抽出
monthly_data = data.resample('BM').last()

ここで使っているresample('BM')は、ビジネス月末(Business Month end)という意味です。これにより、膨大な日次データから、毎月の投資タイミングだけをスマートに抜き出すことができます。

もちろん、「毎月1日に買いたい」という場合は別の設定も可能です。自分の実際の積立日に合わせた設定にすることで、より自分事としてシミュレーションの結果を捉えられるようになります。

保有口数の累計をPandasで計算する

積立投資で大事なのは「今、何口持っているか」の累計です。毎月の投資額をその時の価格で割り、それを足し合わせていきます。

毎月3万円を積み立てると仮定してみましょう。

monthly_investment = 30000

# 毎月の購入口数を計算(価格 = Adj Close)
monthly_data['Units Bought'] = monthly_investment / monthly_data['Adj Close']

# 保有口数の累計を計算
monthly_data['Total Units'] = monthly_data['Units Bought'].cumsum()

cumsum()は「累積和」を出す関数です。これを1つ書くだけで、毎月コツコツ積み上がっていく資産の「量」が計算されます。

価格が下がっている時期は、この「購入口数(Units Bought)」が増えているはずです。後でこの数字を確認すると、暴落時期がいかにお得な仕込み時期だったかが分かり、投資のモチベーション維持にもつながります。

積立総額と評価額を比較するコード

最後に、「これまでに注ぎ込んだ合計金額」と「今の評価額」を並べて比較します。これこそが、皆さんが一番知りたい数字のはずです。

# 積立総額(元本)
monthly_data['Total Investment'] = [monthly_investment * (i+1) for i in range(len(monthly_data))]

# 評価額(累計口数 × 現在の価格)
monthly_data['Portfolio Value'] = monthly_data['Total Units'] * monthly_data['Adj Close']

この2つの列を比較して、評価額が積立総額を上回っていれば「含み益」の状態です。

積立初期は、価格が下がると評価額も元本を割り込みやすいですが、時間が経って口数が積み上がってくると、少しの価格上昇で評価額が大きく跳ね上がる様子が観察できるでしょう。これが長期積立の醍醐味です。

運用結果を可視化して直感的に理解する

数字の列だけを見ていても、資産運用の全体像は掴みにくいものです。Pythonの強力なグラフ作成機能を使って、視覚的に結果を確認しましょう。

「百聞は一見に如かず」の通り、グラフにすることで初めて気づくリスクやチャンスがあります。

Matplotlibで資産推移をグラフにする

まずは、積立投資の「元本」と「評価額」の推移を1つのグラフに描いてみましょう。

plt.figure(figsize=(10, 6))
plt.plot(monthly_data.index, monthly_data['Portfolio Value'], label='Portfolio Value')
plt.plot(monthly_data.index, monthly_data['Total Investment'], label='Total Investment', linestyle='--')
plt.title('Monthly Accumulation Simulation')
plt.legend()
plt.show()

評価額(実線)が元本(点線)を突き抜けて上にいく様子が見えれば成功です。逆に、暴落時にどれくらい元本を割り込んだかも一目瞭然になります。

グラフが右肩上がりになっているかだけでなく、元本と評価額の「スキマ」が後半にかけてどう広がっているかに注目してください。それが複利の力そのものです。

ベンチマーク(指数)と比較して性能を評価しよう

自分の選んだ銘柄が、市場全体(S&P500など)と比べて優秀だったのかを知ることは非常に重要です。

これを比較しないと、単に相場が良かっただけなのか、その銘柄が本当に優れていたのかが判断できません。

# ベンチマークとしてS&P500のデータを取得して重ねる
benchmark = yf.download("SPY", start="2019-01-01", end="2023-12-31")['Adj Close']
benchmark_return = benchmark / benchmark.iloc[0]

plt.plot(data.index, data['Cumulative Return'], label='My Fund')
plt.plot(benchmark_return.index, benchmark_return, label='S&P500 (Benchmark)')
plt.legend()
plt.show()

「自分の銘柄はS&P500よりリターンは低いが、下落幅はマイルドだった」といった特徴が見えてくれば、より納得して投資を続けられるはずです。

もしベンチマークに完敗し続けているなら、投資先を見直すきっかけにもなります。感情を排除して客観的に比較できるのがバックテストの良いところです。

下落幅(ドローダウン)を視覚化してリスクを知る

リターンの影に隠れがちなのが「ドローダウン(資産の落ち込み)」です。最高値から何%下がった状態が続いたかを可視化すると、自分の精神力が試される場面がわかります。

# 最高値を更新し続けるシリーズを作成
rolling_max = data['Adj Close'].cummax()
# 最高値からの乖離率を計算
drawdown = (data['Adj Close'] / rolling_max) - 1

plt.fill_between(drawdown.index, drawdown, 0, color='red', alpha=0.3)
plt.title('Drawdown Chart')
plt.show()

グラフがマイナス圏(赤い部分)に深く沈んでいるほど、大きな損失を抱えていた期間が長かったことを示します。

「20%の下落が1年間続いた」といった事実をあらかじめ知っておけば、将来同じことが起きてもパニックにならずに済みます。バックテストは、未来の自分への「心の準備」でもあるのです。

リスク効率と最大損失を数値で分析する

グラフで直感的に理解したら、次は「数字」でシビアに評価しましょう。プロの投資家も使っている指標を算出することで、銘柄の本当の実力が見えてきます。

単に利益が出たかどうかだけでなく、その利益を得るために「どれだけのリスク(不安)を背負ったか」を評価するのがポイントです。

シャープレシオで運用の効率を計算しよう

シャープレシオは、取ったリスクに対してどれだけ効率よくリターンを得られたかを示す指標です。数値が高いほど「効率の良い投資」と言えます。

# 年率換算のリターンとリスク(標準偏差)から計算
annual_return = data['Daily Return'].mean() * 252
annual_volatility = data['Daily Return'].std() * (252**0.5)

sharpe_ratio = annual_return / annual_volatility
print(f"Sharpe Ratio: {sharpe_ratio:.2f}")

※252は1年間の営業日数の目安です。

例えば、リターンが同じ10%の銘柄が2つあったとき、シャープレシオが高い方は「値動きが穏やかで、着実に利益を出した」ことを意味します。逆に低い方は「激しく上下した末にたまたま10%になった」ということです。

どちらが精神的に楽に持ち続けられるかは明白ですね。利益の大きさだけでなく、この「効率」に注目するのが上級者への道です。

最大ドローダウンから耐えるべき下落率を把握する

最大ドローダウン(Max Drawdown)は、全期間を通じて最も大きな資産の落ち込み幅のことです。「最悪のケースで何%資産が減るか」という数値です。

max_drawdown = drawdown.min()
print(f"Max Drawdown: {max_drawdown*100:.2f}%")

これが「-30%」であれば、1,000万円が700万円になる場面があったということです。この数字を見て「自分なら耐えられない」と感じるなら、それはリスクを取りすぎている証拠かもしれません。

自分の貯金額や年齢と照らし合わせて、この最大損失額を受け入れられる範囲に収まるよう、投資額や銘柄を調整しましょう。

年率換算のリターンとボラティリティを出す

「5年で50%増えた」と言われてもピンとこないかもしれませんが、「年利○%」と言われれば他の金融商品と比較しやすくなります。

これを計算するのが年率換算です。

指標意味算出のメリット
年率リターン1年あたりの平均利回り銀行預金や債券と比較できる
ボラティリティ価格の変動の激しさ1年でどれくらい上下に振れるか予想できる
累積リターン全期間を通じたトータルの増減最終的な資産の増え方がわかる

以下のコードで算出できます。

# 年率リターンの算出(複利考慮)
total_return = data['Cumulative Return'].iloc[-1]
years = len(data) / 252
annual_return_compound = (total_return ** (1/years)) - 1
print(f"Annual Return (Compound): {annual_return_compound*100:.2f}%")

こうした数値を1つずつ確認していくことで、なんとなく「儲かりそう」という感覚から、「これくらいの確率で、これくらいの変動がある」という論理的な投資判断に変えていくことができます。

より実戦的なシミュレーションにするための補足

バックテストの基本がわかったところで、さらに精度を高めるための要素をいくつか紹介します。現実の投資には、教科書通りの計算ではこぼれ落ちてしまう細かなコストやルールが存在するからです。

これらを考慮に入れることで、あなたのシミュレーションはより「本物」に近づきます。

信託報酬(経費率)を計算に組み込む

投資信託の基準価額は、すでに信託報酬が差し引かれた後のものが多いですが、指数(S&P500そのものなど)を使ってシミュレーションする場合は、自分でコストを引く必要があります。

年利0.1%のコストを毎日引く場合は、以下のような処理を加えます。

fee_annual = 0.001 # 0.1%
fee_daily = fee_annual / 252

# 毎日少しずつ資産から差し引く
data['Adjusted Asset'] = data['Asset Value'] * (1 - fee_daily).cumprod()

わずかな差に見えますが、20年、30年と積み重なると、このコストが数百万円の差を生むこともあります。コストの重みを実感できるのも、Pythonによる詳細な計算のメリットです。

自分が検討している銘柄の目論見書を読み、正確な信託報酬率をコードに反映させてみましょう。

再投資される分配金の扱いをどうするか

投資信託には「分配金」が出るものがあります。これを現金で受け取るのか、再投資して口数を増やすのかで、最終的な成績は大きく変わります。

多くのインデックスファンドは内部で自動再投資されていますが、yfinanceの「Adj Close」はこの再投資を考慮した価格になっているため、基本的にはそのままで問題ありません。

もし分配金が出るタイプのETFを分析し、それを自分で再投資するシミュレーションをしたい場合は、分配金が出た日にその金額分だけ「Units Bought(購入口数)」を加算する処理を書く必要があります。

この「複利効果のブースト」を可視化すると、分配金をすぐに使ってしまうのがいかにもったいないかがよくわかります。

過去の結果を過信しないための注意点

最後に、最も重要なことをお伝えします。どれだけ精緻なバックテストを行っても、それはあくまで「過去」のデータです。

「過去5年が年利10%だったから、次の5年も10%になる」という保証はどこにもありません。

  • オーバーフィッティング(過剰適合): 過去のデータに合わせすぎて、特定の期間だけに通用するルールを作ってしまうこと。
  • サバイバーシップ・バイアス: 今生き残っている優秀な銘柄だけを分析対象にしてしまうこと。
  • 市場環境の変化: 金利や世界情勢が変われば、過去のセオリーが通じなくなることもある。

バックテストは、未来を予言する道具ではなく、過去のパターンから「最悪の場合のシナリオ」や「銘柄の特性」を学ぶための道具だと考えてください。

理論武装をしつつも、常に謙虚な姿勢で市場と向き合う。そのためのパートナーとして、Pythonを使いこなしていきましょう。

まとめ:Pythonで納得のいく資産運用を

この記事では、Pythonを使って投資信託のバックテストを行う方法について、データの取得からリスク分析まで一通り解説しました。

  • Google Colab を使えば、誰でもすぐに分析環境が手に入る
  • Pandas を使えば、積立投資の複雑な計算も数行で完了する
  • 可視化と指標算出 によって、リターンだけでなく「リスク」を数字で把握できる

シミュレーター任せにするのではなく、自分の手でコードを書いて導き出した結果は、暴落時の不安を和らげ、長期投資を支える強い根拠になります。

まずは、自分が気になっている銘柄のコードを調べて、1行のグラフを描くところから始めてみてください。その一歩が、あなたの投資の解像度を劇的に高めてくれるはずです。

もし特定の期間での比較や、もっと複雑なリバランスのコードを知りたい場合は、ぜひ具体的な条件を決めて追加で検証を進めてみてください。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

目次