FX自動売買基礎と応用

MQLプログラミング言語でチャートにボタンを描画する方法


ボタン押下の動きをスムーズ化


MQLプログラミング言語でチャートにボタンを追加する方法」ではボタンを追加し、矢印の表示/非表示を切り替える機能を実装しました。

参考記事:MQLプログラミング言語でチャートにボタンを追加する方法

次にDrawArrowという関数を一つ定義して、この中で矢印を描画するためのプログラムを記述します。入れたいのはstart関数の矢印の描画に関する内容と同じものですが、同一の文を使うと後々修正したくなったときに不都合が生じるので、関数としてまとめて利用します。DrawArrow関数を次のように定義しましょう。


//+------------------------------------------------------------------+ 
//| Draw function                                                    | 
//+------------------------------------------------------------------+ 
void DrawArrow()
{
   int limit = MathMin(Bars  - 1, BARS);

   ObjectsDeleteAll(0, "3RCI_Sign_");

   for(int i = limit; i >= 0; i--) {      
      if (!ObjectGetInteger(0, "Button", OBJPROP_STATE)) continue;
      
      bool upNow = RCI0[i] > RCI1[i] && RCI1[i] > RCI2[i];
      bool upPre = RCI0[i + 1] > RCI1[i + 1] && RCI1[i + 1] > RCI2[i + 1];
      bool dnNow = RCI0[i] < RCI1[i] && RCI1[i] < RCI2[i];
      bool dnPre = RCI0[i + 1] < RCI1[i + 1] && RCI1[i + 1] < RCI2[i + 1];
      
      if (upNow && !upPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, Low[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
      }
      if (dnNow && !dnPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, High[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrDodgerBlue);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
      }
   }   
}

DrawArrow関数を定義したら、これをstart関数のところに組み込みます。


int start()
{
   int counted_bars = IndicatorCounted();
//---- check for possible errors
   if(counted_bars < 0) return -1;
//---- last counted bar will be recounted
   if(counted_bars > 0) counted_bars--;

   int limit = MathMin(Bars  - 1, BARS);

   for(int i = limit; i >= 0; i--) {
      RCI0[i] = iRCI(NULL, 0, PERIOD_S, i);
      RCI1[i] = iRCI(NULL, 0, PERIOD_M, i);
      RCI2[i] = iRCI(NULL, 0, PERIOD_L, i);
   }

   DrawArrow();

   return 0;
}

そしてこれを、ボタンクリックされたときの動作に指定します。


//+------------------------------------------------------------------+ 
//| ChartEvent function                                              | 
//+------------------------------------------------------------------+ 
void OnChartEvent(const int id,         // Event identifier   
                  const long& lparam,   // Event parameter of long type 
                  const double& dparam, // Event parameter of double type 
                  const string& sparam) // Event parameter of string type 
  { 
//--- the left mouse button has been pressed on the chart 
   if(id== CHARTEVENT_OBJECT_CLICK) {
     if (sparam == “Button”) {
       DrawArrow();
     }
   }
}

これでボタンを押したときの動きがスムーズになり、押した瞬間に矢印の表示/非表示が切り替わるようになります。


ソースコード


今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                                        3RCI_Sign |
//|                                                            HT FX |
//|                                        http://htfx.blog.fc2.com/ |
//+------------------------------------------------------------------+
#property copyright "HT FX"
#property link      "http://htfx.blog.fc2.com/"
#property description "Copyright (C) 2020  HT FX  All Rights Reserved.¥n"
#property description "http://htfx.blog.fc2.com/¥n"
#property description "htfxjp@gmail.com"
#property version "1.00"
#property strict
#property indicator_separate_window
#property indicator_maximum  1
#property indicator_minimum -1
#property indicator_buffers 3
#property indicator_plots   3
#property indicator_color1 clrWhite
#property indicator_color2 clrYellow
#property indicator_color3 clrRed
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID

//+------------------------------------------------------------------+
//| Input parameters                                                 |
//+------------------------------------------------------------------+
input int BARS = 500;    // 計算バー本数
input int PERIOD_S = 10; // 短期
input int PERIOD_M = 20; // 中期
input int PERIOD_L = 50; // 長期

//--- indicator buff
double RCI0[], RCI1[], RCI2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IndicatorSetInteger(INDICATOR_DIGITS, 6);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexStyle(2, DRAW_LINE);
   SetIndexBuffer(0, RCI0, INDICATOR_DATA);
   SetIndexBuffer(1, RCI1, INDICATOR_DATA);
   SetIndexBuffer(2, RCI2, INDICATOR_DATA);
   SetIndexLabel(0, "RCI(" + (string)PERIOD_S + ")");
   SetIndexLabel(1, "RCI(" + (string)PERIOD_M + ")");
   SetIndexLabel(2, "RCI(" + (string)PERIOD_L + ")");
   string name = "RCI(" + (string)PERIOD_S + "," + (string)PERIOD_M + "," + (string)PERIOD_L  + ")";
   IndicatorSetString(INDICATOR_SHORTNAME, name);
   
   ButtonCreate(0, "Button", ChartWindowFind(), 0, 15);
   
   return 0;
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, "3RCI_Sign_");
   
   if (reason == REASON_PARAMETERS || reason == REASON_RECOMPILE || reason == REASON_REMOVE)
      ObjectDelete("Button");
  }
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int counted_bars = IndicatorCounted();
//---- check for possible errors
   if(counted_bars < 0) return -1;
