English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 クックブック:典型的なチャートイベントの処理

MQL5 クックブック:典型的なチャートイベントの処理

MetaTrader 5 | 25 11月 2015, 09:35
2 394 0
Denis Kirichenko
Denis Kirichenko

はじめに

本稿では MQL5 の開発者によって事前に定義されている典型的(標準的)なイベントについて OnChartEvent() を用いた機能と実践練習について記述したいと思います。MQL5 の数々の記事および コードベース ですでにこのハンドラの使用例は取り上げられています。

ですが、私の目的は「イベント駆動プログラミング(EOP)」の考え方でこの手段を分析することです。このハンドラを完全に自動化されたトレーディングシステムと半自動トレーディングシステムで問題なく使用することができると考えています。


1. "ChartEvent" イベント

それでは最初にこのイベントタイプがどんなものであるか見ていきます。

ドキュメンテーションによると ChartEvent イベントはチャート作業時に出現するようです。特に以下の場合です。

  • チャートウィンドウに着目し、キーボード上でキーを押すとき。
  • グラフィックオブジェクトを作成するとき
  • グラフィックオブジェクトを削除するとき
  • グラフィックオブジェクト上でクリックするとき
  • マウスでグラフィックオブジェクトをドラッグするとき
  • LabelEdit graphical オブジェクトのテキストフィールドでテキスト編集を終了するとき

よってこのイベントは双方向性をもたらしチャートとの交流を可能にします。その上、そのような相互作用はなんらかのアルゴリズム処理(自動トレーディング)同様マニュアルトレーディングの結果でありえます。

MQL5 開発者は ChartEvent イベントを ENUM_CHART_EVENT リストで指定されたタイプに分類しています。

このリストにはユーザー定義イベントが含まれ、それはプログラマーに役立つ隠れた蓄えのようなものであることに注意することが重要です。MQL5 開発者はカスタムイベントに 65,535個の IDを提供しています。

カスタムイベントと連携するにはプログラマーのニーズに応じて特殊な作成関数 EventChartCustom() が利用できます。ただし、本稿ではカスタムイベントは考察しません。


2. ChartEvent ハンドラとジェネレータ

ChartEvent イベントの処理はすべて特殊なハンドラ関数 OnChartEvent()によって行われます。これは MQL5 言語コンセプトと一致しており、それはたとえばトレードイベントは OnTrade() 関数で処理され、Init イベントは OnInit() 関数で処理される、などです。

OnChartEvent() 関数は以下のシグネチャーを持ちます。

void OnChartEvent(const int id,         // event identifier  
                  const long& lparam,   // parameter of the event of type long
                  const double& dparam, // parameter of the event of type double
                  const string& sparam  // parameter of the event of type string
                  )

入力パラメータはすべて定数で、ハンドラが呼ばれる時有用な情報を伝達します。

そのため id パラメータの値はどの特定のイベントがハンドラを呼んだか明らかにすることができます。その他ロング、ダブル、文字列タイプの値を持ちます。この方法でイベントに関する別の情報を取得することができます。

その後、進行中のことがらを分析するために使われる指定のパラメータ値の例を作成します。

ChartEvent イベントのカスタム部分は実装するプログラマー次第ですが、EventChartCustom() 関数に連携されます。まさにこの関数がイベントを生成します。以下がその関数のシグネチャーです。

bool  EventChartCustom(long    chart_id,        // receiving chart identifier
                       ushort  custom_event_id, // event identifier
                       long    lparam,          // the long parameter
                       double  dparam,          // the double parameter
                       string  sparam           // the string parameter
                       )

実際、ジェネレータ関数がイベントを作成し、入力パラメータを持つ現在チャートを含む任意のチャートにそのイベントを送信します。後者は ushort、ロング、ダブル、文字列タイプです。

関数 OnChartEvent() および EventChartCustom() はともに「イベント駆動プログラミング」の恩恵の好例である力強いツールを作成します。


3. 標準イベント処理テンプレート

チャートイベントタイプを考察し、それぞれの例を示してこうと思います。各イベントは独自のバージョンの EventProcessor.mq5 を持ち、そのコードはチャートイベントを処理します。MQL5には典型的なイベントが10種類あります。

