English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 クックブック:トリプルスクリーン戦略に基づくトレーディングシステムに対するフレームワーク作成

MQL5 クックブック:トリプルスクリーン戦略に基づくトレーディングシステムに対するフレームワーク作成

MetaTrader 5 | 26 11月 2015, 07:54
749 0
Anatoli Kazharski
Anatoli Kazharski

はじめに

トレーディングシステムの開発を検索するとき、多くのトレーダーは Dr. Alexander Elder博士によって紹介されている「トリプルスクリーン」戦略について聴いたことがあるにちがいありません。インターネットでその戦略に否定的な判定をする人は多くいるものです。しかし数多くの人が収益を得るのにそれが役立つと考えています。その2つの意見のどちらかを信用する必要はありません。すべてはまず確認が必要です。プログラミングを学習しているなら、バックテストによってトレーディング戦略のパフォーマンスを確認することができるので、すべてはあなたの手の中です。

本稿では MQL5で「リプルスクリーン」戦略に基づくトレーディングシステムに対するフレームワークを作成します。Expert Advisor を一から作成することはしません。代わりに、先行記事 "MQL5 Cookbook: Using Indicators to Set Trading Conditions in Expert Advisors" のプログラムを変更するだけとします。よって本稿は既製プログラムのパターンを簡単に変更する方法もお伝えします。

先行記事からの Expert Advisor はすでにストップロス/テイクプロフィット/トレーリングストップレベル、ポジションボリュームの増加、逆シグナルでのポジションリバースを有効/無効にする機能を備えています。必要な関数はすべて所定箇所に設定されています。よってわれわれのタスクはその他オプションの追加と外部関数をいくつか変更することで外部パラメータリストを変更することが中心です。

説明用に移動平均インディケータを用いて作成されるタイムフレーム3種類でシグナルを作成します。そののち、作成したフレームワークで実験を続ける際コードをわずかに変更することでその他あらゆるインディケータを取り入れることができるようになります。また各画面に対しタイムフレームを設定する機能も実装します。インディケータ起案に影響を与えるパラメータがゼロ値であれば、これは対応する画面が使用されないことを表します。すなわち、システムは1~2のタイムフレームを持つように設定することができるのです。

スタート前に先行記事から借用する Expert Advisor のファイルを持つフォルダをコピーし、その名前を変えます。

 

Expert Advisor の作成

それでは外部パラメータから始めましょう。描きは更新済みリストのコードです。新しい行を抜粋します。タイムフレームは列挙タイプ ENUM_TIMEFRAMES を使って宣言されています。ドロップダウンリストから任意のタイムフレームを選択することができます。

//--- External parameters of the Expert Advisor
sinput   long              MagicNumber=777;        // Magic number
sinput   int               Deviation=10;           // Slippage
//---
input    ENUM_TIMEFRAMES   Screen01TimeFrame=PERIOD_W1;  // Time frame of the first screen
input    int               Screen01IndicatorPeriod=14;   // Indicator period of the first screen
//---
input    ENUM_TIMEFRAMES   Screen02TimeFrame=PERIOD_D1;  // Time frame of the second screen
input    int               Screen02IndicatorPeriod=24;   // Indicator period of the second screen
//---
input    ENUM_TIMEFRAMES   Screen03TimeFrame=PERIOD_H4;  // Time frame of the third screen
input    int               Screen03IndicatorPeriod=44;   // Indicator period of the third screen
//---
input    double            Lot=0.1;                      // Lot
input    double            VolumeIncrease=0.1;           // Position volume increase
input    double            VolumeIncreaseStep=10;        // Step for position volume increase
input    double            StopLoss=50;                  // Stop Loss
input    double            TakeProfit=100;               // Take Profit
input    double            TrailingStop=10;              // Trailing Stop
input    bool              Reverse=true;                 // Position reversal
sinput   bool              ShowInfoPanel=true;           // Display of the info panel

IndicatorSegments パラメータは AllowedNumberOfSegments 変数、CorrectInputParameters() 関数と共に例からは除外します。この条件のご興味のある方はご自身で実装してみることができます。またこの Expert Advisor はインディケータを1件だけ採用するためEnums.mqh ファイルのインディケータの列挙も除外します。

