English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 クックブック:ポジションプロパティを取得するためのディール履歴と関数ライブラリ

MQL5 クックブック:ポジションプロパティを取得するためのディール履歴と関数ライブラリ

MetaTrader 5 | 26 11月 2015, 09:45
1 841 0
Anatoli Kazharski
Anatoli Kazharski

はじめに

ポジションプロパティについて先行記事で提供されている情報を簡単にまとめます。本稿では、ディールヒストリーにアクセスした後にのみ取得可能なプロパティを得る関数を数個追加して作成します。また便利な方法でポジションやシンボルプロパティにアクセスできるようにするデータストラクチャについても知識を得ます。

存在する限りポジションボリュームが変わらないトレーディングシステムは実は本稿で提供される関数の使用は必要としません。ただもっと後の段階で資金管理システムの実装とトレーディング戦略でポジションロットサイズの管理を計画しているなら、これら関数は外せません。

始める前に本稿へのリンクをたどってきた読者の方、本ウェブサイトを初めて訪問するかMQL5 言語の学習を始めたばかりという場合には『MQL5クックブックシリーズ』の先行記事から始めることを提案します。


Expert Advisor の作成

先行記事"MQL5 Cookbook: How to Avoid Errors When Setting/Modifying Trade Levels"で変更した Expert Advisor の新しい関数の処理を確認するには、ポジションがすでに存在しながら、オープンのシグナルが再び発生する場合にポジションボリュームを増やす機能を追加します。

ポジション履歴には複数のディールがあるかもしれません。トレード中にポジションボリュームに変更が生じるようなら、現ポジション価格にも変更が行われるはずです。最初のエントリーポイント価格を見つけるためにはその指定ポジションに関するディール履歴にアクセスする必要があります。下図はポジションだけが1件のディール(エントリーポイント)を持つ場合を示しています。

図1 ポジションにおける最初のディール

図1 ポジションにおける最初のディール

次の図は二番目のディールに続くポジション価格の変化を示しています。

図2 ポジションにおける2番目のディール

図2 ポジションにおける2番目のディール

先行記事で示しているように、標準識別子によって現ポジション価格(POSITION_PRICE_OPEN)およびポジションがオープンしているあるシンボルの現在価格(POSITION_PRICE_CURRENT)のみ取得可能です。

ただしトレーディングシステムの中には最初のエントリーポイントからの価格による距離、最後のディールの価格を知る必要があります。これら情報はすべてディール/オーダーのアカウント履歴で入手可能です。以下は前出の図に関するディールリストです。

図3 アカウントのディールヒストリー

図3 アカウントのディールヒストリー

これで状況は明確で目標は設定されたと思います。先行記事で取り上げられた Expert Advisor の変更を続けます。まずポジションプロパティの列挙に 0、6、9、12、16と番号付けされた新しい識別子を追加します。

//--- Enumeration of position properties
enum ENUM_POSITION_PROPERTIES
  {
   P_TOTAL_DEALS     = 0,
   P_SYMBOL          = 1,
   P_MAGIC           = 2,
   P_COMMENT         = 3,
   P_SWAP            = 4,
   P_COMMISSION      = 5,
   P_PRICE_FIRST_DEAL= 6,
   P_PRICE_OPEN      = 7,
   P_PRICE_CURRENT   = 8,
   P_PRICE_LAST_DEAL = 9,
   P_PROFIT          = 10,
   P_VOLUME          = 11,
   P_INITIAL_VOLUME  = 12,
   P_SL              = 13,
   P_TP              = 14,
   P_TIME            = 15,
   P_DURATION        = 16,
   P_ID              = 17,
   P_TYPE            = 18,
   P_ALL             = 19
  };

各プロパティに対するコメントはもう少し下で検討するストラクチャに付けられます。

外部パラメータの数を増やします。これで以下を指定することができます。

  • MagicNumber -Expert Advisor のユニーク ID (マジックナンバー)
  • Deviation -スリッページ
  • VolumeIncrease -ポジションボリュームが増やされるポジション値
  • InfoPanel -情報パネルの表示を有効化/無効化することのできるパラメータ

以下はその実装方法です。