そのうちの3個(マウスイベント、グラフィックオブジェクト作成イベント、グラフィックオブジェクト消去イベント)に対してチャートを準備する必要があります。ChartSetInteger() 関数を使用することでそれを行います。それによりチャートは指定のイベントに応答することができます。

以下がチャートイベント処理の典型的なブロックの記述です。

void OnChartEvent(const int id, 
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   string comment="Last event: ";

//--- select event on chart
   switch(id)
     {
      //--- 1
      case CHARTEVENT_KEYDOWN:
        {
         comment+="1) keystroke";
         break;
        }
      //--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         break;
        }
      //--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         break;
        }
      //--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         break;
        }
      //--- 5
      case CHARTEVENT_OBJECT_DELETE:
        {
         comment+="5) delete graphical object";
         break;
        }
      //--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         break;
        }
      //--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         break;
        }
      //--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         break;
        }
      //--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) finish editing text";
         break;
        }
      //--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         comment+="10) modify chart";
         break;
        }
     }
//---
   Comment(comment);
  }

それぞれのケースで私は選択されたイベントを記述する文字列を追加しました。結果、コメント行でチャート上に起こった最後のイベントを確認することができます。テンプレートを実行し、チャートでさまざまな操作を行うと、コメント行が異なるレコードを持つことがわかります。

あきらかにイベントタイプを判断するだけの Expert Advisor はほとんど利用されません。その機能を拡張する必要があります。


4. 標準イベント処理例


4.1. キーストロークイベント

最初のケースを取りあげ、キーボードのボタンと連携します。それでわれわれの EA はキーストロークに応答するようになります。『上向き矢印』を押すと買い、『下向き矢印』を押すと売りとします。この場合の記述は以下のようなものになります。

//--- 1
      case CHARTEVENT_KEYDOWN:
        {
         //--- "up" arrow
         if(lparam==38)
            TryToBuy();

         //--- "down" arrow
         else if(lparam==40)
            TryToSell();

         comment+="1) keystroke";
         //---         
         break;
        }

TryToBuy() および TryToSell() の実装詳細については添付の EA ソースコードを参照ください。トレードパラメータ(ロットサイズ、ストップロス、テイクプロフィット等)は入力変数(InpLotInpStopLossInpTakeProfit等)として指定します。またパラメータ lparam は押されたキーのコードを取得することも述べる必要があります。


EA の更新バージョンは EventProcessor1.mq5と呼ばれます。


4.2. マウスイベント

このイベントタイプはプロパティ CHART_EVENT_MOUSE_MOVE がチャートに対して指定されたときのみ処理されます。このため EA の初期化ブロックには以下のような文字列が入ります。

//--- mouse move
bool is_mouse=false;
if(InpIsEventMouseMove)
   is_mouse=true;
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,is_mouse);

マウスを使用するなら当然マウスイベントも頻繁に起こることを覚えておく必要があります。よってこのイベントの処理を無効にするチャンスは有用です。ハンドラのパラメータ lparam およびdparam はそれぞれ X 軸と Y 軸の座標を知らせています。

作成された例についてお話します。右の境界からゼロバーの移動があるとします。シフトから右に画面上にカーソルを置くと、買いまたは売りを提案するウィンドウが表示されます。

そのためまずシフトを決定する必要があります。右境界からパーセント(InpChartShiftSize)でゼロバーシフトのサイズを決める入力変数を取り込みます。

図1 トレード処理ウィンドウ

図1 トレード処理ウィンドウ

シフトとサイズを有効にする関数、ChartShiftSet()および ChartShiftSizeSet()を使います。それからカーソルの X 座標が前に境界の左にあり右に移動したか特定します。そのとおりであれば、買いまたは売りを提案するウィンドウが表示されます(図1)。

以下が対象設定を実装するコードの記述です。

//--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         //--- if a mouse event is processed
         if(InpIsEventMouseMove)
           {
            long static last_mouse_x;

            //--- enable shift
            if(ChartShiftSet(true))
               //--- set shift size 
               if(ChartShiftSizeSet(InpChartShiftSize))
                 {
                  //--- chart width
                  int chart_width=ChartWidthInPixels();

                  //--- calculate X coordinate of shift border
                  int chart_shift_x=(int)(chart_width-chart_width*InpChartShiftSize/100.);

                  //--- border crossing condition
                  if(lparam>chart_shift_x && last_mouse_x<chart_shift_x)
                    {
                     int res=MessageBox("Yes: buy / No: sell","Trade operation",MB_YESNO);
                     //--- buy
                     if(res==IDYES)
                        TryToBuy();
                     //--- sell
                     else if(res==IDNO)
                        TryToSell();
                    }

                  //--- store mouse X coordinate
                  last_mouse_x=lparam;
                 }
           }

         //---
         break;
        }