それぞれのタイムフレームには個別のインディケータがあるため、各インディケータのハンドルを取得するには個別の変数が必要となります。

//--- Indicator handles
int                  Screen01IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the first screen
int                  Screen02IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the second screen
int                  Screen03IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the third screen

新規バーは最小タイムフレームを用いて確認されます。外部パラメータに最小タイムフレームを設定するとき、一定の順序に従う必要はありません。すなわち最大、中間、最小などです。逆順と基本的に任意の順序でいけます。よって指定の全タイムフレームから最小タイムフレームを特定する関数が必要です。

Expert Advisor は1種類、2種類、3種類のタイムフレームで処理するよう設定することができるため、最小タイムフレームを判断する際すべてのオプションが考慮される必要があります。GetMinimumTimeframe() 関数のコードの場合は以下です。

//+------------------------------------------------------------------+
//| Determining the minimum time frame for the new bar check         |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES GetMinimumTimeframe(ENUM_TIMEFRAMES timeframe1,int period1,
                                    ENUM_TIMEFRAMES timeframe2,int period2,
                                    ENUM_TIMEFRAMES timeframe3,int period3)
  {
//--- Default minimum time frame value
   ENUM_TIMEFRAMES timeframe_min=PERIOD_CURRENT;

//--- Convert time frame values to seconds for calculations
   int t1= PeriodSeconds(timeframe1);
   int t2= PeriodSeconds(timeframe2);
   int t3= PeriodSeconds(timeframe3);

//--- Check for incorrect period values
   if(period1<=0 && period2<=0 && period3<=0)
      return(timeframe_min);

//--- Conditions for a single time frame
   if(period1>0 && period2<=0 && period3<=0)
      return(timeframe1);
   if(period2>0 && period1<=0 && period3<=0)
      return(timeframe2);
   if(period3>0 && period1<=0 && period2<=0)
      return(timeframe3);

//--- Conditions for two time frames
   if(period1>0 && period2>0 && period3<=0)
     {
      timeframe_min=(MathMin(t1,t2)==t1) ? timeframe1 : timeframe2;
      return(timeframe_min);
     }
   if(period1>0 && period3>0 && period2<=0)
     {
      timeframe_min=(MathMin(t1,t3)==t1) ? timeframe1 : timeframe3;
      return(timeframe_min);
     }
   if(period2>0 && period3>0 && period1<=0)
     {
      timeframe_min=(MathMin(t2,t3)==t2) ? timeframe2 : timeframe3;
      return(timeframe_min);
     }

//--- Conditions for three time frames
   if(period1>0 && period2>0 && period3>0)
     {
      timeframe_min=(int)MathMin(t1,t2)==t1 ? timeframe1 : timeframe2;
      int t_min=PeriodSeconds(timeframe_min);
      timeframe_min=(int)MathMin(t_min,t3)==t_min ? timeframe_min : timeframe3;
      return(timeframe_min);
     }
   return(WRONG_VALUE);
  }

最小タイムフレーム値を保存するためにもう一つ別のグローバルスコープ変数を作成します。

//--- Variable for determining the minimum time frame
ENUM_TIMEFRAMES  MinimumTimeframe=WRONG_VALUE;

OnInit() 関数内で Expert Advisor が初期化される場合GetMinimumTimeframe() 関数が呼ばれる必要があります。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }

それからMinimumTimeframe 変数値が関数 CheckNewBar() および GetBarsData() で使用されます。

以下がGetIndicatorHandle() 関数の今の表記です。器官およびタイムフレームが各インディケータに対して指定されています。

