短期売買の中でも最も難しいといわれる日経平均ですが、もう少し長い時間軸である週次でのトレードは可能なのでしょうか?Pythonによる分析も含め、検証してみたいと思います。
始めに
以下のようなツイートを拝見しました。
相場の世界に長くいると、日経平均は基本的には米国の動向にされやすく、基本的に短期的には逆張り戦略が機能しやすいという言説を耳にすることが多いのですが、”週次”といったデイトレーディングをする人から見たら比較的長めの保有時間でもそのような傾向はあるのでしょうか?
また、多くのプロやセミプロなどが目を皿のように見ていて、先行きを予想している日経平均に”歪み”など存在するのでしょうか?過去のデータをもとに確認してみたいと思います。
2021/10/03時点で以下のコードはエラーなく動いていることを確認しています。
目標
・プログラム言語Pythonを使って日経平均指数のデータを取得し、グラフ・チャートを表示します。
・順張り、逆張りなど、どのようなアプローチをとるとどのような結果になったのかを確認します。
・条件などを付けることで、マーケットの歪みを見つけることができるのか、マーケットから再現性のある方法で収益を得る方ができるのか、検証します。
初心者の方にも簡単にできるように使い方、コードを書いてありますので、入門編としても最適だと思います。
実際のコードとやっていること
Google Colaboratoryのpythonを使うことにより、無料で、簡単に行うことができます。
Colaboratoryを使えば、Chromeブラウザ上で無料でPythonの実行環境を手に入れる ことができます。新規に費用をかけずにやりたいことである「株価データの取得と解析」ができるのでお勧めのツールになります。
以前、以下のような記事を書かせていただきました。
データの取得
コードの前半部分は以下の通りです。
!pip install yfinance --upgrade --no-cache-dir
import datetime
import yfinance as yf
import matplotlib.pyplot as plt
import pandas as pd
pd.options.display.float_format = '{:.4f}'.format
start_D="2010-1-1"
end_D = datetime.date.today()
codelist = ["^N225"]
data2 = yf.download(codelist, start=start_D, end=end_D)["Adj Close"]
display(data2.head().append(data2.tail()))
Yahoo USから日経平均株価指数のデータを今回のツイートの期間と同じ2010-01-01からのデータを取得します。
df_W=pd.DataFrame()
df_W["Adj_Close"]=data2.resample("W-FRI").last()
plt.plot(df_W.index,(1+df_W["Adj_Close"].pct_change()).cumprod(),label="Buy&Hold")
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), fontsize=18)
display(df_W.head().append(df_W.tail()))
週次のデータに resample を使用して変更します。単純に変えてしまうと、日曜日の日付になるので、取引の行われている月曜日から金曜日という事で、金曜日の日付での終値を使用します。
また、単純な指数の値そのものでなく、パーセンテージでの変化率に表記に変更し、累積積を算出してグラフ(チャート)に表示しています。
人によっては対数正規分布での対数表記を利用するかもしれませんが、ここでは簡便のためにこの表記で行きます。
データのクオリティチェック
今回取得したデータ正しいものか、検証をする前にデータチェックをしておきます。
df_W["pct"]=df_W.pct_change()
df_W["Pre"]=df_W["pct"].shift()
display(df_W.loc[[df_W['pct'].idxmax()]])
display(df_W.loc[[df_W['pct'].idxmin()]])
これによるとコロナの直後2020-03-27の週に17%程度も上昇し、同じくコロナのパニック時2020-03-13
に-16%近く一週間で落ちたようです。実際そうなのか、TradingViewで確認してみます。
TradingViewは月曜日の日付での表記のようですが、確かに2020-03-23の週に17%上昇しています。
また2020-03-09月曜日の週も確かに16%下落しているようです。
データ自体に問題は無いようなので、検証に進みます。
順張りと逆張り
順張りと逆張りで、どのような成績になるかを確認します。今回のツイートの条件は
日経225を
・そのままホールド(灰)
・週間のリターンを見て、上がったら翌週買い、下がったら翌週売りを繰り返す。つまりトレンドフォロー(赤)
・そこで、順張り→逆張りにしてみましたが、成果は全く出ず。
とのことなので、前の週の変化率と、順張り(トレンドフォロー)での成績と逆張り(ミーンリバージョン)の成績をDataFrame内に転記させます。
このあたりのテクニックについてはこちらの記事にて紹介しています。
df_W["TrendF"]=df_W["pct"].copy()
df_W.loc[df_W["Pre"]<0,"TrendF"]= -df_W["pct"]
df_W["MeanR"]=df_W["pct"].copy()
df_W.loc[df_W["Pre"]>=0,"MeanR"]= -df_W["pct"]
display(df_W.head().append(df_W.tail()))
2021-10-01については前週が0.8%下落でしたので、順張りでは売りの週で実際5%近い下落の週でしたので、戦略的にプラスになっているのが見て取れます。その前の週も同様です。
それをプロットすると以下のようになります。
plt.plot(df_W.index,(1+df_W["pct"]).cumprod(),label="Buy&HOLD")
plt.plot(df_W.index,(1+df_W["TrendF"]).cumprod(),label="Trend Follow")
plt.plot(df_W.index,(1+df_W["MeanR"]).cumprod(),label="Mean Reversion")
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), fontsize=18)
実際のツイートのグラフも同様の物になっているのが見て取れます。
歪みはないのか?
なかなか素のままで利用するのは難しいようです。では、つけ入るスキはないのでしょうか?
少し違うアプローチをしてみたいと思います。統計的な傾向を調べるためにクロスプロットを書いてみます。
import seaborn as sns
plt.rc("legend", fontsize=18)
sns.set(color_codes=True)
sns.jointplot("Pre","pct",df_W,kind='reg',size=5)
plt.tick_params(axis='both', labelsize=18)
plt.show()
display(df_W.describe())
横軸(x軸)に前の週(一期前)の日経平均のリターンとし、縦軸(y軸)を今週の日経平均のリターンをした場合、相関ならびに決定係数がほぼ水平で、何の相関もないことが分かります。
これでは、”下がったから買えばよい”とか、”下がったら売ればよい”とか、言えるのもではないことが分かります。
極端な相場状況・センチメントでは?
このままではマーケットから収益を得ることはできません、、という事になるのですが、人間が常に合理的な行動がとれるものでもないので、なにか歪みはないものでしょうか。
極端に相場環境が悪く、テレビのニュースなどで下落がトップで流れるような場合などはどうなのでしょうか。今回のデータ数に対して、下落の上位25%は週次で-1.2%、上昇の上位25%は同じく週次で1.8%の上昇のようです。
今回は切りよく週次で2%の下落や上昇をした週の翌週の傾向を調べてみたいと思います。
plot = sns.jointplot("Pre","pct",df_W,kind='reg',size=5)
plot.ax_joint.axvline(x=-0.02, color="Red",linestyle='--')
plot.ax_joint.axvline(x=0.02, color="Green",linestyle='--')
plt.tick_params(axis='both', labelsize=18)
plt.show()
上記グラフの赤いの左側(前の週が2%以上下落した 次の週 )と緑の線の右側(前の週が2%以上上昇した次の週)とでは、どのような傾向があるのでしょうか。
display(df_W[df_W["Pre"]<=-0.02]["pct"].sum())
display(df_W[(df_W["Pre"]>-0.02) & (df_W["Pre"]<0.02)]["pct"].sum())
display(df_W[df_W["Pre"]>=0.02]["pct"].sum())
全体としては傾向がないにも関わらず、ある特定のセンチメントや環境においては”歪み”や”傾向”があるような場合があります。今回の例では、多くの人たちが悲観の状態では、翌週上げやすいといったものや、多くの人たちが強気の場合はそれが継続しやすい、という物でしょうか。
—-2021/12/18追記
この記事を書いたのは2021年10月でした、その後2021年12月までに複数回2%を超える下落をした週があったようです。それを確認します。
display(df_W.tail(12))
plot = sns.jointplot("Pre","pct",df_W,kind='reg',size=5)
plot.ax_joint.axvline(x=-0.02, color="Red",linestyle='--')
plot.ax_joint.axvline(x=0.02, color="Green",linestyle='--')
plt.tick_params(axis='both', labelsize=18)
plt.show()
df_W_check=df_W.copy()
df_W_check["zone1"]="before"
df_W_check.loc[df_W_check.index >= "2021-10-01", 'zone1'] ="after"
plot = sns.jointplot("Pre","pct",df_W_check,size=5,hue="zone1")
plot.ax_joint.axvline(x=-0.02, color="Red",linestyle='--')
plot.ax_joint.axvline(x=0.02, color="Green",linestyle='--')
下の散布図でオレンジで色のついている部分が2021/10月以降のデータになります。
2%以上下落した週は4回あったように見えます。実際4回で翌週はどのように動いたのか確認してみましょう。
display(df_W_check.tail(12))
display(df_W_check[df_W_check["Pre"]<=-0.02][["pct","Pre"]]["2021-10-01":])
display(df_W_check[df_W_check["Pre"]<=-0.02]["pct"]["2021-10-01":].sum())
実際4週で、その翌週のリターンと、その合計はほぼ0だったようです。
なかなか簡単に儲かるわけでもなさそうですが、試行回数を上げていくと大数の法則により平均に収束していく、、、かもしれませんね。
今後も継続して確認していきたいと思います。
—-2021/12/18追記
ただ、その ”歪み”や”傾向” が偶然そうなっているのか、精密に検証する必要があります。そうしなければただのカーブフィッティングになる可能性が高いです。
このあたりのセンチメントに対するものと、区間ごとのリターンに対する期待に対する考え方についての記事を参考として、ご紹介いたします。
外部サイトです。
最後に
昔の物で、単純なパーセントでの累積だったり、お見せできるほどのものでもないので、コードは割愛しますが、五分位に切り分けて、かつ時系列でそのトレードを行った場合どうなるかをご紹介します。
区間の切り方や、2010年からではなく、もっと以前はどうだったのかなど、いろいろ検証できる部分がありそうです。
また、実際には指数は取引できませんので、先物・ETFでのエントリーであったり、買うタイミング、スリッページなど、実際の運用サイドの課題なども出て来たります。
興味を持たれた方はご自身で調査、検証などされてみてはいかがでしょうか。
最後まで、読んでいただきありがとうございました。
ディスクレーマー
投資に関する免責事項情報の提供・作業代行を目的としており、投資勧誘を目的とするものではありません。
---
関連した記事をご紹介します。
コメント