先日、twitterにブログ記事を何か書けばよいか、tweetしたところ、
ファクターの有効性の分析手法のリクエストがありました。
そのため、今回はPythonコード付きで説明し、実際にトレード手法まで発展させていく過程を書いてゆこうと思います。
株価取得と分析フォーマット作成
まずは、Pythonで株価取得と各々のデータ結合までをやっていこうと思います。
トレードストラテジーを作ってゆくためには、データが命です。
また、プログラミングが出来ない人はこの過程を抜かしても、気合でデータ入手・加工をすればよいだけなので、他の言語・他のツールが良いという人はここは読み飛ばしてもよいです。
では、行きましょう。
#まずは準備。必要なライブラりをそろえる
import pandas as pd
import pandas_datareader.data as web #データのダウンロードライブラリ
PythonはExcelのアドインのように、追加でインストールできるライブラリが色々あります。
ここでは必要になるライブラリを読み込んでゆきます。
ここにあるPandasを使うと、データの統計量を表示したり、グラフ化するなど、データ分析(データサイエンス)を簡単に行うことができるようになります。
#株価の用意する。
#SPYはS&P500に連動するETF
price1 = web.DataReader("SPY","yahoo","2015/1/1").dropna()
print(price1)
一番目のブロックで’web’をpandas datareader.dataとして定義しており、その構文を使えば簡単にyahoo finance @USからデータを入手できます。3行目はyahooから2015年1月1日から現在に至るまでのティッカー”SPY”のデータを入手しなさいという意味です。SPYとはS&P500に連動するETFです。
その次の行ではそれをプリントさせています。結果は以下のようになるはずです。
High Low Open Close Volume \ Date 2014-12-31 208.190002 205.389999 207.990005 205.539993 130333800.0 2015-01-02 206.880005 204.179993 206.380005 205.429993 121465900.0 2015-01-05 204.369995 201.350006 204.169998 201.720001 169632600.0 2015-01-06 202.720001 198.860001 202.089996 199.820007 209151400.0 2015-01-07 202.720001 200.880005 201.419998 202.309998 125346700.0 ... ... ... ... ... ... 2021-08-02 440.929993 437.209991 440.339996 437.589996 58783300.0 2021-08-03 441.279999 436.100006 438.440002 441.149994 57987900.0 2021-08-04 441.119995 438.730011 439.779999 438.980011 46732200.0 2021-08-05 441.850006 439.880005 440.220001 441.760010 38969700.0 2021-08-06 442.940002 441.799988 442.100006 442.489990 46864100.0 Adj Close Date 2014-12-31 181.653259 2015-01-02 181.556000 2015-01-05 178.277176 2015-01-06 176.598022 2015-01-07 178.798615 ... ... 2021-08-02 437.589996 2021-08-03 441.149994 2021-08-04 438.980011 2021-08-05 441.760010 2021-08-06 442.489990 [1662 rows x 6 columns]
次にデータの加工をやってゆきましょう。
今回は終値である修正済み終値(Adj close)しか必要ありません。
このデータだけを使って、前日比を計算しましょう。
#データの中のAdj Close(終値)を用いて、前日比を求める
price2=price1.loc[:,'Adj Close'].pct_change()*100
#データ型を変換。seriesからdata frameへ
price2=pd.DataFrame(price2)
#行に名前を付ける
price2.columns=['SPY_change']
print(price2)
Pythonを勉強している人はわかっていると思いますが、pandasにおけるデータ型だけはしっかりと抑えておきましょう。
処理するたびにseries型やDaraFrame型に変わってゆきますので、途中で確認しながら処理をする必要があります。
2行目にあるpct_change()は時系列データの変化率を計算する構文です。
こういうのがPythonは便利です。
このコードの結果は以下のようになります。
SPY_change Date 2014-12-31 NaN 2015-01-02 -0.053541 2015-01-05 -1.805957 2015-01-06 -0.941878 2015-01-07 1.246102 ... ... 2021-08-02 -0.209804 2021-08-03 0.813546 2021-08-04 -0.491892 2021-08-05 0.633286 2021-08-06 0.165244 [1662 rows x 1 columns]
一瞬で、S&P500の前日比データが作成できました。
つぎは日経平均のデータを加工してゆきましょう。
#日本株のデータをダウンロード。日経平均を使ってみる。
price3 = web.DataReader("^N225","yahoo","2015/1/1").dropna()#jpy
print(price3)
これの実行結果は以下の通りです。
High Low Open Close \ Date 2015-01-05 17540.919922 17219.220703 17325.679688 17408.710938 2015-01-06 17111.359375 16881.730469 17101.580078 16883.189453 2015-01-07 16974.609375 16808.259766 16808.259766 16885.330078 2015-01-08 17243.710938 17016.089844 17067.400391 17167.099609 2015-01-09 17342.650391 17129.529297 17318.740234 17197.730469 ... ... ... ... ... 2021-08-02 27834.599609 27493.320312 27493.320312 27781.019531 2021-08-03 27724.449219 27492.400391 27580.029297 27641.830078 2021-08-04 27636.339844 27488.740234 27612.900391 27584.080078 2021-08-05 27741.550781 27526.669922 27526.669922 27728.119141 2021-08-06 27888.869141 27709.220703 27709.220703 27820.039062 Volume Adj Close Date 2015-01-05 116500000.0 17408.710938 2015-01-06 166000000.0 16883.189453 2015-01-07 138600000.0 16885.330078 2015-01-08 140600000.0 17167.099609 2015-01-09 155200000.0 17197.730469 ... ... ... 2021-08-02 60100000.0 27781.019531 2021-08-03 57900000.0 27641.830078 2021-08-04 67500000.0 27584.080078 2021-08-05 55900000.0 27728.119141 2021-08-06 56400000.0 27820.039062 [1613 rows x 6 columns]
次にこのデータを加工します。
予測するターゲットをここで作るわけです。
ここでは日経の日中の動き、マーケットが始まってから終わるまで、寄りから引けまでのリターンを計算します。
#日本株の日中の動きを米国株の上げ下げで予想するため、openからclose(寄りから引け)までのリターンを計算する
price3=pd.DataFrame(price3)
price3=(price3['Close']-price3['Open'])/price3['Open']*100
#seriesになったデータを再度daraframeにする
price3=pd.DataFrame(price3)
#行に名前をいれる
price3.columns=['N225_change']
print(price3)
3行目で計算してますね。
Pythonが良いのはここでdo文を書かずとも、列の名前の指定だけで各行のデータを計算してくれます。
そして勝手に日付と同期したデータを作成してくれる所が便利です。
結果は以下の通りになるはずです。
N225_change Date 2015-01-05 0.479238 2015-01-06 -1.277020 2015-01-07 0.458526 2015-01-08 0.584150 2015-01-09 -0.698722 ... ... 2021-08-02 1.046433 2021-08-03 0.224078 2021-08-04 -0.104373 2021-08-05 0.731833 2021-08-06 0.399933 [1613 rows x 1 columns]
次にS&P500の加工データと日経225の加工データを連結します。
注意はS&P500のデータは予測する日経225データの過去でなければなりません。
すなわちは、8月6日の日経を予測するためには8月5日以前のS&P500データでなければなりません。
下ではshift()を使って一日分データをずらしています。
#S&P500 (price2)と日経225 (price3)のリターンデータを結合する。
#ポイントはS6P500の前日のリターンで予測するのでデータは一日前にずらす。
price2=price2.shift()
#shift()だけでずらせる。便利!
conbine_price=price3.merge(price2,on='Date')
print(conbine_price)
上ではmergeを使って結合してます。
基準は日付基準で、その意味で’Date’を指定しています。
結果は以下の通りです。
N225_change SPY_change Date 2015-01-05 0.479238 -0.053541 2015-01-06 -1.277020 -1.805957 2015-01-07 0.458526 -0.941878 2015-01-08 0.584150 1.246102 2015-01-09 -0.698722 1.774514 ... ... ... 2021-08-02 1.046433 -0.485643 2021-08-03 0.224078 -0.209804 2021-08-04 -0.104373 0.813546 2021-08-05 0.731833 -0.491892 2021-08-06 0.399933 0.633286 [1560 rows x 2 columns]
ここで、おまけでつけておきますが、Pythonで統計量を調べることができます。
corr()の構文で相関係数を出すことができます。
以下では相関係数を2乗した決定係数を計算しています。
conbine_corr=conbine_price.corr()**2
print(conbine_corr)
結果は以下になります。
N225_change SPY_change N225_change 1.00000 0.00435 SPY_change 0.00435 1.00000
0.00435という数字を見て、どう思うでしょうか?
株の予測分析の世界では0.01を超えれば、合格ラインです。
ですので、0.01を超えるファクターを見つけるたとしたら、それは秘密にしておきましょう。
私もブログには書きません。
使っている人に迷惑ですので。
今回は0.00435という数字ですが、まぁまぁ有望ということでこのまま進めてゆきます。
つぎはCSVに落としてExcelで色々調理してゆくことにしましょう。
#最後はCSVに落として、好きに料理してゆきましょう
conbine_price.to_csv('C:/Users/*************/cobine_price.csv',encoding='utf_8_sig')
*****のところは自分で好きに選んで場所を指定してください。
ここからEXCELを使う理由はその方が色々と調理しやすいと感じているだけです。
Python力が高い人はこのまま進めていっても構いません。
データ分析とトレードストラテジーへの落とし込み
ここからは分析です。
CSVファイルを開けると、下のように数字が並んでいると思います。
ここからは簡単でB行とC行を選び、散布図を作成します。
(もっと簡単に言うとB行をドラッグした後、CTRLを押しながらC行をドラッグし、散布図を作成します。)
その後、グラフができると、グラフ上で右クリックをして”近似曲線の追加”を押し、線形近似を選び、且つ、”グラフに数式を表示する”と”グラフにR 2乗値を追加する”にチェックを入れます。
そうすると以下のグラフが出来きるはずです。
ここからわかるのは、近似曲線が右肩あがりであるためS&P500の前日比リターンは次の日の日経平均に対し正の相関を持っている事、そして決定係数は0.044(既知ですが)という事です。
つまり、
S&P500の前日比リターンが+であれば、N225を寄りで買って引けで売る、
S&P500の前日比リターンが ーであれば寄りで売って引けで買い戻せば、
というトレードで少しは稼げることを示唆しています。所謂、順張りトレードですね。
では、実際にそのようにしてトレードした結果を示しましょう。
以下の通りです。
2015年から毎日1500回ほどトレードして、この結果です。
一応累積リターンは25%程度で、右肩あがりでも、このアップダウンだと精神が持たない気がします。
何とかいい方法は無いのだろうか、と思うのが普通の人です。
では、ちょっとファクターを変更し、S&P500の過去1日のリターンを使って分析していたところを少し改造を加えたものをファクターとして適用してみます。(改造内容は秘密。非常にシンプル。)
結果が下です。
おおお、決定係数が増加して0.0062となっているではないですか。
目標の0.01に近づきました!
では、上と同様に順張りトレードを寄り・引けで実施すればどうなるでしょうか?
改善を期待してみましょう。
え、意外とイケる。5年半のトレードでトータル65%はちょっと控え目ですが、右肩上がりのグラフが出来ました。ここから改善策は無いのかと問われると、またもや企業機密になってきます。
ただし、本当にあるのかどうかを示すために、ちょっと老舗の味を混ぜて調理してみました。
下はある一つの条件を、上のトレード条件に加えたものです。
素晴らしい!リターンが1.5倍になりました。これは単利でのトレード結果なので複利で運用すれば、結構な稼ぎになります。
更に、更に、もう一つの条件を入れてトレードしてみましょう。
おおおお、5年半で140%も単利で稼いているでは無いですか!!!
もし日経平均先物で、レバレッジ3倍で運用、且つ複利で運用すれば…。
ただし、昔はS&Pに対し、逆張りでトレードしていれば稼げたところが、昨今では順張りになっているのです。そのため、この法則がいつまでも続くという保証はありませんので、実弾を投入するには躊躇する次第です。
でも、今回言いたいことは、株価の分析は簡単にでき、更には過去データに基づいて分析すれば簡単にその有効性を調べることができます。そして、有効なファクターを幾つか組み合わせて機械学習をすれば、更に有効なトレード手法が見つかるかもしれません。更に更に付け加えると、ファクターは別にテクニカル系の計算値でも構わないわけです。それが有効であれば、秘密で使ってゆきましょう。
過去のデータと未来のデータに相関関係があれば、それは利益の源泉です。
今回は日足データを使いましたが、別に分足でも月足でもよいし、データも質的データを数値化したものでもよいし、なんでも良い訳です。S&Pの代わりにAPPLEの株価を使っても良いのです。有効であれば。
参考事例に囚われず、どんどん視点を変えて分析していってもらえれば、と思います。