データサイエンスと機械学習(第04回):現在の株式市場の暴落を予測する
はじめに
この連載の第02回では、タイタニックのデータを基に簡単なロジスティックモデルを作成しましたが、今日は市場の暴落を予測するのに役立つロジスティックモデルを作成します。
今回は、ロジスティックモデルの有用な応用として、株式市場の暴落の予測モデルを作ってみます。モデルをテストするために、現在の株式市場の暴落に関するテストデータを使用します。これは私たち全員に関係することだと思います。
株式市場の暴落
株式市場の暴落とは、市場の総価値が急激かつ急速に下落することで、通常、価格は数日以内に10%以上下落します。大規模な株式市場の暴落の有名な例としては、1987年のブラックマンデーや2008年の不動産バブルなどが挙げられます。暴落は通常、価格バブルの崩壊に起因し、株式市場参加者の大半が同時に資産を売ろうとすることで発生する大規模な売り浴びせによるものです。
このことをさらに詳しく説明する前に、次のことについて免責事項を述べたいと思います。
これは、金融や取引のアドバイスではありません。私は、バフェット氏でも、チャーリー・マンガーでも、プロの株式投資家でもありません。私は、科学的モデルを取引に関連付ける方法を探しているデータ科学者に過ぎません。これらの意見の大部分はオンラインで収集されたものであり、記事の最後の参照セクションにリンクされているさまざまな信頼できる情報源から収集されたものであるため、この記事の内容を真剣に受け止めないでください。 この記事で説明されている方法を用いて取引をおこなうことを決定する前に、よく調査をおこなってください。
さて、それはさておき、次に進みましょう。
まず、株価に影響を与える要因を見てみましょう。これらの要因を理解すれば、ロジスティックモデルのデータ(独立変数)として使用することができるため、どこから手をつけていいのかがわかります。
株価に影響を与える要因
株式市場に影響を与える要因は数多くあります。以下はその一例です。相場がどのように動くかについての明確な指標が存在しないことを念頭に置いて、私は次のような要因を使うことにしています。
- 需要と供給
- 会社関連の要因
- 金利
- 時事問題
- インフレ
01:需要と供給
株式市場に影響を与える要因はたくさんありますが、外側のものをすべて取り除いて非常に基本的な要因を見ると、それは単純で、需要と供給です。需要と供給の間の不均衡は、株式の価格を上げ下げします。
リンゴが急に品薄になると、それを買うために行列する人が増え、リンゴの値段はたちまち高騰します。
同じように、会社の業績がよくて、誰もが同じ会社の株を買いたがれば、株が不足して株価は急上昇しますし、逆に株が多くても誰も買いたがらない場合は、株価は急落することになるのです。
モデルで使用できるすべての需要と供給のデータを取得することは不可能です(私は言うかもしれません)。そのため、この要因をデータセットから外しますが、データを正確に取得することができる人は、聖杯の構築に一歩近づくと思います。
02:会社関連の要因
会社内で起こることはすべて株価に直接影響します。製品の発売が成功し、収益が増加し、負債が減少し、会社が上昇している場合、投資家の流入が増えて、会社の価格は上昇するに違いありません。 急上昇を繰り返す会社の株は誰もが買いたいからです。
しかし、企業が損失を計上し、製品が失敗し、負債が増加している場合、株主の大多数はその企業の株式を売ろようとするため、株価が下がることになります。
この点を明確にするための良い例が、NetflixとAppleです。
Netflixは、一部の会員の価格を上昇したことによって、2022年の最初の3ヶ月間で20万人以上の加入者を失いました。その他にも社内で多くの事態が発生し、直接Netflixbの株価を下落させました。
一方、Appleは、製品リリースの成功、社内での優れたリーダーシップ、および社内のその他の前向きな状況により、非常に長い間成功を収めてきました。これが、近年の強気な株価につながりました。
会社の健全性を判断するために、株価収益率と呼ばれる指標を使用します。
株価収益率
株価収益率は企業を評価するためのもので、1株当たりの利益(EPS)に対する現在の株価を測定します。株価収益率は、企業の健全性を示す指標として使われます。 AppleとNetflixの株価と株価収益率からチャートを見ると以下のようになります。
APPLE
データソース:macrotrends.net
NETFLIX
データソース macrotrends.net
株価収益率は年の四半期ごとに計算されるようです。 無料のデータソースはこれだけだったようです。有料のソースはもっとあるでしょう。モデルの計算が効果的に機能するためには、すべてのデータセット列に同じ数の行が必要なため、データにいくつかの穴があると考えるかもしれません。これはAPPLEのデータです。
データが年の四半期ごとに計算される場合、次の四半期までの四半期の残りについては事前に計算された同じデータを使用することになるため、この場合、データを複製しましょう。
NETFLIXについても同じことをします。
03:金利
連邦準備銀行の動向は株価に直接影響します。準備銀行は経済を安定させるため、一定期間ごとに金利を変え続けています。当然のことながら、金利が高いということは、企業がより多くのローンを支払う必要があり、その結果、利益が少なくなることを意味します。これにより、株価が下がります。逆に、金利が低いということは、企業が銀行からより少ないコストでお金を借りることができて、より高い利益を上げられることを意味します。この場合、株式の価格が上昇します。
連邦準備制度理事会は最近、需要を破壊し、企業に価格を下げさせ、最終的にインフレが下がるようにするために利上げをおこなっています。
2010年から今日までの連邦準備制度理事会の資金率のグラフは次のようなものです。
04:時事問題
一般的に、国や世界で進行中の問題は、株式市場にも大きな影響を与えることがあります。2019年後半から2020年にかけて、コロナの大流行が株式市場に非常に強い悪影響を与えたことは誰も否定できませんし、同じ年に米国で起きた平等を求める暴動もそうです。
株式相場に影響を与えるその他の問題には、戦争、テロなどがあります。
これらの出来事はすべて、株価を急激に下落させ、市場のボラティリティに影響を与えるに違いありません。
この要因からデータを収集するつもりはありません。なぜなら、これらの出来事に対して訓練するためには、非常に多くの作業とより多くのモデルが必要であり、これはこの連載ですでに取り上げた範囲を超えているからです。
05:インフレ
インフレとは、ある通貨の購買力が時間とともに低下することです。購買力の低下を定量的に見積もるには、ある一定期間の経済において、選択された財やサービスのバスケットの平均価格水準の上昇に反映させることができます。物価の上昇は、しばしば割合で表され、1単位の通貨で購入できるものが実質的に以前の期間より少ないことを意味します。
インフレについて詳しくはhttps://www.investopedia.com/terms/i/inflation.aspをご覧ください。
基本的にインフレにはコアCPIとCPIの2種類があります。
- コアCPI:エネルギーと食品を除くすべての価格
- CPI(消費者物価指数):エネルギー、食品価格、教育、娯楽など、経済内部のすべてのもの。特定の経済圏の人々の日常生活に存在するすべてのもの
インフレは1ドルの利益の価値を下げるので、市場は市場指数を構成する企業の現在の価値を測定することが困難になります。さらに、原材料、在庫、人件費などの価格上昇は、企業の調整に伴い、業績に影響を与える可能性があります。そのため、株価は変動しやすく、ボラティリティ(変動率)が高くなります。
連邦準備制度理事会の引き締めは債券投資にマイナスの影響を与えますが、良いニュースは、株式はこのようなサイクルの中で歴史的にしばしば良い結果を出してきたということです。
次は、1970年以降のアメリカの消費者物価指数のグラフです。
では、必要なデータをすべて集めて、1つのCSVファイルに保存してみましょう。
APPLEから始めます。
データ収集
CSVファイルで収集するデータは、コアCPI、CPI、連邦準備制度理事会の資金率、EPS、株価収益率です。これだけのデータが揃っています。
データセットに欠けているデータは1つだけで、それは従属変数です。株価は生の値しかありません。特定の月に株式市場が暴落したかどうかを知ることができるスクリプトを作成してみましょう。
CrashClassifyScript.mq5:
void DetectCrash(double &prices[], int& out_binary[]) { double prev_high = prices[0]; ArrayResize(out_binary,ArraySize(prices)-1); //we reduce the size by one since we ignore the current we predict the previous one for (int i=1; i<ArraySize(prices); i++) { int prev = i-1; if (prices[i] >= prev_high) prev_high = prices[i]; //grab the highest price double percent_crash = ((prev_high - prices[i]) / prev_high) * 100.0; //convert crash to percentage printf("crash percentage %.2f high price %.4f curr price %.4f ", percent_crash,prev_high,prices[i]); //based on the definition of a crash; markets has to fall more than 10% percent if (percent_crash > 10) out_binary[prev] = 0; //downtrend (crash) else out_binary[prev] = 1; //uptrend (no crash ) } }
最初のprev_highに注意を払うとまず以前の価格の値を指定したことに気付くでしょう。2010年1月1日ではなくて2009年12月1日からAppleの値をコピーしたため、最初の計算でクラッシュを検出する余地が必要でした。その月を追加することで可能になりましたが、その月は不要になるため、出力データセットには無視します。インデックス1からループを開始するため、out_binary[prev]でインデックスprevは i-1です。
out_binary配列を出力すると次のとおりになります。
CrashClassifyScript DATE 1/1/2010 TREND 1
CrashClassifyScript DATE 2/1/2010 TREND 1
.........
CrashClassifyScript DATE 4/1/2022 TREND 0
CrashClassifyScript DATE 5/1/2022 TREND 0
1つのcsvファイルにすべてのデータ列を追加すると、csvファイルは次のようになります。
さて、これで準備は整いましたので、もう少しコードを書き込んでみましょう。
ロジスティックモデルの裏側には線形回帰アルゴリズムがあり、線形モデルでデータを使用する前に、そのデータが独立変数と相関があるかどうかを確認しなければならないことは周知のとおりです。前回の記事で作成した LinearRegressionライブラリに追加したcorrcoeff メソッドを呼び出して確認します。
TestScript.mq5の内部
m_lr = new CMatrixRegression; Print("Matrix multiple regression"); m_lr.Init(8,"2,4,5,6,7",file_name,",",0.7); m_lr.corrcoeff(); m_lr.MultipleMatLinearRegMain(); delete m_lr;
次が出力されます。
Matrix multiple regression
TestScript Init, number of X columns chosen =5
TestScript "2" "4" "5" "6" "7"
TestScript All data Array Size 740 consuming 52 bytes of memory
TestScript Correlation Coefficients
TestScript Independent Var Vs Trend = 0.225
TestScript Independent Var Vs CPI = -0.079
TestScript Independent Var Vs Core CPI = -0.460
TestScript Independent Var Vs EPS($) = -0.743
TestScript Independent Var Vs PE Ratio = -0.215
オンラインで多くの人がこれらは株式市場に影響を与える要因だと主張しているにもかかわらず、今別の場所で集めたデータはすべて株価と相関がないようです。情報筋は当初、市場がどのように行動するかについての明確な指標はないという免責事項を与えたことを理解していますが、線形モデルの数字は非常に異なるストーリーを示しています。例えば、CPI対Appleの価格です。ここに非常に強い負の相関があると期待していましたが、線形回帰で使用するには相関が弱すぎるようです。有望な唯一の負の相関はコアCPIが示している約-0.46です。 最強なのはEPS(一株当たり利益)が示す0.743の負の相関(約0.74%に変換可能)です。
それで終わりではありません。計算がうまくいかなかった場合や数値から何かが欠けている場合に備えて、Python でデータを視覚化し、自分で確認することが非常に重要です。
出力
この時点で、私たちが収集したデータのほとんどに強い関係がないことは非常に明らかだと思います。データをフィルターしましょう。
ここでは、以下の3つの独立変数のみを用いてモデルを構築することにします。
- コアCPI(約-46%の相関、真ん中あたり)
- EPS(約-74.2%の相関、全データで最高)
- 連邦準備制度理事会の資金率(約-33%の相関、最も相関がない、本格的なモデル構築の際には非推奨)
では、必要なカラムだけでライブラリを初期化しましょう。
log_reg.Init(file_name,delimiter,2,"3,5,6",0.7);
ロジスティック回帰の基本的な機能をご存じない方は、こちらの記事をご参照ください。
ライブラリのさらなる改善
//These should be called before the Init void FixMissingValues(string columns); void LabelEncoder(string columns, string members);
ロジスティックモデルは欠損値に敏感であり、分類のための機械学習モデルであるため、データが欠落していることを示す可能性のあるゼロデータを分類されたクラスとして扱います。MQL5 でファイルを読み取る方法に応じて、nan値と文字列をゼロとして扱うこともできます。よってライブラリを改良しました。
欠損値を平均値に置き換える関数と文字列をラベルにエンコードする関数を、
Init関数の前に呼び出す必要があります。
このロジスティックライブラリは、前回の記事で作成したMatrixRegressionライブラリのコンポーネントを継承しています。
class CLogisticRegression: protected CMatrixRegression
では、早速、このモデルの実力を見てみましょう。
出力は次のようになります。
Confusion Matrix [ 0 13 ] [ 0 31 ] Tested model accuracy =0.7045
テストデータセットでのモデル精度は70.45%です。😲この時点で呆然としていています。
先ほど50%にも達しないというデータの欠点があったので、どこかでエラーが起きているのだろうと思いましたが、pythonで同じことをやってみたら、同じ結果になりました。
B A M
従属変数は、この記事の前半でクラッシュを検出するためにスクリプトで収集した[傾向]列です。[価格]列は、線形モデルの相関係数を表示するために使用されただけです。下降トレンドと上昇トレンドをそれぞれ示す0と1のバイナリ値を使用して相関関係を見つけることはできないため、その場合の株式の実際の価格になります。
次に、NETFLIXに焦点を移しましょう。
相関係数の数値はどのようになっているかというと、こんな感じです。
Correlation Coefficients Independent Var Vs Trend = 0.071 Independent Var Vs rate (FEDs rate) = 0.310 Independent Var Vs CPI = 0.509 Independent Var Vs Core CPI = 0.607 Independent Var Vs EPS = 0.917 Independent Var Vs PE Ratio = -0.213
以下で説明する要因の大部分がNETFLIXにプラスの影響を与えているように見えますが、株価収益率だけがマイナスです。最も強力な要因は、株価と約92%の相関関係を持つ1株当たりの利益であり、その他はコアCPIとCPIです。 したがって、NETFLIX では、モデルを構築するために次の3つのデータのみを使用します。
- EPS
- コアCPI
- CPI
もう一度、データを可視化してみましょう。
前回のAppleの時よりもNETFLIXの方が断然良さそうです。
以下にまとめてみます。
log_reg = new CLogisticRegression(); Print("NETFLIX"); file_name = "Netflix Dataset.csv"; log_reg.Init(file_name,delimiter,2,"4,5,6",0.7); log_reg.LogisticRegressionMain(accuracy); printf("Tested model accuracy =%.4f",accuracy); delete log_reg;
出力
FN 0 07:54:45.106 TestScript NETFLIX PN 0 07:54:45.108 TestScript ==== TRAINED LINEAR REGRESSION MODEL COEFFICIENTS ==== ED 0 07:54:45.108 TestScript [ RO 0 07:54:45.108 TestScript 1.43120 -0.05632 -0.54159 0.48957 EE 0 07:54:45.108 TestScript ] CQ 0 07:54:45.108 TestScript columns = 4 rows = 1 PH 0 07:54:45.108 TestScript ========= LINEAR REGRESSION MODEL TESTING STARTED ========= QP 0 07:54:45.108 TestScript Tested Linear Model R square is = -0.35263665822405277 GR 0 07:54:45.108 TestScript Confusion Matrix EE 0 07:54:45.108 TestScript [ 0 18 ] HN 0 07:54:45.108 TestScript [ 0 26 ] MJ 0 07:54:45.108 TestScript Tested model accuracy =0.5909
株価と強い直線的な相関を持つデータがあったにもかかわらず、NETFLIXの精度は 約60%と、APPLEモデルの 70%より低くなります。残りのデータセットを使って、モデルがどのように見えるかを確認できます。
リアルタイムの株式市場テスト
エキスパートアドバイザー(EA)内でライブマーケットでテストできるようにするには、メインのLogisticRegression関数を少し修正する必要があります。ストラテジーテスターで使用して、モデルに従って市場がどこに行くかのシグナルを引き出すために、この関数で予測値とそれぞれの日付をCSVファイルに保存する必要があります。
次のように、データを収集し、csvファイルに保存します。
WriteToCSV(TestPredicted,dates,"Predicted "+m_filename,m_delimiter);
収集しているのはテストデータセットの結果のみであることを忘れないでください。
データがcsvファイルにどのように保存されるかは簡単に次の通りです。
NETFLIX Predicted, date_time 1,8/1/2018 1,9/1/2018 1,10/1/2018 1,11/1/2018 1,12/1/2018 1,1/1/2019 APPLE Predicted, date_time 1,9/1/2018 1,10/1/2018 1,11/1/2018 1,12/1/2018 1,1/1/2019 1,2/1/2019
混同行列の部分に注目した場合、モデルが上昇トレンドの良い予測因子であることに気づくでしょう。行列の全行に多数のTP(真陽性)がありました。
リアルタイム株価テストEA
EAを作成する最初のステップはCSVファイルからデータを収集することですが、その前に、このファイルをテスト中に使用することをストラテジーテスターに通知します。
#property tester_file "Predicted Apple Dataset.csv"
私がコーディングしてOnInit関数で呼び出した関数の概要を簡単に説明します。
GetColumnDatatoArray(1,Trend); GetColumnDatatoArray(2,dates);
これらの関数は非常に一般的で、ライブラリでもよく使用しています。基本的に、最初の列からデータを収集してTrend[]配列に格納し、dates[]配列にも同じ処理をおこないます。
次に重要なのは、csvファイルから収集した時刻をMQL5で理解できる標準的な時刻形式に変換することです。
ConvertTimeToStandard();
その関数の中身は次の通りです。
void ConvertTimeToStandard() { // A one time attempt to convert the date to yy.mm.dd ArrayResize(date_datetime,ArraySize(dates)); for (int i=0; i<ArraySize(dates); i++) { StringReplace(dates[i],"/","."); //replace comma with period in each and every date //Print(dates[i]); string mm_dd_yy[]; ushort sep = StringGetCharacter(".",0); StringSplit(dates[i],sep,mm_dd_yy); //separate month, day and year //Print("mm dd yy date format"); //ArrayPrint(mm_dd_yy); string year = mm_dd_yy[2]; string day = mm_dd_yy[1]; string month = mm_dd_yy[0]; dates[i] = year+"."+month+"."+day; //store to a yy.mm.dd format date_datetime[i] = StringToTime(dates[i]); //lastly convert the string datetime to an actual date and time } }
これらは説明する価値があると思う関数です。Init()関数でおこなわれてきました。
次にやるのは、EAの柱であるOntick関数で、モデルの予測値をテストすることです。
datetime today[1]; int trend_signal = -1; //1 is buy signal 0 is sell signal CopyTime(Symbol(),PERIOD_D1,0,1,today); if (isNewBar()) for (int i=0; i<ArraySize(date_datetime); i++) { if (today[0] == date_datetime[i]) //train in that specific day only { if ((int)Trend[i] == 1) trend_signal = 1; else trend_signal = 0; // close all the existing positions since we are coming up with new data signals ClosePosByType(POSITION_TYPE_BUY); ClosePosByType(POSITION_TYPE_SELL); break; } if (MQLInfoInteger(MQL_TESTER) && today[0] > date_datetime[ArrayMaximum(date_datetime)]) { Print("we've run out of the testing data, Tester will be cancelled"); ExpertRemove(); } } //--- Time to trade MqlTick tick; SymbolInfoTick(Symbol(),tick); double ask = tick.ask , bid = tick.bid; //--- if (trend_signal == 1 && PositionCounter(POSITION_TYPE_BUY)<1) { m_trade.Buy(Lots,Symbol(),ask,0,0," Buy trade "); ClosePosByType(POSITION_TYPE_SELL); //if the model predicts a bullish market close all sell trades if available } if (trend_signal == 0 && PositionCounter(POSITION_TYPE_SELL)<1) { m_trade.Sell(Lots,Symbol(),bid,0,0,"Sell trade"); ClosePosByType(POSITION_TYPE_BUY); //vice versa if the model predicts bear market } }
特定の日とNewBarイベントハンドルでモデルを訓練することにした主な理由は、アプリケーションのテストコストを減らすためです。このコストをさらに減らすために、テストデータセットがなくなったらストラテジーテスターを停止するという条件もハードコーディングしています。
以下のリンクにあるフルコードを参照してください。次に、モードをストラテジーテスターでテストします。
テスト結果
チャート
一方、Netflixのテスターレポート:
テスターグラフ
ご覧のように、Appleモデルの精度は約70%であり、競合するNETFLIXと比較して、これまでのところより優れた予測モデルを作成しており、ストラテジーテスターのグラフもより優れています。
ボトムライン
ロジスティックモデルの良いところは、構築と学習が簡単で、かつデータの分類がうまくいくことです。しかし、モデルで見つけるデータが見つかることは、一度間違えると非効率的なモデルにつながる可能性がある最も重要なステップの1つであるため、当然のことと考えるべきではありません。
データを収集してCrashclassifyスクリプト内で分類した方法はクラッシュを観察する効果的な方法ではないと今でも信じているため、ライブラリをさらに改善してデータを再度収集することはできます。
本記事のGithubリポジトリのリンクはhttps://github.com/MegaJoctan/LogisticRegression-MQL5-and-pythonです。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/10983
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索