こんにちは!今回は、投資家の間でよく話題になる「5%投資ルール」について取り上げたいと思います。この方法は、市場が5%下落したタイミングで積極的に購入し、その後のリターンを観察するという戦略です。実はいろいろなサイトを見てみてもシミュレーション結果だけ見せて勝率などは書いていないことが多いですよね。
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 1. 市場指標のティッカーを設定
tickers = {
'All Country': 'VT',
'Nasdaq100': 'QQQ',
}
# 2. 週足データを直接ダウンロード
start_date = '1984-01-01'
end_date = '2024-01-01'
data = {name: yf.download(ticker, start=start_date, end=end_date, interval='1wk') for name, ticker in tickers.items()}
# 3. 5%下落の検出(前週比で5%以上下がった週を探す)
df['Return'] = df['Adj Close'].pct_change(fill_method=None) * 100
df['5% Drop'] = df['Return'] <= -5
return df
data = {name: detect_drops(df) for name, df in data.items()}
# 4. 各期間(4週間、13週間、26週間、52週間)のリターンを計算
def calculate_returns(df):
periods = [4, 13, 26, 52]
for period in periods:
df[f'{period}W Return'] = df['Adj Close'].pct_change(periods=period) * 100
return df
data = {name: calculate_returns(df) for name, df in data.items()}
# 5. 勝率とリスクリワードレシオを計算
def calculate_win_rate_and_risk_reward(df):
results = {}
periods = [4, 13, 26, 52]
for period in periods:
returns = df[df['5% Drop']][f'{period}W Return'].dropna()
if len(returns) > 0:
win_rate = (returns > 0).mean()
win_returns = returns[returns > 0].mean() # 勝った時のリターンの平均
loss_returns = abs(returns[returns < 0].mean()) # 負けた時のリターンの平均(絶対値を使用)
risk_reward_ratio = loss_returns / win_returns if loss_returns != 0 else np.nan
results[period] = {'勝率': win_rate, 'リスクリワードレシオ': risk_reward_ratio}
else:
results[period] = {'勝率': np.nan, 'リスクリワードレシオ': np.nan}
return results
# 6. 各指標に対して勝率とリスクリワードレシオを計算
results = {name: calculate_win_rate_and_risk_reward(df) for name, df in data.items()}
# 7. 結果を表形式にまとめる
result_dict = {}
for name in results:
for period in [4, 13, 26, 52]:
# 各指標・各期間の勝率とリスクリワードレシオを辞書に格納
result_dict.setdefault(f'{period}週間後 勝率', {})[name] = results[name][period]['勝率']
result_dict.setdefault(f'{period}週間後 リスクリワードレシオ', {})[name] = results[name][period]['リスクリワードレシオ']
# 辞書をDataFrameに変換
result_df = pd.DataFrame(result_dict)
# 8. 勝率とリスクリワードレシオのグラフを描画
fig, axes = plt.subplots(2, 1, figsize=(10, 10))
# 勝率のグラフ
for name in results:
win_rates = [results[name][period]['勝率'] for period in [4, 13, 26, 52]]
axes[0].plot([4, 13, 26, 52], win_rates, label=name, marker='o')
axes[0].set_title('Win Rate (5% Rule)')
axes[0].set_xlabel('Holdoing Period (Weeks)')
axes[0].set_ylabel('Win Rate')
axes[0].legend()
# リスクリワードレシオのグラフ
for name in results:
risk_rewards = [results[name][period]['リスクリワードレシオ'] for period in [4, 13, 26, 52]]
axes[1].plot([4, 13, 26, 52], risk_rewards, label=name, marker='o')
axes[1].set_title('Risk Reward Ratio (5% Rule)')
axes[1].set_xlabel('Holdoing Period (Weeks)')
axes[1].set_ylabel('Risk Reward Ratio')
axes[1].legend()
# グラフを表示
plt.tight_layout()
plt.show()
それでは、実際に得られた結果を見てみましょう。以下の表は、それぞれの市場指標において、5%下落があった後の各期間(4週間、13週間、26週間、52週間)の勝率とリスクリワードを視覚化してみました。
この結果を見ると長いこと持てば持つほど勝率は上がっていく傾向にありますが、残念ながら5割を超えていません。もちろん5割を超えなくても勝つときのリターンが大きければ問題ないのですが、リスクリワードレシオも1を下回るものは残念ながらありません。損失トレード平均/勝利トレードの平均なのでリスクリワードレシオは低ければ低いほど、損失に対して得られる利益が大きいことを意味します。