Twitterで出てくる知見は本当か自分で調べてみるシリーズです。株式投資において、季節、月による特徴的な値動きや有利なポジションでの新規エントリーや手じまいなど可能なのでしょうか?Pythonによる分析で確認してみたいと思います。
また、また、株式投資をしない人でもPythonで日付取り扱いなど”実務”の視点からすぐに使える、コピペで使えるものとなっています!
記事を書こうと思ったきっかけ
以前このような4月にS&P500の上昇しやすいものを確認した記事”【アノマリー】4月は上昇しやすい【季節性】は本当か?Google ColabのPythonで自分で調べてみよう!(Python コードあり)【コピペで動く!】Twitterで出てくる知見は本当か自分で調べてみようシリーズ”という事を書いたことがあります。
4月以外にもそういったアノマリーはあるのでしょうか?
以下のようなTweetを拝見しました。
6月下旬に安値を付けて、7月は強い傾向があるようです。
また、このようなアノマリーもあるようです。
2022/07/03の段階で、素晴らしい2週間が予言されていたようです。
こうなってくると、もう調べるまでもなく7月は強いような気もします。
2022/09/01追記:開始
上記7月の強さを強調するものが以外に9月の弱さを指摘する物もあります。
2022/09/01追記:終了
まあ、何事にも例外はあるでしょうから、今後のために今回調べていきます。
あと、個人のTwitterだけでなく大手のWebではこのように見えているようです。
平均という形ではないですが、直近の指定の年数の価格の推移が見れます。
確かに7月は強くここ5年では全勝(すべて上昇)だったようです。
使用するツール
使用するツールはGoogle Colaboratoryのpythonを使いますので、無料で、簡単に行うことができます。Google Colaboratoryについては以前書いた記事をご参照いただければと思います。
実際のコードとやっていること
今回使ったコードはGoogle Colabのファイルとして以下にシェアしてあります。
以前書いた記事”曜日による米国株指数(S&P500)のパフォーマンスに違いはあるのか?有利なポジション取りはできるのか?【Google ColabのPython:コピペで動く!】Twitterで出てくる知見は本当か自分で調べてみよう。”などを参考にしながらコーディングしていきます。
今回はhttps://charts.equityclock.com/ で”11 Year range ending 12/31/2121″での平均と出ていたので、Vanguard S&P 500 ETF (VOO)で検証確認開始を2010/01/01とすることにします。
実際のコードは以下の通りです。まず、最初に月ごとの上昇幅を調べます。
!pip install yfinance --upgrade --no-cache-dir
import yfinance as yf
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import datetime
start_D="2000-1-1"#@param {type:"string"}
end_D=datetime.date.today()
codelist1 = ["VOO"]
data2 = yf.download(codelist1, start=start_D, end=end_D)
display(data2.dropna().head(1).append(data2.dropna().tail(1)))
data2["Adj Close"].plot()
plt.show()
VOOについてはトレード開始したのは2010/09/09のようですので、約20年という事になります。
データがYahoo Finance USから取得できましたので、次は次ごとの成績を調べます。
この部分については以前の記事”【アノマリー】4月は上昇しやすい【季節性】は本当か?Google ColabのPythonで自分で調べてみよう!(Python コードあり)【コピペで動く!】Twitterで出てくる知見は本当か自分で調べてみようシリーズ“を参考にしながら進めます。
import pandas as pd
import datetime
analyse=100*data2["Adj Close"].pct_change().copy()
def MonthNumberToMonthName(month):
date = datetime.date(2022, month, 1)
return date.strftime("%B")
analyse_SIM=pd.DataFrame()
for i in range(1,13):
month_name = MonthNumberToMonthName(i)
analyse_SIM[month_name]=analyse[analyse.index.month==i].groupby([lambda x: x.year]).sum()
グラフ・チャートで可視化すると以下のようになります。
display(analyse_SIM.mean())
analyse_SIM.mean().plot.bar(figsize=(10,4),fontsize=18)
plt.grid(True)
plt.axhline(y=0, linewidth=4, color='r')
plt.show()
箱ひげ図で可視化すると以下のようになります。〇は外れ値になります。こうやって見ると外れ値は下落時に出やすいのが見て取れるような気がします。7月、8月は外れ値が出にくく、平均的な値動きという事になるのでしょうか。
plt.rcParams["font.size"] = 9
fig, ax = plt.subplots(figsize=(12, 7))
ax =analyse_SIM.boxplot()
年間累積では以下のような損益曲線になります。
analyse_SIM.mean().cumsum().plot(figsize=(10,4),fontsize=18)
plt.grid(True)
plt.axhline(y=0, linewidth=4, color='r')
plt.show()
これを日にちでもう少し細かく見ていきます。
年の情報を削除し、うるう年の2/29が対応できるように2020年での日数にいったん日にちを変換します。
import datetime
df=pd.DataFrame()
df["VOO"]=pd.DataFrame(data2["Adj Close"].pct_change())
df=df.reset_index()
df["MMDD"]=df["Date"].dt.strftime('2020/%m/%d')
df["MMDD"]=pd.to_datetime(df["MMDD"])
display(df)
display(df.info())
2021/12/31までのデータと今年のデータを分けて、dataframeに変換しておきます。
df1=(df[["VOO","MMDD"]][df.Date<="2021/12/31"].copy()).set_index("MMDD")
df2=(df[["VOO","MMDD"]][df.Date>"2021/12/31"].copy()).set_index("MMDD")
df3=(df1.groupby([lambda x: x.month,lambda y: y.date]).mean()).reset_index()
df3=df3.set_index("level_1")
display(df3.tail(2))
display(df2.tail(2))
平均値のデータと今年のデータをプロットします。
import matplotlib.dates as mdates
plt.rcParams["font.size"] = 12
fig, ax = plt.subplots(figsize=(10, 5))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
plt.plot((1+df3["VOO"]).cumprod(),label="20years average")
plt.plot((1+df2["VOO"]).cumprod(),label="This year")
plt.legend(bbox_to_anchor=(1, 0.5), fontsize=12)
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
plt.grid()
plt.show()
Webサービスでの表示はこのようになっており、似たよなチャートになっていることが分かります。
2022/09/01追記:S&P500 インデックスで50年間(1971年から)確認できるようにしました。
以下のように過去50年での成績が出ていましたので、確認もかねて、ETFではなくS&P500インデックスで1970年から調べられるようにしました。
start_D="1970-1-1"
end_D=datetime.date.today()
codelist1 = ["^GSPC"]
としてあります。参照Google Colabファイルはこの内容になっています。
結果は
でなりました。
2022/09/01追記:終了
考察
2022年の7月は非常に強かったですね。20年間の統計的にも上半期が終わって、リバランスなど買いが入りやすいのでしょうか?それとも空売りなどで儲けるタイプのヘッジファンドマネージャーが夏休みになってあまり売りが出てこないのでしょうか。
ただ、”4月は上がりやすいアノマリー”に全く反応しなかったのに、7月だけ従うと判断するのもなかなか難しかったかもしれませんし、そもそも平均値では年間で緩やかな上昇を期待する中、今年は比較的大幅な下落をする状態ですので、どこまで”アノマリー”にかけられるかという胆力が試される展開だったかもしれません。
今後ともアノマリー的な値動きはフォローアップしてみたいと思います。
最後に自動更新される最新データでのアノマリーデータと今年のデータを載せておきます。
”相場は韻を踏むのか?2007年の下落と似ているところと似ていないところ”同様自動更新されますので、興味ある方は継続して確認してみてください。
追記:大統領選挙の4年サイクルのアノマリー
以下のようなコメントをいただきました。
それほど難しくないので、ご希望にこたえて検証してみたいと思います。
まず、コーディングする前に、オフィシャルな正しい結果を確認してみたいと思います。
いくつか情報があります。https://charts.equityclock.com/ では以下のような結果があります。
選挙前年のチャートも下方には出ています。
また、MONEXさんの方では以下のような記事を2022/08/08に書かれているようです。
7月のアノマリーは分かりませせんが、一般的には9月まで弱そうな感じです。
それを踏まえて確認をしてみたいと思います。
実はそんなにむずくかしくないです。方針としては選挙は4年に一度なので、年を4で割ると余りが0,1,2,3になりますので、その対応する余りの年だけ取り出して、同じコードを適応すればよいだけになるはずです。
また、参照するデータ数が1/4になってしまいますのでもう少し長い期間で確認する必要があります。上記MONEXさんの記事ではデータの取得を1930年から行っていました。
前回はVOOというS&P500に対応するETFでデータ分析を行いましたが、1930年からは当然そのETFはありませんので、今回の検証ではS&P500のインデックス指数そのものを使ってみたいと思います。
修正分のコードは以下の通りです。
!pip install yfinance --upgrade --no-cache-dir
import yfinance as yf
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import datetime
start_D="1930-1-1"#@param {type:"string"}
end_D=datetime.date.today()
codelist1 = ["^GSPC"]
data2 = yf.download(codelist1, start=start_D, end=end_D)
display(data2.dropna().head(1).append(data2.dropna().tail(1)))
data2["Adj Close"].plot()
plt.show()
データ取得開始日を 1930-1-1 にしています。
取得データのコードを ^GSPC とS&P500の指数インデックスにしています。
import pandas as pd
import datetime
df_full=100*data2["Adj Close"][:"2022-1-1"].pct_change().copy()
analyse=df_full[df_full.index.year%4==2].copy()
def MonthNumberToMonthName(month):
date = datetime.date(2022, month, 1)
return date.strftime("%B")
analyse_SIM=pd.DataFrame()
for i in range(1,13):
month_name = MonthNumberToMonthName(i)
analyse_SIM[month_name]=analyse[analyse.index.month==i].groupby([lambda x: x.year]).sum()
display(analyse_SIM.mean())
#display(analyse_SIM)
df_full=100*data2[“Adj Close”][:”2022-1-1″].pct_change().copy() analyse=df_full[df_full.index.year%4==2].copy()
分かりやすく2行に分けてみました。今回は中間選挙の年、大統領選挙の2年前という事ですので、余り2の年を抜き出しています。
結果だけ書くとこのような感じです。
月次は上記MONEXさんと似たようなものに当然なります。
また、日次の累積も以下のようになります。
ダウ平均との差がありますが、9月までの下落傾向は同じようなものが見て取れると思います。
今年との比較はこのようになるようです。
コメントありがとうございました。すべてに答えられるものではありませんが、可能なものに対しては対応させていただきたいと思います。
引き続きよろしくお願いいたします。
ディスクレーマー
投資に関する免責事項情報の提供・作業代行を目的としており、投資勧誘を目的とするものではありません。
—
投資に関する記事をご紹介します。
コメント