English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 Cookbook:カスタム情報パネル上のポジションプロパティ

MQL5 Cookbook:カスタム情報パネル上のポジションプロパティ

MetaTrader 5 | 26 11月 2015, 14:14
737 0
Anatoli Kazharski
Anatoli Kazharski

はじめに

今回は、現在シンボルについてポジションプロパティを取得し、マニュアルトレーディングの間カスタム情報パネルにそのポジションプロパティを表示するシンプルな Expert Advisor を作成します。情報パネルはグラフィカルオブジェクトを用いて作成され、表示される情報はティック毎にリフレッシュされます。これは "MQL5 Cookbook: Getting Position Properties"と呼ばれるシリーズの以前の記事に記載があるスクリプトをつねにマニュアルで実行しなければならないのよりはるかに便利になります。

 

Expert Advisorの開発

グラフィカルオブジェクトから始めます。情報パネル作成には、背景用のオブジェクト、ヘッダ、名前、ポジションプロパティの値が必要です。背景およびヘッダには価格とともに移動しない長方形が必要です。その長方形は長方形ラベルまたは編集のようなグラフィカルオブジェクトを用いて作成可能です。また名前とオブジェクトプロパティの値はテキストレベルを用いて作成されます。

そのコードについての作業を進める前に、まず情報パネルのレイアウトを準備します。設定ウィンドウ内のプロパティはすべてすばやく変更することが可能で、情報パネルの外観はカスタマイズすることができるためそれは好都合です。

各オブジェクトは選択したオブジェクトのコンテクストメニューから開くことのできる設定ウィンドウを持ちます。設定ウィンドウはまた必要なオブジェクトを選択しプロパティをクリックすることでオブジェクトリスト (Ctrl+B) から開くこともできます。以下が情報パネルのレイアウトです。それはコードを書く際サイズと座標を推定するのにも利用可能です。情報パネル用コードが準備できたら、レイアウトオブジェクトをマニュアルで削除する必要があります。というのも Expert Advisor はそれらを「見る」ことができないため、チャートから消去することができないのです。

図1 情報パネル用レイアウトの準備

図1 情報パネル用レイアウトの準備

ここでExpert Advisor用テンプレートを作成する必要があります。スクリプトに対すると同じくらいすばやく作成することができます。MQL5 ウィザードではデフォルトでExpert Advisor (テンプレート)オプションが選択されています。オプションに対しては変更をまったく加えず次のステップをすべて行います。今回は変更の必要がないからです。そして「終了」をクリックすると、以下のようなテンプレートが表示されます。

//+------------------------------------------------------------------+
//|                                      PositionPropertiesPanel.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+