//--- External parameters of the Expert Advisor
sinput   long        MagicNumber=777;     // Magic number
sinput   int         Deviation=10;        // Slippage
input    int         NumberOfBars=2;      // Number of Bullish/Bearish bars for a Buy/Sell
input    double      Lot=0.1;             // Lot
input    double      VolumeIncrease=0.1;  // 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

sinput 修飾子が設定されたパラメータに注意してください。この修飾子はストラレジーテスタの最適化の無効を可能にします。実際、自己使用のためのプログラムを開発する際、どのパラメータが最終結果に影響を与えるか完璧に理解しています。そのためみなさんはただ最適化からチェックを外すのです。ただひじょうに大きな数のパラメータとなると、この方法ではそれらがグレー表示されるため視覚的にそれらをその他から分離することができます。

図4 最適化から無効化されるパラメータはグレー表示されます

図4 最適化から無効化されるパラメータはグレー表示されます。

ポジションとシンボルプロパティ値を格納するグローバル変数をデータストラクチャ(struct)と置き換えます。

//--- Position properties
struct position_properties
  {
   uint              total_deals;      // Number of deals
   bool              exists;           // Flag of presence/absence of an open position
   string            symbol;           // Symbol
   long              magic;            // Magic number
   string            comment;          // Comment
   double            swap;             // Swap
   double            commission;       // Commission   
   double            first_deal_price; // Price of the first deal in the position
   double            price;            // Current position price
   double            current_price;    // Current price of the position symbol      
   double            last_deal_price;  // Price of the last deal in the position
   double            profit;           // Profit/Loss of the position
   double            volume;           // Current position volume
   double            initial_volume;   // Initial position volume
   double            sl;               // Stop Loss of the position
   double            tp;               // Take Profit of the position
   datetime          time;             // Position opening time
   ulong             duration;         // Position duration in seconds
   long              id;               // Position identifier
   ENUM_POSITION_TYPE type;            // Position type
  };
//--- Symbol properties
struct symbol_properties
  {
   int               digits;        // Number of decimal places in the price
   int               spread;        // Spread in points
   int               stops_level;   // Stops level
   double            point;         // Point value
   double            ask;           // Ask price
   double            bid;           // Bid price
   double            volume_min;    // Minimum volume for a deal
   double            volume_max;    // Maximum volume for a deal
   double            volume_limit;  // Maximum permissible volume for a position and orders in one direction
   double            volume_step;   // Minimum volume change step for a deal
   double            offset;        // Offset from the maximum possible price for a transaction
   double            up_level;      // Upper Stop level price
   double            down_level;    // Lower Stop level price
  }

ここで、ストラクチャの特定エレメントにアクセスするため、このストラクチャタイプの変数を作成する必要があります。手順は記事 "MQL5 Cookbook: Analyzing Position Properties in the MetaTrader 5 Strategy Tester"で考察されているトレードクラス用オブジェクトの作成に似ています。

//--- variables for position and symbol properties
position_properties  pos;
symbol_properties    symb;

クラスメソッドを処理するときと同じ方法でエレメントにアクセスすることができます。すなわち、その特定のストラクチャ内のエレメントリストを表示するためにストラクチャ変数名の後にドットと1個入れるだけです。これはひじょうに便利です。1行コメントがストラクチャフィールドに与えられている場合(われわれの例のように)、それらは右側のツールチップに表示されます。

図5a ポジションプロパティ用ストラクチャフィールドリスト 図5b シンボルプロパティ用ストラクチャフィールドリスト

図5 ストラクチャフィールドリスト

もう一つ重要なポイントです。Expert Advisorの変更において、実質的に多くの関数で使用されるグローバル変数をすべて変更しました。よってここではそれらをシンボルおよびポジションプロパティの対応するストラクチャフィールドと置き換える必要があります。たとえば、オープンポジションの在/不在のフラグを格納するのに使用したグローバル変数pos_openposition_properties ストラクチャタイプのexistsフィールドと置き換えられました。よってpos_open 変数が使用されるときはいつでもpos.existsと置き換えられる必要があります。

