今日は前に書いた記事の若干発展版で、もうExcelを使わずにトレードバックテストまでやってゆきましょう、という記事です。
Excelは便利で、細かな調整等に向いていますが、大まかな調査についてはプログラミングで実施した方が良いと思いますし、データ量が多くなってくると、Excelでは難しいものがあります。

今回は上の記事を、少し趣向を変えて、全てPythonでやってしまおう、というのが今回の記事ですが、それでは面白くないので、トレード期間と対象銘柄を変更しております。
なので、展開がわかっている人も少しは役に立つかもしれません。

では行きましょう。

#まずは準備。必要なライブラりをそろえる
import pandas as pd
import pandas_datareader.data as web #データのダウンロードライブラリ

#株価の用意する。
#^GSPCはS&P500の意味
df_1 = web.DataReader("^GSPC","yahoo","2009/12/31").dropna()

#データの中のAdj Close(終値)を用いて、前日比を求める
df_11=df_1.loc[:,'Adj Close'].pct_change()*100 
#データ型を変換。seriesからdata frameへ
df_11=pd.DataFrame(df_11)
#行に名前を付ける
df_11.columns=['SP500_change']
print(df_11)

上のコードではS&P500の株価を取得した後、S&P500の前日比リターンを割り出していますね。
結果は以下です。

  SP500_change
Date                    
2009-12-30           NaN
2009-12-31     -1.004960
2010-01-04      1.604342
2010-01-05      0.311568
2010-01-06      0.054552
...                  ...
2021-09-13      0.227649
2021-09-14     -0.574664
2021-09-15      0.847400
2021-09-16     -0.155114
2021-09-17     -0.911087

[2950 rows x 1 columns]

次に日本株のTOPIX・ETF(1306)の価格を取得してゆきます。
皆さんは良く知っておいて欲しいのですが、TOPIXとNIKKEI225ではちょっとだけ性質が違います。構成銘柄が全く違うので、異なるのは当たり前ですが、ボラティリティをはじめ、色々な感応度が異なります。

#日本株のデータをダウンロード。TOPIXを使ってみる。
df_2 = web.DataReader("1306.T","yahoo","2010/1/1").dropna()#jpy
#日本株の日中の動きを米国株の上げ下げで予想するため、openからclose(寄りから引け)までのリターンを計算する
df_21=(df_2['Close']-df_2['Open'])/df_2['Open']*100
#seriesになったデータを再度daraframeにする
df_21=pd.DataFrame(df_21)
#行に名前をいれる
df_21.columns=['Topix_change']
print(df_21)

結果は以下です。

            Topix_change
Date                    
2010-01-04      0.107759
2010-01-05     -0.743100
2010-01-06      0.531350
2010-01-07     -0.316456
2010-01-08      0.419727
...                  ...
2021-09-13      0.464684
2021-09-14      0.459982
2021-09-15     -0.230627
2021-09-16     -0.599078
2021-09-17      0.185185

[2885 rows x 1 columns]

どんどん行きましょう。

次はデータ結合。前回記事を読んでいればここまではほぼ同一です。

#S&P500と日経225のリターンデータを結合する。ポイントはS6P500の前日のリターンで予測すするのでデータは一日前にずらす。
df_11=df_11.shift()

conbine_price=df_11.merge(df_21,on='Date')

print(conbine_price)
print(conbine_price.corr())
            SP500_change  Topix_change
Date                                  
2010-01-04     -1.004960      0.107759
2010-01-05      1.604342     -0.743100
2010-01-06      0.311568      0.531350
2010-01-07      0.054552     -0.316456
2010-01-08      0.400120      0.419727
...                  ...           ...
2021-09-13     -0.772258      0.464684
2021-09-14      0.227649      0.459982
2021-09-15     -0.574664     -0.230627
2021-09-16      0.847400     -0.599078
2021-09-17     -0.155114      0.185185

[2787 rows x 2 columns]
              SP500_change  Topix_change
SP500_change      1.000000     -0.111822
Topix_change     -0.111822      1.000000

ここでポイントはcorrで相関係数を求めているところです。

ここで見て欲しいのはTOPIXはS&P500の騰落に対して日中は負の相関且つ、絶対値が0.1以上という強い相関を持っているという事です。
いつも言っているように決定係数が0.01を超えていれば、相関が強いと言っておりますが、
この決定係数は相関係数の2乗の値なので、相関係数で考えると絶対値0.1以上が相関が強いと言っていいのです。

では負の相関であることから、S&P500が上がっていれば売り、下がっていれば買いというトレードで儲かる可能性が高いので、そのままシグナルを作るためにコードに書いてみましょう。
売りであればー1、買いであれば1を出力します。

#売買シグナルを作ってゆきましょう。逆張りなので、下の式では最後に-1がかけてあります。
Signal=conbine_price['SP500_change']/abs(conbine_price['SP500_change'])*(-1)
Signal=pd.DataFrame(Signal)
print (Signal)
            SP500_change