Expert Advisor のテンプレートはスクリプトテンプレートとは異なることにすぐに気づきます。プログラムプロパティ(#property)とは別に、主要な関数が3個あります。:OnInit()、OnDeinit()、OnTick()です。

OnInit() 関数はプログラムをロード、外部パラメータを変更、プログラムをコンパイル、プログラムがそのときチャートに追加されるならシンボルや期間を変更するときに呼ばれます。必要ならば、のちに連携することができるようにこの関数の特定の変数や配列を初期化することができます。

OnDeinit() 関数はチャートからプログラムを削除するとき、アカウント、シンボル、期間を変更するときに呼ばれます。再初期化理由となる可能性のあるものはすべて MQL5 参照資料にあります。この Expert Advisor はユーザー定義関数GetDeinitReasonText() を採用します。これは再初期化理由識別子( OnDeinit()関数パラメータ)をテキストに変換します。

そして最後にOnTick() 関数です。これは Expert Advisor が現在開いているチャートのシンボル上に新規ティックが出現するたびに呼ばれます。

ここで、Expert Advisorで使用していく定数、編集、配列をすべて準備します。それらをプログラムの冒頭に置きます。まず、プログラムをとおして値が変更しない変数を定義します。

//---
#define INFOPANEL_SIZE 14 // Size of the array for info panel objects
#define EXPERT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) // Name of the Expert Advisor
//---

続いてポジションプロパティに対するグローバル変数を定義します。

//--- GLOBAL VARIABLES
bool                 pos_open=false;         // Flag of presence/absence of an open position
string               pos_symbol="";          // Symbol
long                 pos_magic=0;            // Magic number
string               pos_comment="";         // Comment
double               pos_swap=0.0;           // Swap
double               pos_commission=0.0;     // Commission
double               pos_price=0.0;          // Position price
double               pos_cprice=0.0;         // Current price of the position
double               pos_profit=0.0;         // Profit/Loss of the position
double               pos_volume=0.0;         // Position volume
double               pos_sl=0.0;             // Stop Loss of the position
double               pos_tp=0.0;             // Take Profit of the position
datetime             pos_time=NULL;          // Position opening time
long                 pos_id=0;               // Position identifier
ENUM_POSITION_TYPE   pos_type=WRONG_VALUE;   // Position type

変数のあと、グラフィカルオブジェクト名の配列を宣言します。これらオブジェクトはポジションプロパティとその値をチャート上に表示します。このため、文字列配列を2つ作成し、すぐに値に対してそのエレメントを初期化します。カギカッコ内でプログラム冒頭で宣言した定数 INFOPANEL_SIZE の値を使用します。そうすると、各配列にはエレメントが14あることになります。

// Array of names of objects that display names of position properties
string positionPropertyNames[INFOPANEL_SIZE]=
  {
   "name_pos_symbol",
   "name_pos_magic",
   "name_pos_comment",
   "name_pos_swap",
   "name_pos_commission",
   "name_pos_price",
   "name_pos_cprice",
   "name_pos_profit",
   "name_pos_volume",
   "name_pos_sl",
   "name_pos_tp",
   "name_pos_time",
   "name_pos_id",
   "name_pos_type"
  };
//---
// Array of names of objects that display values of position properties
string positionPropertyValues[INFOPANEL_SIZE]=
  {
   "value_pos_symbol",
   "value_pos_magic",
   "value_pos_comment",
   "value_pos_swap",
   "value_pos_commission",
   "value_pos_price",
   "value_pos_cprice",
   "value_pos_profit",
   "value_pos_volume",
   "value_pos_sl",
   "value_pos_tp",
   "value_pos_time",
   "value_pos_id",
   "value_pos_type"
  };
//---

これら名前を使用し、プログラムによりチャートに必要なオブジェクトを見つけ、表示されるテキスト、色、サイズなどのプロパティを設定または変更します。また、これら名前はチャート上に作成されたのち、オブジェクトリスト (Ctrl+B) ウィンドウに表示されます。ただし、そこにそれらを見ることはできません。なぜなら MQL5 プログラムによって作成されるオブジェクトはデフォルトでは非表示となっているためです。それらを表示するにはオブジェクトリストウィンドウの全リストをクリックします。マニュアルで作成したオブジェクトを確実にひじょうに便利なプログラムが作成したオブジェクトと区別するのにこの機能が役立ちます。

さらにグラフィカルオブジェクトを作成するために Expert Advisor が採用するユーザー定義関数が必要となります。グラフィカルオブジェクトを作成するために MQL5 が提供する関数は ObjectCreate()です。またオブジェクトプロパティの設定も必要なので、オブジェクト自体が複数回作成される一方で、コード1行に実装することのできる便利で手軽な方法を考える方がよいでしょう。

情報パネルの背景とヘッダを作成するにはグラフィカルオブジェクト編集を使用していきます。まずCreateEdit() 関数を書きます。

//+------------------------------------------------------------------+
//| CREATING THE EDIT OBJECT                                         |
//+------------------------------------------------------------------+
void CreateEdit(long             chart_id,         // chart id
                int              sub_window,       // (sub)window number
                string           name,             // object name
                string           text,             // displayed text
                ENUM_BASE_CORNER corner,           // chart corner
                string           font_name,        // font
                int              font_size,        // font size
                color            font_color,       // font color
                int              x_size,           // width
                int              y_size,           // height
                int              x_distance,       // X-coordinate
                int              y_distance,       // Y-coordinate
                long             z_order,          // Z-order
                color            background_color, // background color
                bool             read_only)        // Read Only flag
  {
// If the object has been created successfully,...
   if(ObjectCreate(chart_id,name,OBJ_EDIT,sub_window,0,0))
     {
      // ...set its properties
      ObjectSetString(chart_id,name,OBJPROP_TEXT,text);                 // displayed text
      ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner);            // set the chart corner
      ObjectSetString(chart_id,name,OBJPROP_FONT,font_name);            // set the font
      ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size);       // set the font size
      ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color);         // font color
      ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,background_color); // background color
      ObjectSetInteger(chart_id,name,OBJPROP_XSIZE,x_size);             // width
      ObjectSetInteger(chart_id,name,OBJPROP_YSIZE,y_size);             // height
      ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance);     // set the X coordinate
      ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance);     // set the Y coordinate
      ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);         // cannot select the object if FALSE
      ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order);           // Z-order of the object
      ObjectSetInteger(chart_id,name,OBJPROP_READONLY,read_only);       // Read Only
      ObjectSetInteger(chart_id,name,OBJPROP_ALIGN,ALIGN_LEFT);         // align left
      ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n");              // no tooltip if "\n"
     }
  }