以前に作成されたトレード関数によって売りと買いが行われます。EA の更新バージョンを EventProcessor2.mq5と名づけます。


4.3. グラフィックオブジェクト作成イベント

このイベントタイプはチャート上にオブジェクトが作成されるとき生成されます。マウスイベント同様、このタイプはプロパティ CHART_EVENT_OBJECT_CREATEによって処理に対する許可を受け取る必要があります。新規グラフィックオブジェクトに応答しようとする場合、それをブロック内で一度のみ指定する必要があります。

//--- object create
bool is_obj_create=false;
if(InpIsEventObjectCreate)
   is_obj_create=true;
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,is_obj_create);

情報を持つハンドラのパラメータは1個だけです。それは作成されるグラフィックオブジェクト名を保持する文字列パラメータ sparam です。そのオブジェクトは名前で検索することができます。それを処理したら次に何をするか決めます。

シンプルな例があります。チャートに水平線を引き、ロボットにそれをチャートに反映されるすべてのバーの最大値に置かせ別に2本の線を引きます。下側の線は安値の位置に、三番目の線は先の2本の線それぞれから等間隔にその2本の間に引きます。

以下はこのタスクの実装コードです。

//--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         //--- if graphical object creation event is processed
         if(InpIsEventObjectCreate)
           {
            //--- capture creation of horizontal line
            int all_hor_lines=ObjectsTotal(0,0,OBJ_HLINE);

            //--- if this is the only line
            if(all_hor_lines==1)
              {
               string hor_line_name1=sparam;

               //--- calculate levels
               int visible_bars_num=ChartVisibleBars();

               //--- arrays for high and low prices
               double highs[],lows[];
               //---
               int copied=CopyHigh(_Symbol,_Period,0,visible_bars_num-1,highs);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy highs!");
                  return;
                 }
               copied=CopyLow(_Symbol,_Period,0,visible_bars_num-1,lows);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy lows!");
                  return;
                 }
               //--- high and low prices
               double ch_high_pr,ch_low_pr,ch_mid_pr;
               //---
               ch_high_pr=NormalizeDouble(highs[ArrayMaximum(highs)],_Digits);
               ch_low_pr=NormalizeDouble(lows[ArrayMinimum(lows)],_Digits);
               ch_mid_pr=NormalizeDouble((ch_high_pr+ch_low_pr)/2.,_Digits);

               //--- place created line on high
               if(ObjectFind(0,hor_line_name1)>-1)
                  if(!ObjectMove(0,hor_line_name1,0,0,ch_high_pr))
                    {
                     Print("Failed to move!");
                     return;
                    }
               //--- create line on low
               string hor_line_name2="Hor_line_min";
               //---
               if(!ObjectCreate(0,hor_line_name2,OBJ_HLINE,0,0,ch_low_pr))
                 {
                  Print("Failed to create the 2nd horizontal line!");
                  return;
                 }
               //--- create line between high and low 
               string hor_line_name3="Hor_line_mid";
               //---
               if(!ObjectCreate(0,hor_line_name3,OBJ_HLINE,0,0,ch_mid_pr))
                 {
                  Print("Failed to create the 3rd horizontal line!");
                  return;
                 }
              }
           }
         break;
        }

EA の更新バージョンの名前は EventProcessor3.mq5です。

図2 グラフィックオブジェクト作成イベント処理結果

図2 グラフィックオブジェクト作成イベント処理結果

その手順が完了すると以下の描画を受け取りました(図2)。統合関数が EA にグラフィックオブジェクト作成に対して反応する機能を持たせ、その後それに従って処理を行います。


4.4. プロパティダイアログによるグラフィックオブジェクトのプロパティ変更イベント

このイベントタイプは部分的に前のタイプに似ています。これはグラフィックオブジェクトのプロパティの一つがプロパティダイアログによって変更されたときに起こります。Iこのツールはたとえば同じタイプのオブジェクトのグラフィックプロパティの同期などに有用です。

