有望なシグナルの自動選択

Alexander Fedosov | 12 2月, 2018


イントロダクション

金融相場での自動トレードは、相場が絶えず変化しているため、新しいトレーディングロボットの開発は究極的な目標です。 しかし、自動トレーディングEAは、相場でのすべての状況に対応することはできません。 したがって、最も効果的な方法は、トレーディングロボットの複数使用と、自動システムに対する人間の制御です。 このような相互作用の良い例は、トレーディングシグナルサービスにあります。 このサービスは、さまざまなリスクパラメータまたはトレーディングダイナミクスを持つトレーディングシステムとメソッドの選択ができます。 多くのツールにより、ユーザーが望むシグナルを見つけることができます。 しかし、今回のタスクは、異なるトレードスタイルに適合するパラメータのセットを決定することです。 簡便的な解決策は、トレードシグナルパラメータのセットと、適度で保守的なトレーディングスタイルに適した値を決定することです。

トレードシグナル評価モデル

トレーディングシグナルの総合的な評価に、5つの評価基準があります。 各々は、0が危険なトレードスタイルを意味し、20は保守的なトレードを意味し、20点のスケールのシステム上で分配されています。 合計で、各トレードシグナルは100ポイントで評価されます。 トレードシグナルの特性は評価に使用されます。

1) トレード口座のレバレッジ

ご存じのように、より高いレバレッジは、価格の急激なスパイクの際には資産の大半を失う高いリスクを意味します。 20ポイントシステムの次の値は、レバレッジ評価に使用されます。 

  • 20 ポイントは、 1:1のレバレッジに与えられます。
  • 0 ポイントは、 1:500 以上のレバレッジに与えられます。

レバレッジ値に基づいてシグナルを評価するには、次の直線の式を使用します。

ただし、Xa = 1、 Ya = 20、および、 Xb = 500 およびYb = 0。 2つの点を通る直線の方程式です。 今回の場合では、この方程式は、現在のレバレッジの値に20ポイントのスケールでのスコアの依存性を反映しています。 

この依存性は0から20までの指定された評価範囲に対してのみ有効であることに注意してください。 使用されているレバレッジが 1:500 (たとえば 1:1000) を上回っている場合でも、そのスコアは0になることを意味します。

2) アカウントの増加率 (%)

20点システムに従ってこのパラメータを評価するには、2つの要素を考慮に入れる必要があります。 まず、成長がマイナスになることがあります。 さらに、その絶対値を比較することは正しくありません。 したがって、次のルールと仮定になります。

  • 負の損益は、シグナルが現在危険にさらされていることを意味しますので、0が与えられます。
  • 絶対的な成長を評価するのではなく、時間の経過とともに、アカウントの成長をシグナルの有効期間に週で分割することで、そのダイナミクスを測定します。
  • リスクは主観的な概念です。 10% の週の成長は、トレーダーに十分ではないかもしれないですが、またある人にとってはの良い成長かもしれません。 ただし、一定の範囲を設定する必要があります。 したがって、1% の成長は、保守的なシグナルの基準成長として使用され、15% はリスクの高いトレードのしきい値として設定されます。

ここでも、 Xa = 1、 Ya = 20、およびXb = 15 とYb = 0 の2つの点を通じて、上記の直線の式を使用します。 次の依存性が得られます。

3) % での最大ドローダウン。

この値は、トレーディングリスクを直接特徴付けるものです。 次のルールを使用して、制限値を決定してみましょう。

  • 最大 20% までのドローダウンは、保守的なトレードスタイルと見なされます。 そのスコアは20に等しくなります。
  • 40% 以上のドローダウン値は危険と見なされ、0ポイントが与えられます。
  • 最大ドローダウンの 20-40% の間隔は、2つの前の点に基づいて直線の方程式から評価されます。  

この式では、 Xa = 20、 Ya = 20、 Xb = 40、 Yb = 0 です。 次の依存性が得られます。

4) パーセント単位のROI (投資収益率)

100% の上の投資のリターンは資金の有効な使用を意味します。;100% 以下の値は、投資が有効でないことを意味します。 20点のスケールに従って、成功のこのインジケーターを評価してみましょう。

  • 100% 以下の ROI は0ポイントを与えられます。
  • 200% 以上の ROI は、20ポイントを与えられます。
  • 100-200 の間隔は、2つの前の点に基づいて直線の方程式から評価されます。