マニュアルでしなけらばならないと長く疲れるプロセスです。よって MetaEditor 機能を利用してこのタスクに対するソリューションを自動化するのが良いでしょう。編集 メニューまたはキーの組合せCtrl+H から検索と置換 -> 地検と進みます。


図6 テキストの検索と置換

図6 テキストの検索と置換

ファイルをコンパイルしたら、のちに検証を行うためシンボルおよびポジションプロパティに対するグローバル変数をすべて検索し置き換える必要があります。エラーが検出されなけらば、すべてが正しく行われたということです。本稿が不必要に長くならないようにここでコードは表示しません。また既製のソースコードが本稿末尾でダウンロード可能です。

変数について整理できたところで、既存の関数を修正し新しい関数を作成していきます。

外部パラメータではこれでマジックナンバーとポイント表示のスリッページを設定することができます。また Expert Advisorのコードに適切な変更を加える必要があります。ユーザー定義の補助関数 OpenPosition()を作成します。ここにポジションオープンのオーダーを送信する前に CTrade クラスの関数を用いてプロパティをセットします。

//+------------------------------------------------------------------+
//| Opening a position                                               |
//+------------------------------------------------------------------+
void OpenPosition(double lot,
                  ENUM_ORDER_TYPE order_type,
                  double price,
                  double sl,
                  double tp,
                  string comment)
  {
   trade.SetExpertMagicNumber(MagicNumber); // Set the magic number in the trading structure
   trade.SetDeviationInPoints(CorrectValueBySymbolDigits(Deviation)); // Set the slippage in points
//--- If the position failed to open, print the relevant message
   if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment))
     { Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError())); }
  }

Expert Advisor のメインのトレード関数-TradingBlock()のコードに少し変更を加えるだけです。以下は変更が施された関数コードの一部です。

//--- If there is no position
   if(!pos.exists)
     {
      //--- Adjust the volume
      lot=CalculateLot(Lot);
      //--- Open a position
      OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
     }
//--- If there is a position
   else
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- If the position is opposite to the signal and the position reversal is enabled
      if(pos.type==opposite_position_type && Reverse)
        {
         //--- Get the position volume
         GetPositionProperties(P_VOLUME);
         //--- Adjust the volume
         lot=pos.volume+CalculateLot(Lot);
         //--- Reverse the position
         OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
         return;
        }
      //--- If the signal is in the direction of the position and the volume increase is enabled, increase the position volume
      if(!(pos.type==opposite_position_type) && VolumeIncrease>0)
        {
         //--- Get the Stop Loss of the current position
         GetPositionProperties(P_SL);
         //--- Get the Take Profit of the current position
         GetPositionProperties(P_TP);
         //--- Adjust the volume
         lot=CalculateLot(Increase);
         //--- Increase the position volume
         OpenPosition(lot,order_type,position_open_price,pos.sl,pos.tp,comment);
         return;
        }

上記コードは現行ポジションの方向がシグナル方向に対してチェックされるブロックによって強化されました。その方向が一致しており、ポジションボリューム増加が外部パラメータ(VolumeIncreaseパラメータ値がゼロより大きい)可能であれば、既定のロットを確認/調整し、適切なオーダーを送信します。ここでオーダーのオープンまたはクローズ送信、あるいはポジションボリュームを増やすために必要なことはすべてコードの1行に書き込みます。

ディールの履歴からポジションプロパティを取得するための関数を作成します。現行ポジションでディール番号を返す関数 CurrentPositionTotalDeals() から始めます。

//+------------------------------------------------------------------+
//| Returning the number of deals in the current position            |
//+------------------------------------------------------------------+
uint CurrentPositionTotalDeals()
  {
   int    total       =0;  // Total deals in the selected history list
   int    count       =0;  // Counter of deals by the position symbol
   string deal_symbol =""; // symbol of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
            //--- If the symbol of the deal and the current symbol are the same, increase the counter
            if(deal_symbol==_Symbol)
               count++;
        }
     }
//---
   return(count);
  }

上記コードにはかなり詳細なコメントが付けられています。ただ履歴の選択方法について少し解説が必要です。われわれの場合、HistorySelect() 関数を使用してオープン時刻によって決められる現在ポジションのオープン時点から現在時点までのリストを取得しました。履歴が選択されたら、 HistoryDealsTotal() 関数を用いてリスト上のディール数を見つけ出すことができます。その他はコメントから明らかでしょう。