Date                    
2010-01-04           1.0
2010-01-05          -1.0
2010-01-06          -1.0
2010-01-07          -1.0
2010-01-08          -1.0
...                  ...
2021-09-13           1.0
2021-09-14          -1.0
2021-09-15           1.0
2021-09-16          -1.0
2021-09-17           1.0

[2787 rows x 1 columns]

もうここまでくれば簡単ですね。
これをリターンにかけ合わせれば、トレードの結果になるのです。

Return=conbine_price['Topix_change']*Signal['SP500_change']
Return=pd.DataFrame(Return)
Return.columns=['Topix_trade_return']
print(Return)
            Topix_trede_return
Date                          
2010-01-04            0.107759
2010-01-05            0.743100
2010-01-06           -0.531350
2010-01-07            0.316456
2010-01-08           -0.419727
...                        ...
2021-09-13            0.464684
2021-09-14           -0.459982
2021-09-15           -0.230627
2021-09-16            0.599078
2021-09-17            0.185185

[2787 rows x 1 columns]

ここからはExcelでもできる作業ですが、今回はPythonでやってゆきましょう。
時系列のリターン累積をcumsumを使って出しましょう。

import numpy as np
Total_return=np.cumsum(Return)
print(Total_return)
            Topix_trede_return
Date                          
2010-01-04            0.107759
2010-01-05            0.850858
2010-01-06            0.319509
2010-01-07            0.635964
2010-01-08            0.216237
...                        ...
2021-09-13          139.611989
2021-09-14          139.152008
2021-09-15          138.921380
2021-09-16          139.520459
2021-09-17          139.705644

[2787 rows x 1 columns]

最後はプロット作業。
ラベルとか無視するならば、plt.plot(Total_Return)で一発ででます。

fig, ax = plt.subplots()
ax.plot(Total_return)
ax.set_xlabel('Time [year]', fontsize=12)
ax.set_ylabel('Return [%]', fontsize=12)
ax.set_title('S&P500 contrary trade', fontsize=16)
plt.show()

トレード期間10年ですが、長期でみればええ感じの右肩上がりのグラフができました。

ここで見て欲しいのは2020年初頭のコロナショックではエグイリターンを叩き出しています。
一方で、東日本大震災の際にはかなり下げています。

ここからは私の推論ですが、アメリカ発のショックにはNY逆張りは有効で、その逆の日本初のショックには弱いという側面があるのかと思います。

アメリカ出来事には課題に朝寄付きで反応し、徐々に日中で修正するという事ではないでしょうか。

前回の記事でも書いたように、日本以外の国でのショックに関しては逆張りが有効であると推察されるということで、過剰反応系に対応したトレードストラテジーも組んではいかがでしょうか。

投稿者

SHIN

5件のコメント

  1. ブログの更新ありがとうございます。
    ひとつ質問させてください。

    S&P500のリターンを求めるときにpct_change()を使って終値同士のリターンを計算していると思います。
    (トレード日より2日前と1日前の終値同士の比較)

    この方法に対して、トレード日の前日の始値と終値から計算されるリターンではないのが気になったのですが、何か理由はあるでしょうか?
    (トレード日より1日前のopen-closeの比較)

    ちなみに、後者の方法で計算すると、損益曲線の形状が若干変わるようです。(あまり気になるほどではありませんが)

    ところで、ショックに対しての逆張りは有効そうですね。
    そういえば土屋さんのブログでも、売られすぎ銘柄の逆張りは有効な戦略だと書かれていた記憶があります。

    たいやき
    1. よく効く方を使えばいいと思います。

      個人的な経験から、前日比・当日の騰落率のどちらでも似たような結果だと記憶してます。
      なので、日本株に情報が盛り込まれていない前日比を使っています。

      VIXの値が上がるほど逆張りの戦略がうまくいく気がしてます。
      そのあたりも、何かの指数でその戦略リターンを回帰分析すればわかると思いますね。

      >そういえば土屋さんのブログでも、売られすぎ銘柄の逆張りは有効な戦略だと書かれていた記憶があります。
      脳裏に残っている気がします。
      他のブログの方も、日本株は逆張り性が高いことを解析でしめしていたので、ストラテジーポートフォリオには必須なのかと思います。

      SHIN
  2. 回答ありがとうございました。どちらも大きな違いはないようですね。

    VIXは上がってくれば売るという戦略はよくありますが、ある意味売られすぎの逆張りといえるかもしれません。
    日足の-3σタッチの銘柄だけを探している人もいるようで、みんな同じこと考えていそうです。

    たいやき
    1. モメンタム・リバーサルともにバランスよく戦略に組みこんで、オールウェザーが好ましいと思ってます。
      アメリカはモメンタム・日本はリバーサルと言われていますので、この辺も簡単に分析できるならば記事にいたします。

      今晩はNYが荒れそうです。コントラリアンの気持ちが昂ります。

      SHIN

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です