//---- last counted bar will be recounted
   if(counted_bars > 0) counted_bars--;

   int limit = MathMin(Bars  - 1, BARS);

   for(int i = limit; i >= 0; i--) {
      RCI0[i] = iRCI(NULL, 0, PERIOD_S, i);
      RCI1[i] = iRCI(NULL, 0, PERIOD_M, i);
      RCI2[i] = iRCI(NULL, 0, PERIOD_L, i);
   }

   DrawArrow();

   return 0;
}  
//+------------------------------------------------------------------+ 
//| Draw function                                                    | 
//+------------------------------------------------------------------+    
void DrawArrow()
{
   int limit = MathMin(Bars  - 1, BARS);

   ObjectsDeleteAll(0, "3RCI_Sign_");

   for(int i = limit; i >= 0; i--) {      
      if (!ObjectGetInteger(0, "Button", OBJPROP_STATE)) continue;
      
      bool upNow = RCI0[i] > RCI1[i] && RCI1[i] > RCI2[i];
      bool upPre = RCI0[i + 1] > RCI1[i + 1] && RCI1[i + 1] > RCI2[i + 1];
      bool dnNow = RCI0[i] < RCI1[i] && RCI1[i] < RCI2[i];
      bool dnPre = RCI0[i + 1] < RCI1[i + 1] && RCI1[i + 1] < RCI2[i + 1];
      
      if (upNow && !upPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, Low[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
      }
      if (dnNow && !dnPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, High[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrDodgerBlue);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
      }
   }   
}

//+------------------------------------------------------------------+ 
//| ChartEvent function                                              | 
//+------------------------------------------------------------------+ 
void OnChartEvent(const int id,         // Event identifier   
                  const long& lparam,   // Event parameter of long type 
                  const double& dparam, // Event parameter of double type 
                  const string& sparam) // Event parameter of string type 
{ 
//--- the mouse has been clicked on the graphic object 
   if(id==CHARTEVENT_OBJECT_CLICK) { 
      if (sparam == "Button") {
         DrawArrow();
      }
   } 
} 

//+------------------------------------------------------------------+ 
//| Create the button                                                | 
//+------------------------------------------------------------------+ 
bool ButtonCreate(const long              chart_ID=0,               // chart's ID 
                  const string            name="Button",            // button name 
                  const int               sub_window=0,             // subwindow index 
                  const int               x=0,                      // X coordinate 
                  const int               y=0,                      // Y coordinate 
                  const int               width=40,                 // button width 
                  const int               height=24,                // button height 
                  const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // chart corner for anchoring 
                  const string            text="Sign",              // text 
                  const string            font="Arial",             // font 
                  const int               font_size=10,             // font size 
                  const color             clr=clrBlack,             // text color 
                  const color             back_clr=C'236,233,216',  // background color 
                  const color             border_clr=clrNONE,       // border color 
                  const bool              state=true,               // pressed/released 
                  const bool              back=false,               // in the background 
                  const bool              selection=false,          // highlight to move 
                  const bool              hidden=true,              // hidden in the object list 
                  const long              z_order=0)                // priority for mouse click 
  { 
//--- reset the error value 
   ResetLastError(); 
//--- create the button 
   if(!ObjectCreate(chart_ID,name,OBJ_BUTTON,sub_window,0,0)) 
     { 
      Print(__FUNCTION__, 
            ": failed to create the button! Error code = ",GetLastError()); 
      return(false); 
     } 
//--- set button coordinates 
   ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); 
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); 
//--- set button size 
   ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width); 
   ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height); 
//--- set the chart's corner, relative to which point coordinates are defined 
   ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); 
//--- set the text 
   ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); 
//--- set text font 
   ObjectSetString(chart_ID,name,OBJPROP_FONT,font); 
//--- set font size 
   ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); 
//--- set text color 
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- set background color 
   ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr); 
//--- set border color 
   ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr); 
//--- display in the foreground (false) or background (true) 
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- set button state 
   ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state); 
//--- enable (true) or disable (false) the mode of moving the button by mouse 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- hide (true) or display (false) graphical object name in the object list 
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- set the priority for receiving the event of a mouse click in the chart 
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- successful execution 
   return(true); 
  }


本記事の監修者・HT FX


2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。



この記事をシェアする

ホーム » FX自動売買基礎と応用 » MQLプログラミング言語でチャートにボタンを描画する方法