//+------------------------------------------------------------------+
//| Getting indicator handles                                        |
//+------------------------------------------------------------------+
void GetIndicatorHandles()
  {
//--- Get handles of the indicators specified in the parameters
   if(Screen01IndicatorPeriod>0)
     Screen01IndicatorHandle=iMA(_Symbol,Screen01TimeFrame,Screen01IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen02IndicatorPeriod>0)
     Screen02IndicatorHandle=iMA(_Symbol,Screen02TimeFrame,Screen02IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen03IndicatorPeriod>0)
     Screen03IndicatorHandle=iMA(_Symbol,Screen03TimeFrame,Screen03IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
     
//--- If the indicator handle for the first time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 1!");
//--- If the indicator handle for the second time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 2!");
//--- If the indicator handle for the third time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 3!");
  }

またインディケータ値を取得するために配列を追加する必要があります(各タイムフレーム値に個別に)。

//--- Arrays for values of the indicators
double               indicator_buffer1[];
double               indicator_buffer2[];
double               indicator_buffer3[];

インディケータ値を取得するため GetIndicatorsData() 関数記述は以下です。取得したハンドルは正確性がチェックされ、すべてが問題なければインディケータ値が配列に書き込まれます。

//+------------------------------------------------------------------+
//| Getting indicator values                                         |
//+------------------------------------------------------------------+
bool GetIndicatorsData()
  {
//--- Number of indicator buffer values for determining the trading signal   
   int NumberOfValues=3;
//--- If indicator handles have not been obtained
   if((Screen01IndicatorPeriod>0 && Screen01IndicatorHandle==INVALID_HANDLE) ||
      (Screen02IndicatorPeriod>0 && Screen02IndicatorHandle==INVALID_HANDLE) ||
      (Screen03IndicatorPeriod>0 && Screen03IndicatorHandle==INVALID_HANDLE))
      //--- try to get them again
      GetIndicatorHandles();

//--- If the time frame of the first screen is used and the indicator handle has been obtained
   if(Screen01TimeFrame>0 && Screen01IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer1,true);
      //--- Get indicator values
      if(CopyBuffer(Screen01IndicatorHandle,0,0,NumberOfValues,indicator_buffer1)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer1 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the second screen is used and the indicator handle has been obtained
   if(Screen02TimeFrame>0 && Screen02IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer2,true);
      //--- Get indicator values
      if(CopyBuffer(Screen02IndicatorHandle,0,0,NumberOfValues,indicator_buffer2)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer2 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the third screen is used and the indicator handle has been obtained
   if(Screen03TimeFrame>0 && Screen03IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer3,true);
      //--- Get indicator values
      if(CopyBuffer(Screen03IndicatorHandle,0,0,NumberOfValues,indicator_buffer3)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer3 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//---
   return(true);
  }

関数 GetTradingSignal() および GetSignal() は対象タスクに応じて変更する必要があります。以下は検討する関数のコードです。

//+------------------------------------------------------------------+
//| Determining trading signals                                      |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetTradingSignal()
  {
//--- If there is no position
   if(!pos.exists)
     {
      //--- A Sell signal
      if(GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      //--- A Buy signal
      if(GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
     }
//--- If the position exists
   if(pos.exists)
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- Get the last deal price
      GetPositionProperties(P_PRICE_LAST_DEAL);

      //--- A Sell signal
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_SELL && 
         close_price[1]<pos.last_deal_price-CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_SELL);

      //--- A Buy signal
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_BUY && 
         close_price[1]>pos.last_deal_price+CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_BUY);

     }
//--- No signal
   return(WRONG_VALUE);
  }

ちょうど最小タイムフレームで決めたように GetSignal() 関数はポジションオープンの条件に関する外部パラメータ状態の可能性ある全変数うを考慮します。以下がその関数コードです。

//+------------------------------------------------------------------+
//| Checking the condition and returning a signal                    |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetSignal()
  {
//--- A SELL SIGNAL: the current value of the indicators on completed bars is lower than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
//---
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2]
         )
         return(ORDER_TYPE_SELL);
     }

//--- A BUY SIGNAL: the current value of the indicators on completed bars is higher than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
     
//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2]
         )
         return(ORDER_TYPE_BUY);
     }
     
//--- No signal
   return(WRONG_VALUE);
  }

ここでは関数 OnInit() および OnDeinit() にちょっとした変更を加えるだけです。加えた変更は下記コードの強調表示箇所で確認できます。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Print the deinitialization reason to the journal
   Print(GetDeinitReasonText(reason));
//--- When deleting from the chart
   if(reason==REASON_REMOVE)
     {
      //--- Delete all objects relating to the info panel from the chart
      DeleteInfoPanel();
      //--- Delete the indicator handles
      IndicatorRelease(Screen01IndicatorHandle);
      IndicatorRelease(Screen02IndicatorHandle);
      IndicatorRelease(Screen03IndicatorHandle);
     }
  } 