この式では、 Xa = 100、 Ya = 0、 Xb = 200 およびYb = 20 です。 次の依存性が得られます。

5) トレーディングシグナルの有効期間

このライフタイムは、シグナルが主に正しくトレードされているかどうかを示す、非常に重要な特性です。 20点スケールで評価するには、まず、信頼性と検証される時間の量を決定します。 1週間は、測定の単位として使用される、すでに成長の評価に週を使用します。 個々の特性であることに注意してください。 誰もが信頼性の特定の時間基準を持つことができます. システムには以下のしきい値を使用します。

  • 4週間 (1 ヶ月の完全な週の数) の下のライフタイムのシグナルは0ポイントを与えられます。
  • 25週の上のライフタイム (6 か月の完全な週の数) は25ポイントを与えられます。
  • 4〜25週間の間隔は、上記の2つの点によって設定された直線の式に従って評価されます。  


シグナル評価ツールの実装

アイデアを実装するためにグラフィカルインターフェイス EasyandFastGUI のライブラリを使います。 アプリケーションの構造は、図1a と 図1b (下記参照) に示されています。 次の要素で構成されています。

  • ターミナル内の現在のアカウントで使用可能なシグナルのテーブル。
  • カテゴリ別にテーブルで選択されたシグナルの詳細な評価。
  • 現在のアカウントで使用可能なトレードシグナルの数。
  • テーブルで選択されたトレードシグナルのビジュアル集計スコア。


図1a アプリケーションの構造 (左の部分)

重みづけとして表される集計評価では、左の部分 (赤色) が不利なシグナルを反映しており、緑の部分は潜在的に有望と思われるシグナルを示しているわけではありません。 特定のトレードシグナルのトレードスタイルの可視化をします。 危険なトレードは損失の高い可能性を意味しますが、同時に、高い収益性を意味します。


図1b アプリケーションの構造 (右辺)

プログラムの実装では、アプリケーションの本質を反映する主要なメソッドにこだわりましょう。 最初のメソッドはCreateGUI()であり、他のすべてのメソッドのアセンブリであり、ビジュアル情報の表示をします。

  • CreateWindow()メソッドは、ヘッダーを使用してアプリケーションのウィンドウを作成します。 閉じて最小化することができます。
  • CreateTable ()は、現在のアカウントで使用可能なすべてのシグナルを含むテーブルを作成します。
  • CreateStatusBar()メソッドは、利用可能なトレードシグナルの合計数を示すステータスバーを作成します。
  • CreatePicture1 ()CreatePicture2 ()は、それぞれスケールのグラデーションスケールとポインタを作成します。
  • CreateTextLabel ()メソッドは、選択したトレードシグナルの評価に関する詳細情報の表示を設定します。
  • CreateButton ()メソッドは、テーブルで選択されたシグナルをサブスクライブするためのボタンを作成します。
//+------------------------------------------------------------------+
//プログラムのグラフィカルインターフェイスを作成します。                    |
//+------------------------------------------------------------------+
boolCProgram:: CreateGUI (void)
  {
//パネルの作成---
   if(!CreateWindow("Auto Search Signal"))
      return(false);
//テーブルの作成---
   if(!CreateTable(7,100))
      return(false);
//---ステータスバー
   if(!CreateStatusBar(1,26))
      return(false);
//---画像
   if(!CreatePicture1(618,40))
      return(false);
   if(!CreatePicture2(610,80))
      return(false);
//---テキストラベル
   if(!CreateTextLabel1(20,20,"Leverage score: -"))
      return(false);
   if(!CreateTextLabel2(20,40,"Growth score: -"))
      return(false);
   if(!CreateTextLabel3(20,60,"Drawdown score: -"))
      return(false);
   if(!CreateTextLabel4(200,20,"ROI score: -"))
      return(false);
   if(!CreateTextLabel5(200,40,"Lifetime score: -"))
      return(false);
//---アイコンボタン
   if(!CreateButton(440,40,"Subscribe"))
      return(false);
//---GUI の作成を完了する
   CWndEvents::CompletedGUI();
   return(true);
  }
//+-----------------------------------------------------------------


次のメソッドは、インタラクションを担当します。テーブル内のリストからのトレードシグナルの選択と、そのシグナルに関する情報の表示をします。 また、作成したボタンをクリックし、テーブルで選択したシグナルをサブスクライブするイベントもします。

