見出し画像

ハナコスト平均法はドルコスト平均法よりも優れるか?

ハナコスト平均法とは?

youtubeで活躍されている花子さんという方がいるのですが、その方の提唱している投資手法にハナコスト平均法というのがあります。これはドルコスト平均法とよく似ており、毎月ある一定の額をS&P 500などの米国株ETFに投資するという手法である点は同じですが、違いとしては1)2%以上下落した日にその月の投資額の20%を買う、月末になり残金があればそれをすべて追加投資、という手法です。株価は上がったり下がったりしますので、ハナコスト平均法を使うとうまく下値で拾えそうですし、ドルコスト平均法よりも効率が良い、とのことです。

ハナコスト平均法は本当に優れているのか?

実際にデータで検証したいところです。yahoo finaiceなど過去データをcsvで提供しているサイトはたくさんありますし、Chat GPTなども活用すれば株価投資シミュレーションも簡単にできそうです。
S&P500のデータを入手、シミュレーションをしてみます。読み込ませるデータは1列目'date’に日付、2列目'value'に株価が入っていればOKです。今回使用したデータは2010年6月から2023年4月までの約13年間のデータです。

Chat GPTも活用してコードをpythonで書いてみます。実行環境はJupyter Notebook, Google ColaboratoryなどなんでもOKです。

import pandas as pd
import numpy as np
from datetime import datetime
from matplotlib import pyplot as plt
from pandas.plotting import register_matplotlib_converters

register_matplotlib_converters()

# データの読み込み
df = pd.read_csv('data.csv')
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)

# null値のある行を削除
df = df.dropna(subset=['value'])

# 指定した日付以降のデータだけを保持
start_date = "1995-01-01"
df = df[df.index >= start_date]

# 25日と75日の移動平均線を計算
df['25_day_MA'] = df['value'].rolling(window=25).mean()
df['75_day_MA'] = df['value'].rolling(window=75).mean()

# 投資戦略の設定
strategies = ["hanacost_averaging", "first_day_investment", "lump_sum_investment", "moving_average_crossover"]
strategy_labels = ["Hanacost Averaging", "First Day Investment", "Lump Sum Investment", "Moving Average Crossover"]

# 各戦略についてシミュレーションを行う
for strategy in strategies:
    total_investment = 0
    total_shares = 0
    cash = 100000
    df[strategy + '_shares'] = 0
    df[strategy + '_investment'] = 0
    df[strategy + '_profit'] = 0
    df[strategy + '_cash'] = cash  # Keep track of remaining cash
    
    for i, row in df.iterrows():
        month = i.month
        next_month = df.index[df.index > i].month[0] if df.index[df.index > i].month.size > 0 else month
        is_last_row = i == df.index[-1]

        if strategy == "hanacost_averaging":
            if row['value'] < df['value'].shift(1)[i]*0.98 and not is_last_row:
                investment = min(cash, 20000)
            elif month != next_month:  # If it's the last day of the month
                investment = cash  # Invest all remaining cash
            else:
                investment = 0
        elif strategy == "first_day_investment" and (i == df.index[0] or month != df.index[df.index < i][-1].month) and not is_last_row:
            investment = cash
        elif strategy == "lump_sum_investment" and i == df.index[0]:  # Lump sum investment at the first day
            investment = 100000 * len(df.resample('M'))  # Monthly investment multiplied by number of months
        elif strategy == "moving_average_crossover":
            if i != df.index[0] and df.loc[df.index[df.index < i][-1], '25_day_MA'] < df.loc[df.index[df.index < i][-1], '75_day_MA'] and row['25_day_MA'] > row['75_day_MA'] and not is_last_row:
                investment = cash  # Invest all cash when golden cross occurs
            else:
                investment = 0
        else:
            investment = 0

        shares = investment // row['value']
        cost = shares * row['value']
        cash = cash - cost + (100000 if month != next_month else 0)

        total_investment += cost
        total_shares += shares

        df.at[i, strategy + '_shares'] = total_shares
        df.at[i, strategy + '_investment'] = total_investment
        df.at[i, strategy + '_profit'] = total_shares * row['value'] - total_investment
        df.at[i, strategy + '_cash'] = cash  # Update remaining cash

# 利益と株価をプロット
fig, ax1 = plt.subplots(figsize=(20, 10))

# 利益のプロット
for strategy, label in zip(strategies, strategy_labels):
    ax1.plot(df.index, df[strategy + '_profit'], label=label)
ax1.set_xlabel('Date')
ax1.set_ylabel('Profit in $')

# 株価のプロット
ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis
ax2.plot(df.index, df['value'], label='Stock Price', color='gray', linestyle='dashed')
ax2.set_ylabel('Stock Price in $')  # we already handled the x-label with ax1

# Adjust the scale of the stock price
ax2.set_ylim([df['value'].min() - 50, df['value'].max() + 50])

# Combining legends from both the axis
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines1 + lines2, labels1 + labels2, loc='upper left')

fig.tight_layout()  # otherwise the right y-label is slightly clipped

plt.show()

# 投資額のプロット
fig, ax3 = plt.subplots(figsize=(20, 10))  # define a new figure and axis for investment
for strategy, label in zip(strategies, strategy_labels):
    ax3.plot(df.index, df[strategy + '_investment'], label=label)  # use ax3 instead of axs[1]
ax3.set_xlabel('Date')
ax3.set_ylabel('Investment in $')
ax3.legend()
ax3.grid(True)

plt.show()

# 株価のみのプロット
fig, ax = plt.subplots(figsize=(20, 10))
ax.plot(df.index, df['value'], color='blue', label='Stock Price')
ax.set_xlabel('Date')
ax.set_ylabel('Stock Price in $')
ax.legend()
ax.grid(True)
plt.show()