チャート上のいくつかのオブジェクト番号をイメージします。トレーダーは通常チャート上に数多くの様々な線を持ちます。こういった線は削除せず非表示にすることが必要となる場合があります。このタスクを行う方法を見つけていきます。変更された線の色を変え、他のグラフィックオブジェクトにも同じようにします。以下がそのときのコード例です。

//--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         //---
         string curr_obj_name=sparam;
         //--- find the changed object
         if(ObjectFind(0,curr_obj_name)>-1)
           {
            //--- get object color
            color curr_obj_color=(color)ObjectGetInteger(0,curr_obj_name,OBJPROP_COLOR);
            //--- total number of objects on chart
            int all_other_objects=ObjectsTotal(0);
            //--- find other objects
            for(int obj_idx=0;obj_idx<all_other_objects;obj_idx++)
              {
               string other_obj_name=ObjectName(0,obj_idx);
               if(StringCompare(curr_obj_name,other_obj_name)!=0)
                  if(!ObjectSetInteger(0,other_obj_name,OBJPROP_COLOR,curr_obj_color))
                    {
                     Print("Failed to change the object color!");
                     return;
                    }
              }
            //--- redraw chart
            ChartRedraw();
           }
         //---
         break;

チャート上に一組の線があるとします(図3)。

図3 Multi-colored 変動ライン

図3 Multi-colored 変動ライン

任意の線の色を変えようとするか、もっと正確に言えばプロパティダイアログ内でその色を変える(図4)場合、チャートには法事されている線はなくなります。同時にグラフィックオブジェクトはまだそこに表示されています。

図4 線色の変更

図4 線色の変更

EA の更新バージョンはEventProcessor4.mq5と名づけられます。


4.5. グラフィックオブジェクト削除イベント

このイベント名から判るように、チャートからオブジェクトを削除するときに出現するイベントです。グループの最終イベントで、処理に対する直接の事前承認が必要となります。プロパティ CHART_EVENT_OBJECT_DELETEによって行われます。

//--- object delete
   bool is_obj_delete=false;
   if(InpIsEventObjectDelete)
      is_obj_delete=true;
   ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,is_obj_delete);

別の仮定としての例です。EA がアタッチされているチャート上に異なるタイプのグラフィックオブジェクトがあります。特定タイプのオブジェクトを1個だけ削除する必要があるとします。たとえば縦線です(図5)。

図5 5本の縦線とその他ライン

図5 5本の縦線とその他ライン

われわれは縦線1本だけ消去し、後は「エキスパート」が消去します(図6)。

図6 残りの線

図6 残りの線

『エキスパート』の登録で次の入力が表示されます。

NS      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines before removing: 4
MD      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines removed from the chart: 4
QJ      0       10:31:18.078    EventProcessor5 (EURUSD.e,W1)   Vertical lines after removing: 0

重要な側面についてお話する必要があるでしょう。オブジェクトが消去されると、そのプロパティにアクセスすることはできません。まえもってオブジェクトの必要なデータを取り戻さなければ 、消去後そのデータにアクセスできなくなる、ということです。消去されるオブジェクトタイプを見つける必要があれば、オブジェクト自体が消去される前にそれを格納しなければなりません。私は MQL5 開発者にターミナルで利用可能なチャートの履歴を作成いただくことを提案したいと思います。それで消去されるオブジェクトのプロパティを参照することができるようになります。

「エキスパート」の最終バージョンに EventProcessor5.mq5と名づけます。


4.6. チャート上のマウスクリックイベント

このイベントはチャートが左マウスボタンでクリックされると発生します。チャート上での右クリックはコンテキストメニューを開き、中央ボタンのクリックは crosshair.をもたらします。ハンドラのパラメータ lparam およびdparam はそれぞれ X 軸と Y 軸の座標を知らせています。

続くシンプルなタスクは例の役割をします。マウスのクリックが行われる場所に「買い」の矢印が描画されるように手配します。オブジェクト「矢印」にはアンカーポイントが1つしかありません。結果、アンカーポイントの時間と価格値に対する X 軸と Y 軸の変換が1件だけ必要となります。

以下は上記例のコードです。