//+------------------------------------------------------------------+
//イベントハンドラ                                                     |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//リストまたはテーブルの項目を押す
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LIST_ITEM)
     {
      int x=610+3*int(m_table.GetValue(9,m_table.SelectedItem()));
      //---
      CreateTextLabel1(20,20,"Leverage score: "+IntegerToString(GetLeverageRating(int(m_table.GetValue(2,m_table.SelectedItem())))));
      CreateTextLabel2(20,40,"Growth score: "+IntegerToString(GetGainRating(int(m_table.GetValue(3,m_table.SelectedItem())),int(m_table.GetValue(8,m_table.SelectedItem())))));
      CreateTextLabel3(20,60,"Drawdown score: "+IntegerToString(GetDrawDownRating(int(m_table.GetValue(5,m_table.SelectedItem())))));
      CreateTextLabel4(200,20,"ROI score: "+IntegerToString(GetROIRating(int(m_table.GetValue(4,m_table.SelectedItem())))));
      CreateTextLabel5(200,40,"Lifetime score: "+IntegerToString(GetWeeksRating(int(m_table.GetValue(8,m_table.SelectedItem())))));
      CreatePicture2(x,80);
      //---
      m_button.IsLocked(false);
      Update(true);
     }
//---
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //ボタンが押されている場合
      if(lparam==m_button.Id())
        {
         SignalSubscribe(long(m_table.GetValue(6,m_table.SelectedItem())));
        }
     }
  }

次に、トレーディングシグナルの評価を実装するメソッドを考えてみましょう。 まず、現在のアカウントで利用可能なトレードシグナルのリストと、テーブルに追加する必要な情報を取得し、合計評価のコンパイルに使用する必要があります。

GetTradingSignals ()メソッドは、使用可能なトレードシグナルに関する情報を取得し、データ配列に追加します。

//+------------------------------------------------------------------+
//利用可能なトレードシグナルに関する情報の受信                             |
//+------------------------------------------------------------------+
boolCProgram:: GetTradingSignals (void)
  {
//シグナルデータベース内のシグナルの合計数をリクエスト 
   m_signals_total=SignalBaseTotal();
//---
   ArrayResize(m_name,m_signals_total);
   ArrayResize(m_curr,m_signals_total);
   ArrayResize(m_leverage,m_signals_total);
   ArrayResize(m_gain,m_signals_total);
   ArrayResize(m_roi,m_signals_total);
   ArrayResize(m_max_drawdown,m_signals_total);
   ArrayResize(m_pips,m_signals_total);
   ArrayResize(m_subscr,m_signals_total);
   ArrayResize(m_weeks,m_signals_total);
   ArrayResize(m_rating,m_signals_total);
//すべてのシグナルをループ 
   for(int i=0;i<m_signals_total;i++)
     {
      //以上の操作のシグナルを選ぶ--- 
      if(SignalBaseSelect(i))
        {
         //---受信シグナルのプロパティ 
         m_name[i]=SignalBaseGetString(SIGNAL_BASE_NAME);                                                //シグナルの名前
         m_curr[i]=SignalBaseGetString(SIGNAL_BASE_CURRENCY);                                            //シグナルの通貨
         m_leverage[i]=SignalBaseGetInteger(SIGNAL_BASE_LEVERAGE);                                       //レバレッジ
         m_gain[i]=SignalBaseGetDouble(SIGNAL_BASE_GAIN);                                                //% でのアカウントの増加
         m_roi[i]=SignalBaseGetDouble(SIGNAL_BASE_ROI);                                                  //ROI
         m_max_drawdown[i]=SignalBaseGetDouble(SIGNAL_BASE_MAX_DRAWDOWN);                                //最大ドローダウン
         m_id[i]=SignalBaseGetInteger(SIGNAL_BASE_ID);                                                   //シグナル ID
         m_subscr[i]=SignalBaseGetInteger(SIGNAL_BASE_SUBSCRIBERS);                                      //購読者数
         m_weeks[i]=int((TimeCurrent()-SignalBaseGetInteger(SIGNAL_BASE_DATE_PUBLISHED))/3600/24/7);     //シグナルの有効期間
         //合計評価を受け取る
         m_rating[i]=GetLeverageRating(m_leverage[i])+GetGainRating(m_gain[i],m_weeks[i])+GetDrawDownRating(m_max_drawdown[i])+GetROIRating(m_roi[i])+GetWeeksRating(m_weeks[i]);
        }
      else
        {
         PrintFormat("Signal selection error. Error code=%d",GetLastError());
         return(false);
        }
     }
   return (true);
  }