# 各戦略の最終的な利益と投資額、利益率、そして残金を表示
for strategy, label in zip(strategies, strategy_labels):
    final_profit = df[strategy + '_profit'][-1]
    total_investment = df[strategy + '_investment'][-1]
    final_cash = df[strategy + '_cash'][-1]  # Add this line to get the remaining cash
    print(f'Final profit for {label}: ${final_profit:.2f}')
    print(f'Total investment for {label}: ${total_investment:.2f}')
    print(f'Final cash for {label}: ${final_cash:.2f}')  # Add this line to display the remaining cash
    print(f'Return on Investment for {label}: {final_profit/total_investment*100:.2f}%')


# 結果をエクセルファイルに保存
df.to_excel('investment_results.xlsx')

まずはチャートを見てみます

2010年6月からのS&P 500のチャートは下記のようになっています。

S&P 500 2010年6月~2023年4月

月々100,000ドルづつ投資する場合、最適な投資戦略はなんでしょうか?

このPythonスクリプトは、4つの異なる投資戦略を用いて株価のデータをシミュレートし、その結果を分析しています。各投資戦略は以下の通りです:

  1. Hanacost Averaging: この戦略では、株価が前日の価格の98%未満になったとき、または月の最終日になったときに投資を行います。つまり、価格が下がったときや、定期的に(月末)に資金を投入します。一般的には「ドルコスト平均法」と呼ばれる戦略で、価格変動のリスクを減らすために、定期的に一定額を投資します。

  2. First Day Investment: この戦略では、各月の最初の日に全ての現金を投資します。これは、定期的な投資戦略で、投資タイミングを選ばずに、毎月一定の日に投資を行います。

  3. Lump Sum Investment: この戦略では、シミュレーションの最初の日に全ての投資を一度に行います。全ての資金を一度に投入し、その後は市場に任せる方法です。これは、一定の投資額が手元にある場合に、一度に全てを投資してしまう戦略です。

  4. Moving Average Crossover: この戦略では、25日移動平均が75日移動平均を上回ったとき(ゴールデンクロス)に全ての現金を投資します。移動平均線はトレンドを把握するための指標で、短期的な移動平均線が長期的な移動平均線を上回るとき、それは価格の上昇トレンドを示していると解釈されます。

1が今回注目したハナコスト平均法です、2がいわゆるドルコスト平均法、3が一括投資です、4が移動平行線に基づいた投資戦略です、4はゴールデンクロスが発生したときにのみ購入します。

これを実際のデータで検証してみます。

シミュレーション結果

Hanacost Averaging ハナコスト平均法: 97.82%
First Day Investment ドルコスト平均法: 98.42%
Lump Sum Investment 一括投資: 289.41% 
Moving Average Crossover 移動平均線法: 88.42%
となっておりリターン順に並べると一括投資>>ドルコスト平均法≒ハナコスト平均法>移動平均線法となっています。

シミュレーション結果

シミュレーションの正当性をみるために総投資額もプロットしてみますが総投資金額は全く同じです。それぞれの投資結果は
Final profit for Hanacost Averaging: $15061467.00 Total investment for Hanacost Averaging: $15396584.00 Final cash for Hanacost Averaging: $103415.00 Return on Investment for Hanacost Averaging: 97.82% Final profit for First Day Investment: $15252348.00 Total investment for First Day Investment: $15497566.00 Final cash for First Day Investment: $2433.00 Return on Investment for First Day Investment: 98.42% Final profit for Lump Sum Investment: $44857794.00 Total investment for Lump Sum Investment: $15499597.00 Final cash for Lump Sum Investment: $402.00 Return on Investment for Lump Sum Investment: 289.41% Final profit for Moving Average Crossover: $13704437.00 Total investment for Moving Average Crossover: $15498600.00 Final cash for Moving Average Crossover: $1399.00 Return on Investment for Moving Average Crossover: 88.42%
となっています。
*正確には最終月は投資を行わないため若干ずれがでます。

投資額

ハナコスト平均法はドルコスト平均法と同じ

残念ながら長期で見るとハナコスト平均法のリターンはドルコスト平均法と全く同じです。株価が次の2条件を満たすとします。

  1. 株価の短期的な変動は予測できない

  2. 株価は長期的には上昇することが期待される

その場合の最適解は一括投資です、投資初日に分散することなく一括投資を行うのが期待値としては一番リターンが大きいです。ハナコスト平均法は一見良いようにも見えますが、ドルコスト平均法が月の初日に購入するのに対しその月の中で分散投資をするので期待値は低くなります。移動平均線法は株式購入が遅れますので期待値は低くなります。

株価は見ないほうが良い

ファンダメンタル分析ができないのであれば株価は見ないほうが良いです。ハナコスト平均法のために毎日株価をみて一喜一憂する必要はありません、ドルコスト平均法とリターンは一緒です。

数学的に優れているのは一括投資

投資が余剰資金で行われているのであれば期待値が一番大きいのは一括投資です。もう一度チャートに戻ります。

S&P 500 2010年6月~2023年4月

一番リターンが大きい=一番たくさん株が買える=最安値で買える、ということですので一番株価が安いのは投資を始めた日である可能性が一番高いです。余剰資金であるのであれば一括投資が一番リターンの期待値が大きいです。

反論お待ちしております

そうは言っても始める時期によって違うんじゃない?とか他にも良い手法があるよ、みたいなのがあると思います。良い案があれば実際にシミュレーションしてみますのでご連絡ください。


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