//--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         //--- object counter 
         static uint sign_obj_cnt;
         string buy_sign_name="buy_sign_"+IntegerToString(sign_obj_cnt+1);
         //--- coordinates 
         int mouse_x=(int)lparam;
         int mouse_y=(int)dparam;
         //--- time and price
         datetime obj_time;
         double obj_price;
         int sub_window;
         //--- convert the X and Y coordinates to the time and price values
         if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
           {
            //--- create object
            if(!ObjectCreate(0,buy_sign_name,OBJ_ARROW_BUY,0,obj_time,obj_price))
              {
               Print("Failed to create buy sign!");
               return;
              }
            //--- redraw chart
            ChartRedraw();
            //--- increase object counter
            sign_obj_cnt++;
           }
         //---
         break;
        }

EA の現在バージョンを EventProcessor6.mq5と名づけます。


4.7. グラフィックオブジェクト上でのマウスクリックイベント

チャートイベントのこのタイプが前出のイベントと異なるのはマウスのクリックがグラフィックオブジェクト上で起こる点のみです。文字列パラメータ sparam はクリックがその上で行われるオブジェクト名を持ちます。前出の例では「買い」矢印を作成しました。このタイプのオブジェクト上でのクリックが「売り」矢印に変えるようにしましょう。

以下はハンドラのこのブロックのコード記述です。

//--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         //---
         string sign_name=sparam;

         //--- delete buy arrow
         if(ObjectDelete(0,sign_name))
           {
            //--- redraw chart
            ChartRedraw();
            //---
            static uint sign_obj_cnt;
            string sell_sign_name="sell_sign_"+IntegerToString(sign_obj_cnt+1);

            //--- coordinates 
            int mouse_x=(int)lparam;
            int mouse_y=(int)dparam;
            //--- time and price
            datetime obj_time;
            double obj_price;
            int sub_window;
            //--- convert the X and Y coordinates to the time and price values
            if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
              {
               //--- create object
               if(!ObjectCreate(0,sell_sign_name,OBJ_ARROW_SELL,0,obj_time,obj_price))
                 {
                  Print("Failed to create sell sign!");
                  return;
                 }
               //--- redraw chart
               ChartRedraw();
               //--- increase object counter
               sign_obj_cnt++;
              }
           }
         //---
         break;
        }

この例のためにマウスクリック処理に触れずにおいたのです。EAを起動し、マウスの左クリックを3度行い3本の買い矢印を取得しました(図7)。その場所を黄色で強調しました。

図7 「買い」矢印

図7 「買い」矢印

ここで各「買い」矢印をクリックすると、次の描画を受け取ります(図8)。

図8 「買い」矢印と「売り」矢印

図8 「買い」矢印と「売り」矢印

「売り」矢印が予定どおり表示されましたが、「買い」矢印は表示されるよう予定されませんでした。「買い」矢印の名前を黄色で強調した箇所のチャート上にオブジェクトリストを持ってきているのには理由があります。

EA が4番目、5番目、6番目の「買い」矢印を作成したのはすぐに判ります。それはなぜ起こったのでしょうか?それはオブジェクト上の最初のクリックが2件のイベントを発生させたためです。1番目は実際のオブジェクト上のクリック、2番目はチャート上のクリックです。最後のイベントが「買い」矢印の作成を行います。2番目のイベント、チャート上のクリックを妨げるメカニズムを追加することが必要です。私にはそれは時間上の制御がそのようなメカニズムに思えます。

グローバル変数 gLastTimeを追加します。それは「買い」矢印作成時間の制御を促します。「売り」矢印作成後250秒以内にシンプルなクリックハンドラが呼ばれると、この呼び出しは渡されます。

チャートが再描写される前に下記の文字列がオブジェクト上のクリック処理のブロックに追加されます。

//--- store the moment of creation
gLastTime=GetTickCount();

チャート上のクリック処理のブロックに時間の検証を追加する必要があります。

uint lastTime=GetTickCount();
if((lastTime-gLastTime)>250)
  {
   //--- click handling
  }

再び「買い」タイプのチャート上に3本の矢印を作成します(図9)。

図9 「買い」矢印

図9 「買い」矢印

サイズが小さいですが、矢印の上でクリックしてみます。クリックしたら矢印は『売り』タイプに変わりました(図10)。

図10 「売り」矢印

図10 「売り」矢印

前のものと同様、新しいバージョンをEventProcessor7.mq5.と名づけます。