//+------------------------------------------------------------------+


上記の一覧でわかるようにm_rating [] は配列で、各トレードシグナルの結果の評価が追加されます。 したがって、この計算で使用されるメソッドについて考えてみましょう。 これらのメソッドは、この記事の最初のパートからモデルのプログラムの実装です。

//+------------------------------------------------------------------+
//トレーディングレバレッジの評価                                         |
//+------------------------------------------------------------------+
int CProgram::GetLeverageRating(long leverage)
  {
   int lev_rating=int(-20.0/499.0*double(leverage)+10000.0/499.0);
   lev_rating=(lev_rating>20)?20:lev_rating;
   return lev_rating;
  }
//+------------------------------------------------------------------+
//成長の評価                                                          |
//+------------------------------------------------------------------+
int CProgram::GetGainRating(double gain,int weeks)
  {
   weeks=(weeks==0)?1:weeks;
   int gain_rating=int(-10*(gain/double(weeks)/7.0)+150.0/7.0);
   gain_rating=(gain_rating>20)?20:gain_rating;
   gain_rating=(gain_rating<0)?0:gain_rating;
   gain_rating=(gain<0)?0:gain_rating;
   return gain_rating;
  }
//+------------------------------------------------------------------+
//最大ドローダウンの評価                                                |
//+------------------------------------------------------------------+
int CProgram::GetDrawDownRating(double max_drawdown)
  {
   int drawdn_rating=int(-max_drawdown+40);
   drawdn_rating=(drawdn_rating>20)?20:drawdn_rating;
   drawdn_rating=(drawdn_rating<0)?0:drawdn_rating;
   return drawdn_rating;
  }
//+------------------------------------------------------------------+
//ROI の評価                                                          |
//+------------------------------------------------------------------+
int CProgram::GetROIRating(double roi)
  {
   int roi_rating=int(0.2*roi-20);
   roi_rating=(roi_rating>20)?20:roi_rating;
   roi_rating=(roi_rating<0)?0:roi_rating;
   return roi_rating;
  }
//+------------------------------------------------------------------+
//トレーディングシグナルの有効期間の評価                                  |
//+------------------------------------------------------------------+
int CProgram::GetWeeksRating(int weeks)
  {
   int age_rating=int(20.0*double(weeks)/21.0-80.0/21.0);
   age_rating=(age_rating>20)?20:age_rating;
   age_rating=(age_rating<0)?0:age_rating;
   return age_rating;
  }

次に、取得したすべてのデータがInitializingTable ()メソッドを使用してテーブルに追加され、 CreateTable ()メソッドを使用して視覚的に表示されます。

//+------------------------------------------------------------------+
//テーブルの初期化                                                     |
//+------------------------------------------------------------------+
void CProgram::InitializingTable(void)
  {
//---
   string columns[10]=
     {
      "Signal name",
      "Account currency",
      "Account leverage",
      "Account growth, %",
      "ROI",
      "Max drawdown",
      "Signal ID",
      "Number of subscribers",
      "Lifetime, weeks",
      "Rating"
     };
//---
   for(int c=0; c<COLUMNS1_TOTAL; c++)
     {
      //ヘッダータイトルを設定
      m_table.SetHeaderText(c,columns[c]);
      //---
      for(int r=0; r<m_signals_total; r++)
        {
         if(c==0)
            m_table.SetValue(c,r,m_name[r]);
         else if(c==1)
            m_table.SetValue(c,r,m_curr[r]);
         else if(c==2)
            m_table.SetValue(c,r,IntegerToString(m_leverage[r]));
         else if(c==3)
            m_table.SetValue(c,r,DoubleToString(m_gain[r],2));
         else if(c==4)
            m_table.SetValue(c,r,DoubleToString(m_roi[r],2));
         else if(c==5)
            m_table.SetValue(c,r,DoubleToString(m_max_drawdown[r],2));
         else if(c==6)
            m_table.SetValue(c,r,IntegerToString(m_id[r]));
         else if(c==7)
            m_table.SetValue(c,r,IntegerToString(m_subscr[r]));
         else if(c==8)
            m_table.SetValue(c,r,IntegerToString(m_weeks[r]));
         else if(c==9)
            m_table.SetValue(c,r,IntegerToString(m_rating[r]));
        }
     }
  }