これでグラフィカルオブジェクト編集 (OBJ_EDIT)はコード1行を用いて作成することができます。チャート上に情報パネルを設定する関数を作成する際例を用いて説明します。

これからポジションプロパティのリストおよびその値を表示するのに使うテキストラベルオブジェクトの作業を続け、同様の方法で CreateLabel() 関数を作成します。

//+------------------------------------------------------------------+
//| CREATING THE LABEL OBJECT                                        |
//+------------------------------------------------------------------+
void CreateLabel(long               chart_id,   // chart id
                 int                sub_window, // (sub)window number
                 string             name,       // object name
                 string             text,       // displayed text
                 ENUM_ANCHOR_POINT  anchor,     // anchor point
                 ENUM_BASE_CORNER   corner,     // chart corner
                 string             font_name,  // font
                 int                font_size,  // font size
                 color              font_color, // font color
                 int                x_distance, // X-coordinate
                 int                y_distance, // Y-coordinate
                 long               z_order)    // Z-order
  {
// If the object has been created successfully,...
   if(ObjectCreate(chart_id,name,OBJ_LABEL,sub_window,0,0))
     {
      // ...set its properties
      ObjectSetString(chart_id,name,OBJPROP_TEXT,text);              // displayed text
      ObjectSetString(chart_id,name,OBJPROP_FONT,font_name);         // set the font
      ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color);      // set the font color
      ObjectSetInteger(chart_id,name,OBJPROP_ANCHOR,anchor);         // set the anchor point
      ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner);         // set the chart corner
      ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size);    // set the font size
      ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance);  // set the X-coordinate
      ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance);  // set the Y-coordinate
      ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);      // cannot select the object if FALSE
      ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order);        // Z-order of the object
      ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n");           // no tooltip if "\n"
     }
  }

MQL5 参照資料で関数に目を通すことをお薦めします。

チャートから削除されると Expert Advisor は次に以前にチャートに追加したオブジェクトをすべて削除する必要があります。このためにはただDeleteObjectByName() 関数にそのオブジェクト名を渡すだけです。そうするとそれは指定の名前でオブジェクトを検索し、見つかれば、それを削除します。その際、オブジェクトを検索する内蔵の ObjectFind() 関数とオブジェクトを削除する ObjectDelete() 関数を使用します。

