MetaTrader 5 / エキスパート

Schnick [サポートベクターマシン学習ツールテスタ - デモ版] - MetaTrader 5のためのエキスパート

1093
(16)

このスクリプトはMQL5ウェブサイトに掲載された記事「Machine Learning: How Support Vector Machines can be used in Trading(マシンラーニング:サポートベクターマシンをトレーディングで利用する方法)」の一部として書かれました。

このバージョンのコードは、MQL5マーケットから 無料で入手できるサポートベクターマシン学習ツールのデモ版と組み合わせた使用のために具体的に書かれています。

この仮定シナリオをイメージしてください。みなさんは北極のかなたでしか見られないシュニックと呼ばれるまぼろしの生き物を調査している研究者です。この生き物は人になつかないためこれまでに非常に少数の固体しか見つかっていません(例えば5,000体)。研究者として疑問に行き詰っています。どのようにシュニックだと確認できるのだろう?と。

自由に入手できるものは、この生き物を1体だけ見た一握りの研究者によって以前に出版された研究論文だけです。こういった研究論文では、著者は見つけたシュニックについてある特性を述べています。すなわち体高、体重、足の本数などです。

シュニックのような新種の生物を特定するためにこのデータをどのように利用することができるのでしょうか?

この問題の解決策として可能性があるのは、データ内のパターンを特定するためにサポートベクターマシンを利用し、生物がシュニック であるかシュニックでないか分類するために使うことのできる枠組みを作成することです。まず最初のステップは シュニックを特定するためにサポートベクターマシンをトレーニングするデータセットを作成することです。トレーニングデータはインプット1 セット、およびサポートベクターマシン向けに分析しそこからパターンを抽出するインプットに一致したアウトプットです。

このスクリプトは、分類スタイルの問題を解決する上でのMQL5マーケットで利用可能なサポートベクターマシンの力の発揮を試みます。この仮想的な問題と、スクリプトの完全な説明は「Machine Learning: How Support Vector Machines can be used in Trading(マシンラーニング:サポートベクターマシンをトレーディングで利用する方法)」稿で参照まできす。当稿は、スクリプト使用のチュートリアルと、この問題は市場の動向の評価に機械学習をどのように用いるかの洞察を含みます。

コード:

//+------------------------------------------------------------------+ //|                                                 Schnick_Demo.mq5 | //|                        Copyright 2011, MetaQuotes Software Corp. | //|                                              http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link      "http://www.mql5.com" #property version   "1.00" //+------------------------------------------------------------------+ //| このスクリプトは、サポートベクターマシンの能力を実証する //|                     マシン学習ツール //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 次のステートメントは「svMachineTool.ex5」サポートベクターマシンツールに含まれている //| すべての関数をインポートする' //+------------------------------------------------------------------+ #import "svMachineTool_demo.ex5" enum ENUM_TRADE {BUY,SELL}; enum ENUM_OPTION {OP_MEMORY,OP_MAXCYCLES,OP_TOLERANCE}; int  initSVMachine(void); void setIndicatorHandles(int handle,int &indicatorHandles[],int offset,int N); void setParameter(int handle,ENUM_OPTION option,double value); bool genOutputs(int handle,ENUM_TRADE trade,int StopLoss,int TakeProfit,double duration); bool genInputs(int handle); bool setInputs(int handle,double &Inputs[],int nInputs); bool setOutputs(int handle,bool &Outputs[]); bool training(int handle); bool classify(int handle); bool classify(int handle,int offset); bool classify(int handle,double &iput[]); void deinitSVMachine(void); #import //--- svmで使う入力の数 int N_Inputs=7; //+------------------------------------------------------------------+ //| エキスパート初期化関数                                   | //+------------------------------------------------------------------+ int OnInit()   {    double inputs[];           // トレーニング入力に使われる空のdouble配列    bool   outputs[];          //トレーニング入力に使われる空のbool配列    int N_TrainingPoints=5000; // 作成されるトレーニングサンプルの数を定義する    int N_TestPoints=5000;     // テストで使われるサンプルの数を定義する    genTrainingData(inputs,outputs,N_TrainingPoints); // svmのトレーニングに使われる入力と出力を生成する    int handle1=initSVMachine();             // 新しいサポートベクターマシンを初期化してハンドルを返す    setInputs(handle1,inputs,7);             // サポートベクターマシンに(エラーなしの)入力を渡す    setOutputs(handle1,outputs);             // サポートベクターマシンに(エラーなしの)出力を渡す    setParameter(handle1,OP_TOLERANCE,0.01); // 許容誤差パラメータを<5%に設定する    training(handle1);                       // 渡された入出力を使ってサポートベクターマシンをトレーニングする    insertRandomErrors(inputs,outputs,500);  // 生成された元の入力/出力を受け取り、データにランダムエラーが追加する    int handle2=initSVMachine();             // 新しいサポートベクターマシンを初期化してハンドルを返す    setInputs(handle2,inputs,7);             // サポートベクターマシンに(エラーなしの)入力を渡す    setOutputs(handle2,outputs);             // サポートベクターマシンに(エラーなしの)出力を渡す    setParameter(handle2,OP_TOLERANCE,0.01); // 許容誤差パラメータを<5%に設定する    training(handle2);                       // 渡された入出力を使ってサポートベクターマシンをトレーニングする    double t1=testSVM(handle1,N_TestPoints); // トレーニングされたサポートベクターマシンの精度をテストしてt1に保存する    double t2=testSVM(handle2,N_TestPoints); // トレーニングされたサポートベクターマシンの精度をテストしてt2に保存する    Print("The SVM accuracy is ",NormalizeDouble(t1,2),"% (using training inputs/outputs without errors)");    Print("The SVM accuracy is ",NormalizeDouble(t2,2),"% (using training inputs/outputs with errors)");    deinitSVMachine(); // メモリリークを回避するために、SVMを生成する際に使用されるメモリのすべてをクリーンアップする    return(0);   } //+------------------------------------------------------------------+ //| エキスパート初期化解除関数                                 | //+------------------------------------------------------------------+ void OnDeinit(const int reason)   { //--- OnDeinit()で関数が実行されない   } //+------------------------------------------------------------------+ //| エキスパートティック関数                                             | //+------------------------------------------------------------------+ void OnTick()   { //--- OnTick()で関数が実行されない      } //+------------------------------------------------------------------+ //| この関数は、観察された動物の観察特性を取り、  //| 選択された基準に基づいて、それがシュニックがあるかどうかの //| true/falseを返す //+------------------------------------------------------------------+ bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call)   {    if(height   < 1000  || height   > 1100)  return(false); //If the height is outside the parameters > return(false)    if(weight   < 40    || weight   > 50)    return(false); //If the weight is outside the parameters > return(false)    if(N_legs   < 8     || N_legs   > 10)    return(false); //If the N_Legs is outside the parameters > return(false)    if(N_eyes   < 3     || N_eyes   > 4)     return(false); //If the N_eyes is outside the parameters > return(false)    if(L_arm    < 400   || L_arm    > 450)   return(false); //If the L_arm  is outside the parameters > return(false)    if(av_speed < 2     || av_speed > 2.5)   return(false); //If the av_speed is outside the parameters > return(false)    if(f_call   < 11000 || f_call   > 15000) return(false); //If the f_call is outside the parameters > return(false)    return(true);                                           //Otherwise > return(true)   } //+------------------------------------------------------------------+ //| この関数は、空のdouble配列とboolean配列を受け取り //| SVMのトレーニングに使用される入力/出力を生成する //+------------------------------------------------------------------+  void genTrainingData(double &inputs[],bool &outputs[],int N)   {    double in[];                    // 生成された入力を一時的に格納するのに使われる                                    // 空のdouble配列を作成する    ArrayResize(in,N_Inputs);       // in[] 配列をN_Inputsにリサイズする    ArrayResize(inputs,N*N_Inputs); // inputs[] 配列を N*N_Inputsにリサイズする    ArrayResize(outputs,N);         // outputs[] 配列を N にリサイズする    for(int i=0;i<N;i++)      {       in[0]=    randBetween(980,1120);    // 高さのためにランダムに生成された入力       in[1]=    randBetween(38,52);       // 重さのためにランダムに生成された入力       in[2]=    randBetween(7,11);        // N_legsのためにランダムに生成された入力       in[3]=    randBetween(3,4.2);       // N_eyesのためにランダムに生成された入力       in[4]=    randBetween(380,450);     // L_armsのためにランダムに生成された入力       in[5]=    randBetween(2,2.6);       // av_speedのためにランダムに生成された入力       in[6]=    randBetween(10500,15500); // f_callのためにランダムに生成された入力       //--- 新しくランダムに生成された入力をトレーニング入力配列にコピーする       ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs);       //--- ランダムな入力を評価し、それがシュニックであるかどうかを判断する       outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]);      }   } //+------------------------------------------------------------------+ //| この関数は、訓練されたSVMのハンドルを取り //| それが新しいランダムな入力をどんなにうまく分類するかをテストする //+------------------------------------------------------------------+  double testSVM(int handle,int N)   {    double in[];    int atrue=0;    int afalse=0;    int N_correct=0;    bool Predicted_Output;    bool Actual_Output;    ArrayResize(in,N_Inputs);    for(int i=0;i<N;i++)      {       in[0]=    randBetween(980,1120);    // 高さのためにランダムに生成された入力       in[1]=    randBetween(38,52);       // 重さのためにランダムに生成された入力       in[2]=    randBetween(7,11);        // N_legsのためにランダムに生成された入力       in[3]=    randBetween(3,4.2);       // N_eyesのためにランダムに生成された入力       in[4]=    randBetween(380,450);     // L_armsのためにランダムに生成された入力       in[5]=    randBetween(2,2.6);       // av_speedのためにランダムに生成された入力       in[6]=    randBetween(10500,15500); // f_callのためにランダムに生成された入力       //--- isItASchnick関数をつかって実際に希望された出力を決定する       Actual_Output=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]);       //--- トレーニングされたSVMを使って予期された出力を返す       Predicted_Output=classify(handle,in);       if(Actual_Output==Predicted_Output)         {          N_correct++; // このステートメントは、予測された出力が正しい回数のカウントを保持する         }      } //--- トレーニングされたSVMの精度を百分率で返す    return(100*((double)N_correct/(double)N));   } //+------------------------------------------------------------------+ //| この関数は、正しいトレーニング入力と出力を生成して  //| データにNつのエラーをランダムに挿入する //+------------------------------------------------------------------+  void insertRandomErrors(double &inputs[],bool &outputs[],int N)   {    int nTrainingPoints=ArraySize(outputs); // トレーニングされたポイントの数を計算する    int index;                              // 新しい整数「index」を生成する    bool randomOutput;                      // 新しい bool 「randomOutput」を生成する    double in[];                            // 生成された入力を一時的に格納するのに使われる                                            // 空のdouble配列を作成する    ArrayResize(in,N_Inputs);               // in[] 配列をN_Inputsにリサイズする    for(int i=0;i<N;i++)      {       in[0]=    randBetween(980,1120);    // 高さのためにランダムに生成された入力       in[1]=    randBetween(38,52);       // 重さのためにランダムに生成された入力       in[2]=    randBetween(7,11);        // N_legsのためにランダムに生成された入力       in[3]=    randBetween(3,4.2);       // N_eyesのためにランダムに生成された入力       in[4]=    randBetween(380,450);     // L_armsのためにランダムに生成された入力       in[5]=    randBetween(2,2.6);       // av_speedのためにランダムに生成された入力       in[6]=    randBetween(10500,15500); // f_callのためにランダムに生成された入力       //--- ランダムエラーを挿入するためトレーニングされた入力のうちの1つを選択する       index=(int)MathRound(randBetween(0,nTrainingPoints-1));       //--- エラーを作成するために使用されるランダムなブール出力を生成する        if(randBetween(0,1)>0.5) randomOutput=true;       else                     randomOutput=false;       //--- 新しくランダムに生成された入力をトレーニング入力配列にコピーする       ArrayCopy(inputs,in,index*N_Inputs,0,N_Inputs);       //--- 新しくランダムに生成された出力をトレーニング出力配列にコピーする       outputs[index]=randomOutput;      }   } //+------------------------------------------------------------------+ //| この関数は、t1とt2との間のランダムな値を作成するために使用される //+------------------------------------------------------------------+  double randBetween(double t1,double t2)   {    return((t2-t1)*((double)MathRand()/(double)32767)+t1);   } //+------------------------------------------------------------------+ 

MetaQuotes Ltdによって英語から翻訳されました。
元のコード: https://www.mql5.com/en/code/1370