トリプルスクリーン戦略に基づくトレーディングシステムに対するフレームワークは準備できました。インディケータを変更するか別の条件を追加するなどして、必要に応じそれはいつでも変更可能です。

 

パラメータの最適化と Expert Advisorの検証

パラメータの最適化に進み、結果を確認します。ストラテジーテスタは以下に示されているように設定します(3種類のタイムフレームで一番低いものをかなラス指定します)。

図1 ストラレジーテスタ設定

図1 ストラレジーテスタ設定

最適化するための Expert Advisor パラメータは以下のように設定済みです。タイムフレームは最適化用に設定されますが、私はマニュアルで設定するのを好みます。

図2 Expert Advisorの設定

図2 Expert Advisorの設定

デュアルコアプロセッサの場合、最適化は約30分で完了します。最適化グラフ は以下に提供されています。

図3 最適化グラフ

図3 最適化グラフ

最大残高検証結果は最大リカバリーファクタ検証結果よりも低いドローダウンを示しています。これは最大残高検証結果がデモ目的で使用されているためです。

図4 最大残高検証結果

図4 最大残高検証結果

図5 最大残高検証グラフ

図5 最大残高検証グラフ

 

おわりに

本稿はメインの関数が利用可能であれば Expert Advisor がひじょうに迅速に変更されることを実践的に示しました。シグナルブロックとインディケータを変更するだけで新しいトレーディングシステムを手に入れることができるのです。本稿にはみなさんの自習用に本稿に述べられているExpert Advisor のコードを持つダウンロードできるアーカイブが添付されています。また入力パラメータ設定のある設定ファイルも添付されています。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/647

添付されたファイル |
Expert Advisor パラメータのユーザーパネルからの『オンザフライ』の変更 Expert Advisor パラメータのユーザーパネルからの『オンザフライ』の変更
本稿ではパラメータをユーザーパネルから管理できる Expert Advisor の実装を示すちょっとした例を提供します。『オンザフライ』でパラメータを変更するとき、Expert Advisor はのちにファイルから読み込みパネル上で適切に表示するために情報パネルからファイルに取得した値を書きます。本稿はマニュアルでトレードを行う方または半自動モードでトレードを行う方に適しているでしょう。
MQL5 クックブック: マルチ通貨 Expert Advisor - シンプル、かしこい、迅速なアプローチ MQL5 クックブック: マルチ通貨 Expert Advisor - シンプル、かしこい、迅速なアプローチ
本稿ではマルチ通貨 Expert Advisorに適切なシンプルなアプローチの実装について述べます。これは理想的な条件下でありながら各シンボルに対して異なるパラメータでExpert Advisor を検証/トレーディングする設定を可能にするということです。例として2個のシンボルに対するパターンを作成しますが、コードに少し変更を加えるだけで必要に応じてそれ以外のシンボルも追加できるようにしておきます。
MQL5 クックブック:Expert Advisorsにトレード条件を設定するためのインディケータ利用 MQL5 クックブック:Expert Advisorsにトレード条件を設定するためのインディケータ利用
本稿では MQL5 クックブックシリーズの先行記事をとおして作業をおこなってきているExpert Advisorの修正を続行します。今回は、Expert Advisor は値がポジションオープンの条件を確認するのに使用されるインディケータを使って強化されます。それに一点添えるために、外部パラメータにドロップダウンリストを作成し、3つのトレードインディケータの中から1つを選ぶことができるようにします。
MQL5 クックブック:パラメータ数無制限での複数通貨対応 EXPERT 作成 MQL5 クックブック:パラメータ数無制限での複数通貨対応 EXPERT 作成
本稿ではトレーディングシステムの最適化に対して一組のパラメータを使うパターンを作成していきます。同時にパラメータ数は無制限に認めます。シンボルリストは標準的なテキストファイル (*.txt)内に作成します。各シンボルに対する入力パラメータもファイルに格納されます。このように Expert Advisorの入力パラメータ数に関してターミナルの制約を回避することができます。