//+------------------------------------------------------------------+
//レンダリングされたテーブルの作成                                       |
//+------------------------------------------------------------------+
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_up.bmp」
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_down.bmp」
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp16\\circle_gray.bmp」
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp16\\calendar.bmp」
//---
boolCProgram:: CreateTable (const int x_gap、const int y_gap)
  {
#defineCOLUMNS1_TOTAL 10
//メインコントロールへのポインタの格納
   m_table.MainPointer(m_window);
//列の幅の配列
   int width[COLUMNS1_TOTAL];
   ::ArrayInitialize(width,110);
   width[1]=80;
   width[2]=100;
   width[4]=90;
   width[8]=85;
   width[9]=90;
//列の X 軸に沿ったテキストオフセットの配列
   int text_x_offset[COLUMNS1_TOTAL];
   ::ArrayInitialize(text_x_offset,7);
//列内のテキスト配置の配列
   ENUM_ALIGN_MODE align[COLUMNS1_TOTAL];
   ::ArrayInitialize(align,ALIGN_CENTER);
//---
   GetTradingSignals();
//プロパティ
   m_table.XSize(1000);
   m_table.YSize(470);
   m_table.CellYSize(20);
   m_table.TableSize(COLUMNS1_TOTAL,m_signals_total);
   m_table.TextAlign(align);
   m_table.ColumnsWidth(width);
   m_table.TextXOffset(text_x_offset);
   m_table.LabelXGap(5);
   m_table.LabelYGap(4);
   m_table.IconXGap(7);
   m_table.IconYGap(4);
   m_table.MinColumnWidth(0);
   m_table.ShowHeaders(true);
   m_table.IsSortMode(true);
   m_table.LightsHover(true);
   m_table.SelectableRow(true);
   m_table.IsWithoutDeselect(true);
   m_table.ColumnResizeMode(true);
   m_table.IsZebraFormatRows(clrWhiteSmoke);
   m_table.AutoXResizeMode(true);
   m_table.AutoXResizeRightOffset(7);
   m_table.AutoYResizeBottomOffset(28);
   m_table.HeadersColor(clrSkyBlue);
   m_table.DataType(2,TYPE_INT);
   m_table.DataType(3,TYPE_FLOAT);
   m_table.DataType(4,TYPE_FLOAT);
   m_table.DataType(5,TYPE_FLOAT);
   m_table.DataType(6,TYPE_INT);
   m_table.DataType(7,TYPE_INT);
   m_table.DataType(8,TYPE_INT);
   m_table.DataType(9,TYPE_INT);

//テーブルにデータを読み込む
   InitializingTable();
//コントロールの作成
   if(!m_table.CreateTable(x_gap,y_gap))
      return(false);
//オブジェクトグループの共通配列にオブジェクトを追加---
   CWndContainer::AddToElementsArray(0,m_table);
   m_table.SortData(9);
   m_table.SortData(9);
   return(true);
  }

トレードシグナルのテーブルのデータをより便利に使用するには、表示されるセルのデータ型を割り当てる必要があります。 これでテーブル列内のデータの適切な並べ替えが可能になります。 より視覚的に表示されるように、テーブルは最初の列 (つまり、複雑なシグナルの評価によって降順) で並べ替えられます。並べ替えは2回実行されます: 最初の並べ替えは降順、2番目と次の並べ替えは、前のものとは逆のオーダーで実行されます。

最後の要素は、グラデーションスケールとへのポインターの形で最終評価の視覚的な表示です。 これは、2つのメソッドによって行われ、リストは以下に提供されます。 スケール上のポインターの位置の変更は、上記のOnEvent ()メソッドで既に示されています。