特定ポジションの履歴は HistorySelectByPosition() を用いるとその識別子でも選択することができます。ここでポジション識別子はポジションが逆転しても変わらないことに配慮が必要です。それは Expert Advisorで時々起ることです。ただしポジションオープン時刻は逆転で変わり、そのためこのバリアントは実装がより簡単です。ですが現在オープンしているポジションに対してのみディールヒストリーが適用しなければ、識別子を使う必要があります。今後の記事でディールヒストリーの話題に戻りたいと思います。

ポジションの最初のディール価格、すなわちポジションがオープンしているときのディール価格を返す関数CurrentPositionFirstDealPrice() を作成を続けます。

//+------------------------------------------------------------------+
//| Returning the price of the first deal in the current position    |
//+------------------------------------------------------------------+
double CurrentPositionFirstDealPrice()
  {
   int      total       =0;    // Total deals in the selected history list
   string   deal_symbol ="";   // symbol of the deal
   double   deal_price  =0.0;  // Price of the deal
   datetime deal_time   =NULL; // Time of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- Get the time of the deal
         deal_time=(datetime)HistoryDealGetInteger(HistoryDealGetTicket(i),DEAL_TIME);
         //--- If the time of the deal equals the position opening time, 
         //    and if the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_time==pos.time && deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

ここでの原則は前出の関数のときと同じです。ポジションがオープンしている点からヒストリーを取得し、それからディール時刻と各反復でポジションオープンの時刻を確認します。ディール価格とともにシンボル名とディール時刻も取得します。一番最初のディールはディール時刻がポジションオープン時刻に一致するとき特定されます。その価格がすでに適切な変数に割り当てられているため必要なことは値を返すだけです。

先に進みます。現ポジションの最終ディール価格を取得することが必要なこともあります。このためには CurrentPositionLastDealPrice() 関数を作成します。

//+------------------------------------------------------------------+
//| Returning the price of the last deal in the current position     |
//+------------------------------------------------------------------+
double CurrentPositionLastDealPrice()
  {
   int    total       =0;   // Total deals in the selected history list
   string deal_symbol ="";  // Symbol of the deal 
   double deal_price  =0.0; // Price
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- If the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

今回、ループはリストにある最終ディールで始まり、よくあるのは必要なディールがループの最初の反復で特定されるというものです。ですが複数シンボルでトレードをするなら、ループはディールシンボルが現シンボルに一致するまでループを続けます。

現ポジションボリュームは標準識別子 POSITION_VOLUME を用いて取得することができます。最初のポジションボリューム(1番目のディールのボリューム)を見つけるには CurrentPositionInitialVolume() 関数を作成します。

//+------------------------------------------------------------------+
//| Returning the initial volume of the current position             |
//+------------------------------------------------------------------+
double CurrentPositionInitialVolume()
  {
   int             total       =0;           // Total deals in the selected history list
   ulong           ticket      =0;           // Ticket of the deal
   ENUM_DEAL_ENTRY deal_entry  =WRONG_VALUE; // Position modification method
   bool            inout       =false;       // Flag of position reversal
   double          sum_volume  =0.0;         // Counter of the aggregate volume of all deals, except for the first one
   double          deal_volume =0.0;         // Volume of the deal
   string          deal_symbol ="";          // Symbol of the deal 
   datetime        deal_time   =NULL;        // Deal execution time
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- If the order ticket by its position is obtained, then...
         if((ticket=HistoryDealGetTicket(i))>0)
           {
            //--- Get the volume of the deal
            deal_volume=HistoryDealGetDouble(ticket,DEAL_VOLUME);
            //--- Get the position modification method
            deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY);
            //--- Get the deal execution time
            deal_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(ticket,DEAL_SYMBOL);
            //--- When the deal execution time is less than or equal to the position opening time, exit the loop
            if(deal_time<=pos.time)
               break;
            //--- otherwise calculate the aggregate volume of deals by the position symbol, except for the first one
            if(deal_symbol==_Symbol)
               sum_volume+=deal_volume;
           }
        }
     }