4.8. マウスでグラフィックオブジェクトを移動するイベント

このイベントはオブジェクトがチャート領域内で移動されると発生します。ハンドラが移動したオブジェクト名を文字列パラメータ sparamの形式で受け取ります。

ここに別の例があります。Intra-day デイトレーダーはよく特定の時間間隔でトレードします。縦ラインはい時間間隔の限度です。図はおおよそ図11のようになります。関心のある間隔は強調表示されています。

図11 時間間隔の限度

図11 時間間隔の限度

時間間隔はマニュアルで変更可能です。われわれの半自動はそのような変更に対応の必要があります。

2本の縦ライン名を記載している変数をグローバルレベルで作成します。:gTimeLimit1_name と gTimeLimit2_nameです。また長方形の名前に対して数個の変数を作成する必要があります。それはチャート上のトレードのない時間の色を暗くします。アンカーポイント用のグローバル変数もまた作成する必要があります。長方形が2個あるので、アンカーポイントは4個になります。

以下はCHARTEVENT_OBJECT_DRAG ハンドラの場合のコードです。

//--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         string curr_obj_name=sparam;
         //--- if one of the vertical lines is moved
         if(!StringCompare(curr_obj_name,gTimeLimit1_name) || 
            !StringCompare(curr_obj_name,gTimeLimit2_name))
           {
            //--- the time coordinate of vertical lines
            datetime time_limit1=0;
            datetime time_limit2=0;
            //--- find the first vertical line
            if(ObjectFind(0,gTimeLimit1_name)>-1)
               time_limit1=(datetime)ObjectGetInteger(0,gTimeLimit1_name,OBJPROP_TIME);
            //--- find the second vertical line
            if(ObjectFind(0,gTimeLimit2_name)>-1)
               time_limit2=(datetime)ObjectGetInteger(0,gTimeLimit2_name,OBJPROP_TIME);

            //--- if vertical lines are found
            if(time_limit1>0 && time_limit2>0)
               if(time_limit1<time_limit2)
                 {
                  //--- update properties of rectangles
                  datetime start_time=time_limit1;
                  datetime finish_time=time_limit2;
                  //---
                  if(RefreshRecPoints(start_time,finish_time))
                    {
                     //---
                     if(!ObjectMove(0,gRectLimit1_name,0,gRec1_time1,gRec1_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit1_name,1,gRec1_time2,gRec1_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                     //---
                     if(!ObjectMove(0,gRectLimit2_name,0,gRec2_time1,gRec2_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit2_name,1,gRec2_time2,gRec2_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                    }
                 }
           }
         //---
         break;
        }

このコードにはカスタム関数 RefreshRecPoints()が含まれています。それは2個の長方形のアンカーポイントの値を更新します。EA 初期化のブロックはグラフィックオブジェクト作成に関する情報をもたらします。更新バージョンは EventProcessor8.mq5と名づけます。


4.9. テキストフィールド内のテキスト編集終了 イベント

このイベントタイプは高度に特殊化された性質があり、データ入力フィールドのテキストが編集されるときに発生します。パラメータ sparam いんは作業対象のオブジェクト名が含まれます。

ここに考察する例があります。データ入力フィールドでは実行しようとしているトレード処理を入力します。処理を2件だけ:売りと買いとします。入力フィールドに「買い」と入れると EA は資産を買い入れ、「売り」と入れると売却します。このフィールドが大文字小文字の区別をしないように手配しようと思います。「売り」と「買い」とタイプできるようにするのです。テキストと入力フィールドは売却で赤色にし、購入で青色にします(図12)。

図12 テキストフィールドでの買い

図12 テキストフィールドでの買い

以下はケース CHARTEVENT_OBJECT_ENDEDITのコードです。

//--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) end of editing a text in the data entry field";
         //---
         string curr_obj_name=sparam;
         //--- if specified text field is being edited
         if(!StringCompare(curr_obj_name,gEdit_name))
           {
            //--- get object description
            string obj_text=NULL;
            if(ObjectGetString(0,curr_obj_name,OBJPROP_TEXT,0,obj_text))
              {
               //--- check value
               if(!StringCompare(obj_text,"Buy",false))
                 {
                  if(TryToBuy())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrBlue);
                 }
               else if(!StringCompare(obj_text,"Sell",false))
                 {
                  if(TryToSell())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrRed);
                 }
               else
                 {
                  //--- set text color
                  ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrGray);
                 }
               //--- redraw chart
               ChartRedraw();
              }
           }
         //---
         break;
        }