//+------------------------------------------------------------------+
//グラデーションスケールを作成                                           |
//+------------------------------------------------------------------+
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp64\\000.bmp」
#resource「\\Images\\EasyAndFastGUI\\Controls\\ArrowUp_blue.bmp」
//---
boolCProgram:: CreatePicture1 (const int x_gap、const int y_gap)
  {
//メインコントロールへのポインタの格納
   m_picture1.MainPointer(m_window);
//プロパティ
   m_picture1.XSize(300);
   m_picture1.YSize(40);
   m_picture1.IconFile("Images\\EasyAndFastGUI\\Icons\\bmp64\\000.bmp");
//ボタンの作成
   if(!m_picture1.CreatePicture(x_gap,y_gap))
      return(false);
//要素へのポインターをベースに追加
   CWndContainer::AddToElementsArray(0,m_picture1);
   return(true);
  }
//+------------------------------------------------------------------+
//スケールのポインタを作成                                              |
//+------------------------------------------------------------------+
boolCProgram:: CreatePicture2 (const int x_gap、const int y_gap)
  {
//メインコントロールへのポインタの格納
   m_picture2.MainPointer(m_window);
//プロパティ
   m_picture2.XSize(16);
   m_picture2.YSize(16);
   m_picture2.IconFile("Images\\EasyAndFastGUI\\Controls\\ArrowUp_blue.bmp");
//ボタンの作成
   if(!m_picture2.CreatePicture(x_gap,y_gap))
      return(false);
//要素へのポインターをベースに追加
   CWndContainer::AddToElementsArray(0,m_picture2);
   return(true);
  }


潜在的に有望なシグナルの選択

シグナルを選択し、その見通しを決定するとき、将来に一定の結果をもたらす良いシグナルを期待します。 テストでは、短い期間で高い成長率を示すシグナルが長生きしないことを示しています。 これは、この手のシグナルが高い利益を得るためにハイリスクのトレーディングスタイルを使用するためです。 にもかかわらず、トレーダーが異なる目標を持っている可能性があるため、リストからハイリスクのトレーディングスタイルのトレードシグナルを削除しないでください。 あるトレーダーは、長い時間に相場に滞在し、ゆっくりと稼ぐ計画かもしれません。 またあるトレーダーは、短期間で利益を出す計画かもしれません。 

そこで、上記評価システムを3つのカテゴリーに分けて視覚的に分類します (図2)。

  • 最初のカテゴリ。 レッドゾーン。 このゾーンからのシグナルは高い収益性がありますが、高いリスクを伴います。
  • 2 番目のカテゴリ。 イエローゾーン。 このシグナルは適度なリスクがあり適度な収益性を示します。
  • 3 番目のカテゴリ。 グリーンゾーン。 シグナルは高い信頼性を示すため、収益性が高くなることはありませんが、長期的に有望であると考えられています。

図2. トレーディングシグナル評価尺度の分類

この分類をプログラムするには、 InitializingTable ()メソッドに次の行を追加します。

//+------------------------------------------------------------------+
//テーブルの初期化                                                     |
//+------------------------------------------------------------------+
void CProgram::InitializingTable(void)
  {
//---
   string columns[10]=
     {
      "Signal name",
      "Account currency",
      "Account leverage",
      "Account growth, %",
      "ROI",
      "Max drawdown",
      "Signal ID",
      "Number of subscribers",
      "Lifetime, weeks",
      "Rating"
     };
//---
   for(int c=0; c<COLUMNS1_TOTAL; c++)
     {
      //ヘッダータイトルを設定
      m_table.SetHeaderText(c,columns[c]);

      //---
      for(int r=0; r<m_signals_total; r++)
        {
         if(c==0)
           {
            m_table.SetValue(c,r,m_name[r]);
            if(m_rating[r]<=30)
               m_table.TextColor(c,r,clrCrimson);
            else if(m_rating[r]>30 && m_rating[r]<=66)
               m_table.TextColor(c,r,clrOrange);
            else if(m_rating[r]>66)
               m_table.TextColor(c,r,clrForestGreen);
           }
         else if(c==1)
            m_table.SetValue(c,r,m_curr[r]);
         else if(c==2)
            m_table.SetValue(c,r,IntegerToString(m_leverage[r]));
         else if(c==3)
            m_table.SetValue(c,r,DoubleToString(m_gain[r],2));
         else if(c==4)
            m_table.SetValue(c,r,DoubleToString(m_roi[r],2));
         else if(c==5)
            m_table.SetValue(c,r,DoubleToString(m_max_drawdown[r],2));
         else if(c==6)
            m_table.SetValue(c,r,IntegerToString(m_id[r]));
         else if(c==7)
            m_table.SetValue(c,r,IntegerToString(m_subscr[r]));
         else if(c==8)
            m_table.SetValue(c,r,IntegerToString(m_weeks[r]));
         else if(c==9)
            m_table.SetValue(c,r,IntegerToString(m_rating[r]));
        }
     }
  }