//--- If the position modification method is a reversal
   if(deal_entry==DEAL_ENTRY_INOUT)
     {
      //--- If the position volume has been increased/decreased
      //    I.e. the number of deals is more than one
      if(fabs(sum_volume)>0)
        {
         //--- Current volume minus the volume of all deals except for the first one
         double result=pos.volume-sum_volume;
         //--- If the resulting value is greater than zero, return the result, otherwise return the current position volume         
         deal_volume=result>0 ? result : pos.volume;
        }
      //--- If there are no more deals, other than the entry,
      if(sum_volume==0)
         deal_volume=pos.volume; // return the current position volume
     }
//--- Return the initial position volume
   return(NormalizeDouble(deal_volume,2));
  }

この関数はその前の関数よりも複雑に表現されています。私は誤った値になる状況として可能なものすべてを考慮するようにしてきました。注意深い検証により問題は何も出ませんでした。コードにつけられている詳細コメントは重要事項を理解するのに役立つはずです。

ポジション継続時間を返す関数も便利です。ユーザーが秒、分、時間、日など戻り値の適切なフォーマットを選択できるように作成します。このためもう一つ別の列挙を作成します。

//--- Position duration
enum ENUM_POSITION_DURATION
  {
   DAYS     = 0, // Days
   HOURS    = 1, // Hours
   MINUTES  = 2, // Minutes
   SECONDS  = 3  // Seconds
  };

以下は適切な計算をすべて行う関数 CurrentPositionDuration() のコードです。

//+------------------------------------------------------------------+
//| Returning the duration of the current position                   |
//+------------------------------------------------------------------+
ulong CurrentPositionDuration(ENUM_POSITION_DURATION mode)
  {
   ulong     result=0;   // End result
   ulong     seconds=0;  // Number of seconds
//--- Calculate the position duration in seconds
   seconds=TimeCurrent()-pos.time;
//---
   switch(mode)
     {
      case DAYS      : result=seconds/(60*60*24);   break; // Calculate the number of days
      case HOURS     : result=seconds/(60*60);      break; // Calculate the number of hours
      case MINUTES   : result=seconds/60;           break; // Calculate the number of minutes
      case SECONDS   : result=seconds;              break; // No calculations (number of seconds)
      //---
      default        :
         Print(__FUNCTION__,"(): Unknown duration mode passed!");
         return(0);
     }
//--- Return result
   return(result);
  }

ではポジションプロパティが表示される情報パネルについての関数 CurrentPositionDurationToString() を作成します。この関数は秒で表されているポジション継続時間をユーザーが理解しやすいフォーマットに変換します。秒数は関数に渡され、関数は日数、時間数、分、秒でポジション継続時間を持つ文字列を返します。

//+------------------------------------------------------------------+
//| Converting the position duration to a string                     |
//+------------------------------------------------------------------+
string CurrentPositionDurationToString(ulong time)
  {
//--- A dash if there is no position
   string result="-";
//--- If the position exists
   if(pos.exists)
     {
      //--- Variables for calculation results
      ulong days=0;
      ulong hours=0;
      ulong minutes=0;
      ulong seconds=0;
      //--- 
      seconds=time%60;
      time/=60;
      //---
      minutes=time%60;
      time/=60;
      //---
      hours=time%24;
      time/=24;
      //---
      days=time;
      //--- Generate a string in the specified format DD:HH:MM:SS
      result=StringFormat("%02u d: %02u h : %02u m : %02u s",days,hours,minutes,seconds);
     }
//--- Return result
   return(result);
  }

これですべて準備が整いました。上記の変更すべてに従って修正が必要な関数 GetPositionProperties() および GetPropertyValue() は提供しません。シリーズの先行記事をお読みになればご自身でこれを行うのは難しくないはずです。いずれにせよソースコードファイルは本稿に添付されています。

結果、情報パネルは以下のように表示されます。

図7 情報パネル上の全ポジションプロパティ表示

図7 情報パネル上の全ポジションプロパティ表示

これでポジションプロパティを取得するための関数ライブラリを取得しました。続きは必要に応じて今後の記事にゆだねることとなるでしょう。


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