EA の更新バージョンは EventProcessor9.mq5と名づけます。ソースファイルでテキストフィールド作成ブロックを確認することができます。


4.10. チャート変更イベント

本稿で考察する最後のイベントはチャート設定変更に関連するものです。これは特殊なイベントです。というのもここではチャート上のオブジェクトではなくチャートそのものを対象とするからです。開発者によるとこのイベントはチャートサイズ変更時、または新規設定が行われるときに発生する、ということです。

ここに別の例があります。いくつかのチャート設定変更には禁止事項があるとします。そうすると制約下での設定変更をしようとしても無視されます。実際、EA は単に前回値を返すだけです。チャートの次のパラメータを固定します。

  • 表示グリッド
  • チャート表示タイプ
  • 背景色

以下は上記に該当するコードです。

//--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         //--- current height and width of the chart         
         int curr_ch_height=ChartHeightInPixelsGet();
         int curr_ch_width=ChartWidthInPixels();
         //--- if chart height and width have not changed
         if(gChartHeight==curr_ch_height && gChartWidth==curr_ch_width)
           {
            //--- fix the properties:
            //--- display grid
            if(!ChartShowGridSet(InpToShowGrid))
              {
               Print("Failed to show grid!");
               return;
              }
            //--- type of chart display
            if(!ChartModeSet(InpMode))
              {
               Print("Failed to set mode!");
               return;
              }
            //--- background color
            if(!ChartBackColorSet(InpBackColor))
              {
               Print("Failed to set background сolor!");
               return;
              }
           }
         //--- store window dimensions
         else
           {
            gChartHeight=curr_ch_height;
            gChartWidth=curr_ch_width;
           }
         //---
         comment+="10) modify chart";
         //---
         break;
        }

最終バージョンは EventProcessor10.mq5と名づけます。


おわりに

本稿では MetaTrader 5における典型的なチャートイベントの多様性の説明を試みました。ここで述べたイベント処理例が MQL5でコーディングを始めるプログラマーの方々の役に立つことを願っています。

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

添付されたファイル |
code_en.zip (19.59 KB)
MQL5 プログラムのデバッグ MQL5 プログラムのデバッグ
本稿は第一にすでに言語を学習したがまだプログラム開発を完全にはマスターしていないプログラマーを対象としています。本稿ではいくつかデバッグテクニックを提供し、著者やその他多くのプログラマーの経験を紹介します。
計算用OpenCL のインストール方法と使用法 計算用OpenCL のインストール方法と使用法
MQL5 が OpenCLに対するネイティブサポートを開始して1年以上経過しました。とはいうものの、Expert Advisors、インディケータ、スクリプトで並列計算を行うことの真の価値を解っているユーザーは多くありません。本稿はみなさんが MetaTrader 5 トレーディングターミナルでこの技術を使ってみることができるようにお手持ちのコンピュータに OpenCL をインストールしセットアップするお手伝いをいたします。
MQL5 クックブック:オーバーフィットの影響低減とクオート不足への対処 MQL5 クックブック:オーバーフィットの影響低減とクオート不足への対処
どのようなトレーディング戦略を使っていようと、将来の収益を確保するためどのパラメータを選択すべきかという疑問は常にあるものです。本稿は同時に複数のシンボルパラメータを最適化する機能を備えたExpert Advisor 例を提供します。この方法はパラメータのオーバーフィットによる影響を軽減し、1個のシンボルからのデータが調査に十分でない場合に対処するものです。
もうひとつ別の MQL5 OOP クラス もうひとつ別の MQL5 OOP クラス
本稿では一からオブジェクト指向 Expert Advisor を構築する方法をお伝えします。トレードの理論的考えを着想することからその考えを実験的世界で実現する MQL5 EA をプログラムするまでです。実践から学ぶことは IMHO で成功への確実な方法です。よってみなさんが最終的に Forex ロボットのコーディングをするために考えを整理できる方法を確認していただけるよう実例を示していきます。また私の目標はみなさんにオブジェクト指向の原理に忠実に従うようお勧めすることです。