受信したレーティングに基づいて、 TextColor ()メソッドを使用してトレードシグナル名 (最初の列) の色を変更します。 したがって、評価値を含むテーブルの最後の列をチェックせずに、シグナルが属しているカテゴリを見ることが可能です。

図3 トレーディングシグナルの色表示

シグナルは、最後の列でテーブルを並べ替えることによってカテゴリに分類できます。 この並べ替えはデフォルトで有効になっています。 最後は、シグナルをサブスクライブする機会を実装することです。 CreateButton ()メソッドを使用して実行できます。

//+------------------------------------------------------------------+
//画像ボタンを作成                                                     |
//+------------------------------------------------------------------+
#resource「\\Images\\EasyAndFastGUI\\Icons\\bmp16\\start.bmp」
//---
bool CProgram::CreateButton(const int x_gap,const int y_gap,const string text)
  {
//メインコントロールへのポインタの格納
   m_button.MainPointer(m_window);
//プロパティ
   m_button.XSize(120);
   m_button.YSize(22);
   m_button.IconXGap(3);
   m_button.IconYGap(3);
   m_button.FontSize(10);
   m_button.IsCenterText(true);
   m_button.IconFile("Images\\EasyAndFastGUI\\Icons\\bmp16\\start.bmp");
   m_button.IsLocked(true);
//コントロールの作成
   if(!m_button.CreateButton(text,x_gap,y_gap))
      return(false);
//要素へのポインターをベースに追加
   CWndContainer::AddToElementsArray(0,m_button);
   return(true);
  }
//+------------------------------------------------------------------+


上記で開発された関数のエラーを回避するために、ターミナルの事前設定が必要であることを確認してみましょう。

1. ターミナルでトレードシグナルを処理するには、MetaTrader5 で MQL5 アカウントを使用してログインする必要があります。

図4ターミナルでの認証

2. アプリケーションを起動するときに、[シグナル設定の変更を許可する] オプションを有効にします。 こうしないと、このアプリケーションを使用したトレードシグナルへのサブスクリプションは、エラー 4014 ("関数は呼び出しを許可されていません") を返します。

図5アプリケーション開始時の構成

3. そして、アプリケーションの正しい操作に影響を与えることができる最後は、signal .datファイルです。 テーブル内のデータが正しく表示されないか、まったく表示されない場合は、C:\Users\Computer name\AppData\Roaming\MetaQuotes\Terminal\.. でこのファイルを見つける必要があります。\bases\signals を削除します。 次に、ターミナルを再起動し、図6に示すように [シグナル] タブを開きます。 新しいファイルが自動的に生成され、その後、アプリケーションを起動して使用することができます。

図6 MetaTrader5ターミナルの [シグナル] タブ

ウェブサイトのシグナルサービスのようなすべてのシグナルを表示する代わりに、ターミナルのシグナルセクションには、現在選択されているトレーディングアカウントでのタスクに適したシグナルのみが表示されます。 


結論

本稿では, 異なるシグナルの特性に対して与えられたポイントに基づく評価シグナルのシステムを開発しました。 このシステムは、トレーディングスタイルを100点で評価します。 この評価に基づいて、すべての利用可能なシグナルは、トレード口座の見通し、トレードリスク、ライフタイムとパーセンテージの成長のポイントで3つのカテゴリーに分けられました。

添付されたアーカイブには、該当するフォルダにあるすべてのファイルがあります。 これを行うには、 MQL5フォルダをターミナルルートディレクトリに保存するだけです。 このアプリは、関連する記事からグラフィックインターフェイスライブラリEasyAndFastGUIを使用します。 ライブラリは若干変更されており、この記事にも添付されています。

記事で使用されるプログラム:

#
 名前
タイプ
詳細
1
AutoSearch.mq5 EA
 有望なシグナルの自動選択のアプリケーション
2
Program.mqh コードベース  アプリケーション作成用のクラス
3
MainWindow.mqh コードベース  アプリケーションの作成に使用されるメソッドのセット