//+------------------------------------------------------------------+
//| DELETING THE OBJECT BY NAME                                      |
//+------------------------------------------------------------------+
void DeleteObjectByname(string name)
  {
   int  sub_window=0;      // Returns the number of the subwindow where the object is located
   bool res       =false;  // Result following an attempt to delete the object
//--- Find the object by name
   sub_window=ObjectFind(ChartID(),name);
//---
   if(sub_window>=0) // If it has been found,..
     {
      res=ObjectDelete(ChartID(),name); // ...delete it
      //---
      // If an error occurred when deleting the object,..
      if(!res) // ...print the relevant message
        {
         Print("Error deleting the object: ("+IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
        }
     }
  }

その後DeleteObjectByName() 関数ではまたオブジェクト削除時のエラー確認を実装します。エラーが発生するとエラーコードと記述を持つ適切なメッセージが表示されます。上記コードに見られるように、エラーコードとテキスト記述に変換するもうひとつのユーザー定義関数を使用します。それが ErrorDescription() 関数です。エラーコードは数多くあるので、この関数の一部(以下のコードを参照ください)のみ使用して上に例示しました。完全なコードは本稿添付のソースコードファイルで確認可能です。

//+------------------------------------------------------------------+
//| RETURNING THE ERROR DESCRIPTION                                  |
//+------------------------------------------------------------------+
string ErrorDescription(int error_code)
  {
   string error_string="";
//---
   switch(error_code)
     {
      //--- Trade server return codes

      case 10004: error_string="Requote";                                                                break;
      case 10006: error_string="Request rejected";                                                       break;
      case 10007: error_string="Request canceled by trader";                                             break;
      case 10008: error_string="Order placed";                                                           break;
      case 10009: error_string="Request executed";                                                       break;
      case 10010: error_string="Request executed partially";                                             break;
      case 10011: error_string="Request processing error";                                               break;
      case 10012: error_string="Request timed out";                                                      break;
      case 10013: error_string="Invalid request";                                                        break;
      case 10014: error_string="Invalid request volume";                                                 break;
      case 10015: error_string="Invalid request price";                                                  break;
      case 10016: error_string="Invalid Stop orders in the request";                                     break;
      case 10017: error_string="Trading forbidden";                                                      break;
      case 10018: error_string="Market is closed";                                                       break;
      case 10019: error_string="Insufficient funds";                                                     break;
      case 10020: error_string="Prices changed";                                                         break;
      case 10021: error_string="No quotes to process the request";                                       break;
      case 10022: error_string="Invalid order expiration in the request";                                break;
      case 10023: error_string="Order status changed";                                                   break;
      case 10024: error_string="Too many requests";                                                      break;
      case 10025: error_string="No changes in the request";                                              break;
      case 10026: error_string="Automated trading is disabled by trader";                                break;
      case 10027: error_string="Automated trading is disabled by the client terminal";                   break;
      case 10028: error_string="Request blocked for processing";                                         break;
      case 10029: error_string="Order or position frozen";                                               break;
      case 10030: error_string="The specified type of order execution by balance is not supported";      break;
      case 10031: error_string="No connection with trade server";                                        break;
      case 10032: error_string="Transaction is allowed for live accounts only";                          break;
      case 10033: error_string="You have reached the maximum number of pending orders";                  break;
      case 10034: error_string="You have reached the maximum order and position volume for this symbol"; break;

      ...

     }
//---
   return(error_string);
  }

前稿ではポジションプロパティを取得する GetPositionProperties() 関数を取り上げました。今回は関数のストラクチャはそれよりもやや複雑になります。現在オープンとなっているポジションを確認します。それにはグローバル変数 pos_openに格納されているオープンポジションの在/不在のフラグを使います。この情報は別の関数で必要とされる可能性があります。毎回 PositionSelect() 関数を呼ぶ必要はありません。

そしてオープンポジションがあれば、そのプロパティを取得します。なければ全変数はゼロ設定となります。シンプルなZeroPositionProperties() 関数を書きます。

//+------------------------------------------------------------------+
//| ZEROING OUT VARIABLES FOR POSITION PROPERTIES                    |
//+------------------------------------------------------------------+
void ZeroPositionProperties()
  {
   pos_symbol     ="";
   pos_comment    ="";
   pos_magic      =0;
   pos_price      =0.0;
   pos_cprice     =0.0;
   pos_sl         =0.0;
   pos_tp         =0.0;
   pos_type       =WRONG_VALUE;
   pos_volume     =0.0;
   pos_commission =0.0;
   pos_swap       =0.0;
   pos_profit     =0.0;
   pos_time       =NULL;
   pos_id         =0;
  }

その上 GetPositionProperties() 関数の末尾では、チャート上の情報パネルを描画/更新するユーザー定義関数 SetInfoPanel() を呼びます。

//+------------------------------------------------------------------+
//| GETTING POSITION PROPERTIES                                      |
//+------------------------------------------------------------------+
void GetPositionProperties()
  {
// Check if there is an open position
   pos_open=PositionSelect(_Symbol);
//---
   if(pos_open) // If an open position exists, get its properties
     {
      pos_symbol     =PositionGetString(POSITION_SYMBOL);
      pos_comment    =PositionGetString(POSITION_COMMENT);
      pos_magic      =PositionGetInteger(POSITION_MAGIC);
      pos_price      =PositionGetDouble(POSITION_PRICE_OPEN);
      pos_cprice     =PositionGetDouble(POSITION_PRICE_CURRENT);
      pos_sl         =PositionGetDouble(POSITION_SL);
      pos_tp         =PositionGetDouble(POSITION_TP);
      pos_type       =(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
      pos_volume     =PositionGetDouble(POSITION_VOLUME);
      pos_commission =PositionGetDouble(POSITION_COMMISSION);
      pos_swap       =PositionGetDouble(POSITION_SWAP);
      pos_profit     =PositionGetDouble(POSITION_PROFIT);
      pos_time       =(datetime)PositionGetInteger(POSITION_TIME);
      pos_id         =PositionGetInteger(POSITION_IDENTIFIER);
     }
   else // If there is no open position, zero out variables for position properties
      ZeroPositionProperties();
//---
   SetInfoPanel(); // Set/update the info panel
  }

次にSetInfoPanel() 関数を書きます。以下は詳細コメントを持つこの関数のコードです。

//+------------------------------------------------------------------+
//| SETTING THE INFO PANEL                                           |
//|------------------------------------------------------------------+
void SetInfoPanel()
  {
   int               y_bg=18;             // Y-coordinate for the background and header
   int               y_property=32;       // Y-coordinate for the list of properties and their values
   int               line_height=12;      // Line height
//---
   int               font_size=8;         // Font size
   string            font_name="Calibri"; // Font
   color             font_color=clrWhite; // Font color
//---
   ENUM_ANCHOR_POINT anchor=ANCHOR_RIGHT_UPPER; // Anchor point in the top right corner
   ENUM_BASE_CORNER  corner=CORNER_RIGHT_UPPER; // Origin of coordinates in the top right corner of the chart
//--- X-coordinates
   int               x_first_column=120// First column (names of properties)
   int               x_second_column=10;  // Second column (values of properties)
//--- Array of Y-coordinates for the names of position properties and their values
   int               y_prop_array[INFOPANEL_SIZE]={0};
//--- Fill the array with coordinates for each line on the info panel
   y_prop_array[0]=y_property;
   y_prop_array[1]=y_property+line_height;
   y_prop_array[2]=y_property+line_height*2;
   y_prop_array[3]=y_property+line_height*3;
   y_prop_array[4]=y_property+line_height*4;
   y_prop_array[5]=y_property+line_height*5;
   y_prop_array[6]=y_property+line_height*6;
   y_prop_array[7]=y_property+line_height*7;
   y_prop_array[8]=y_property+line_height*8;
   y_prop_array[9]=y_property+line_height*9;
   y_prop_array[10]=y_property+line_height*10;
   y_prop_array[11]=y_property+line_height*11;
   y_prop_array[12]=y_property+line_height*12;
   y_prop_array[13]=y_property+line_height*13;
//--- Background of the info panel
   CreateEdit(0,0,"InfoPanelBackground","",corner,font_name,8,clrWhite,230,190,231,y_bg,0,C'15,15,15',true);
//--- Header of the info panel
   CreateEdit(0,0,"InfoPanelHeader","POSITION PROPERTIES",corner,font_name,8,clrWhite,230,14,231,y_bg,1,clrFireBrick,true);
//--- List of the names of position properties and their values
//    Property name
   CreateLabel(0,0,pos_prop_names[0],"Symbol :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[0],2);
//    Property value
   CreateLabel(0,0,pos_prop_values[0],GetValInfoPanel(0),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[0],2);
//---
   CreateLabel(0,0,pos_prop_names[1],"Magic Number :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[1],2);
   CreateLabel(0,0,pos_prop_values[1],GetValInfoPanel(1),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[1],2);
//---
   CreateLabel(0,0,pos_prop_names[2],"Comment :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[2],2);
   CreateLabel(0,0,pos_prop_values[2],GetValInfoPanel(2),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[2],2);
//---
   CreateLabel(0,0,pos_prop_names[3],"Swap :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[3],2);
   CreateLabel(0,0,pos_prop_values[3],GetValInfoPanel(3),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[3],2);
//---
   CreateLabel(0,0,pos_prop_names[4],"Commission :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[4],2);
   CreateLabel(0,0,pos_prop_values[4],GetValInfoPanel(4),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[4],2);
//---
   CreateLabel(0,0,pos_prop_names[5],"Open Price :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[5],2);
   CreateLabel(0,0,pos_prop_values[5],GetValInfoPanel(5),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[5],2);
//---
   CreateLabel(0,0,pos_prop_names[6],"Current Price :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[6],2);
   CreateLabel(0,0,pos_prop_values[6],GetValInfoPanel(6),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[6],2);
//---
   CreateLabel(0,0,pos_prop_names[7],"Profit :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[7],2);
   CreateLabel(0,0,pos_prop_values[7],GetValInfoPanel(7),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[7],2);
//---
   CreateLabel(0,0,pos_prop_names[8],"Volume :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[8],2);
   CreateLabel(0,0,pos_prop_values[8],GetValInfoPanel(8),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[8],2);
//---
   CreateLabel(0,0,pos_prop_names[9],"Stop Loss :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[9],2);
   CreateLabel(0,0,pos_prop_values[9],GetValInfoPanel(9),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[9],2);
//---
   CreateLabel(0,0,pos_prop_names[10],"Take Profit :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[10],2);
   CreateLabel(0,0,pos_prop_values[10],GetValInfoPanel(10),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[10],2);
//---
   CreateLabel(0,0,pos_prop_names[11],"Time :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[11],2);
   CreateLabel(0,0,pos_prop_values[11],GetValInfoPanel(11),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[11],2);
//---
   CreateLabel(0,0,pos_prop_names[12],"Identifier :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[12],2);
   CreateLabel(0,0,pos_prop_values[12],GetValInfoPanel(12),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[12],2);
//---
   CreateLabel(0,0,pos_prop_names[13],"Type :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[13],2);
   CreateLabel(0,0,pos_prop_values[13],GetValInfoPanel(13),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[13],2);
//---
   ChartRedraw(); // Redraw the chart
  }

それではSetInfoPanel() 関数を詳しく見ましょう。グラフィカルオブジェクトのプロパティに関連する変数(座標、色、フォント、表示テキスト、等)は関数の冒頭で宣言されます。情報パネルのポジションプロパティリスト用Y座標の配列書き込み手順には注意が必要です。それは初心者にわかりやすい方法で実装されています。ただ、ループを使用する際に数行コード行を減らすこともできます。それを以下のように書くことが可能です。

//--- Fill the array with coordinates for each line on the info panel
   for(int i=0; i<INFOPANEL_SIZE; i++)
     {
      if(i==0) y_prop_array[i]=y_property;
      else     y_prop_array[i]=y_property+line_height*i;
     }

パネルに表示される必要のあるオブジェクトの全プロパティは以前に作成した関数 CreateLabel() および CreateEdit() で指定する必要があります。その際一度に取るオブジェクトは1個です。リスト全体はまたループを使って数行のコードで実装することが可能です。このためにチャート上のポジションプロパティ名のテキストを表示するオブジェクト用の配列を別にもうひとつ作成する必要があります。が、これはみなさんの宿題といたしましょう。

オブジェクト数を受け取る GetPropertyValue() 関数はそのあと4番目のパラメータ(表示されるテキスト)として CreateLabel() 関数に渡される値を返します。これはポジションプロパティの値を表示するすべてのオブジェクトに関連します。関数によって返される値は最終的にパネルに表示されることになる、調整されたストリング値です。以下は詳細コメントを持つこの関数のコードです。

//+------------------------------------------------------------------+
//| RETURNING THE STRING WITH POSITION PROPERTY VALUE                |
//+------------------------------------------------------------------+
string GetPropertyValue(int number)
  {
//--- Sign indicating the lack of an open position or a certain property
//    E.g. the lack of a comment, Stop Loss or Take Profit
   string empty="-";
//--- If an open position exists, return the value of the requested property
   if(pos_open)
     {
      switch(number)
        {
         case 0  : return(pos_symbol);                                           break;
         case 1  : return(IntegerToString((int)pos_magic));                      break;
         //--- return the value of the comment, if any, otherwise return the sign indicating the lack of comment
         case 2  : return(pos_comment!="" ? pos_comment : empty);                break;
         case 3  : return(DoubleToString(pos_swap,2));                           break;
         case 4  : return(DoubleToString(pos_commission,2));                     break;
         case 5  : return(DoubleToString(pos_price,_Digits));                    break;
         case 6  : return(DoubleToString(pos_cprice,_Digits));                   break;
         case 7  : return(DoubleToString(pos_profit,2));                         break;
         case 8  : return(DoubleToString(pos_volume,2));                         break;
         case 9  : return(pos_sl!=0.0 ? DoubleToString(pos_sl,_Digits) : empty); break;
         case 10 : return(pos_tp!=0.0 ? DoubleToString(pos_tp,_Digits) : empty); break;
         case 11 : return(TimeToString(pos_time,TIME_DATE|TIME_MINUTES));        break;
         case 12 : return(IntegerToString((int)pos_id));                         break;
         case 13 : return(PositionTypeToString(pos_type));                       break;
         
         default : return(empty);
        }
     }
//---
// If there is no open position, return the sign indicating the lack of the open position "-"
   return(empty);
  }

上記コードは、オープンしたポジションがある場合、特定の値が関数に渡されるそれぞれの数に対して準備されることを示しています。現時点でオープンしたポジションがなければ、関数はポジションプロパティの値に関連する全オブジェクトに対して表示されるよこ棒(-)を返します。

SetInfoPanel() 関数の末尾では、強制異的チャートの再作成のために造られる ChartRedraw() 関数を呼びます。それが呼ばれなければ、加えられた変更を確認することができません。

ここで Expert Advisorによって作成されたグラフィカルオブジェクトをすべて削除する関数を書く必要があります。その関数をDeleteInfoPanel() と名づけます。

//+------------------------------------------------------------------+
//| DELETING THE INFO PANEL                                          |
//+------------------------------------------------------------------+
void DeleteInfoPanel()
  {
   DeleteObjectByName("InfoPanelBackground");   // Delete the panel background
   DeleteObjectByName("InfoPanelHeader");       // Delete the panel header
//--- Delete position properties and their values
   for(int i=0; i<INFOPANEL_SIZE; i++)
     {
      DeleteObjectByName(pos_prop_names[i]);    // Delete the property
      DeleteObjectByName(pos_prop_values[i]);   // Delete the value
     }
//---
   ChartRedraw(); // Redraw the chart
  }

そしてMQL5 ウィザードで作成したあとテンプレートに元々あった Expert Advisor の主な関数の中に作成したメソッドを配布する必要があります。これはもっとも簡単な部分です。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Get the properties and set the panel
   GetPositionProperties();
//---
   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();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Get the properties and update the values on the panel
   GetPositionProperties();

  }
//+------------------------------------------------------------------+

唯一偶然見つけるものは、最初期化の理由を述べるコードのテキスト記述を返す GetDeinitReasonText() 関数です。

//+---------------------------------------------------------------------+
//| RETURNING A TEXTUAL DESCRIPTION OF THE DEINITIALIZATION REASON CODE |
//+---------------------------------------------------------------------+
string GetDeinitReasonText(int reason_code)
  {
   string text="";
//---
   switch(reason_code)
     {
      case REASON_PROGRAM :     // 0
         text="The Expert Advisor has stopped working calling the ExpertRemove() function.";   break;
      case REASON_REMOVE :      // 1
         text="The '"+EXPERT_NAME+"' program has been removed from the chart.";                break;
      case REASON_RECOMPILE :   // 2
         text="The '"+EXPERT_NAME+"' program has been recompiled.";                            break;
      case REASON_CHARTCHANGE : // 3
         text="Chart symbol or period has been changed.";                                      break;
      case REASON_CHARTCLOSE :  // 4
         text="The chart is closed.";                                                          break;
      case REASON_PARAMETERS :  // 5
         text="Input parameters have been changed by the user.";                               break;
      case REASON_ACCOUNT :     // 6
         text="A different account has been activated.";                                       break;
      case REASON_TEMPLATE :    // 7
         text="A different chart template has been applied.";                                  break;
      case REASON_INITFAILED :  // 8
         text="A flag specifying that the OnInit() handler returned zero value.";              break;
      case REASON_CLOSE :       // 9
         text="The terminal has been closed.";                                                 break;
      default : text="The reason is undefined.";
     }
//---
   return text;
  }

現時点でオープンしたポジションがないチャート上のシンボルについて Expert Advisor を使用してみたいなら、パネルにはポジションプロパティの値の代わりに横棒が表示されます。特定のポジションをクローズしたあとのパネル表示は同じです。

図2  オープンポジション不在時の情報パネル

図2 オープンポジション不在時の情報パネル

オープンポジションのあるシンボルのチャートに Expert Advisor が追加される場合、また Expert Advisor がチャートに追加されたあとにポジションがオープンする場合、横棒はすべて適切なポジションプロパティの値と置き換わります。

図3  オープンポジションのプロパティを表示している情報パネル

図3  オープンポジションのプロパティを表示している情報パネル

ひとつ特殊なことがあります。ポジションをクローズしたら、パネル上の値が更新されるのは新規ティックの後です。即座に値を更新する方法もありますが、これを実装するにはシリーズの次の記事でそのために何が必要かお話します。

 

おわりに

本稿で紹介した関数の中には MQL5 Cookbook シリーズの今後の記事で使用されるものがあります。また作業中のタスクによって変更され改良されるものもあります。記事は順番に読むのがよいでしょう。ひとつずつ新しい記事は理論的に前のものの続きとなっているからです。またそれは確実にみなさんの能力と技能のレベルに依存します。よって最新の公表物から始めるのがより合理的でおもしろいかもしれません。 

ソースコードファイルは本稿に添付があります。

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

添付されたファイル |
MQL5 クックブック:Position プロパティの取得 MQL5 クックブック:Position プロパティの取得
本稿では position プロパティをすべて取得しユーザーに対してダイアログボックスにそれを表示するスクリプトを作成します。スクリプト実行時外部パラメータのドロップダウンリストから利用可能なモード2種類から選択することができます。現在シンボルの position プロパティのみ閲覧するかすべてのシンボルの position プロパティを閲覧するかです。
MQL5 クックブック:MetaTrader 5 ストラレジーテスタでの position プロパティ分析 MQL5 クックブック:MetaTrader 5 ストラレジーテスタでの position プロパティ分析
先行記事 "MQL5 Cookbook: Position Properties on the Custom Info Panel"の Expert Advisor の変更バージョンを提供します。お伝えする問題の中にはバーからのデータ取得、現シンボルにおける新規バーイベント確認、ファイルに標準ライブラリのトレードクラスのインクルード、トレード処理実行用トレードシグナルおよび関数検索のための関数作成、OnTrade() 関数におけるトレードイベント決定などがあります。
MetaTrader4とMetaTrader5のトレーディングシグナル用ウィジェット MetaTrader4とMetaTrader5のトレーディングシグナル用ウィジェット
MetaTrader4とMetaTrader5ユーザーがシグナル提供者になり、さらなる利益を生む機会を得ることができるようになりました。新しいウィジェットを用いて、あなたのサイトやブログ、SNSページにトレーディング実績を掲載できます。ウィジェットを用いる利点は明確です;シグナルプロバイダーの人気を向上し、成功したトレーダーとしての評判を築くのみでなく、新しい購読者を惹きつけます。その他のサイトにウィジェットを載せているトレーダーはこれらの利益を享受できます。
MQL5 Cookbook:トレードレベルを設定/変更する際エラーを避ける方法 MQL5 Cookbook:トレードレベルを設定/変更する際エラーを避ける方法
シリーズの前稿 "MQL5 Cookbook: Analyzing Position Properties in the MetaTrader 5 Strategy Tester" からの Expert Advisor への取り組みの続編として、既存の関数を改良、最適化しつつ有用な関数を数多く用いて Expert Advisor を強化していきます。今回 Expert Advisor は MetaTrader 5 「ストラテジーテスタ」で最適化可能な外部パラメータを取得し、いくつかの点でシンプルなトレーディングシステムのようになります。