実験的に Expert Advisorのパラメータを最適化してみましょう。今入手したものはまだ完全に機能するトレーディングシステムとは言えませんが、達成する結果は何かについてわれわれの目を開けてくれ、トレーディングシステム開発者としての経験を高めてくれることでしょう。

ストラテジーテスタの設定は以下のように行います。

図8 パラメータ最適化のためのストラテジーテスタ設定

図8 パラメータを最適化のためのストラテジーテスタ設定

Expert Advisor の外部パラメータ設定は以下のようなものとなります。

図9 最適化のためのExpert Advisor のパラメータ設定

図9 最適化のためのExpert Advisor のパラメータ設定

最適化に続き最大リカバリーファクターによりアーカイブされた結果をソートします。

図10 最大リカバリーファクターによりソートされた結果

図10 最大リカバリーファクターによりソートされた結果

リカバリーファクター値が4.07であるパラメータの一番上のセットを検証します。最適化は EURUSDに対して行われましたが、多くのシンボルにたいして結果はポジティブであることが確認できます。

EURUSDに対する結果

図11 EURUSDに対する結果

図11 EURUSDに対する結果

AUDUSDに対する結果

図12 AUDUSDに対する結果

図12 AUDUSDに対する結果

NZDUSDに対する結果

図13 NZDUSDに対する結果

図13 NZDUSDに対する結果


おわりに

実際どのような考えも作成し強化することが可能です。トレーディングシステムは不良品として却下する前にどれもひじょうに注意深く検証する必要があります。後の記事でほとんどあらゆるトレーディングシステムをカスタマイズしそこに取り入れるひじょうに役立つさまざまなメカニズムとスキームを見ていくつもりです。

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

添付されたファイル |
MQL5 Cookbook:トレードレベルを設定/変更する際エラーを避ける方法 MQL5 Cookbook:トレードレベルを設定/変更する際エラーを避ける方法
シリーズの前稿 "MQL5 Cookbook: Analyzing Position Properties in the MetaTrader 5 Strategy Tester" からの Expert Advisor への取り組みの続編として、既存の関数を改良、最適化しつつ有用な関数を数多く用いて Expert Advisor を強化していきます。今回 Expert Advisor は MetaTrader 5 「ストラテジーテスタ」で最適化可能な外部パラメータを取得し、いくつかの点でシンプルなトレーディングシステムのようになります。
MQL5 クックブック:Expert Advisorsにトレード条件を設定するためのインディケータ利用 MQL5 クックブック:Expert Advisorsにトレード条件を設定するためのインディケータ利用
本稿では MQL5 クックブックシリーズの先行記事をとおして作業をおこなってきているExpert Advisorの修正を続行します。今回は、Expert Advisor は値がポジションオープンの条件を確認するのに使用されるインディケータを使って強化されます。それに一点添えるために、外部パラメータにドロップダウンリストを作成し、3つのトレードインディケータの中から1つを選ぶことができるようにします。
MQL5 クックブック:MetaTrader 5 ストラレジーテスタでの position プロパティ分析 MQL5 クックブック:MetaTrader 5 ストラレジーテスタでの position プロパティ分析
先行記事 "MQL5 Cookbook: Position Properties on the Custom Info Panel"の Expert Advisor の変更バージョンを提供します。お伝えする問題の中にはバーからのデータ取得、現シンボルにおける新規バーイベント確認、ファイルに標準ライブラリのトレードクラスのインクルード、トレード処理実行用トレードシグナルおよび関数検索のための関数作成、OnTrade() 関数におけるトレードイベント決定などがあります。
Expert Advisor パラメータのユーザーパネルからの『オンザフライ』の変更 Expert Advisor パラメータのユーザーパネルからの『オンザフライ』の変更
本稿ではパラメータをユーザーパネルから管理できる Expert Advisor の実装を示すちょっとした例を提供します。『オンザフライ』でパラメータを変更するとき、Expert Advisor はのちにファイルから読み込みパネル上で適切に表示するために情報パネルからファイルに取得した値を書きます。本稿はマニュアルでトレードを行う方または半自動モードでトレードを行う方に適しているでしょう。