English Русский 中文 Deutsch Português
preview
エキスパートアドバイザー(EA)に指標を追加するための既製のテンプレート(第2部):出来高指標とビルウィリアムズの指標

エキスパートアドバイザー(EA)に指標を追加するための既製のテンプレート(第2部):出来高指標とビルウィリアムズの指標

MetaTrader 5 | 12 2月 2024, 10:14
271 0
Artyom Trishkin
Artyom Trishkin

内容


はじめに

この記事では、EAで指標を使用するための既製のテンプレートについての話題を続けます。ここでは、出来高指標とビルウィリアムズの指標をEAに接続して使用することについて見ていきます。本連載の第1回で作成したダッシュボードに、指標から受け取ったデータを表示します。パネルも改良されました。記事の最後に、その変更点と改善点を簡単に紹介します。

この記事では、検討中の各指標について、カスタムプログラムで使用するための既製のテンプレートを紹介します。

  • 入力変数とグローバル変数
  • 変数の初期化と指標ハンドルの作成
  • 初期化解除
  • 指標からEAのデータを受け取る
  • 取得したデータをダッシュボードに表示した例
本連載のすべての記事同様、この記事はあくまで参考であり、記事のコードをコピーペーストするだけで使用できるという実用的な利点があります。


出来高指標

出来高指標は出来高を説明します。外国為替市場では、「出来高」は時間間隔で発生したティック(価格の変動)の数を意味します。株式証券の場合、それは(契約や金銭面で)実行された取引の量を意味します。


Accumulation/Distribution(累積/分配)

累積/分配(A/D)は価格と出来高の変化によって決まります。出来高は、価格の変化における重み付け係数として機能します。係数(出来高)が大きいほど、(この期間の)価格変化の指標値への寄与が大きくなります。

実際、この指標は、より一般的に使用されているオンバランスボリューム指標のバラエティです。これらはどちらも、それぞれの出来高を測るための手段として、価格変化を確認する目的に使われます。

A/D指標の上昇は特定の証券の蓄積(買い)を意味します。買い数量の圧倒的なシェアが価格の上昇傾向に関連しているためです。多くの売買が下降トレンドの間におこなわれるので、この指標の下降や、売りが集まっていることを意味します。

A/D指標と証券価格のダイバージェンスは、後の価格変化の兆候を表します。一般に、上記のようなダイバージェンスの場合、指標が動いた方向に価格が動く傾向があります。そのため、もし指標が上がっているにもかかわらず価格が下がった場合、価格が変化することが予想されます。



パラメータ

指標ハンドルの作成にはiAD()関数が使用されます。

累積/分配指標のハンドルを返します。バッファは1つだけです。

int  iAD(
   string               symbol,             // symbol name
   ENUM_TIMEFRAMES      period,             // period
   ENUM_APPLIED_VOLUME  applied_volume      // type of volume used for calculations
   );

symbol

[in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

period

[in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

applied_volume

[in]使用されるボリューム。ENUM_APPLIED_VOLUMEのいずれかです。

指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用の指標からコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

指標を作成するために、EAで入力変数グローバル変数を宣言します。

//+------------------------------------------------------------------+
//|                                                 TestVolumeAD.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- enums
enum ENUM_LINE_STATE
  {
   LINE_STATE_NONE,        // Undefined state
   LINE_STATE_UP,          // Upward
   LINE_STATE_DOWN,        // Downward
   LINE_STATE_TURN_UP,     // Upward reversal
   LINE_STATE_TURN_DOWN,   // Downward reversal
   LINE_STATE_STOP_UP,     // Upward stop
   LINE_STATE_STOP_DOWN,   // Downward stop
   LINE_STATE_ABOVE,       // Above value
   LINE_STATE_UNDER,       // Below value
   LINE_STATE_CROSS_UP,    // Crossing value upwards
   LINE_STATE_CROSS_DOWN,  // Crossing value downwards
   LINE_STATE_TOUCH_BELOW, // Touching value from below 
   LINE_STATE_TOUCH_ABOVE, // Touch value from above
   LINE_STATE_EQUALS,      // Equal to value
  };
//--- input parameters
input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
//--- global variables
int      handle=INVALID_HANDLE;  // Indicator handle
int      ind_digits=0;           // Number of decimal places in the indicator values
string   ind_title;              // Indicator description

ENUM_LINE_STATE列挙は、指標ラインの状態(他の指標または任意のレベルの線に対する形状と位置)を簡単に取得するために作成されました。
列挙の詳細については、前回の記事のATRパラメータのセクションを参照してください。

EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスファイルをインクルードします

//+------------------------------------------------------------------+
//|                                                 TestVolumeAD.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- includes
#include <Dashboard\Dashboard.mqh>
//--- enums
enum ENUM_LINE_STATE
  {
   LINE_STATE_NONE,        // Undefined state
   LINE_STATE_UP,          // Upward
   LINE_STATE_DOWN,        // Downward
   LINE_STATE_TURN_UP,     // Upward reversal
   LINE_STATE_TURN_DOWN,   // Downward reversal
   LINE_STATE_STOP_UP,     // Upward stop
   LINE_STATE_STOP_DOWN,   // Downward stop
   LINE_STATE_ABOVE,       // Above value
   LINE_STATE_UNDER,       // Below value
   LINE_STATE_CROSS_UP,    // Crossing value upwards
   LINE_STATE_CROSS_DOWN,  // Crossing value downwards
   LINE_STATE_TOUCH_BELOW, // Touching value from below 
   LINE_STATE_TOUCH_ABOVE, // Touch value from above
   LINE_STATE_EQUALS,      // Equal to value
  };
//--- input parameters
input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
//--- global variables
int      handle=INVALID_HANDLE;  // Indicator handle
int      ind_digits=0;           // Number of decimal places in the indicator values
string   ind_title;              // Indicator description
//--- variables for the panel
int      mouse_bar_index;        // Index of the bar the data is taken from
CDashboard *panel=NULL;          // Pointer to the panel object


初期化

指標のグローバル変数の値を設定し、ハンドルを作成します。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);

//--- Indicator
//--- Set the indicator name and the number of decimal places
   ind_title="A/D";
   ind_digits=0;
//--- Create indicator handle
   ResetLastError();
   handle=iAD(Symbol(),PERIOD_CURRENT,InpVolume);
   if(handle==INVALID_HANDLE)
     {
      PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
      return INIT_FAILED;
     }

//--- Successful initialization
   return(INIT_SUCCEEDED);
  }

EAがダッシュボードを使用する場合は、ここで作成します

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);

//--- Indicator
//--- Set the indicator name and the number of decimal places
   ind_title="A/D";
   ind_digits=0;
//--- Create indicator handle
   ResetLastError();
   handle=iAD(Symbol(),PERIOD_CURRENT,InpVolume);
   if(handle==INVALID_HANDLE)
     {
      PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
      return INIT_FAILED;
     }

//--- Dashboard
//--- Create the panel
   panel=new CDashboard(1,20,20,199,225);
   if(panel==NULL)
     {
      Print("Error. Failed to create panel object");
      return INIT_FAILED;
     }
//--- Set font parameters
   panel.SetFontParams("Calibri",9);
//--- Display the panel with the "Symbol, Timeframe description" header text
   panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
//--- Create a table with ID 0 to display bar data in it
   panel.CreateNewTable(0);
//--- Draw a table with ID 0 on the panel background
   panel.DrawGrid(0,2,20,6,2,18,97);

//--- Create a table with ID 1 to display indicator data in it
   panel.CreateNewTable(1);
//--- Get the Y2 table coordinate with ID 0 and
//--- set the Y1 coordinate for the table with ID 1
   int y1=panel.TableY2(0)+22;
//--- Draw a table with ID 1 on the panel background
   panel.DrawGrid(1,2,y1,3,2,18,97);
   
//--- Display tabular data in the journal
   panel.GridPrint(0,2);
   panel.GridPrint(1,2);
//--- Initialize the variable with the index of the mouse cursor bar
   mouse_bar_index=0;
//--- Display the data of the current bar on the panel
   DrawData(mouse_bar_index,TimeCurrent());

//--- Successful initialization
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+


初期化解除

EA OnDeinit()ハンドルの指標ハンドルを解放します

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
//--- Release handle of the indicator
   ResetLastError();
   if(!IndicatorRelease(handle))
      PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
//--- Clear all comments on the chart
   Comment("");
  }

作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
//--- Release handle of the indicator
   ResetLastError();
   if(!IndicatorRelease(handle))
      PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
//--- Clear all comments on the chart
   Comment("");
   
//--- If the panel object exists, delete it
   if(panel!=NULL)
      delete panel;
  }


データ検索

指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

//+------------------------------------------------------------------+
//| Return the indicator data on the specified bar                   |
//+------------------------------------------------------------------+
double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
  {
   double array[1]={0};
   ResetLastError();
   if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
     {
      PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
      return EMPTY_VALUE;
     }
   return array[0];
  }
//+------------------------------------------------------------------+
//| Return the state of the indicator line                           |
//+------------------------------------------------------------------+
ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
  {
//--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
   const double value0=IndicatorValue(ind_handle,index,  buffer_num);
   const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
   const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
//--- If at least one of the values could not be obtained, return an undefined value 
   if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
      return LINE_STATE_NONE;
//--- Line upward reversal (value2>value1 && value0>value1)
   if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
      return LINE_STATE_TURN_UP;
//--- Line upward direction (value2<=value1 && value0>value1)
   else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
      return LINE_STATE_UP;
//--- Line upward stop (value2<=value1 && value0==value1)
   else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
      return LINE_STATE_STOP_UP;
//--- Line downward reversal (value2<value1 && value0<value1)
   if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
      return LINE_STATE_TURN_DOWN;
//--- Line downward direction (value2>=value1 && value0<value1)
   else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
      return LINE_STATE_DOWN;
//--- Line downward stop (value2>=value1 && value0==value1)
   else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
      return LINE_STATE_STOP_DOWN;
//--- Undefined state
   return LINE_STATE_NONE;
  }
//+------------------------------------------------------------------+
//| Return the state of the line relative to the specified level     |
//+------------------------------------------------------------------+
ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
  {
//--- Get the values of the indicator line with the shift (0,1) relative to the passed index
   const double value0=IndicatorValue(ind_handle,index,  buffer_num);
   const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
//--- If at least one of the values could not be obtained, return an undefined value 
   if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
      return LINE_STATE_NONE;
//--- Define the second level to compare
   double level=(level1==EMPTY_VALUE ? level0 : level1);
//--- The line is below the level (value1<level && value0<level0)
   if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
      return LINE_STATE_UNDER;
//--- The line is above the level (value1>level && value0>level0)
   if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
      return LINE_STATE_ABOVE;
//--- The line crossed the level upwards (value1<=level && value0>level0)
   if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
      return LINE_STATE_CROSS_UP;
//--- The line crossed the level downwards (value1>=level && value0<level0)
   if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
      return LINE_STATE_CROSS_DOWN;
//--- The line touched the level from below (value1<level0 && value0==level0)
   if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
      return LINE_STATE_TOUCH_BELOW;
//--- The line touched the level from above (value1>level0 && value0==level0)
   if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
      return LINE_STATE_TOUCH_BELOW;
//--- Line is equal to the level value (value1==level0 && value0==level0)
   if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
      return LINE_STATE_EQUALS;
//--- Undefined state
   return LINE_STATE_NONE;
  }
//+------------------------------------------------------------------+
//| Return the indicator line state description                      |
//+------------------------------------------------------------------+
string LineStateDescription(const ENUM_LINE_STATE state)
  {
   switch(state)
     {
      case LINE_STATE_UP         :  return "Up";
      case LINE_STATE_STOP_UP    :  return "Stop Up";
      case LINE_STATE_TURN_UP    :  return "Turn Up";
      case LINE_STATE_DOWN       :  return "Down";
      case LINE_STATE_STOP_DOWN  :  return "Stop Down";
      case LINE_STATE_TURN_DOWN  :  return "Turn Down";
      case LINE_STATE_ABOVE      :  return "Above level";
      case LINE_STATE_UNDER      :  return "Under level";
      case LINE_STATE_CROSS_UP   :  return "Crossing Up";
      case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
      case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
      case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
      case LINE_STATE_EQUALS     :  return "Equals";
      default                    :  return "Unknown";
     }
  }

ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

//+------------------------------------------------------------------+
//| Display data from the specified timeseries index to the panel    |
//+------------------------------------------------------------------+
void DrawData(const int index,const datetime time)
  {
//--- Declare the variables to receive data in them
   MqlTick  tick={0};
   MqlRates rates[1];

//--- Exit if unable to get the current prices
   if(!SymbolInfoTick(Symbol(),tick))
      return;
//--- Exit if unable to get the bar data by the specified index
   if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
      return;

//--- Set font parameters for bar and indicator data headers
   int  size=0;
   uint flags=0;
   uint angle=0;
   string name=panel.FontParams(size,flags,angle);
   panel.SetFontParams(name,9,FW_BOLD);
   panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
   panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
//--- Set font parameters for bar and indicator data
   panel.SetFontParams(name,9);

//--- Display the data of the specified bar in table 0 on the panel
   panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
   panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
   panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
   panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
   panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
   panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);

//--- Display the indicator data from the specified bar on the panel in table 1
   panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
   double value=IndicatorValue(handle,index,0);
   string value_str=(value!=EMPTY_VALUE ? DoubleToString(value,ind_digits) : "");
   panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
   
//--- Display a description of the indicator line state
   panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
   ENUM_LINE_STATE state=LineState(handle,index,0);
   panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,90);
   
//--- Redraw the chart to immediately display all changes on the panel
   ChartRedraw(ChartID());
  }

その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- Handling the panel
//--- Call the panel event handler
   panel.OnChartEvent(id,lparam,dparam,sparam);

//--- If the cursor moves or a click is made on the chart
   if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
     {
      //--- Declare the variables to record time and price coordinates in them
      datetime time=0;
      double price=0;
      int wnd=0;
      //--- If the cursor coordinates are converted to date and time
      if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
        {
         //--- write the bar index where the cursor is located to a global variable
         mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
         //--- Display the bar data under the cursor on the panel 
         DrawData(mouse_bar_index,time);
        }
     }

//--- If we received a custom event, display the appropriate message in the journal
   if(id>CHARTEVENT_CUSTOM)
     {
      //--- Here we can implement handling a click on the close button on the panel
      PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
     }
  }

EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


TestVolumeAD.mq5テストEAは、記事に添付されているファイルに含まれています。


Money Flow Index(マネーフローインデックス)

マネーフローインデックス(MFI)は、ある証券に資金が投資され、その証券から資金が引き出される割合を示すテクニカル指標です。この指標の構成と解釈はRSI(相対力指数)と似ており、MFIでは出来高が重要である点が異なるだけです。

MFIを分析するには、下記の点に注意しなくてはなりません。

  • 指標と価格のダイバージェンス(価格が上がったにも関わらず、MFIが下がった場合(もしくはそれぞれ逆の場合)、価格が転換する可能性が非常に高い)
  • 80以上、20以下のMFI値は、相場が天井か底にある可能性を示唆している



    パラメータ

    指標ハンドルの作成にはiMFI()関数が使用されます。

    int  iMFI(
       string               symbol,             // symbol name
       ENUM_TIMEFRAMES      period,             // period
       int                  ma_period,          // averaging period
       ENUM_APPLIED_VOLUME  applied_volume      // type of volume used for calculations
       );
    

    symbol

    [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

    period

    [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

    ma_period

    [in]指標の計算期間(バー数)

    applied_volume

    [in]使用されるボリューム。ENUM_APPLIED_VOLUMEのいずれかです。

    指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

    指標を作成するために、EAで入力変数グローバル変数を宣言します。

    //+------------------------------------------------------------------+
    //|                                                TestVolumeMFI.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input uint                 InpPeriod   =  14;            /* Period         */
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    input double               InpOverbough=  80;            /* Overbough level*/
    input double               InpOversold =  20;            /* Oversold level */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      period=0;               // RSI calculation period
    int      ind_digits=0;           // Number of decimal places in the indicator values
    double   overbough=0;            // Overbought level
    double   oversold=0;             // Oversold level
    string   ind_title;              // Indicator description
    
    

    EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

    //+------------------------------------------------------------------+
    //|                                                TestVolumeMFI.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- includes
    #include <Dashboard\Dashboard.mqh>
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input uint                 InpPeriod   =  14;            /* Period         */
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    input double               InpOverbough=  80;            /* Overbough level*/
    input double               InpOversold =  20;            /* Oversold level */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      period=0;               // RSI calculation period
    int      ind_digits=0;           // Number of decimal places in the indicator values
    double   overbough=0;            // Overbought level
    double   oversold=0;             // Oversold level
    string   ind_title;              // Indicator description
    //--- variables for the panel
    int      mouse_bar_index;        // Index of the bar the data is taken from
    CDashboard *panel=NULL;          // Pointer to the panel object
    
    


    初期化

    指標のグローバル変数の値を設定し、ハンドルを作成します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set and adjust the calculation period and levels if necessary
       period=int(InpPeriod<1 ? 14 : InpPeriod);
       overbough=InpOverbough;
       oversold=(InpOversold>=overbough ? overbough-0.01 : InpOversold);
    //--- Set the indicator name and the number of decimal places
       ind_title=StringFormat("MFI(%lu)",period);
       ind_digits=Digits();
    //--- Create indicator handle
       ResetLastError();
       handle=iMFI(Symbol(),PERIOD_CURRENT,period,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    

    EAがダッシュボードを使用する場合は、ここで作成します

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set and adjust the calculation period and levels if necessary
       period=int(InpPeriod<1 ? 14 : InpPeriod);
       overbough=InpOverbough;
       oversold=(InpOversold>=overbough ? overbough-0.01 : InpOversold);
    //--- Set the indicator name and the number of decimal places
       ind_title=StringFormat("MFI(%lu)",period);
       ind_digits=Digits();
    //--- Create indicator handle
       ResetLastError();
       handle=iMFI(Symbol(),PERIOD_CURRENT,period,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Dashboard
    //--- Create the panel
       panel=new CDashboard(1,20,20,229,243);
       if(panel==NULL)
         {
          Print("Error. Failed to create panel object");
          return INIT_FAILED;
         }
    //--- Set font parameters
       panel.SetFontParams("Calibri",9);
    //--- Display the panel with the "Symbol, Timeframe description" header text
       panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
    //--- Create a table with ID 0 to display bar data in it
       panel.CreateNewTable(0);
    //--- Draw a table with ID 0 on the panel background
       panel.DrawGrid(0,2,20,6,2,18,112);
    
    //--- Create a table with ID 1 to display indicator data in it
       panel.CreateNewTable(1);
    //--- Get the Y2 table coordinate with ID 0 and
    //--- set the Y1 coordinate for the table with ID 1
       int y1=panel.TableY2(0)+22;
    //--- Draw a table with ID 1 on the panel background
       panel.DrawGrid(1,2,y1,4,2,18,112);
       
    //--- Display tabular data in the journal
       panel.GridPrint(0,2);
       panel.GridPrint(1,2);
    //--- Initialize the variable with the index of the mouse cursor bar
       mouse_bar_index=0;
    //--- Display the data of the current bar on the panel
       DrawData(mouse_bar_index,TimeCurrent());
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    


    初期化解除

    EA OnDeinit()ハンドルの指標ハンドルを解放します

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
      }
    
    

    作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
       
    //--- If the panel object exists, delete it
       if(panel!=NULL)
          delete panel;
      }
    


    データ検索

    指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

    //+------------------------------------------------------------------+
    //| Return the indicator data on the specified bar                   |
    //+------------------------------------------------------------------+
    double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
      {
       double array[1]={0};
       ResetLastError();
       if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
         {
          PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
          return EMPTY_VALUE;
         }
       return array[0];
      }
    //+------------------------------------------------------------------+
    //| Return the state of the indicator line                           |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
      {
    //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
       const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Line upward reversal (value2>value1 && value0>value1)
       if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_TURN_UP;
    //--- Line upward direction (value2<=value1 && value0>value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_UP;
    //--- Line upward stop (value2<=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_UP;
    //--- Line downward reversal (value2<value1 && value0<value1)
       if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_TURN_DOWN;
    //--- Line downward direction (value2>=value1 && value0<value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_DOWN;
    //--- Line downward stop (value2>=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_DOWN;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the state of the line relative to the specified level     |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
      {
    //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Define the second level to compare
       double level=(level1==EMPTY_VALUE ? level0 : level1);
    //--- The line is below the level (value1<level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_UNDER;
    //--- The line is above the level (value1>level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_ABOVE;
    //--- The line crossed the level upwards (value1<=level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_CROSS_UP;
    //--- The line crossed the level downwards (value1>=level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_CROSS_DOWN;
    //--- The line touched the level from below (value1<level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- The line touched the level from above (value1>level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- Line is equal to the level value (value1==level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_EQUALS;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the indicator line state description                      |
    //+------------------------------------------------------------------+
    string LineStateDescription(const ENUM_LINE_STATE state)
      {
       switch(state)
         {
          case LINE_STATE_UP         :  return "Up";
          case LINE_STATE_STOP_UP    :  return "Stop Up";
          case LINE_STATE_TURN_UP    :  return "Turn Up";
          case LINE_STATE_DOWN       :  return "Down";
          case LINE_STATE_STOP_DOWN  :  return "Stop Down";
          case LINE_STATE_TURN_DOWN  :  return "Turn Down";
          case LINE_STATE_ABOVE      :  return "Above level";
          case LINE_STATE_UNDER      :  return "Under level";
          case LINE_STATE_CROSS_UP   :  return "Crossing Up";
          case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
          case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
          case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
          case LINE_STATE_EQUALS     :  return "Equals";
          default                    :  return "Unknown";
         }
      }
    
    

    ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

    //+------------------------------------------------------------------+
    //| Display data from the specified timeseries index to the panel    |
    //+------------------------------------------------------------------+
    void DrawData(const int index,const datetime time)
      {
    //--- Declare the variables to receive data in them
       MqlTick  tick={0};
       MqlRates rates[1];
    
    //--- Exit if unable to get the current prices
       if(!SymbolInfoTick(Symbol(),tick))
          return;
    //--- Exit if unable to get the bar data by the specified index
       if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
          return;
    
    //--- Set font parameters for bar and indicator data headers
       int  size=0;
       uint flags=0;
       uint angle=0;
       string name=panel.FontParams(size,flags,angle);
       panel.SetFontParams(name,9,FW_BOLD);
       panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
       panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
    //--- Set font parameters for bar and indicator data
       panel.SetFontParams(name,9);
    
    //--- Display the data of the specified bar in table 0 on the panel
       panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
       panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
       panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
       panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
       panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
       panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
    
    //--- Display the indicator data from the specified bar on the panel in table 1
       panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
       double value=IndicatorValue(handle,index,0);
       string value_str=(value!=EMPTY_VALUE ? DoubleToString(value,ind_digits) : "");
       panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,100);
       
    //--- Display a description of the indicator line state relative to the overbought level
       string ovb=StringFormat("%+.2f",overbough);
       panel.DrawText("Overbough", panel.CellX(1,2,0)+2, panel.CellY(1,2,0)+2);
       panel.DrawText(ovb, panel.CellX(1,2,0)+66, panel.CellY(1,2,0)+2);
       ENUM_LINE_STATE state_ovb=LineStateRelative(handle,index,0,overbough);
    //--- The label color changes depending on the value of the line relative to the level
       color clr=(state_ovb==LINE_STATE_CROSS_DOWN ? clrRed : clrNONE);
       string ovb_str=(state_ovb==LINE_STATE_ABOVE ? "Inside the area" : LineStateDescription(state_ovb));
       panel.DrawText(ovb_str,panel.CellX(1,2,1)+2,panel.CellY(1,2,1)+2,clr,100);
       
    //--- Display a description of the indicator line state relative to the oversold level
       panel.DrawText("Oversold", panel.CellX(1,3,0)+2, panel.CellY(1,3,0)+2);
       string ovs=StringFormat("%+.2f",oversold);
       panel.DrawText(ovs, panel.CellX(1,3,0)+68, panel.CellY(1,3,0)+2);
       ENUM_LINE_STATE state_ovs=LineStateRelative(handle,index,0,oversold);
    //--- The label color changes depending on the value of the line relative to the level
       clr=(state_ovs==LINE_STATE_CROSS_UP ? clrBlue : clrNONE);
       string ovs_str=(state_ovs==LINE_STATE_UNDER ? "Inside the area" : LineStateDescription(state_ovs));
       panel.DrawText(ovs_str,panel.CellX(1,3,1)+2,panel.CellY(1,3,1)+2,clr,100);
       
    //--- Display a description of the indicator line state
       panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
       ENUM_LINE_STATE state=LineState(handle,index,0);
    //--- The label color changes depending on the location of the line in the overbought/oversold areas
       clr=(state_ovb==LINE_STATE_ABOVE || state_ovb==LINE_STATE_CROSS_DOWN ? clrRed : state_ovs==LINE_STATE_UNDER || state_ovs==LINE_STATE_CROSS_UP ? clrBlue : clrNONE);
       panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,100);
       
    //--- Redraw the chart to immediately display all changes on the panel
       ChartRedraw(ChartID());
      }
    
    

    買われすぎ/売られすぎのエリアにおける指標ラインの位置は、パネル上に文字色で表示されます。

    その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //--- Handling the panel
    //--- Call the panel event handler
       panel.OnChartEvent(id,lparam,dparam,sparam);
    
    //--- If the cursor moves or a click is made on the chart
       if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
         {
          //--- Declare the variables to record time and price coordinates in them
          datetime time=0;
          double price=0;
          int wnd=0;
          //--- If the cursor coordinates are converted to date and time
          if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
            {
             //--- write the bar index where the cursor is located to a global variable
             mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
             //--- Display the bar data under the cursor on the panel 
             DrawData(mouse_bar_index,time);
            }
         }
    
    //--- If we received a custom event, display the appropriate message in the journal
       if(id>CHARTEVENT_CUSTOM)
         {
          //--- Here we can implement handling a click on the close button on the panel
          PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
         }
      }
    
    

    EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


    TestVolumeMFI.mq5テストEAは、記事に添付されているファイルに含まれています。


    On Balance Volume(オンバランスボリューム)

    オンバランスボリューム(OBV)は、出来高と価格変動を関連付けるモメンタムテクニカル指標です。Joseph Granvilleが考案したこの指標はとてもシンプルです。現在足の終値が1つ前の足の終値よりも高い場合、現在足の出来高が1つ前のOBVに加算されます。現在足の終値が1つ前の足の終値よりも低い場合、現在足の出来高が1つ前のOBVから減算されます。

    オンバランスボリュームの分析での基本的な前提は、OBVの変化は価格の変化に先立つということです。OBVが上昇することによって、投資金が株価に流れるという考え方です。大多数がその後資金を投入すると、株価とオンバランスボリュームがどちらも上昇します。

    株価の動きがOBVの動きに先だった場合「非確認」が起こります。非確認は、ブル市場の天井で(株価がOBVの上昇なしで上昇した時)起こります。また、ベア市場の底でも(株価がOBVの追随なしに下落した時)起こります。

    新しい天井が次々と上昇し、新しい底が次々と上昇している時、OBVは上昇トレンドにあります。同じように、連続した天井が次々に下がり、連続した底が次々に下がっていく時、OBVは下降トレンドにあります。OBVが横這いし、相次ぐ新しい高値や安値が形成されない場合、トレンドはありません。

    一度トレンドが形成されると、トレンドが消滅するまでその効力を維持します。OBVのトレンドが消失するケースは2つあります。1つ目のケースは、トレンドが上昇トレンドから下降トレンドに変わる時、もしくは、トレンドが下降トレンドから上昇トレンドに変わる時に起こります。

    トレンドが消失する2つ目のケースは、そのトレンドがはっきりしないトレンドになった時、もしくは、3日以上トレンドがはっきりしない時です。したがって、証券が上昇傾向から疑わしい傾向に変化し、上昇傾向に戻る前に疑わしい状態が2日間だけ続いた場合、オンバランスボリュームは常に上昇傾向にあったと見なされます。OBVが上昇トレンドまたは下降トレンドに変化したときは、「ブレイクアウト」が発生しています。

    OBVのブレイクアウトは一般的に価格のブレイクアウトに先行するので、投資家はOBVが上にブレイクアウトした時には買い注文を出すべきです。同様に、OBVが下にブレイクアウトした時には売り注文を出すべきです。ポジションはトレンドが変化するまで保持されるべきです。



    パラメータ

    指標ハンドルの作成にはiOBV()関数が使用されます。

    オンバランスボリューム指標のハンドルを戻します。バッファは1つだけです。

    int  iOBV(
       string                symbol,             // symbol name
       ENUM_TIMEFRAMES       period,             // period
       ENUM_APPLIED_VOLUME   applied_volume      // type of volume used for calculations
       );
    
    symbol

    [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

    period

    [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

    applied_volume

    [in]使用されるボリューム。ENUM_APPLIED_VOLUME列挙値のいずれかです。

    指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

    指標を作成するために、EAで入力変数とグローバル変数を宣言します。

    //+------------------------------------------------------------------+
    //|                                                TestVolumeOBV.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    
    

    EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

    //+------------------------------------------------------------------+
    //|                                                TestVolumeOBV.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- includes
    #include <Dashboard\Dashboard.mqh>
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    //--- variables for the panel
    int      mouse_bar_index;        // Index of the bar the data is taken from
    CDashboard *panel=NULL;          // Pointer to the panel object
    
    


    初期化

    指標のグローバル変数の値を設定し、ハンドルを作成します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="OBV";
       ind_digits=0;
    //--- Create indicator handle
       ResetLastError();
       handle=iOBV(Symbol(),PERIOD_CURRENT,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    

    EAがダッシュボードを使用する場合は、ここで作成します

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="OBV";
       ind_digits=0;
    //--- Create indicator handle
       ResetLastError();
       handle=iOBV(Symbol(),PERIOD_CURRENT,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Dashboard
    //--- Create the panel
       panel=new CDashboard(1,20,20,199,225);
       if(panel==NULL)
         {
          Print("Error. Failed to create panel object");
          return INIT_FAILED;
         }
    //--- Set font parameters
       panel.SetFontParams("Calibri",9);
    //--- Display the panel with the "Symbol, Timeframe description" header text
       panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
    //--- Create a table with ID 0 to display bar data in it
       panel.CreateNewTable(0);
    //--- Draw a table with ID 0 on the panel background
       panel.DrawGrid(0,2,20,6,2,18,97);
    
    //--- Create a table with ID 1 to display indicator data in it
       panel.CreateNewTable(1);
    //--- Get the Y2 table coordinate with ID 0 and
    //--- set the Y1 coordinate for the table with ID 1
       int y1=panel.TableY2(0)+22;
    //--- Draw a table with ID 1 on the panel background
       panel.DrawGrid(1,2,y1,3,2,18,97);
       
    //--- Display tabular data in the journal
       panel.GridPrint(0,2);
       panel.GridPrint(1,2);
    //--- Initialize the variable with the index of the mouse cursor bar
       mouse_bar_index=0;
    //--- Display the data of the current bar on the panel
       DrawData(mouse_bar_index,TimeCurrent());
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    


    初期化解除

    EA OnDeinit()ハンドルの指標ハンドルを解放します

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
      }
    
    

    作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
       
    //--- If the panel object exists, delete it
       if(panel!=NULL)
          delete panel;
      }
    


    データ検索

    指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

    //+------------------------------------------------------------------+
    //| Return the indicator data on the specified bar                   |
    //+------------------------------------------------------------------+
    double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
      {
       double array[1]={0};
       ResetLastError();
       if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
         {
          PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
          return EMPTY_VALUE;
         }
       return array[0];
      }
    //+------------------------------------------------------------------+
    //| Return the state of the indicator line                           |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
      {
    //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
       const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Line upward reversal (value2>value1 && value0>value1)
       if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_TURN_UP;
    //--- Line upward direction (value2<=value1 && value0>value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_UP;
    //--- Line upward stop (value2<=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_UP;
    //--- Line downward reversal (value2<value1 && value0<value1)
       if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_TURN_DOWN;
    //--- Line downward direction (value2>=value1 && value0<value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_DOWN;
    //--- Line downward stop (value2>=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_DOWN;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the state of the line relative to the specified level     |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
      {
    //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Define the second level to compare
       double level=(level1==EMPTY_VALUE ? level0 : level1);
    //--- The line is below the level (value1<level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_UNDER;
    //--- The line is above the level (value1>level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_ABOVE;
    //--- The line crossed the level upwards (value1<=level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_CROSS_UP;
    //--- The line crossed the level downwards (value1>=level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_CROSS_DOWN;
    //--- The line touched the level from below (value1<level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- The line touched the level from above (value1>level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- Line is equal to the level value (value1==level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_EQUALS;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the indicator line state description                      |
    //+------------------------------------------------------------------+
    string LineStateDescription(const ENUM_LINE_STATE state)
      {
       switch(state)
         {
          case LINE_STATE_UP         :  return "Up";
          case LINE_STATE_STOP_UP    :  return "Stop Up";
          case LINE_STATE_TURN_UP    :  return "Turn Up";
          case LINE_STATE_DOWN       :  return "Down";
          case LINE_STATE_STOP_DOWN  :  return "Stop Down";
          case LINE_STATE_TURN_DOWN  :  return "Turn Down";
          case LINE_STATE_ABOVE      :  return "Above level";
          case LINE_STATE_UNDER      :  return "Under level";
          case LINE_STATE_CROSS_UP   :  return "Crossing Up";
          case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
          case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
          case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
          case LINE_STATE_EQUALS     :  return "Equals";
          default                    :  return "Unknown";
         }
      }
    
    

    ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

    //+------------------------------------------------------------------+
    //| Display data from the specified timeseries index to the panel    |
    //+------------------------------------------------------------------+
    void DrawData(const int index,const datetime time)
      {
    //--- Declare the variables to receive data in them
       MqlTick  tick={0};
       MqlRates rates[1];
    
    //--- Exit if unable to get the current prices
       if(!SymbolInfoTick(Symbol(),tick))
          return;
    //--- Exit if unable to get the bar data by the specified index
       if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
          return;
    
    //--- Set font parameters for bar and indicator data headers
       int  size=0;
       uint flags=0;
       uint angle=0;
       string name=panel.FontParams(size,flags,angle);
       panel.SetFontParams(name,9,FW_BOLD);
       panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
       panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
    //--- Set font parameters for bar and indicator data
       panel.SetFontParams(name,9);
    
    //--- Display the data of the specified bar in table 0 on the panel
       panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
       panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
       panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
       panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
       panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
       panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
    
    //--- Display the indicator data from the specified bar on the panel in table 1
       panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
       double value=IndicatorValue(handle,index,0);
       string value_str=(value!=EMPTY_VALUE ? DoubleToString(value,ind_digits) : "");
       panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
       
    //--- Display a description of the indicator line state
       panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
       ENUM_LINE_STATE state=LineState(handle,index,0);
       panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,90);
       
    //--- Redraw the chart to immediately display all changes on the panel
       ChartRedraw(ChartID());
      }
    
    

    その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //--- Handling the panel
    //--- Call the panel event handler
       panel.OnChartEvent(id,lparam,dparam,sparam);
    
    //--- If the cursor moves or a click is made on the chart
       if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
         {
          //--- Declare the variables to record time and price coordinates in them
          datetime time=0;
          double price=0;
          int wnd=0;
          //--- If the cursor coordinates are converted to date and time
          if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
            {
             //--- write the bar index where the cursor is located to a global variable
             mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
             //--- Display the bar data under the cursor on the panel 
             DrawData(mouse_bar_index,time);
            }
         }
    
    //--- If we received a custom event, display the appropriate message in the journal
       if(id>CHARTEVENT_CUSTOM)
         {
          //--- Here we can implement handling a click on the close button on the panel
          PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
         }
      }
    
    

    EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


    TestVolumeOBV.mq5テストEAは、記事に添付されているファイルに含まれています。


    Volume(ボリューム)

    外国為替市場では、出来高指標は、選択された時間枠の各期間内の価格変動の数を示す指標です。株式銘柄については、これは実際に取引された出来高(契約、お金、ユニットなど)の指標です。



    パラメータ

    指標ハンドルの作成にはiVolumes()関数が使用されます。

    出来高を表す指標のハンドルを返します。バッファは1つだけです。

    int  iVolumes(
       string               symbol,             // symbol name
       ENUM_TIMEFRAMES      period,             // period
       ENUM_APPLIED_VOLUME  applied_volume      // volume type
       )
    

    symbol

    [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

    period

    [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

    applied_volume

    [in]使用されるボリューム。ENUM_APPLIED_VOLUME列挙値のいずれかです。

    指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

    指標を作成するために、EAで入力変数とグローバル変数を宣言します。

    //+------------------------------------------------------------------+
    //|                                                TestVolumeOBV.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    
    

    EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

    //+------------------------------------------------------------------+
    //|                                                TestVolumeOBV.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- includes
    #include <Dashboard\Dashboard.mqh>
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    //--- variables for the panel
    int      mouse_bar_index;        // Index of the bar the data is taken from
    CDashboard *panel=NULL;          // Pointer to the panel object
    
    


    初期化

    指標のグローバル変数の値を設定し、ハンドルを作成します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="Volumes";
       ind_digits=0;
    //--- Create indicator handle
       ResetLastError();
       handle=iVolumes(Symbol(),PERIOD_CURRENT,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    

    EAがダッシュボードを使用する場合は、ここで作成します

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="Volumes";
       ind_digits=0;
    //--- Create indicator handle
       ResetLastError();
       handle=iVolumes(Symbol(),PERIOD_CURRENT,InpVolume);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Dashboard
    //--- Create the panel
       panel=new CDashboard(1,20,20,199,225);
       if(panel==NULL)
         {
          Print("Error. Failed to create panel object");
          return INIT_FAILED;
         }
    //--- Set font parameters
       panel.SetFontParams("Calibri",9);
    //--- Display the panel with the "Symbol, Timeframe description" header text
       panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
    //--- Create a table with ID 0 to display bar data in it
       panel.CreateNewTable(0);
    //--- Draw a table with ID 0 on the panel background
       panel.DrawGrid(0,2,20,6,2,18,97);
    
    //--- Create a table with ID 1 to display indicator data in it
       panel.CreateNewTable(1);
    //--- Get the Y2 table coordinate with ID 0 and
    //--- set the Y1 coordinate for the table with ID 1
       int y1=panel.TableY2(0)+22;
    //--- Draw a table with ID 1 on the panel background
       panel.DrawGrid(1,2,y1,3,2,18,97);
       
    //--- Display tabular data in the journal
       panel.GridPrint(0,2);
       panel.GridPrint(1,2);
    //--- Initialize the variable with the index of the mouse cursor bar
       mouse_bar_index=0;
    //--- Display the data of the current bar on the panel
       DrawData(mouse_bar_index,TimeCurrent());
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    


    初期化解除

    EA OnDeinit()ハンドルの指標ハンドルを解放します

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
      }
    
    

    作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
       
    //--- If the panel object exists, delete it
       if(panel!=NULL)
          delete panel;
      }
    


    データ検索

    指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

    //+------------------------------------------------------------------+
    //| Return the indicator data on the specified bar                   |
    //+------------------------------------------------------------------+
    double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
      {
       double array[1]={0};
       ResetLastError();
       if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
         {
          PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
          return EMPTY_VALUE;
         }
       return array[0];
      }
    //+------------------------------------------------------------------+
    //| Return the state of the indicator line                           |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
      {
    //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
       const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Line upward reversal (value2>value1 && value0>value1)
       if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_TURN_UP;
    //--- Line upward direction (value2<=value1 && value0>value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_UP;
    //--- Line upward stop (value2<=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_UP;
    //--- Line downward reversal (value2<value1 && value0<value1)
       if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_TURN_DOWN;
    //--- Line downward direction (value2>=value1 && value0<value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_DOWN;
    //--- Line downward stop (value2>=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_DOWN;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the state of the line relative to the specified level     |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
      {
    //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Define the second level to compare
       double level=(level1==EMPTY_VALUE ? level0 : level1);
    //--- The line is below the level (value1<level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_UNDER;
    //--- The line is above the level (value1>level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_ABOVE;
    //--- The line crossed the level upwards (value1<=level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_CROSS_UP;
    //--- The line crossed the level downwards (value1>=level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_CROSS_DOWN;
    //--- The line touched the level from below (value1<level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- The line touched the level from above (value1>level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- Line is equal to the level value (value1==level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_EQUALS;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the indicator line state description                      |
    //+------------------------------------------------------------------+
    string LineStateDescription(const ENUM_LINE_STATE state)
      {
       switch(state)
         {
          case LINE_STATE_UP         :  return "Up";
          case LINE_STATE_STOP_UP    :  return "Stop Up";
          case LINE_STATE_TURN_UP    :  return "Turn Up";
          case LINE_STATE_DOWN       :  return "Down";
          case LINE_STATE_STOP_DOWN  :  return "Stop Down";
          case LINE_STATE_TURN_DOWN  :  return "Turn Down";
          case LINE_STATE_ABOVE      :  return "Above level";
          case LINE_STATE_UNDER      :  return "Under level";
          case LINE_STATE_CROSS_UP   :  return "Crossing Up";
          case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
          case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
          case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
          case LINE_STATE_EQUALS     :  return "Equals";
          default                    :  return "Unknown";
         }
      }
    
    

    ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

    //+------------------------------------------------------------------+
    //| Display data from the specified timeseries index to the panel    |
    //+------------------------------------------------------------------+
    void DrawData(const int index,const datetime time)
      {
    //--- Declare the variables to receive data in them
       MqlTick  tick={0};
       MqlRates rates[1];
    
    //--- Exit if unable to get the current prices
       if(!SymbolInfoTick(Symbol(),tick))
          return;
    //--- Exit if unable to get the bar data by the specified index
       if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
          return;
    
    //--- Set font parameters for bar and indicator data headers
       int  size=0;
       uint flags=0;
       uint angle=0;
       string name=panel.FontParams(size,flags,angle);
       panel.SetFontParams(name,9,FW_BOLD);
       panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
       panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
    //--- Set font parameters for bar and indicator data
       panel.SetFontParams(name,9);
    
    //--- Display the data of the specified bar in table 0 on the panel
       panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
       panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
       panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
       panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
       panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
       panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
    
    //--- Display the indicator data from the specified bar on the panel in table 1
       panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
       double value0=IndicatorValue(handle,index,  0);
       double value1=IndicatorValue(handle,index+1,0);
       string value_str=(value0!=EMPTY_VALUE ? DoubleToString(value0,ind_digits) : "");
       color clr=(value0>value1 ? clrGreen : value0<value1 ? clrRed : clrNONE);
       panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
       
    //--- Display a description of the indicator line state
       panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
       ENUM_LINE_STATE state=LineState(handle,index,0);
       panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,90);
       
    //--- Redraw the chart to immediately display all changes on the panel
       ChartRedraw(ChartID());
      }
    
    

    パネル上のステータステキストの色は、カーソルが置かれている指標列の色に対応します。

    その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //--- Handling the panel
    //--- Call the panel event handler
       panel.OnChartEvent(id,lparam,dparam,sparam);
    
    //--- If the cursor moves or a click is made on the chart
       if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
         {
          //--- Declare the variables to record time and price coordinates in them
          datetime time=0;
          double price=0;
          int wnd=0;
          //--- If the cursor coordinates are converted to date and time
          if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
            {
             //--- write the bar index where the cursor is located to a global variable
             mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
             //--- Display the bar data under the cursor on the panel 
             DrawData(mouse_bar_index,time);
            }
         }
    
    //--- If we received a custom event, display the appropriate message in the journal
       if(id>CHARTEVENT_CUSTOM)
         {
          //--- Here we can implement handling a click on the close button on the panel
          PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
         }
      }
    
    

    EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


    TestVolumeVolumes.mq5のテストEAは、記事に添付されているファイルに含まれています。


    ビルウィリアムズによる指標

    ビルウィリアムズの指標は、ビルウィリアムズの本に記載された取引システムの一部であるため、独自のグループに含まれています。


    Accelerator Oscillator(ACオシレーター)

    価格の変化は最後に来ます。その前に、市場の駆動力がその方向を変更し、駆動力の加速度は減速して0に到達しなければなりません。そして、価格が方向転換を始めるまで加速し始めます。

    ACオシレーターは、駆動力の加減速を測定します。この指標は駆動力が変化する前に方向を変え、駆動力は価格が変わる前に方向を変えることになります。加速/減速が早期の警告シグナルであることが認識された場合、明白な利点が得られます。

    ゼロラインは基本的には駆動力が加速とのバランスにあるスポットです。ACオシレータがゼロよりも大きい場合、加速度の上方への継続がより簡単です(ゼロより小さい場合はその逆)。オーサムオシレータとは異なり、ゼロラインクロスはシグナルではありません。市場を制御し、意思決定をおこなうのに唯一必要な物は、色の変化です。後で後悔しないようにこれを覚えておく必要があります。現在の列が赤色の場合、ACオシレーターの助けを借りて買うことは出来ません。同じように、現在の列が緑色の場合、売ることは出来ません。

    駆動力の方向(買いの場合指標がゼロより大きく、売りの場合はゼロより小さい)で市場参入する場合、買いには2つの緑の列のみが必要です。駆動力の反対方向で注文を出す場合(買いの場合指標がゼロより小さく、売りの場合はゼロより大きい)、追加的な列が必要とされるので確認が必要です。この場合、指標は、ロング(買い)ポジションのためにはゼロラインの下の3つの緑列、また、ショート(売り)ポジションのためにはゼロラインの上の3つの赤列を表示します。


    パラメータ

    指標ハンドルの作成にはiAC()関数が使用されます。

    Accelerator Oscillator指標を作成し、そのハンドルを返します。バッファは1つだけです。

    int  iAC(
       string           symbol,     // symbol name
       ENUM_TIMEFRAMES  period      // period
       );
    

    symbol

    [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

    period

    [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

    指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

    EAでグローバル変数を宣言し、指標を作成します(指標は、ヒストグラムの昇順列と降順列の色を設定する以外、何も入力しません)。

    //+------------------------------------------------------------------+
    //|                                               TestWilliamsAC.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    
    

    EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

    //+------------------------------------------------------------------+
    //|                                               TestWilliamsAC.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- includes
    #include <Dashboard\Dashboard.mqh>
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    //--- variables for the panel
    int      mouse_bar_index;        // Index of the bar the data is taken from
    CDashboard *panel=NULL;          // Pointer to the panel object
    
    


    初期化

    指標のグローバル変数の値を設定し、ハンドルを作成します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="AC";
       ind_digits=Digits()+2;
    //--- Create indicator handle
       ResetLastError();
       handle=iAC(Symbol(),PERIOD_CURRENT);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    

    EAがダッシュボードを使用する場合は、ここで作成します

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set the indicator name and the number of decimal places
       ind_title="AC";
       ind_digits=Digits()+2;
    //--- Create indicator handle
       ResetLastError();
       handle=iAC(Symbol(),PERIOD_CURRENT);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Dashboard
    //--- Create the panel
       panel=new CDashboard(1,20,20,199,225);
       if(panel==NULL)
         {
          Print("Error. Failed to create panel object");
          return INIT_FAILED;
         }
    //--- Set font parameters
       panel.SetFontParams("Calibri",9);
    //--- Display the panel with the "Symbol, Timeframe description" header text
       panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
    //--- Create a table with ID 0 to display bar data in it
       panel.CreateNewTable(0);
    //--- Draw a table with ID 0 on the panel background
       panel.DrawGrid(0,2,20,6,2,18,97);
    
    //--- Create a table with ID 1 to display indicator data in it
       panel.CreateNewTable(1);
    //--- Get the Y2 table coordinate with ID 0 and
    //--- set the Y1 coordinate for the table with ID 1
       int y1=panel.TableY2(0)+22;
    //--- Draw a table with ID 1 on the panel background
       panel.DrawGrid(1,2,y1,3,2,18,97);
       
    //--- Display tabular data in the journal
       panel.GridPrint(0,2);
       panel.GridPrint(1,2);
    //--- Initialize the variable with the index of the mouse cursor bar
       mouse_bar_index=0;
    //--- Display the data of the current bar on the panel
       DrawData(mouse_bar_index,TimeCurrent());
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    


    初期化解除

    EA OnDeinit()ハンドルの指標ハンドルを解放します

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
      }
    
    

    作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
       
    //--- If the panel object exists, delete it
       if(panel!=NULL)
          delete panel;
      }
    


    データ検索

    指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

    //+------------------------------------------------------------------+
    //| Return the indicator data on the specified bar                   |
    //+------------------------------------------------------------------+
    double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
      {
       double array[1]={0};
       ResetLastError();
       if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
         {
          PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
          return EMPTY_VALUE;
         }
       return array[0];
      }
    //+------------------------------------------------------------------+
    //| Return the state of the indicator line                           |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
      {
    //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
       const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Line upward reversal (value2>value1 && value0>value1)
       if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_TURN_UP;
    //--- Line upward direction (value2<=value1 && value0>value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_UP;
    //--- Line upward stop (value2<=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_UP;
    //--- Line downward reversal (value2<value1 && value0<value1)
       if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_TURN_DOWN;
    //--- Line downward direction (value2>=value1 && value0<value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_DOWN;
    //--- Line downward stop (value2>=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_DOWN;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the state of the line relative to the specified level     |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
      {
    //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Define the second level to compare
       double level=(level1==EMPTY_VALUE ? level0 : level1);
    //--- The line is below the level (value1<level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_UNDER;
    //--- The line is above the level (value1>level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_ABOVE;
    //--- The line crossed the level upwards (value1<=level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_CROSS_UP;
    //--- The line crossed the level downwards (value1>=level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_CROSS_DOWN;
    //--- The line touched the level from below (value1<level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- The line touched the level from above (value1>level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- Line is equal to the level value (value1==level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_EQUALS;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the indicator line state description                      |
    //+------------------------------------------------------------------+
    string LineStateDescription(const ENUM_LINE_STATE state)
      {
       switch(state)
         {
          case LINE_STATE_UP         :  return "Up";
          case LINE_STATE_STOP_UP    :  return "Stop Up";
          case LINE_STATE_TURN_UP    :  return "Turn Up";
          case LINE_STATE_DOWN       :  return "Down";
          case LINE_STATE_STOP_DOWN  :  return "Stop Down";
          case LINE_STATE_TURN_DOWN  :  return "Turn Down";
          case LINE_STATE_ABOVE      :  return "Above level";
          case LINE_STATE_UNDER      :  return "Under level";
          case LINE_STATE_CROSS_UP   :  return "Crossing Up";
          case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
          case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
          case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
          case LINE_STATE_EQUALS     :  return "Equals";
          default                    :  return "Unknown";
         }
      }
    
    

    ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

    //+------------------------------------------------------------------+
    //| Display data from the specified timeseries index to the panel    |
    //+------------------------------------------------------------------+
    void DrawData(const int index,const datetime time)
      {
    //--- Declare the variables to receive data in them
       MqlTick  tick={0};
       MqlRates rates[1];
    
    //--- Exit if unable to get the current prices
       if(!SymbolInfoTick(Symbol(),tick))
          return;
    //--- Exit if unable to get the bar data by the specified index
       if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
          return;
    
    //--- Set font parameters for bar and indicator data headers
       int  size=0;
       uint flags=0;
       uint angle=0;
       string name=panel.FontParams(size,flags,angle);
       panel.SetFontParams(name,9,FW_BOLD);
       panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
       panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
    //--- Set font parameters for bar and indicator data
       panel.SetFontParams(name,9);
    
    //--- Display the data of the specified bar in table 0 on the panel
       panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
       panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
       panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
       panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
       panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
       panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
    
    //--- Display the indicator data from the specified bar on the panel in table 1
       panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
       double value0=IndicatorValue(handle,index,  0);
       double value1=IndicatorValue(handle,index+1,0);
       string value_str=(value0!=EMPTY_VALUE ? DoubleToString(value0,ind_digits) : "");
       color clr=(value0>value1 ? clrGreen : value0<value1 ? clrRed : clrNONE);
       panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
       
    //--- Display a description of the indicator line state
       panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
       ENUM_LINE_STATE state=LineState(handle,index,0);
       panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,90);
       
    //--- Redraw the chart to immediately display all changes on the panel
       ChartRedraw(ChartID());
      }
    
    

    ダッシュボード上の指標ラインステータスのテキストの色は、カーソルが置かれているヒストグラムの列の色に対応します。

    その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //--- Handling the panel
    //--- Call the panel event handler
       panel.OnChartEvent(id,lparam,dparam,sparam);
    
    //--- If the cursor moves or a click is made on the chart
       if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
         {
          //--- Declare the variables to record time and price coordinates in them
          datetime time=0;
          double price=0;
          int wnd=0;
          //--- If the cursor coordinates are converted to date and time
          if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
            {
             //--- write the bar index where the cursor is located to a global variable
             mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
             //--- Display the bar data under the cursor on the panel 
             DrawData(mouse_bar_index,time);
            }
         }
    
    //--- If we received a custom event, display the appropriate message in the journal
       if(id>CHARTEVENT_CUSTOM)
         {
          //--- Here we can implement handling a click on the close button on the panel
          PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
         }
      }
    
    

    EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


    TestWilliamsAC.mq5テストEAは、記事に添付されているファイルに含まれています。


    Alligator(アリゲーター)

    市場はほとんどの時に静止したままです。トレンドはその15~30%のみの時間で生成され、取引所自体に拠点を置いていないトレーダーは、利益のほとんどがトレンドから得られます。私の祖父はよく繰り返していました。「めくらの鶏でも、いつも同じ時間に与えれば、自分のトウモロコシを見つけることができる」。トレンドの取引は「めくらの鶏の市場」とも呼ばれます。何年もかかりましたが、私たちは「めくらの鶏の市場」に到達するまで備るための指標を生み出しました。
    ビルウィリアムズ

    Alligatorはバランスライン(移動平均)を組み合わせたもので、フラクタル幾何学と非線形力学を利用しています。

    • 青い線(アリゲーターの顎)は、グラフ作成に使用した期間のバランスライン(13期間の平滑化移動平均を8本分未来に移動させたもの)
    • 赤い線(アリゲーターの歯)は、かなりの期間のバランスラインであり、1桁下にある(8期間平滑化移動平均、5バー分未来に移動)
    • 緑の線(アリゲーターの唇)は、かなりの期間のバランスラインであり、もう1桁下にある(5期間平滑化移動平均、3バー分未来に移動)

    アリゲーターの唇、歯、顎は、異なる期間の相互作用を物語っています。市場のトレンドは15~30パーセントしか特定できないので、特定の価格期間内でのみ変動する市場では作業せず、トレンドに従わなければなりません。

    顎、歯、唇が閉じているか、絡み合っているとき、アリゲーターは眠りにつくか、すでに眠っています。眠れば眠るほど、空腹感が増します。そのため、眠れば眠るほど、目が覚めたときに空腹になります。目を覚ますと、まず口を開いてあくびをし始めます。そして、食べ物の匂い(雄牛や熊の肉)を嗅ぎつけ、狩りを始めます。満腹になるまで十分に食べたあとは、アリゲーターは食べ物(価格)に対する興味を失います(バランスラインが集結します)。これは利益を確定するタイミングです。



    パラメータ

    指標ハンドルの作成にはiAlligator()関数が使用されます。

    アリゲーターの指標ハンドルを返します。

    int  iAlligator(
       string              symbol,            // symbol name
       ENUM_TIMEFRAMES     period,            // period
       int                 jaw_period,        // period for calculating jaws
       int                 jaw_shift,         // horizontal shift of jaws
       int                 teeth_period,      // period for calculating teeth
       int                 teeth_shift,       // horizontal shift of teeth
       int                 lips_period,       // period for calculating lips
       int                 lips_shift,        // horizontal shift of lips
       ENUM_MA_METHOD      ma_method,         // smoothing type
       ENUM_APPLIED_PRICE  applied_price      // price type or handle
       );
    

    symbol

    [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

    period

    [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

    jaw_period

    [in]青い線(アリゲーターの顎)の平均期間

    jaw_shift

    [in]価格チャートに対する青い線のシフト

    teeth_period

    [in]赤い線(アリゲーターの歯)の平均期間

    teeth_shift

    [in]価格チャートに対する赤い線のシフト

    lips_period

    [in]緑の線(アリゲーターの唇)の平均期間

    lips_shift

    [in]価格チャートに対する緑の線のシフト

    ma_method

    [in]平均化法。ENUM_MA_METHOD列挙値のいずれかです。

    applied_price

    [in]適用価格。ENUM_APPLIED_PRICE価格定数または別の指標ハンドルのいずれか。

    指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

    バッファのインデックス:0 -GATORJAW_LINE、1 -GATORTEETH_LINE、2 -GATORLIPS_LINE


    指標を作成するために、EAで入力変数とグローバル変数を宣言します。

    //+------------------------------------------------------------------+
    //|                                        TestWilliamsAlligator.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input uint                 InpPeriodJaws  =  13;            /* Jaws Period    */
    input int                  InpShiftJaws   =  8;             /* Jaws Shift     */
    input uint                 InpPeriodTeeth =  8;             /* Teeth Period   */
    input int                  InpShiftTeeth  =  5;             /* Teeth Shift    */
    input uint                 InpPeriodLips  =  5;             /* Lips Period    */
    input int                  InpShiftLips   =  3;             /* Lips Shift     */
    input ENUM_MA_METHOD       InpMethod      =  MODE_SMMA;     /* Smoothed       */
    input ENUM_APPLIED_PRICE   InpAppliedPrice=  PRICE_MEDIAN;  /* Applied Price  */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      period_jaws=0;          // Jaws line calculation period
    int      period_teeth=0;         // Teeth line calculation period
    int      period_lips=0;          // Lips line calculation period
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    
    

    EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

    //+------------------------------------------------------------------+
    //|                                        TestWilliamsAlligator.mq5 |
    //|                                  Copyright 2023, MetaQuotes Ltd. |
    //|                                             https://www.mql5.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, MetaQuotes Ltd."
    #property link      "https://www.mql5.com"
    #property version   "1.00"
    //--- includes
    #include <Dashboard\Dashboard.mqh>
    //--- enums
    enum ENUM_LINE_STATE
      {
       LINE_STATE_NONE,        // Undefined state
       LINE_STATE_UP,          // Upward
       LINE_STATE_DOWN,        // Downward
       LINE_STATE_TURN_UP,     // Upward reversal
       LINE_STATE_TURN_DOWN,   // Downward reversal
       LINE_STATE_STOP_UP,     // Upward stop
       LINE_STATE_STOP_DOWN,   // Downward stop
       LINE_STATE_ABOVE,       // Above value
       LINE_STATE_UNDER,       // Below value
       LINE_STATE_CROSS_UP,    // Crossing value upwards
       LINE_STATE_CROSS_DOWN,  // Crossing value downwards
       LINE_STATE_TOUCH_BELOW, // Touching value from below 
       LINE_STATE_TOUCH_ABOVE, // Touch value from above
       LINE_STATE_EQUALS,      // Equal to value
      };
    //--- input parameters
    input uint                 InpPeriodJaws  =  13;            /* Jaws Period    */
    input int                  InpShiftJaws   =  8;             /* Jaws Shift     */
    input uint                 InpPeriodTeeth =  8;             /* Teeth Period   */
    input int                  InpShiftTeeth  =  5;             /* Teeth Shift    */
    input uint                 InpPeriodLips  =  5;             /* Lips Period    */
    input int                  InpShiftLips   =  3;             /* Lips Shift     */
    input ENUM_MA_METHOD       InpMethod      =  MODE_SMMA;     /* Smoothed       */
    input ENUM_APPLIED_PRICE   InpAppliedPrice=  PRICE_MEDIAN;  /* Applied Price  */
    //--- global variables
    int      handle=INVALID_HANDLE;  // Indicator handle
    int      period_jaws=0;          // Jaws line calculation period
    int      period_teeth=0;         // Teeth line calculation period
    int      period_lips=0;          // Lips line calculation period
    int      ind_digits=0;           // Number of decimal places in the indicator values
    string   ind_title;              // Indicator description
    //--- variables for the panel
    int      mouse_bar_index;        // Index of the bar the data is taken from
    CDashboard *panel=NULL;          // Pointer to the panel object
    
    


    初期化

    指標のグローバル変数の値を設定し、ハンドルを作成します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set and adjust the calculation period if necessary
       period_jaws=int(InpPeriodJaws<1 ? 13 : InpPeriodJaws);
       period_teeth=int(InpPeriodTeeth<1 ? 8 : InpPeriodTeeth);
       period_lips=int(InpPeriodLips<1 ? 5 : InpPeriodLips);
    //--- Set the indicator name and the number of decimal places
       ind_title=StringFormat("Alligator(%lu,%lu,%lu)",period_jaws,period_teeth,period_lips);
       ind_digits=Digits();
    //--- Create indicator handle
       ResetLastError();
       handle=iAlligator(Symbol(),PERIOD_CURRENT,period_jaws,InpShiftJaws,period_teeth,InpShiftTeeth,period_lips,InpShiftLips,InpMethod,InpAppliedPrice);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    

    EAがダッシュボードを使用する場合は、ここで作成します

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- create timer
       EventSetTimer(60);
    
    //--- Indicator
    //--- Set and adjust the calculation period if necessary
       period_jaws=int(InpPeriodJaws<1 ? 13 : InpPeriodJaws);
       period_teeth=int(InpPeriodTeeth<1 ? 8 : InpPeriodTeeth);
       period_lips=int(InpPeriodLips<1 ? 5 : InpPeriodLips);
    //--- Set the indicator name and the number of decimal places
       ind_title=StringFormat("Alligator(%lu,%lu,%lu)",period_jaws,period_teeth,period_lips);
       ind_digits=Digits();
    //--- Create indicator handle
       ResetLastError();
       handle=iAlligator(Symbol(),PERIOD_CURRENT,period_jaws,InpShiftJaws,period_teeth,InpShiftTeeth,period_lips,InpShiftLips,InpMethod,InpAppliedPrice);
       if(handle==INVALID_HANDLE)
         {
          PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
          return INIT_FAILED;
         }
    
    //--- Dashboard
    //--- Create the panel
       panel=new CDashboard(1,20,20,199,261);
       if(panel==NULL)
         {
          Print("Error. Failed to create panel object");
          return INIT_FAILED;
         }
    //--- Set font parameters
       panel.SetFontParams("Calibri",9);
    //--- Display the panel with the "Symbol, Timeframe description" header text
       panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
    //--- Create a table with ID 0 to display bar data in it
       panel.CreateNewTable(0);
    //--- Draw a table with ID 0 on the panel background
       panel.DrawGrid(0,2,20,6,2,18,97);
    
    //--- Create a table with ID 1 to display indicator data in it
       panel.CreateNewTable(1);
    //--- Get the Y2 table coordinate with ID 0 and
    //--- set the Y1 coordinate for the table with ID 1
       int y1=panel.TableY2(0)+22;
    //--- Draw a table with ID 1 on the panel background
       panel.DrawGrid(1,2,y1,5,2,18,97);
       
    //--- Display tabular data in the journal
       panel.GridPrint(0,2);
       panel.GridPrint(1,2);
    //--- Initialize the variable with the index of the mouse cursor bar
       mouse_bar_index=0;
    //--- Display the data of the current bar on the panel
       DrawData(mouse_bar_index,TimeCurrent());
    
    //--- Successful initialization
       return(INIT_SUCCEEDED);
      }
    
    


    初期化解除

    EA OnDeinit()ハンドルの指標ハンドルを解放します

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
      }
    
    

    作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- destroy timer
       EventKillTimer();
       
    //--- Release handle of the indicator
       ResetLastError();
       if(!IndicatorRelease(handle))
          PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
    //--- Clear all comments on the chart
       Comment("");
       
    //--- If the panel object exists, delete it
       if(panel!=NULL)
          delete panel;
      }
    


    データ検索

    指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

    //+------------------------------------------------------------------+
    //| Return the indicator data on the specified bar                   |
    //+------------------------------------------------------------------+
    double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
      {
       double array[1]={0};
       ResetLastError();
       if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
         {
          PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
          return EMPTY_VALUE;
         }
       return array[0];
      }
    //+------------------------------------------------------------------+
    //| Return the state of the indicator line                           |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
      {
    //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
       const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Line upward reversal (value2>value1 && value0>value1)
       if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_TURN_UP;
    //--- Line upward direction (value2<=value1 && value0>value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
          return LINE_STATE_UP;
    //--- Line upward stop (value2<=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_UP;
    //--- Line downward reversal (value2<value1 && value0<value1)
       if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_TURN_DOWN;
    //--- Line downward direction (value2>=value1 && value0<value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
          return LINE_STATE_DOWN;
    //--- Line downward stop (value2>=value1 && value0==value1)
       else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
          return LINE_STATE_STOP_DOWN;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the state of the line relative to the specified level     |
    //+------------------------------------------------------------------+
    ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
      {
    //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
       const double value0=IndicatorValue(ind_handle,index,  buffer_num);
       const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
    //--- If at least one of the values could not be obtained, return an undefined value 
       if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
          return LINE_STATE_NONE;
    //--- Define the second level to compare
       double level=(level1==EMPTY_VALUE ? level0 : level1);
    //--- The line is below the level (value1<level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_UNDER;
    //--- The line is above the level (value1>level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_ABOVE;
    //--- The line crossed the level upwards (value1<=level && value0>level0)
       if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
          return LINE_STATE_CROSS_UP;
    //--- The line crossed the level downwards (value1>=level && value0<level0)
       if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
          return LINE_STATE_CROSS_DOWN;
    //--- The line touched the level from below (value1<level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- The line touched the level from above (value1>level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_TOUCH_BELOW;
    //--- Line is equal to the level value (value1==level0 && value0==level0)
       if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
          return LINE_STATE_EQUALS;
    //--- Undefined state
       return LINE_STATE_NONE;
      }
    //+------------------------------------------------------------------+
    //| Return the indicator line state description                      |
    //+------------------------------------------------------------------+
    string LineStateDescription(const ENUM_LINE_STATE state)
      {
       switch(state)
         {
          case LINE_STATE_UP         :  return "Up";
          case LINE_STATE_STOP_UP    :  return "Stop Up";
          case LINE_STATE_TURN_UP    :  return "Turn Up";
          case LINE_STATE_DOWN       :  return "Down";
          case LINE_STATE_STOP_DOWN  :  return "Stop Down";
          case LINE_STATE_TURN_DOWN  :  return "Turn Down";
          case LINE_STATE_ABOVE      :  return "Above level";
          case LINE_STATE_UNDER      :  return "Under level";
          case LINE_STATE_CROSS_UP   :  return "Crossing Up";
          case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
          case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
          case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
          case LINE_STATE_EQUALS     :  return "Equals";
          default                    :  return "Unknown";
         }
      }
    
    

    ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

    //+------------------------------------------------------------------+
    //| Display data from the specified timeseries index to the panel    |
    //+------------------------------------------------------------------+
    void DrawData(const int index,const datetime time)
      {
    //--- Declare the variables to receive data in them
       MqlTick  tick={0};
       MqlRates rates[1];
    
    //--- Exit if unable to get the current prices
       if(!SymbolInfoTick(Symbol(),tick))
          return;
    //--- Exit if unable to get the bar data by the specified index
       if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
          return;
    
    //--- Set font parameters for bar and indicator data headers
       int  size=0;
       uint flags=0;
       uint angle=0;
       string name=panel.FontParams(size,flags,angle);
       panel.SetFontParams(name,9,FW_BOLD);
       panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
       panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
    //--- Set font parameters for bar and indicator data
       panel.SetFontParams(name,9);
    
    //--- Display the data of the specified bar in table 0 on the panel
       panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
       panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
       panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
       panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
       panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
       panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
    
    //--- Get the indicator lines data
       double value_jaws=IndicatorValue(handle,index,GATORJAW_LINE);
       double value_teeth=IndicatorValue(handle,index,GATORTEETH_LINE);
       double value_lips=IndicatorValue(handle,index,GATORLIPS_LINE);
       
    //--- Display the Jaws line data from the specified bar on the panel in table 1
       string jaws_str=StringFormat("Jaws(%lu)",period_jaws);
       panel.DrawText(jaws_str, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
       string value_str=(value_jaws!=EMPTY_VALUE ? DoubleToString(value_jaws,ind_digits) : "");
       panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
    //--- Display the Teeth line data from the specified bar on the panel in table 1
       string teeth_str=StringFormat("Teeth(%lu)",period_teeth);
       panel.DrawText(teeth_str, panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
       value_str=(value_teeth!=EMPTY_VALUE ? DoubleToString(value_teeth,ind_digits) : "");
       panel.DrawText(value_str,panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,90);
    //--- Display the Lips line data from the specified bar on the panel in table 1
       string lips_str=StringFormat("Lips(%lu)",period_jaws);
       panel.DrawText(lips_str, panel.CellX(1,2,0)+2, panel.CellY(1,2,0)+2);
       value_str=(value_lips!=EMPTY_VALUE ? DoubleToString(value_lips,ind_digits) : "");
       panel.DrawText(value_str,panel.CellX(1,2,1)+2,panel.CellY(1,2,1)+2,clrNONE,90);
       
    //--- Display a description of the Teeth line state relative to the Jaws line
       panel.DrawText("Teeth vs Jaws", panel.CellX(1,3,0)+2, panel.CellY(1,3,0)+2);
       ENUM_LINE_STATE state_tj=LineStateRelative(handle,index,1,value_jaws,IndicatorValue(handle,index+1,GATORJAW_LINE));
       string state_tj_str=
         (
          state_tj==LINE_STATE_ABOVE        ?  "Teeth > Jaws"  : 
          state_tj==LINE_STATE_UNDER        ?  "Teeth < Jaws"  : 
          state_tj==LINE_STATE_TOUCH_ABOVE  || 
          state_tj==LINE_STATE_TOUCH_BELOW  ?  "Touch"     :
          LineStateDescription(state_tj)
         );
    //--- The label color changes depending on the value of the line relative to the level
       color clr=(state_tj==LINE_STATE_CROSS_UP || state_tj==LINE_STATE_ABOVE  ? clrBlue : state_tj==LINE_STATE_CROSS_DOWN || state_tj==LINE_STATE_UNDER ? clrRed : clrNONE);
       panel.DrawText(state_tj_str,panel.CellX(1,3,1)+2,panel.CellY(1,3,1)+2,clr,90);
       
    //--- Display a description of the Lips line state relative to the Teeth line
       panel.DrawText("Lips vs Teeth", panel.CellX(1,4,0)+2, panel.CellY(1,4,0)+2);
       ENUM_LINE_STATE state_lt=LineStateRelative(handle,index,2,value_teeth,IndicatorValue(handle,index+1,GATORTEETH_LINE));
       string state_lt_str=
         (
          state_lt==LINE_STATE_ABOVE        ?  "Lips > Teeth"  : 
          state_lt==LINE_STATE_UNDER        ?  "Lips < Teeth"  : 
          state_lt==LINE_STATE_TOUCH_ABOVE  || 
          state_lt==LINE_STATE_TOUCH_BELOW  ?  "Touch"     :
          LineStateDescription(state_lt)
         );
    //--- The label color changes depending on the value of the line relative to the level
       clr=(state_lt==LINE_STATE_CROSS_UP || state_lt==LINE_STATE_ABOVE  ? clrBlue : state_lt==LINE_STATE_CROSS_DOWN || state_lt==LINE_STATE_UNDER ? clrRed : clrNONE);
       panel.DrawText(state_lt_str,panel.CellX(1,4,1)+2,panel.CellY(1,4,1)+2,clr,90);
       
    //--- Redraw the chart to immediately display all changes on the panel
       ChartRedraw(ChartID());
      }
    
    

    カーソルの下にあるバーの指標ラインの値に加えて、パネルには、歯-顎ラインと唇-歯ラインの比率の状態が表示されます。それらの関係はテキストで表示され、相対的な位置は表示されたテキストの色で示されます。

    その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //--- Handling the panel
    //--- Call the panel event handler
       panel.OnChartEvent(id,lparam,dparam,sparam);
    
    //--- If the cursor moves or a click is made on the chart
       if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
         {
          //--- Declare the variables to record time and price coordinates in them
          datetime time=0;
          double price=0;
          int wnd=0;
          //--- If the cursor coordinates are converted to date and time
          if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
            {
             //--- write the bar index where the cursor is located to a global variable
             mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
             //--- Display the bar data under the cursor on the panel 
             DrawData(mouse_bar_index,time);
            }
         }
    
    //--- If we received a custom event, display the appropriate message in the journal
       if(id>CHARTEVENT_CUSTOM)
         {
          //--- Here we can implement handling a click on the close button on the panel
          PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
         }
      }
    
    

    EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


    TestWilliamsAlligator.mq5のテストEAは、記事に添付されているファイルに含まれています。


    Awesome Oscillator(オーサムオシレータ)

    ビルウィリアムズのオーサムオシレータテクニカル指標(AO)は、34期間の単純移動平均で、バーの中央のポイント(H+L)/2を通してプロットされ、バーの中央のポイント(H+L)/2を通して構築された5期間の単純移動平均から差し引かれます。これは、現時点で市場の原動力に何が起こっているのかをはっきり示します。

    有効な買いシグナル

    ヒストグラムが0より上にある場合、「ソーサ―」は唯一の買シグナルです。次のことを忘れないでください。
    • ソーサ―シグナルは、ヒストグラムが下向きから上向きに反転した場合にのみ発生します。2番目の列が最初の列より安く赤色で、3番目の列が2番目の列より高く緑色です。
    • ソーサ―シグナルの生成にはヒストグラムには少なくとも3列が必要です。

    ソーサ―シグナルの有効性は、全てのAOの列が0より上にあることに依存することにご注意下さい。

    「ゼロライン交差」は値が負から正に転じた際に生成される買いシグナルです。以下を念頭に置いてください。

    • シグナルの生成には2列が必要です。
    • 1つ目は負で、2つ目はゼロラインを交差しなければなりません(負から正への変化)。
    • 買いシグナルと売りシグナルが同時に生成されることはありません。

    「ツインピーク」は、ヒストグラムの値がゼロ以下になったときに発生する唯一の買いシグナルです。次のことを忘れないでください。

    • シグナルは、ゼロラインよりも下にある下向きの尖り(最低値)があり、その後に、以前の下向きの尖りよりも若干高い(絶対値がより小さい負の数値、つまりゼロラインにより近い)、別の下向きの尖りが続くときに生成されます。
    • ヒストグラムはこの2つの尖りの間でゼロラインより下にあります。バーチャートが0ラインより上にある場合、買いシグナルは無効です。ただし、「ゼロライン交差」シグナルが生成されます。
    • バーチャートのそれぞれの新しい尖りは、以前の尖りよりも高い(絶対値がより小さい負の数値、つまりゼロラインにより近い)です。
    • より高い(0ラインにより近い)新しい尖りが更に形成され、バーチャートが0ラインを交差していない場合、更に買いシグナルが生成されます。

      売りシグナル

      オーサムオシレータの売りシグナルは買いシグナルとまったく同じです。ソースシグナルは反転され、ゼロ未満です。「ゼロライン交差」では1つ目のバーはゼロラインの上で、2つ目が下にあります。「2つの尖り」シグナルも0ラインより上と、反転されています。



      パラメータ

      指標ハンドルの作成にはiAO()関数が使用されます。

      オーサムオシレータ指標のハンドルを返します。バッファは1つだけです。

      int  iAO(
         string           symbol,     // symbol name
         ENUM_TIMEFRAMES  period      // period
         );
      

      symbol

      [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

      period

      [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

      指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。


      指標を作成するために、EAで入力変数とグローバル変数を宣言します。

      //+------------------------------------------------------------------+
      //|                                               TestWilliamsAO.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      
      

      EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

      //+------------------------------------------------------------------+
      //|                                               TestWilliamsAO.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- includes
      #include <Dashboard\Dashboard.mqh>
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      //--- variables for the panel
      int      mouse_bar_index;        // Index of the bar the data is taken from
      CDashboard *panel=NULL;          // Pointer to the panel object
      
      


      初期化

      指標のグローバル変数の値を設定し、ハンドルを作成します。

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="AO";
         ind_digits=Digits()+1;
      //--- Create indicator handle
         ResetLastError();
         handle=iAO(Symbol(),PERIOD_CURRENT);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      

      EAがダッシュボードを使用する場合は、ここで作成します

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="AO";
         ind_digits=Digits()+1;
      //--- Create indicator handle
         ResetLastError();
         handle=iAO(Symbol(),PERIOD_CURRENT);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Dashboard
      //--- Create the panel
         panel=new CDashboard(1,20,20,199,225);
         if(panel==NULL)
           {
            Print("Error. Failed to create panel object");
            return INIT_FAILED;
           }
      //--- Set font parameters
         panel.SetFontParams("Calibri",9);
      //--- Display the panel with the "Symbol, Timeframe description" header text
         panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
      //--- Create a table with ID 0 to display bar data in it
         panel.CreateNewTable(0);
      //--- Draw a table with ID 0 on the panel background
         panel.DrawGrid(0,2,20,6,2,18,97);
      
      //--- Create a table with ID 1 to display indicator data in it
         panel.CreateNewTable(1);
      //--- Get the Y2 table coordinate with ID 0 and
      //--- set the Y1 coordinate for the table with ID 1
         int y1=panel.TableY2(0)+22;
      //--- Draw a table with ID 1 on the panel background
         panel.DrawGrid(1,2,y1,3,2,18,97);
         
      //--- Display tabular data in the journal
         panel.GridPrint(0,2);
         panel.GridPrint(1,2);
      //--- Initialize the variable with the index of the mouse cursor bar
         mouse_bar_index=0;
      //--- Display the data of the current bar on the panel
         DrawData(mouse_bar_index,TimeCurrent());
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      


      初期化解除

      EA OnDeinit()ハンドルの指標ハンドルを解放します

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
        }
      
      

      作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
         
      //--- If the panel object exists, delete it
         if(panel!=NULL)
            delete panel;
        }
      


      データ検索

      指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

      //+------------------------------------------------------------------+
      //| Return the indicator data on the specified bar                   |
      //+------------------------------------------------------------------+
      double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
        {
         double array[1]={0};
         ResetLastError();
         if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
           {
            PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
            return EMPTY_VALUE;
           }
         return array[0];
        }
      //+------------------------------------------------------------------+
      //| Return the state of the indicator line                           |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
        {
      //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
         const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Line upward reversal (value2>value1 && value0>value1)
         if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_TURN_UP;
      //--- Line upward direction (value2<=value1 && value0>value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_UP;
      //--- Line upward stop (value2<=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_UP;
      //--- Line downward reversal (value2<value1 && value0<value1)
         if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_TURN_DOWN;
      //--- Line downward direction (value2>=value1 && value0<value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_DOWN;
      //--- Line downward stop (value2>=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_DOWN;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the state of the line relative to the specified level     |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
        {
      //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Define the second level to compare
         double level=(level1==EMPTY_VALUE ? level0 : level1);
      //--- The line is below the level (value1<level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_UNDER;
      //--- The line is above the level (value1>level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_ABOVE;
      //--- The line crossed the level upwards (value1<=level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_CROSS_UP;
      //--- The line crossed the level downwards (value1>=level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_CROSS_DOWN;
      //--- The line touched the level from below (value1<level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- The line touched the level from above (value1>level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- Line is equal to the level value (value1==level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_EQUALS;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the indicator line state description                      |
      //+------------------------------------------------------------------+
      string LineStateDescription(const ENUM_LINE_STATE state)
        {
         switch(state)
           {
            case LINE_STATE_UP         :  return "Up";
            case LINE_STATE_STOP_UP    :  return "Stop Up";
            case LINE_STATE_TURN_UP    :  return "Turn Up";
            case LINE_STATE_DOWN       :  return "Down";
            case LINE_STATE_STOP_DOWN  :  return "Stop Down";
            case LINE_STATE_TURN_DOWN  :  return "Turn Down";
            case LINE_STATE_ABOVE      :  return "Above level";
            case LINE_STATE_UNDER      :  return "Under level";
            case LINE_STATE_CROSS_UP   :  return "Crossing Up";
            case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
            case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
            case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
            case LINE_STATE_EQUALS     :  return "Equals";
            default                    :  return "Unknown";
           }
        }
      
      

      ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

      //+------------------------------------------------------------------+
      //| Display data from the specified timeseries index to the panel    |
      //+------------------------------------------------------------------+
      void DrawData(const int index,const datetime time)
        {
      //--- Declare the variables to receive data in them
         MqlTick  tick={0};
         MqlRates rates[1];
      
      //--- Exit if unable to get the current prices
         if(!SymbolInfoTick(Symbol(),tick))
            return;
      //--- Exit if unable to get the bar data by the specified index
         if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
            return;
      
      //--- Set font parameters for bar and indicator data headers
         int  size=0;
         uint flags=0;
         uint angle=0;
         string name=panel.FontParams(size,flags,angle);
         panel.SetFontParams(name,9,FW_BOLD);
         panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
         panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
      //--- Set font parameters for bar and indicator data
         panel.SetFontParams(name,9);
      
      //--- Display the data of the specified bar in table 0 on the panel
         panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
         panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
         panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
         panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
         panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
         panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
      
      //--- Display the indicator data from the specified bar on the panel in table 1
         panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
         double value0=IndicatorValue(handle,index,  0);
         double value1=IndicatorValue(handle,index+1,0);
         string value_str=(value0!=EMPTY_VALUE ? DoubleToString(value0,ind_digits) : "");
         color clr=(value0>value1 ? clrGreen : value0<value1 ? clrRed : clrNONE);
         panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
         
      //--- Display a description of the indicator line state
         panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
         ENUM_LINE_STATE state=LineState(handle,index,0);
         panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,90);
         
      //--- Display a description of the indicator line state relative to zero
         panel.DrawText("AO vs Zero", panel.CellX(1,2,0)+2, panel.CellY(1,2,0)+2);
         ENUM_LINE_STATE state_zero=LineStateRelative(handle,index,0,0);
         string state_zero_str=
           (
            state_zero==LINE_STATE_ABOVE        ?  "AO > 0"  : 
            state_zero==LINE_STATE_UNDER        ?  "AO < 0"  : 
            state_zero==LINE_STATE_TOUCH_ABOVE  || 
            state_zero==LINE_STATE_TOUCH_BELOW  ?  "Touch"     :
            LineStateDescription(state_zero)
           );
      //--- The label color changes depending on the value of the line relative to the level
         clr=(state_zero==LINE_STATE_CROSS_UP ? clrGreen : state_zero==LINE_STATE_CROSS_DOWN ? clrRed : clrNONE);
         panel.DrawText(state_zero_str,panel.CellX(1,2,1)+2,panel.CellY(1,2,1)+2,clr,90);
         
      //--- Redraw the chart to immediately display all changes on the panel
         ChartRedraw(ChartID());
        }
      
      

      カーソルの下にあるヒストグラムの列の色を持つ指示線の状態を説明することに加えて、パネルはゼロに対する相対的な位置の状態を表示します。指標線がゼロラインを上向きに横切ると緑色の文字で表示され、下向きは赤色の文字で表示されます。

      その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

      //+------------------------------------------------------------------+
      //| ChartEvent function                                              |
      //+------------------------------------------------------------------+
      void OnChartEvent(const int id,
                        const long &lparam,
                        const double &dparam,
                        const string &sparam)
        {
      //--- Handling the panel
      //--- Call the panel event handler
         panel.OnChartEvent(id,lparam,dparam,sparam);
      
      //--- If the cursor moves or a click is made on the chart
         if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
           {
            //--- Declare the variables to record time and price coordinates in them
            datetime time=0;
            double price=0;
            int wnd=0;
            //--- If the cursor coordinates are converted to date and time
            if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
              {
               //--- write the bar index where the cursor is located to a global variable
               mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
               //--- Display the bar data under the cursor on the panel 
               DrawData(mouse_bar_index,time);
              }
           }
      
      //--- If we received a custom event, display the appropriate message in the journal
         if(id>CHARTEVENT_CUSTOM)
           {
            //--- Here we can implement handling a click on the close button on the panel
            PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
           }
        }
      
      

      EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。


      TestWilliamsAO.mq5テストEAは、記事に添付されているファイルに含まれています。


      Fractal(フラクタル)

      すべての市場には、大半の期間、価格はあまり変動せず、短期間(15~30%)だけトレンドの変化が見られるという特徴があります。通常、市場価格がトレンドに応じて変更された場合が最も利益の高い期間となります。

      フラクタルは、底と天井の検出を可能にするビルウィリアムズの5つの取引システムの1つです。上方フラクタルの技術的な定義は、少なくとも5本の連続するバーのうち、最高値の前後に2本のバーがあり、そのバーの方がより低い最大値を持つということです。反転セットは、最安値が真ん中でそれ以外の2つの安値が両端にある、少なくとも5つの連続した一連のバーで、「売り」フラクタルに対応します。グラフ上のフラクタルは高値と安値の値を持ち、上向きまたは下向きの矢印で示されます。

      アリゲーターテクニカル指標を使用して、フラクタルテクニカル指標のシグナルをフィルタリングする必要があります。つまり、フラクタルがアリゲーターの歯線よりも低い場合の買いの決済と、フラクタルがアリゲーターの歯線よりも高い場合の売りの決済は控えるべきです。フラクタルシグナルは形成後、アリゲーターの口線を越えて効力を発揮し、その後、より新しいフラクタルが現れるまで効力を維持します。



      パラメータ

      iFractals()関数は、指標ハンドルを作成するために使用されます。

      フラクタル指標のハンドルを返します。

      int  iFractals(
         string           symbol,     // symbol name
         ENUM_TIMEFRAMES  period      // period
         );
      

      symbol

      [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

      period

      [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

      戻り値

      指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

      バッファインデックス:0 -UPPER_LINE、1 -LOWER_LINE


      指標を作成するために、EAで入力変数とグローバル変数を宣言します。

      //+------------------------------------------------------------------+
      //|                                         TestWilliamsFractals.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      
      

      EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

      //+------------------------------------------------------------------+
      //|                                         TestWilliamsFractals.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- includes
      #include <Dashboard\Dashboard.mqh>
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      //--- variables for the panel
      int      mouse_bar_index;        // Index of the bar the data is taken from
      CDashboard *panel=NULL;          // Pointer to the panel object
      
      


      初期化

      指標のグローバル変数の値を設定し、ハンドルを作成します。

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="Fractals";
         ind_digits=Digits();
      //--- Create indicator handle
         ResetLastError();
         handle=iFractals(Symbol(),PERIOD_CURRENT);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      

      EAがダッシュボードを使用する場合は、ここで作成します

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="Fractals";
         ind_digits=Digits();
      //--- Create indicator handle
         ResetLastError();
         handle=iFractals(Symbol(),PERIOD_CURRENT);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Dashboard
      //--- Create the panel
         panel=new CDashboard(1,20,20,199,225);
         if(panel==NULL)
           {
            Print("Error. Failed to create panel object");
            return INIT_FAILED;
           }
      //--- Set font parameters
         panel.SetFontParams("Calibri",9);
      //--- Display the panel with the "Symbol, Timeframe description" header text
         panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
      //--- Create a table with ID 0 to display bar data in it
         panel.CreateNewTable(0);
      //--- Draw a table with ID 0 on the panel background
         panel.DrawGrid(0,2,20,6,2,18,97);
      
      //--- Create a table with ID 1 to display indicator data in it
         panel.CreateNewTable(1);
      //--- Get the Y2 table coordinate with ID 0 and
      //--- set the Y1 coordinate for the table with ID 1
         int y1=panel.TableY2(0)+22;
      //--- Draw a table with ID 1 on the panel background
         panel.DrawGrid(1,2,y1,3,2,18,97);
         
      //--- Display tabular data in the journal
         panel.GridPrint(0,2);
         panel.GridPrint(1,2);
      //--- Initialize the variable with the index of the mouse cursor bar
         mouse_bar_index=0;
      //--- Display the data of the current bar on the panel
         DrawData(mouse_bar_index,TimeCurrent());
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      


      初期化解除

      EA OnDeinit()ハンドルの指標ハンドルを解放します

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
        }
      
      

      作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
         
      //--- If the panel object exists, delete it
         if(panel!=NULL)
            delete panel;
        }
      


      データ検索

      指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

      //+------------------------------------------------------------------+
      //| Return the indicator data on the specified bar                   |
      //+------------------------------------------------------------------+
      double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
        {
         double array[1]={0};
         ResetLastError();
         if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
           {
            PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
            return EMPTY_VALUE;
           }
         return array[0];
        }
      //+------------------------------------------------------------------+
      //| Return the state of the indicator line                           |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
        {
      //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
         const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Line upward reversal (value2>value1 && value0>value1)
         if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_TURN_UP;
      //--- Line upward direction (value2<=value1 && value0>value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_UP;
      //--- Line upward stop (value2<=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_UP;
      //--- Line downward reversal (value2<value1 && value0<value1)
         if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_TURN_DOWN;
      //--- Line downward direction (value2>=value1 && value0<value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_DOWN;
      //--- Line downward stop (value2>=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_DOWN;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the state of the line relative to the specified level     |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
        {
      //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Define the second level to compare
         double level=(level1==EMPTY_VALUE ? level0 : level1);
      //--- The line is below the level (value1<level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_UNDER;
      //--- The line is above the level (value1>level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_ABOVE;
      //--- The line crossed the level upwards (value1<=level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_CROSS_UP;
      //--- The line crossed the level downwards (value1>=level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_CROSS_DOWN;
      //--- The line touched the level from below (value1<level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- The line touched the level from above (value1>level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- Line is equal to the level value (value1==level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_EQUALS;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the indicator line state description                      |
      //+------------------------------------------------------------------+
      string LineStateDescription(const ENUM_LINE_STATE state)
        {
         switch(state)
           {
            case LINE_STATE_UP         :  return "Up";
            case LINE_STATE_STOP_UP    :  return "Stop Up";
            case LINE_STATE_TURN_UP    :  return "Turn Up";
            case LINE_STATE_DOWN       :  return "Down";
            case LINE_STATE_STOP_DOWN  :  return "Stop Down";
            case LINE_STATE_TURN_DOWN  :  return "Turn Down";
            case LINE_STATE_ABOVE      :  return "Above level";
            case LINE_STATE_UNDER      :  return "Under level";
            case LINE_STATE_CROSS_UP   :  return "Crossing Up";
            case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
            case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
            case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
            case LINE_STATE_EQUALS     :  return "Equals";
            default                    :  return "Unknown";
           }
        }
      
      

      ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

      //+------------------------------------------------------------------+
      //| Display data from the specified timeseries index to the panel    |
      //+------------------------------------------------------------------+
      void DrawData(const int index,const datetime time)
        {
      //--- Declare the variables to receive data in them
         MqlTick  tick={0};
         MqlRates rates[1];
      
      //--- Exit if unable to get the current prices
         if(!SymbolInfoTick(Symbol(),tick))
            return;
      //--- Exit if unable to get the bar data by the specified index
         if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
            return;
      
      //--- Set font parameters for bar and indicator data headers
         int  size=0;
         uint flags=0;
         uint angle=0;
         string name=panel.FontParams(size,flags,angle);
         panel.SetFontParams(name,9,FW_BOLD);
         panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
         panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
      //--- Set font parameters for bar and indicator data
         panel.SetFontParams(name,9);
      
      //--- Display the data of the specified bar in table 0 on the panel
         panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
         panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
         panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
         panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
         panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
         panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
      
      //--- Display the indicator data from the specified bar on the panel in table 1 (upper fractal)
         panel.DrawText(ind_title+" Up", panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
         double value0=IndicatorValue(handle,index,UPPER_LINE);
         string value_str0=(value0!=EMPTY_VALUE ? DoubleToString(value0,ind_digits) : " ");
         panel.DrawText(value_str0,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
      
      //--- Display the indicator data from the specified bar on the panel in table 1 (lower fractal)
         panel.DrawText(ind_title+" Down", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
         double value1=IndicatorValue(handle,index,LOWER_LINE);
         string value_str1=(value1!=EMPTY_VALUE ? DoubleToString(value1,ind_digits) : " ");
         panel.DrawText(value_str1,panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,90);
         
      //--- Redraw the chart to immediately display all changes on the panel
         ChartRedraw(ChartID());
        }
      
      

      その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

      //+------------------------------------------------------------------+
      //| ChartEvent function                                              |
      //+------------------------------------------------------------------+
      void OnChartEvent(const int id,
                        const long &lparam,
                        const double &dparam,
                        const string &sparam)
        {
      //--- Handling the panel
      //--- Call the panel event handler
         panel.OnChartEvent(id,lparam,dparam,sparam);
      
      //--- If the cursor moves or a click is made on the chart
         if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
           {
            //--- Declare the variables to record time and price coordinates in them
            datetime time=0;
            double price=0;
            int wnd=0;
            //--- If the cursor coordinates are converted to date and time
            if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
              {
               //--- write the bar index where the cursor is located to a global variable
               mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
               //--- Display the bar data under the cursor on the panel 
               DrawData(mouse_bar_index,time);
              }
           }
      
      //--- If we received a custom event, display the appropriate message in the journal
         if(id>CHARTEVENT_CUSTOM)
           {
            //--- Here we can implement handling a click on the close button on the panel
            PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
           }
        }
      
      

      EAをコンパイルしてチャート上で起動すると、ダッシュボード上で指標のバッファ値を制御することができます。


      TestWilliamsFractals.mq5テストEAは、記事に添付されているファイルで見ることができます。


      Gator Oscillator(ゲーターオシレータ)

      ゲーターオシレーターは、アリゲーターに基づき、そのバランスライン(移動平均)の収束/発散の度合いを示します。上のヒストグラムは、青線と赤線との絶対差です。下のヒストグラムは上から下に描画されており、赤線と青線との絶対差の符号をマイナスにしたものです。


      パラメータ

      指標ハンドルの作成にはiGator()関数が使用されます。

      ゲーター指標のハンドルを戻します。オシレーターは、青と赤のアリゲーターラインの差(上部ヒストグラム)と、赤と緑のラインの差(下部ヒストグラム)を示す。

      int  iGator(
         string              symbol,            // symbol name
         ENUM_TIMEFRAMES     period,            // period
         int                 jaw_period,        // period for calculating jaws
         int                 jaw_shift,         // horizontal shift of jaws
         int                 teeth_period,      // period for calculating teeth
         int                 teeth_shift,       // teeth shift
         int                 lips_period,       // period for calculating lips
         int                 lips_shift,        // horizontal shift of lips 
         ENUM_MA_METHOD      ma_method,         // smoothing type
         ENUM_APPLIED_PRICE  applied_price      // price type or handle
         );
      

      symbol

      [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

      period

      [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

      jaw_period

      [in]青い線(アリゲーターの顎)の平均期間

      jaw_shift

      [in]価格チャートに対するアリゲーターの青い線のシフト指標ヒストグラムの視覚的なシフトには直接関係しない。

      teeth_period

      [in]赤い線(アリゲーターの歯)の平均期間

      teeth_shift

      [in]価格チャートに対するアリゲーターの赤い線のシフト指標ヒストグラムの視覚的なシフトには直接関係しない。

      lips_period

      [in]緑の線(アリゲーターの唇)の平均期間

      lips_shift

      [in]価格チャートに対するアリゲーターの緑の線のシフト指標ヒストグラムの視覚的なシフトには直接関係しない。

      ma_method

      [in]平均化法。ENUM_MA_METHOD列挙型の任意の値を持つことができます。

      applied_price

      [in]適用価格。ENUM_APPLIED_PRICE価格定数または別の指標ハンドルのいずれか。

      指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。

      バッファのインデックス:0 -UPPER_HISTOGRAM、1 - 上側ヒストグラムのカラーバッファ、2 -LOWER_HISTOGRAM、3 - 下側ヒストグラムのカラーバッファ


      指標を作成するために、EAで入力変数とグローバル変数を宣言します。

      //+------------------------------------------------------------------+
      //|                                            TestWilliamsGator.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- input parameters
      input uint                 InpPeriodJaws  =  13;            /* Jaws Period    */
      input int                  InpShiftJaws   =  8;             /* Jaws Shift     */
      input uint                 InpPeriodTeeth =  8;             /* Teeth Period   */
      input int                  InpShiftTeeth  =  5;             /* Teeth Shift    */
      input uint                 InpPeriodLips  =  5;             /* Lips Period    */
      input int                  InpShiftLips   =  3;             /* Lips Shift     */
      input ENUM_MA_METHOD       InpMethod      =  MODE_SMMA;     /* Smoothed       */
      input ENUM_APPLIED_PRICE   InpAppliedPrice=  PRICE_MEDIAN;  /* Applied Price  */
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      period_jaws=0;          // Jaws line calculation period
      int      period_teeth=0;         // Teeth line calculation period
      int      period_lips=0;          // Lips line calculation period
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      
      

      EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

      //+------------------------------------------------------------------+
      //|                                            TestWilliamsGator.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- includes
      #include <Dashboard\Dashboard.mqh>
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- input parameters
      input uint                 InpPeriodJaws  =  13;            /* Jaws Period    */
      input int                  InpShiftJaws   =  8;             /* Jaws Shift     */
      input uint                 InpPeriodTeeth =  8;             /* Teeth Period   */
      input int                  InpShiftTeeth  =  5;             /* Teeth Shift    */
      input uint                 InpPeriodLips  =  5;             /* Lips Period    */
      input int                  InpShiftLips   =  3;             /* Lips Shift     */
      input ENUM_MA_METHOD       InpMethod      =  MODE_SMMA;     /* Smoothed       */
      input ENUM_APPLIED_PRICE   InpAppliedPrice=  PRICE_MEDIAN;  /* Applied Price  */
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      period_jaws=0;          // Jaws line calculation period
      int      period_teeth=0;         // Teeth line calculation period
      int      period_lips=0;          // Lips line calculation period
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      //--- variables for the panel
      int      mouse_bar_index;        // Index of the bar the data is taken from
      CDashboard *panel=NULL;          // Pointer to the panel object
      
      


      初期化

      指標のグローバル変数の値を設定し、ハンドルを作成します。

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set and adjust the calculation period if necessary
         period_jaws=int(InpPeriodJaws<1 ? 13 : InpPeriodJaws);
         period_teeth=int(InpPeriodTeeth<1 ? 8 : InpPeriodTeeth);
         period_lips=int(InpPeriodLips<1 ? 5 : InpPeriodLips);
      //--- Set the indicator name and the number of decimal places
         ind_title=StringFormat("Gator(%lu,%lu,%lu)",period_jaws,period_teeth,period_lips);
         ind_digits=Digits()+1;
      //--- Create indicator handle
         ResetLastError();
         handle=iGator(Symbol(),PERIOD_CURRENT,period_jaws,InpShiftJaws,period_teeth,InpShiftTeeth,period_lips,InpShiftLips,InpMethod,InpAppliedPrice);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      

      EAがダッシュボードを使用する場合は、ここで作成します

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set and adjust the calculation period if necessary
         period_jaws=int(InpPeriodJaws<1 ? 13 : InpPeriodJaws);
         period_teeth=int(InpPeriodTeeth<1 ? 8 : InpPeriodTeeth);
         period_lips=int(InpPeriodLips<1 ? 5 : InpPeriodLips);
      //--- Set the indicator name and the number of decimal places
         ind_title=StringFormat("Gator(%lu,%lu,%lu)",period_jaws,period_teeth,period_lips);
         ind_digits=Digits()+1;
      //--- Create indicator handle
         ResetLastError();
         handle=iGator(Symbol(),PERIOD_CURRENT,period_jaws,InpShiftJaws,period_teeth,InpShiftTeeth,period_lips,InpShiftLips,InpMethod,InpAppliedPrice);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Dashboard
      //--- Create the panel
         panel=new CDashboard(1,20,20,229,225);
         if(panel==NULL)
           {
            Print("Error. Failed to create panel object");
            return INIT_FAILED;
           }
      //--- Set font parameters
         panel.SetFontParams("Calibri",9);
      //--- Display the panel with the "Symbol, Timeframe description" header text
         panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
      //--- Create a table with ID 0 to display bar data in it
         panel.CreateNewTable(0);
      //--- Draw a table with ID 0 on the panel background
         panel.DrawGrid(0,2,20,6,2,18,112);
      
      //--- Create a table with ID 1 to display indicator data in it
         panel.CreateNewTable(1);
      //--- Get the Y2 table coordinate with ID 0 and
      //--- set the Y1 coordinate for the table with ID 1
         int y1=panel.TableY2(0)+22;
      //--- Draw a table with ID 1 on the panel background
         panel.DrawGrid(1,2,y1,3,2,18,112);
         
      //--- Display tabular data in the journal
         panel.GridPrint(0,2);
         panel.GridPrint(1,2);
      //--- Initialize the variable with the index of the mouse cursor bar
         mouse_bar_index=0;
      //--- Display the data of the current bar on the panel
         DrawData(mouse_bar_index,TimeCurrent());
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      


      初期化解除

      EA OnDeinit()ハンドルの指標ハンドルを解放します

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
        }
      
      

      作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
         
      //--- If the panel object exists, delete it
         if(panel!=NULL)
            delete panel;
        }
      


      データ検索

      指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

      //+------------------------------------------------------------------+
      //| Return the indicator data on the specified bar                   |
      //+------------------------------------------------------------------+
      double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
        {
         double array[1]={0};
         ResetLastError();
         if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
           {
            PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
            return EMPTY_VALUE;
           }
         return array[0];
        }
      //+------------------------------------------------------------------+
      //| Return the state of the indicator line                           |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
        {
      //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
         const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Line upward reversal (value2>value1 && value0>value1)
         if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_TURN_UP;
      //--- Line upward direction (value2<=value1 && value0>value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_UP;
      //--- Line upward stop (value2<=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_UP;
      //--- Line downward reversal (value2<value1 && value0<value1)
         if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_TURN_DOWN;
      //--- Line downward direction (value2>=value1 && value0<value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_DOWN;
      //--- Line downward stop (value2>=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_DOWN;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the state of the line relative to the specified level     |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
        {
      //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Define the second level to compare
         double level=(level1==EMPTY_VALUE ? level0 : level1);
      //--- The line is below the level (value1<level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_UNDER;
      //--- The line is above the level (value1>level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_ABOVE;
      //--- The line crossed the level upwards (value1<=level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_CROSS_UP;
      //--- The line crossed the level downwards (value1>=level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_CROSS_DOWN;
      //--- The line touched the level from below (value1<level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- The line touched the level from above (value1>level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- Line is equal to the level value (value1==level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_EQUALS;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the indicator line state description                      |
      //+------------------------------------------------------------------+
      string LineStateDescription(const ENUM_LINE_STATE state)
        {
         switch(state)
           {
            case LINE_STATE_UP         :  return "Up";
            case LINE_STATE_STOP_UP    :  return "Stop Up";
            case LINE_STATE_TURN_UP    :  return "Turn Up";
            case LINE_STATE_DOWN       :  return "Down";
            case LINE_STATE_STOP_DOWN  :  return "Stop Down";
            case LINE_STATE_TURN_DOWN  :  return "Turn Down";
            case LINE_STATE_ABOVE      :  return "Above level";
            case LINE_STATE_UNDER      :  return "Under level";
            case LINE_STATE_CROSS_UP   :  return "Crossing Up";
            case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
            case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
            case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
            case LINE_STATE_EQUALS     :  return "Equals";
            default                    :  return "Unknown";
           }
        }
      
      

      ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

      //+------------------------------------------------------------------+
      //| Display data from the specified timeseries index to the panel    |
      //+------------------------------------------------------------------+
      void DrawData(const int index,const datetime time)
        {
      //--- Declare the variables to receive data in them
         MqlTick  tick={0};
         MqlRates rates[1];
      
      //--- Exit if unable to get the current prices
         if(!SymbolInfoTick(Symbol(),tick))
            return;
      //--- Exit if unable to get the bar data by the specified index
         if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
            return;
      
      //--- Set font parameters for bar and indicator data headers
         int  size=0;
         uint flags=0;
         uint angle=0;
         string name=panel.FontParams(size,flags,angle);
         panel.SetFontParams(name,9,FW_BOLD);
         panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
         panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
      //--- Set font parameters for bar and indicator data
         panel.SetFontParams(name,9);
      
      //--- Display the data of the specified bar in table 0 on the panel
         panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
         panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
         panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
         panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
         panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
         panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
      
      //--- Get the indicator buffers data
         double value0=IndicatorValue(handle,index,UPPER_HISTOGRAM); // Upper histogram
         double value1=IndicatorValue(handle,index,1);               // Upper histogram color buffer
         double value2=IndicatorValue(handle,index,LOWER_HISTOGRAM); // Lower histogram
         double value3=IndicatorValue(handle,index,3);               // Lower histogram color buffer
         color clr=clrNONE;
      //--- Display the upper histogram data from the specified bar on the panel in table 1
         panel.DrawText(ind_title+" Up", panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
         string value_str=(value0!=EMPTY_VALUE ? DoubleToString(value0,ind_digits) : "");
         clr=(value1>0 ? clrRed : clrGreen);
         panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clr,100);
         
      //--- Display the lower histogram data from the specified bar on the panel in table 1
         panel.DrawText(ind_title+" Down", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
         value_str=(value2!=EMPTY_VALUE ? DoubleToString(value2,ind_digits) : "");
         clr=(value3>0 ? clrRed : clrGreen);
         panel.DrawText(value_str,panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,100);
         
      //--- Redraw the chart to immediately display all changes on the panel
         ChartRedraw(ChartID());
        }
      
      

      指標バッファの値を説明するテキストの色は、指標ヒストグラムの対応する列と同じ色です。

      その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

      //+------------------------------------------------------------------+
      //| ChartEvent function                                              |
      //+------------------------------------------------------------------+
      void OnChartEvent(const int id,
                        const long &lparam,
                        const double &dparam,
                        const string &sparam)
        {
      //--- Handling the panel
      //--- Call the panel event handler
         panel.OnChartEvent(id,lparam,dparam,sparam);
      
      //--- If the cursor moves or a click is made on the chart
         if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
           {
            //--- Declare the variables to record time and price coordinates in them
            datetime time=0;
            double price=0;
            int wnd=0;
            //--- If the cursor coordinates are converted to date and time
            if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
              {
               //--- write the bar index where the cursor is located to a global variable
               mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
               //--- Display the bar data under the cursor on the panel 
               DrawData(mouse_bar_index,time);
              }
           }
      
      //--- If we received a custom event, display the appropriate message in the journal
         if(id>CHARTEVENT_CUSTOM)
           {
            //--- Here we can implement handling a click on the close button on the panel
            PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
           }
        }
      
      

      EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。



      TestWilliamsGator.mq5テストEAは、記事に添付されているファイルに含まれています。


      Market Facilitation Index(マーケットファシリテーションインデックス)

      マーケットファシリテーションインデックス(BW MFI)は、1ティックの価格変動を示す指標です。指標の絶対値自体には意味がなく、指標の値の変化のみに意味があります。ビルウィリアムズは、MFIと出来高のやり取りを重視しています。

      • BW MFIが上がり、出来高も増加した場合。このことは次を意味します。 a) 相場に参加しているトレーダの数が増加する(出来高が増加する)b) 新しく参加したトレーダが足が推移した方向に注文を出す。つまり、値動きが始まり、スピードが上がる。
      • BW MFIが下がり、出来高も下がった場合は、市場参加者の関心が失われたことを意味します。
      • BW MFIが上がったにも関わらず、出来高が下がった場合は、相場が参加者の取引量によって支えられていない、また、トレーダ(ブローカーやディーラー)が「底」と判断することによって価格が変化する可能性があります。
      • BW MFIが下がり、出来高が増加した場合、大規模の取引量を特徴にする強気側と弱気側の戦いがあり、力が等しいため価格は著しく変化しません。最終的に売り手と買い手の一方が勝利します。一般的に、バーのブレイクはその足がトレンドを継続させるかトレンドをなくすかを教えてくれます。ビルウィリアムズはこの様なバーを「おじぎ」と呼んでいます。



      パラメータ

      指標ハンドルの作成にはiBWMFI()関数が使用されます。

      BW MFIのハンドルを返します。バッファは1つだけです。

      int  iBWMFI(
         string               symbol,             // symbol name
         ENUM_TIMEFRAMES      period,             // period
         ENUM_APPLIED_VOLUME  applied_volume      // type of volume used for calculations
         );
      

      symbol

      [in]指標の算出にデータを使用する金融商品の銘柄名。NULLは現在の銘柄を意味します。

      period

      [in]期間値はENUM_TIMEFRAMES列挙値のいずれかになります。0は現在の時間枠を意味します。

      applied_volume

      [in]使用されるボリューム。ENUM_APPLIED_VOLUME列挙値のいずれかです。

      指定したテクニカル指標のハンドルを返します。失敗した場合はINVALID_HANDLEを返します。未使用指標のコンピューターメモリーを解放するには、指標ハンドルに渡されたIndicatorRelease()を使用します。


      指標を作成するために、EAで入力変数とグローバル変数を宣言します。

      //+------------------------------------------------------------------+
      //|                                            TestWilliamsBWMFI.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- input parameters
      input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      
      

      EAでダッシュボードを使用する場合は、グローバル変数を宣言し、パネルクラスのファイルをインクルードします

      //+------------------------------------------------------------------+
      //|                                            TestWilliamsBWMFI.mq5 |
      //|                                  Copyright 2023, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2023, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //--- includes
      #include <Dashboard\Dashboard.mqh>
      //--- enums
      enum ENUM_LINE_STATE
        {
         LINE_STATE_NONE,        // Undefined state
         LINE_STATE_UP,          // Upward
         LINE_STATE_DOWN,        // Downward
         LINE_STATE_TURN_UP,     // Upward reversal
         LINE_STATE_TURN_DOWN,   // Downward reversal
         LINE_STATE_STOP_UP,     // Upward stop
         LINE_STATE_STOP_DOWN,   // Downward stop
         LINE_STATE_ABOVE,       // Above value
         LINE_STATE_UNDER,       // Below value
         LINE_STATE_CROSS_UP,    // Crossing value upwards
         LINE_STATE_CROSS_DOWN,  // Crossing value downwards
         LINE_STATE_TOUCH_BELOW, // Touching value from below 
         LINE_STATE_TOUCH_ABOVE, // Touch value from above
         LINE_STATE_EQUALS,      // Equal to value
        };
      //--- input parameters
      input ENUM_APPLIED_VOLUME  InpVolume   =  VOLUME_TICK;   /* Applied Volume */
      //--- global variables
      int      handle=INVALID_HANDLE;  // Indicator handle
      int      ind_digits=0;           // Number of decimal places in the indicator values
      string   ind_title;              // Indicator description
      //--- variables for the panel
      int      mouse_bar_index;        // Index of the bar the data is taken from
      CDashboard *panel=NULL;          // Pointer to the panel object
      
      


      初期化

      指標のグローバル変数の値を設定し、ハンドルを作成します。

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="BW MFI";
         ind_digits=Digits();
      //--- Create indicator handle
         ResetLastError();
         handle=iBWMFI(Symbol(),PERIOD_CURRENT,InpVolume);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      

      EAがダッシュボードを使用する場合は、ここで作成します

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //--- create timer
         EventSetTimer(60);
      
      //--- Indicator
      //--- Set the indicator name and the number of decimal places
         ind_title="BW MFI";
         ind_digits=Digits();
      //--- Create indicator handle
         ResetLastError();
         handle=iBWMFI(Symbol(),PERIOD_CURRENT,InpVolume);
         if(handle==INVALID_HANDLE)
           {
            PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
            return INIT_FAILED;
           }
      
      //--- Dashboard
      //--- Create the panel
         panel=new CDashboard(1,20,20,199,225);
         if(panel==NULL)
           {
            Print("Error. Failed to create panel object");
            return INIT_FAILED;
           }
      //--- Set font parameters
         panel.SetFontParams("Calibri",9);
      //--- Display the panel with the "Symbol, Timeframe description" header text
         panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
      //--- Create a table with ID 0 to display bar data in it
         panel.CreateNewTable(0);
      //--- Draw a table with ID 0 on the panel background
         panel.DrawGrid(0,2,20,6,2,18,97);
      
      //--- Create a table with ID 1 to display indicator data in it
         panel.CreateNewTable(1);
      //--- Get the Y2 table coordinate with ID 0 and
      //--- set the Y1 coordinate for the table with ID 1
         int y1=panel.TableY2(0)+22;
      //--- Draw a table with ID 1 on the panel background
         panel.DrawGrid(1,2,y1,3,2,18,97);
         
      //--- Display tabular data in the journal
         panel.GridPrint(0,2);
         panel.GridPrint(1,2);
      //--- Initialize the variable with the index of the mouse cursor bar
         mouse_bar_index=0;
      //--- Display the data of the current bar on the panel
         DrawData(mouse_bar_index,TimeCurrent());
      
      //--- Successful initialization
         return(INIT_SUCCEEDED);
        }
      
      


      初期化解除

      EA OnDeinit()ハンドルの指標ハンドルを解放します

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
        }
      
      

      作成されたダッシュボードオブジェクトは、ダッシュボードを使用する際に削除されます。

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //--- destroy timer
         EventKillTimer();
         
      //--- Release handle of the indicator
         ResetLastError();
         if(!IndicatorRelease(handle))
            PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
      //--- Clear all comments on the chart
         Comment("");
         
      //--- If the panel object exists, delete it
         if(panel!=NULL)
            delete panel;
        }
      


      データ検索

      指示ハンドルでデータを取得するための一般的な関数を以下に示します。これらの関数については、オシレーターとEAの接続についての記事でレビューしています。紹介した関数は、カスタムプログラムで「そのまま」使うことができます。

      //+------------------------------------------------------------------+
      //| Return the indicator data on the specified bar                   |
      //+------------------------------------------------------------------+
      double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
        {
         double array[1]={0};
         ResetLastError();
         if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
           {
            PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
            return EMPTY_VALUE;
           }
         return array[0];
        }
      //+------------------------------------------------------------------+
      //| Return the state of the indicator line                           |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
        {
      //--- Get the values of the indicator line with the shift (0,1,2) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
         const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Line upward reversal (value2>value1 && value0>value1)
         if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_TURN_UP;
      //--- Line upward direction (value2<=value1 && value0>value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
            return LINE_STATE_UP;
      //--- Line upward stop (value2<=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_UP;
      //--- Line downward reversal (value2<value1 && value0<value1)
         if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_TURN_DOWN;
      //--- Line downward direction (value2>=value1 && value0<value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
            return LINE_STATE_DOWN;
      //--- Line downward stop (value2>=value1 && value0==value1)
         else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
            return LINE_STATE_STOP_DOWN;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the state of the line relative to the specified level     |
      //+------------------------------------------------------------------+
      ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
        {
      //--- Get the values of the indicator line with the shift (0,1) relative to the passed index
         const double value0=IndicatorValue(ind_handle,index,  buffer_num);
         const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
      //--- If at least one of the values could not be obtained, return an undefined value 
         if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
            return LINE_STATE_NONE;
      //--- Define the second level to compare
         double level=(level1==EMPTY_VALUE ? level0 : level1);
      //--- The line is below the level (value1<level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_UNDER;
      //--- The line is above the level (value1>level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_ABOVE;
      //--- The line crossed the level upwards (value1<=level && value0>level0)
         if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
            return LINE_STATE_CROSS_UP;
      //--- The line crossed the level downwards (value1>=level && value0<level0)
         if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
            return LINE_STATE_CROSS_DOWN;
      //--- The line touched the level from below (value1<level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- The line touched the level from above (value1>level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_TOUCH_BELOW;
      //--- Line is equal to the level value (value1==level0 && value0==level0)
         if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
            return LINE_STATE_EQUALS;
      //--- Undefined state
         return LINE_STATE_NONE;
        }
      //+------------------------------------------------------------------+
      //| Return the indicator line state description                      |
      //+------------------------------------------------------------------+
      string LineStateDescription(const ENUM_LINE_STATE state)
        {
         switch(state)
           {
            case LINE_STATE_UP         :  return "Up";
            case LINE_STATE_STOP_UP    :  return "Stop Up";
            case LINE_STATE_TURN_UP    :  return "Turn Up";
            case LINE_STATE_DOWN       :  return "Down";
            case LINE_STATE_STOP_DOWN  :  return "Stop Down";
            case LINE_STATE_TURN_DOWN  :  return "Turn Down";
            case LINE_STATE_ABOVE      :  return "Above level";
            case LINE_STATE_UNDER      :  return "Under level";
            case LINE_STATE_CROSS_UP   :  return "Crossing Up";
            case LINE_STATE_CROSS_DOWN :  return "Crossing Down";
            case LINE_STATE_TOUCH_BELOW:  return "Touch from Below";
            case LINE_STATE_TOUCH_ABOVE:  return "Touch from Above";
            case LINE_STATE_EQUALS     :  return "Equals";
            default                    :  return "Unknown";
           }
        }
      
      

      ダッシュボードを使用する場合、データは次の関数を使用してパネルに表示されます。

      //+------------------------------------------------------------------+
      //| Display data from the specified timeseries index to the panel    |
      //+------------------------------------------------------------------+
      void DrawData(const int index,const datetime time)
        {
      //--- Declare the variables to receive data in them
         MqlTick  tick={0};
         MqlRates rates[1];
      
      //--- Exit if unable to get the current prices
         if(!SymbolInfoTick(Symbol(),tick))
            return;
      //--- Exit if unable to get the bar data by the specified index
         if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
            return;
      
      //--- Set font parameters for bar and indicator data headers
         int  size=0;
         uint flags=0;
         uint angle=0;
         string name=panel.FontParams(size,flags,angle);
         panel.SetFontParams(name,9,FW_BOLD);
         panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
         panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
      //--- Set font parameters for bar and indicator data
         panel.SetFontParams(name,9);
      
      //--- Display the data of the specified bar in table 0 on the panel
         panel.DrawText("Date",  panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_DATE),     panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
         panel.DrawText("Time",  panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString(  rates[0].time,TIME_MINUTES),  panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
         panel.DrawText("Open",  panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()),      panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
         panel.DrawText("High",  panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()),      panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
         panel.DrawText("Low",   panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()),       panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
         panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()),     panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
      
      //--- Display the indicator data from the specified bar on the panel in table 1
         panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
         double value=IndicatorValue(handle,index,0);
         string value_str=(value!=EMPTY_VALUE ? DoubleToString(value,ind_digits) : "");
         panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
         
      //--- Create Volumes indicator handle
         static bool create=false;
         static int hv=INVALID_HANDLE;
         if(!create)
           {
            ResetLastError();
            hv=iVolumes(Symbol(),PERIOD_CURRENT,InpVolume);
            if(hv==INVALID_HANDLE)
              {
               PrintFormat("%s: Failed to create indicator handle Volumes. Error %ld",__FUNCTION__,GetLastError());
               return;
              }
            create=true;
           }
      
      //--- Get Volumes indicator status
         ENUM_LINE_STATE state_vol=LineState(hv,index,0);
      //--- Display a description of the indicator line state
         panel.DrawText("BW MFI State", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
         ENUM_LINE_STATE state=LineState(handle,index,0);
         color clr=clrNONE;
         string state_str=LineStateDescription(state);
         if((state==LINE_STATE_UP || state==LINE_STATE_TURN_UP) && (state_vol==LINE_STATE_UP || state_vol==LINE_STATE_TURN_UP))
           {
            state_str="MFI Up, Vol Up";
            clr=clrGreen;
           }
         if((state==LINE_STATE_DOWN || state==LINE_STATE_TURN_DOWN) && (state_vol==LINE_STATE_DOWN || state_vol==LINE_STATE_TURN_DOWN))
           {
            state_str="MFI Dn, Vol Dn";
            clr=clrSaddleBrown;
           }
         if((state==LINE_STATE_UP || state==LINE_STATE_TURN_UP) && (state_vol==LINE_STATE_DOWN || state_vol==LINE_STATE_TURN_DOWN))
           {
            state_str="MFI Up, Vol Dn";
            clr=clrBlue;
           }
         if((state==LINE_STATE_DOWN || state==LINE_STATE_TURN_DOWN) && (state_vol==LINE_STATE_UP || state_vol==LINE_STATE_TURN_UP))
           {
            state_str="MFI Dn, Vol Up";
            clr=clrLightCoral;
           }
      
      //--- Set font parameters for indicator state data (bold font)
         name=panel.FontParams(size,flags,angle);
         panel.SetFontParams(name,9,FW_BOLD);
         panel.DrawText(state_str,panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clr,90);
      //--- Restore the normal thickness of the panel font
         panel.SetFontParams(name,9);
         
      //--- Redraw the chart to immediately display all changes on the panel
         ChartRedraw(ChartID());
        }
      
      

      BW MFI指標データは、ここで提供されている汎用関数を通じて、通常の方法で取得できます。ただし、指標列の読み取り値を解釈するには、別の指標である出来高指標が必要です。これは、ヒストグラム列に色を付けるために、ヒストグラム列の値と前の値と比較した出来高値という2つの指標が比較されるためです。関数で出来高を取得するには、Volumes指標ハンドルを作成し(最初のアクセス時に1回)、BW MFIラインとVolumesラインの状態を比較します。それらの相互関係の説明は、テキストとしてパネルに表示されます。

      その上、ダッシュボードを使用すると、OnChartEvent() EAイベントハンドラでパネルイベントハンドラが呼び出され、カーソル下のバーインデックスを受信するイベントも処理されます。

      //+------------------------------------------------------------------+
      //| ChartEvent function                                              |
      //+------------------------------------------------------------------+
      void OnChartEvent(const int id,
                        const long &lparam,
                        const double &dparam,
                        const string &sparam)
        {
      //--- Handling the panel
      //--- Call the panel event handler
         panel.OnChartEvent(id,lparam,dparam,sparam);
      
      //--- If the cursor moves or a click is made on the chart
         if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
           {
            //--- Declare the variables to record time and price coordinates in them
            datetime time=0;
            double price=0;
            int wnd=0;
            //--- If the cursor coordinates are converted to date and time
            if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
              {
               //--- write the bar index where the cursor is located to a global variable
               mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
               //--- Display the bar data under the cursor on the panel 
               DrawData(mouse_bar_index,time);
              }
           }
      
      //--- If we received a custom event, display the appropriate message in the journal
         if(id>CHARTEVENT_CUSTOM)
           {
            //--- Here we can implement handling a click on the close button on the panel
            PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
           }
        }
      
      

      EAをコンパイルしてチャート上で起動したら、パネル上で指標の値とラインの状態を監視できます。

      TestWilliamsBWMFI.mq5テストEAは、記事に添付されているファイルに含まれています。


      ダッシュボードクラスの洗練。Browse

      このシリーズのテストEAでは、最初の記事で作成したダッシュボードを使用します。パネルに1つのテーブルを作成することは可能でした。テーブルの座標は、ダッシュボードにデータを表示するのに使うことができます。これでダッシュボードのクラスが確定しました。データを入れるテーブルをいくつでも作ることができます。また、ダッシュボードを折りたたみ、時間枠を切り替え、再びダッシュボードを展開した後、ダッシュボードのデータが一時的に消えてしまうのを修正しました。ダッシュボードのクラスに加えられた変更のトピックに戻らないように、変更点を簡単に説明しましょう。

      これで、パネル上に作成された各テーブルは、その座標を返すことができるようになりました。X1、Y1-左上隅、X2、Y2-右下隅。各プレートにはIDと名前が割り当てられており、このIDを使ってアクセスし、データを取得することができます。

      CTableData表データクラスには、private変数と、これらの値を書き込んだり返したりするpublicメソッドが追加されました。

      //+------------------------------------------------------------------+
      //| Table data class                                                 |
      //+------------------------------------------------------------------+
      class CTableData : public CObject
        {
      private:
         CArrayObj         m_list_rows;               // List of rows
         uint              m_id;                      // Table ID
         int               m_x1;                      // X1 coordinate
         int               m_y1;                      // Y1 coordinate
         int               m_x2;                      // X2 coordinate
         int               m_y2;                      // Y2 coordinate
         int               m_w;                       // Width
         int               m_h;                       // Height
         string            m_name;                    // Table name
      public:
      //--- Set table name
         void              SetName(const string name) { this.m_name=name;              }
      //--- Return table (1) ID and (2) name
         uint              ID(void)             const { return this.m_id;              }
         string            Name(void)           const { return this.m_name;            }
         
      //--- Set coordinate (1) X1, (2) X2
         void              SetX1(const uint x1)       { this.m_x1=(int)x1;             }
         void              SetX2(const uint x2)       { this.m_x2=(int)x2;             }
      //--- Set coordinate (1) Y1, (2) Y2
         void              SetY1(const uint y1)       { this.m_y1=(int)y1;             }
         void              SetY2(const uint y2)       { this.m_y2=(int)y2;             }
      //--- Set table coordinates
         void              SetCoords(const int x1,const int y1,const int x2,const int y2)
                             {
                              this.SetX1(x1);
                              this.SetY1(y1);
                              this.SetX2(x2);
                              this.SetY2(y2);
                             }
         
      //--- Return coordinate (1) X1, (2) X2
         int               X1(void)             const { return this.m_x1;              }
         int               X2(void)             const { return this.m_x2;              }
      //--- Return coordinate (1) Y1, (2) Y2
         int               Y1(void)             const { return this.m_y1;              }
         int               Y2(void)             const { return this.m_y2;              }
         
      //--- Return (1) width and (2) height
         int               Width(void)          const { return this.m_x2-this.m_x1+1;  }
         int               Height(void)         const { return this.m_y2-this.m_y1+1;  }
         
      //--- Return the list of table rows
      

      指定した行のセル数を返すpublicメソッドを追加しました。

         int               ColumnsInRow(const int row_index)
                             {
                              //--- If there is no row in the list, return 0
                              if(this.RowsTotal()==0)
                                 return 0;
                              //--- Get a pointer to the specified row and return the number of cells in it
                              CTableRow *row=this.GetRow(row_index);
                              return(row!=NULL ? row.CellsTotal() : 0);
                             }
      //--- Return the total number of cells in the table
      

      テーブルセルの総数を返すpublicメソッドを追加しました。

      //--- Return the total number of cells in the table
         int               CellsTotal(void)
                             {
                              //--- If there is no row in the list, return 0
                              if(this.RowsTotal()==0)
                                 return 0;
                              //---
                              int num=0;
                              int total=this.RowsTotal();
                              for(int i=0;i<total;i++)
                                 num+=this.ColumnsInRow(i);
                              return num;
                             }
      //--- Clear lists of rows and table cells
      

      これまでは、テーブルの最初の行にある列の数が各行で同じであることを祈りながら、単純にその数を返していました。これで、表の各行に配置されたセルの数によって、表のセルの総数を求めることができます。指定した行のセル数を取得することもできます。従って、非格子テーブルを作成することも可能です。行のセル数が異なる表の作成は、現在のタスクでは需要がないため、テストしませんでした。おそらく、さらなる改良が必要になるでしょう。しかし、今のところ、そのようなテーブルは必要ありません。

      このクラスは、ID (mode = 0)または名前(mode != 0)でテーブルを比較できる仮想Compareメソッドを備えています。

      //--- Virtual method for comparing two objects
         virtual int       Compare(const CObject *node,const int mode=0) const
                             {
                              const CTableData *compared=node;
                              if(mode==0)
                                 return(this.ID()>compared.ID() ? 1 : this.ID()<compared.ID() ? -1 : 0);
                              else
                                 return(this.Name()==compared.Name() ? 0 : this.Name()>compared.Name() ? 1 : -1);
                             }
      

      作成されたテーブルのIDは、クラスのパラメトリックコンストラクタに渡されます。

      //--- Constructor/destructor
                           CTableData(const uint id) : m_id(id){ this.m_list_rows.Clear(); this.m_name="";  }
                          ~CTableData(void)                    { this.m_list_rows.Clear();                  }
      


      以前は表データオブジェクトのインスタンスがパネルクラスで宣言されていましたが、今度はパネルで作成された表へのポインタを含むリストを宣言します。

      //+------------------------------------------------------------------+
      //| Dashboard class                                                  |
      //+------------------------------------------------------------------+
      class CDashboard : public CObject
        {
      private:
         CCanvas           m_canvas;                  // Canvas
         CCanvas           m_workspace;               // Work space
         CArrayObj         m_list_table;              // List of tables
         ENUM_PROGRAM_TYPE m_program_type;            // Program type
         ENUM_MOUSE_STATE  m_mouse_state;             // Mouse button status
      

      privateセクションに、背景と作業領域のピクセルをファイルに保存するためのファイル名を作成する変数を宣言します。

         string            m_name_gv_m;               // Name of the global terminal variable storing the collapsed panel flag 
      
         string            m_name_gv_u;               // Name of the global terminal variable storing the flag of the pinned panel 
         string            m_filename_bg;             // File name to save background pixels 
         string            m_filename_ws;             // File name for saving work space pixels
         
         uint              m_array_wpx[];             // Array of pixels to save/restore the workspace 
         uint              m_array_ppx[];             // Array of pixels to save/restore the panel background 
      

      パネルフォントを扱うためのメソッドの追加と改良、およびテーブルとその座標の作成と取得のためのメソッドの追加と改良をおこないます。

      //--- Set default panel font parameters
         void              SetFontParams(const string name,const int size,const uint flags=0,const uint angle=0);
      //--- Return the specified dashboard font parameters
         string            FontParams(int &size,uint &flags,uint &angle);
      //--- Return the specified panel (1) font, (2) size and font flags
         string            FontName(void)    const { return this.m_workspace.FontNameGet();  }
         int               FontSize(void)    const { return this.m_workspace.FontSizeGet();  }
         uint              FontFlags(void)   const { return this.m_workspace.FontFlagsGet(); }
      //--- Display a text message at the specified coordinates
         void              DrawText(const string text,const int x,const int y,const color clr=clrNONE,const int width=WRONG_VALUE,const int height=WRONG_VALUE);
      //--- Create a new table
         bool              CreateNewTable(const int id=WRONG_VALUE);
      //--- Return tabular data object by (1) ID and (2) name
         CTableData       *GetTable(const uint id);
         CTableData       *GetTable(const string name);
      //--- Draw a (1) background grid (2) with automatic cell size
         void              DrawGrid(const uint table_id,const uint x,const uint y,const uint rows,const uint columns,const uint row_size,const uint col_size,const color line_color=clrNONE,bool alternating_color=true);
         void              DrawGridAutoFill(const uint table_id,const uint border,const uint rows,const uint columns,const color line_color=clrNONE,bool alternating_color=true);
      //--- Print grid data (line intersection coordinates)
         void              GridPrint(const uint table_id,const uint indent=0)
                             {
                              CTableData *table=this.GetTable(table_id);
                              if(table==NULL)
                                {
                                 ::PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
                                 return;
                                }
                              table.Print(indent);
                             }
      //--- Write the X and Y coordinate values of the specified table cell to variables
         void              CellXY(const uint table_id,const uint row,const uint column, int &x, int &y)
                             {
                              CTableData *table=this.GetTable(table_id);
                              if(table==NULL)
                                {
                                 ::PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
                                 return;
                                }
                              table.CellXY(row,column,x,y);
                             }
      //--- Return the (1) X and (2) Y coordinate of the specified table cell
         int               CellX(const uint table_id,const uint row,const uint column)
                             {
                              CTableData *table=this.GetTable(table_id);
                              if(table==NULL)
                                {
                                 ::PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
                                 return WRONG_VALUE;
                                }
                              return table.CellX(row,column);
                             }
         int               CellY(const uint table_id,const uint row,const uint column)
                             {
                              CTableData *table=this.GetTable(table_id);
                              if(table==NULL)
                                {
                                 ::PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
                                 return WRONG_VALUE;
                                }
                              return table.CellY(row,column);
                             }
      //--- Write X1 and Y1, X2 and Y2 coordinate values of the specified table to the variables
         void              TableCoords(const uint table_id,int &x1,int &y1,int &x2,int &y2)
                             {
                              x1=y1=x2=y2=WRONG_VALUE;
                              CTableData *table=this.GetTable(table_id);
                              if(table==NULL)
                                 return;
                              x1=table.X1();
                              y1=table.Y1();
                              x2=table.X2();
                              y2=table.Y2();
                             }
      
      //--- Return the (1) X1, (2) Y1, (3) X2 and (4) Y2 coordinate of the specified table
         int               TableX1(const uint table_id)
                             {
                              CTableData *table=this.GetTable(table_id);
                              return(table!=NULL ? table.X1() : WRONG_VALUE);
                             }
         int               TableY1(const uint table_id)
                             {
                              CTableData *table=this.GetTable(table_id);
                              return(table!=NULL ? table.Y1() : WRONG_VALUE);
                             }
         int               TableX2(const uint table_id)
                             {
                              CTableData *table=this.GetTable(table_id);
                              return(table!=NULL ? table.X2() : WRONG_VALUE);
                             }
         int               TableY2(const uint table_id)
                             {
                              CTableData *table=this.GetTable(table_id);
                              return(table!=NULL ? table.Y2() : WRONG_VALUE);
                             }
      
      //--- Event handler
         void              OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
      //--- Constructor/destructor
                           CDashboard(const uint id,const int x,const int y, const int w,const int h,const int wnd=-1);
                          ~CDashboard();
      


      クラスのコンストラクタで、背景とワークスペースを保存するためのファイル名を作成します。

      //--- Set the names of global terminal variables to store panel coordinates, collapsed/expanded state and pinning
         this.m_name_gv_x=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_X";
         this.m_name_gv_y=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Y";
         this.m_name_gv_m=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Minimize";
         this.m_name_gv_u=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Unpin";
      
      //--- Set file names for saving background and work space pixels
         this.m_filename_bg=this.m_program_name+"\\Dashboard"+(string)this.m_id+"\\background.bin";
         this.m_filename_ws=this.m_program_name+"\\Dashboard"+(string)this.m_id+"\\workspace.bin";
         
      

      コンストラクタの最後で、パネルが折りたたまれている場合、ファイルからのデータが背景と作業スペースのピクセル配列に読み込まれます。

      //--- If the panel collapse flag is set, load the background and work space pixels from the files into arrays
         if(this.m_minimized)
           {
            if(::FileIsExist(this.m_filename_bg))
               this.FileLoadBackground();
            if(::FileIsExist(this.m_filename_ws))
               this.FileLoadWorkspace();
           }
        }
      

      したがって、ピクセルが以前にファイルに保存され、パネルが最小化された形で作成された場合、パネルの外観はファイルから読み込まれ、パネルは折りたたまれた形で描画されます。展開されると、その外観は、ファイルから満たされたピクセル配列から得られます。

      デストラクタでは、パネルが折りたたまれている場合、パネルオブジェクトを削除する前に、パネルを展開し、ピクセルデータをファイルに書き込み、再び折りたたむ必要があります。その後、パネルオブジェクトを削除することができます。パネルオブジェクトの外観はすでにファイルに保存されており、その後のコンストラクタでの作成時に復元できます。

      //+------------------------------------------------------------------+
      //| Destructor                                                       |
      //+------------------------------------------------------------------+
      CDashboard::~CDashboard()
        {
      //--- Write the current values to global terminal variables
         ::GlobalVariableSet(this.m_name_gv_x,this.m_x);
         ::GlobalVariableSet(this.m_name_gv_y,this.m_y);
         ::GlobalVariableSet(this.m_name_gv_m,this.m_minimized);
         ::GlobalVariableSet(this.m_name_gv_u,this.m_movable);
      
      //--- If the panel is collapsed,
      //--- expand the panel, save the appearance into pixel arrays and collapse the panel
         if(this.m_minimized)
           {
            this.Expand();
            this.SaveBackground();
            this.SaveWorkspace();
            this.Collapse();
           }
      //--- otherwise, if the panel is expanded,
      //--- save the appearance into pixel arrays
         else
           {
            this.SaveBackground();
            this.SaveWorkspace();
           }
      //--- Save pixel arrays to files
         this.FileSaveBackground();
         this.FileSaveWorkspace();
      
      //--- Delete panel objects
         this.m_canvas.Destroy();
         this.m_workspace.Destroy();
        }
      


      パネルの折りたたみ/展開ボタンのクリックを処理するブロックで、フラグを確認し、パネルが展開された場合、背景と作業スペースをピクセル配列に保存します。

            //--- If the panel collapse/expand button is pressed 
            else if(state==MOUSE_STATE_PRESSED_INSIDE_MINIMIZE)
              {
               //--- Disable chart scrolling, right-click menu and crosshair
               this.SetChartsTool(false);
               //--- If the panel is not collapsed, save the background and work space into pixel arrays 
               if(!this.m_minimized)
                 {
                  this.SaveWorkspace();
                  this.SaveBackground();
                 }
               //--- "flip" the panel collapse flag,
               this.m_minimized=!this.m_minimized;
               //--- redraw the panel taking into account the new state of the flag,
               this.Draw(this.m_title);
               //--- redraw the panel header area 
               this.RedrawHeaderArea();
               //--- If the panel is pinned and expanded, move it to the stored location coordinates
               if(this.m_minimized && !this.m_movable)
                  this.Move(this.m_x_dock,this.m_y_dock);
               //--- Update the canvas with chart redrawing and
               this.m_canvas.Update();
               //--- write the state of the panel expand flag to the global terminal variable
               ::GlobalVariableSet(this.m_name_gv_m,this.m_minimized);
              }
      


      ピクセルの配列を保存するための文字列がパネルの折りたたみメソッドから削除されました。ピクセルの保存は、最小化/拡大ボタンを押したときにのみおこなわれるようになりました。

      //+------------------------------------------------------------------+
      //| Collapse the panel                                               |
      //+------------------------------------------------------------------+
      void CDashboard::Collapse(void)
        {
      //--- Save the pixels of the working space and the panel background into arrays
         this.SaveWorkspace();
         this.SaveBackground();
      //--- Remember the current height of the panel
         int h=this.m_h;
      //--- Change the dimensions (height) of the canvas and working space
         if(!this.SetSizes(this.m_canvas.Width(),this.m_header_h))
            return;
      //--- Draw the header area
         this.DrawHeaderArea(this.m_title);
      //--- Return the saved panel height to the variable
         this.m_h=h;
        }
      


      ダッシュボードのフォントパラメータのセットを返すメソッドを実装します。

      //+------------------------------------------------------------------+
      //| Return the specified dashboard font parameters                   |
      //+------------------------------------------------------------------+
      string CDashboard::FontParams(int &size,uint &flags,uint &angle)
        {
         size=this.m_workspace.FontSizeGet();
         flags=this.m_workspace.FontFlagsGet();
         angle=this.m_workspace.FontAngleGet();
         return this.m_workspace.FontNameGet();
        }
      

      このメソッドはフォントの名前を返します。フォントサイズ、フラグ、角度は、リンクから渡された変数に書き込まれます。

      文字色も描画メソッドに渡されるようになりました。デフォルトはclrNONEで、 これは前に設定されたテキスト色を意味します

      //+------------------------------------------------------------------+
      //| Display a text message at the specified coordinates              |
      //+------------------------------------------------------------------+
      void CDashboard::DrawText(const string text,const int x,const int y,const color clr=clrNONE,const int width=WRONG_VALUE,const int height=WRONG_VALUE)
        {
      //--- Declare variables to record the text width and height in them
         int w=width;
         int h=height;
      //--- If the width and height of the text passed to the method have zero values,
      //--- then the entire working space is completely cleared using the transparent color
         if(width==0 && height==0)
            this.m_workspace.Erase(0x00FFFFFF);
      //--- Otherwise
         else
           {
            //--- If the passed width and height have default values (-1), we get its width and height from the text 
            if(width==WRONG_VALUE && height==WRONG_VALUE)
               this.m_workspace.TextSize(text,w,h);
            //--- otherwise,
            else
              {
               //--- if the width passed to the method has the default value (-1) - get the width from the text, or
               //--- if the width passed to the method has a value greater than zero, use the width passed to the method, or
               //--- if the width passed to the method has a zero value, use the value 1 for the width
               w=(width ==WRONG_VALUE ? this.m_workspace.TextWidth(text)  : width>0  ? width  : 1);
               //--- if the height passed to the method has a default value (-1), get the height from the text, or
               //--- if the height passed to the method has a value greater than zero, use the height passed to the method, or
               //--- if the height passed to the method has a zero value, use value 1 for the height
               h=(height==WRONG_VALUE ? this.m_workspace.TextHeight(text) : height>0 ? height : 1);
              }
            //--- Fill the space according to the specified coordinates and the resulting width and height with a transparent color (erase the previous entry)
            this.m_workspace.FillRectangle(x,y,x+w,y+h,0x00FFFFFF);
           }
      //--- Display the text to the space cleared of previous text and update the working space without redrawing the screen
         this.m_workspace.TextOut(x,y,text,::ColorToARGB(clr==clrNONE ? this.m_fore_color : clr));
         this.m_workspace.Update(false);
        }
      


      新しいテーブルを作成し、IDとテーブル名によって表データを取得するメソッドを実装します。

      //+------------------------------------------------------------------+
      //| Create a new table                                               |
      //+------------------------------------------------------------------+
      bool CDashboard::CreateNewTable(const int id=WRONG_VALUE)
        {
         uint num=(id>WRONG_VALUE ? id : this.m_list_table.Total());
         CTableData *table=new CTableData(num);
         this.m_list_table.Sort();
         if(this.m_list_table.Search(table)!=WRONG_VALUE)
           {
            PrintFormat("%s: Error. Table with id %lu already exists in the list",__FUNCTION__,num);
            delete table;
            return false;
           }
         if(!this.m_list_table.Add(table))
           {
            PrintFormat("%s: Error. Failed to add table with id %lu to the list",__FUNCTION__,num);
            delete table;
            return false;
           }
         return true;
        }
      //+------------------------------------------------------------------+
      //| Return tabular data object by ID                                 |
      //+------------------------------------------------------------------+
      CTableData *CDashboard::GetTable(const uint id)
        {
         if(this.m_list_table.Total()==0)
           {
            PrintFormat("%s: Error. The list of tables is empty. First you need to create a table using CreateNewTable",__FUNCTION__);
            .return NULL;
           }
         CTableData *table=new CTableData(id);
         if(table==NULL)
           {
            ::PrintFormat("%s: Error. Failed to create table object with id %lu",__FUNCTION__,id);
            .return NULL;
           }
         this.m_list_table.Sort();
         int index=this.m_list_table.Search(table);
         delete table;
         return this.m_list_table.At(index);
        }
      //+------------------------------------------------------------------+
      //| Return tabular data object by name                               |
      //+------------------------------------------------------------------+
      CTableData *CDashboard::GetTable(const string name)
        {
         if(this.m_list_table.Total()==0)
           {
            PrintFormat("%s: Error. The list of tables is empty. First you need to create a table using CreateNewTable",__FUNCTION__);
            .return NULL;
           }
         CTableData *table=new CTableData(0);
         if(table==NULL)
           {
            ::PrintFormat("%s: Error. Failed to create table object");
            .return NULL;
           }
         table.SetName(name);
         this.m_list_table.Sort(1);
         int index=this.m_list_table.Search(table);
         delete table;
         return this.m_list_table.At(index);
        }
      


      テーブルの描画メソッドを変更します。

      //+------------------------------------------------------------------+
      //| Draw the background grid                                         |
      //+------------------------------------------------------------------+
      void CDashboard::DrawGrid(const uint table_id,
                                const uint x,const uint y,const uint rows,const uint columns,const uint row_size,const uint col_size,
                                const color line_color=clrNONE,bool alternating_color=true)
        {
      //--- Get a table object by ID
         CTableData *table=this.GetTable(table_id);
         if(table==NULL)
           {
            PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
            return;
           }
      //--- Clear all lists of the tabular data object (remove cells from rows and all rows)
         table.Clear();
      //--- Line height cannot be less than 2
         int row_h=int(row_size<2 ? 2 : row_size);
      //--- Column width cannot be less than 2
         int col_w=int(col_size<2 ? 2 : col_size);
         
      //--- The X1 (left) coordinate of the table cannot be less than 1 (to leave one pixel around the perimeter of the panel for the frame)
         int x1=int(x<1 ? 1 : x);
      //--- Calculate the X2 coordinate (right) depending on the number of columns and their width
         int x2=x1+col_w*int(columns>0 ? columns : 1);
      //--- The Y1 coordinate is located under the panel title area
         int y1=this.m_header_h+(int)y;
      //--- Calculate the Y2 coordinate (bottom) depending on the number of lines and their height
         int y2=y1+row_h*int(rows>0 ? rows : 1);
      //--- Set table coordinates
         table.SetCoords(x1,y1-this.m_header_h,x2,y2-this.m_header_h);
         
      //--- Get the color of the table grid lines, either by default or passed to the method
         color clr=(line_color==clrNONE ? C'200,200,200' : line_color);
      //--- If the initial X coordinate is greater than 1, draw a table frame
      //--- (in case of the coordinate 1, the table frame is the panel frame)
         if(x1>1)
            this.m_canvas.Rectangle(x1,y1,x2,y2,::ColorToARGB(clr,this.m_alpha));
      //--- In the loop by table rows,
         for(int i=0;i<(int)rows;i++)
           {
            //--- calculate the Y coordinate of the next horizontal grid line (Y coordinate of the next table row)
            int row_y=y1+row_h*i;
            //--- if the flag of "alternating" line colors is passed and the line is even
            if(alternating_color && i%2==0)
              {
               //--- lighten the table background color and draw a background rectangle
               color new_color=this.NewColor(clr,45,45,45);
               this.m_canvas.FillRectangle(x1+1,row_y+1,x2-1,row_y+row_h-1,::ColorToARGB(new_color,this.m_alpha));
              }
            //--- Draw a table grid horizontal line
            this.m_canvas.Line(x1,row_y,x2,row_y,::ColorToARGB(clr,this.m_alpha));
            
            //--- Create a new table row object
            CTableRow *row_obj=new CTableRow(i);
            if(row_obj==NULL)
              {
               ::PrintFormat("%s: Failed to create table row object at index %lu",(string)__FUNCTION__,i);
               continue;
              }
            //--- Add it to the list of rows of the tabular data object
            //--- (if adding an object failed, delete the created object)
            if(!table.AddRow(row_obj))
               delete row_obj;
            //--- Set its Y coordinate in the created row object taking into account the offset from the panel title
            row_obj.SetY(row_y-this.m_header_h);
           }
           
      //--- In the loop by table columns,
         for(int i=0;i<(int)columns;i++)
           {
            //--- calculate the X coordinate of the next vertical grid line (X coordinate of the next table row)
            int col_x=x1+col_w*i;
            //--- If the grid line goes beyond the panel, interrupt the loop
            if(x1==1 && col_x>=x1+m_canvas.Width()-2)
               break;
            //--- Draw a vertical line of the table grid
            this.m_canvas.Line(col_x,y1,col_x,y2,::ColorToARGB(clr,this.m_alpha));
            
            //--- Get the number of created rows from the table data object 
            int total=table.RowsTotal();
            //--- In the loop by table rows
            for(int j=0;j<total;j++)
              {
               //--- get the next row
               CTableRow *row=table.GetRow(j);
               if(row==NULL)
                  continue;
               //--- Create a new table cell 
               CTableCell *cell=new CTableCell(row.Row(),i);
               if(cell==NULL)
                 {
                  ::PrintFormat("%s: Failed to create table cell object at index %lu",(string)__FUNCTION__,i);
                  continue;
                 }
               //--- Add the created cell to the row
               //--- (if adding an object failed, delete the created object)
               if(!row.AddCell(cell))
                 {
                  delete cell;
                  continue;
                 }
               //--- In the created cell object, set its X coordinate and the Y coordinate from the row object 
               cell.SetXY(col_x,row.Y());
              }
           }
      //--- Update the canvas without redrawing the chart
         this.m_canvas.Update(false);
        }
      //+------------------------------------------------------------------+
      //| Draws the background grid with automatic cell sizing             |
      //+------------------------------------------------------------------+
      void CDashboard::DrawGridAutoFill(const uint table_id,const uint border,const uint rows,const uint columns,const color line_color=clrNONE,bool alternating_color=true)
        {
      //--- Get a table object by ID
         CTableData *table=this.GetTable(table_id);
         if(table==NULL)
           {
            PrintFormat("%s: Error. Failed to get table object with id %lu",__FUNCTION__,table_id);
            return;
           }
      //--- X1 (left) table coordinate
         int x1=(int)border;
      //--- X2 (right) table coordinate
         int x2=this.m_canvas.Width()-(int)border-1;
      //--- Y1 (upper) table coordinate
         int y1=this.m_header_h+(int)border;
      //--- Y2 (lower) table coordinate
         int y2=this.m_canvas.Height()-(int)border-1;
      //--- Set table coordinates
         table.SetCoords(x1,y1,x2,y2);
      
      //--- Get the color of the table grid lines, either by default or passed to the method
         color clr=(line_color==clrNONE ? C'200,200,200' : line_color);
      //--- If the offset from the edge of the panel is greater than zero, draw a table border,
      //--- otherwise, the panel border is used as the table border
         if(border>0)
            this.m_canvas.Rectangle(x1,y1,x2,y2,::ColorToARGB(clr,this.m_alpha));
      
      //--- Height of the entire table grid
         int greed_h=y2-y1;
      //--- Calculate the row height depending on the table height and the number of rows
         int row_h=(int)::round((double)greed_h/(double)rows);
      //--- In the loop based on the number of rows
         for(int i=0;i<(int)rows;i++)
           {
            //--- calculate the Y coordinate of the next horizontal grid line (Y coordinate of the next table row)
            int row_y=y1+row_h*i;
            //--- if the flag of "alternating" line colors is passed and the line is even
            if(alternating_color && i%2==0)
              {
               //--- lighten the table background color and draw a background rectangle
               color new_color=this.NewColor(clr,45,45,45);
               this.m_canvas.FillRectangle(x1+1,row_y+1,x2-1,row_y+row_h-1,::ColorToARGB(new_color,this.m_alpha));
              }
            //--- Draw a table grid horizontal line
            this.m_canvas.Line(x1,row_y,x2,row_y,::ColorToARGB(clr,this.m_alpha));
            
            //--- Create a new table row object
            CTableRow *row_obj=new CTableRow(i);
            if(row_obj==NULL)
              {
               ::PrintFormat("%s: Failed to create table row object at index %lu",(string)__FUNCTION__,i);
               continue;
              }
            //--- Add it to the list of rows of the tabular data object
            //--- (if adding an object failed, delete the created object)
            if(!table.AddRow(row_obj))
               delete row_obj;
            //--- Set its Y coordinate in the created row object taking into account the offset from the panel title
            row_obj.SetY(row_y-this.m_header_h);
           }
           
      //--- Table grid width
         int greed_w=x2-x1;
      //--- Calculate the column width depending on the table width and the number of columns
         int col_w=(int)::round((double)greed_w/(double)columns);
      //--- In the loop by table columns,
         for(int i=0;i<(int)columns;i++)
           {
            //--- calculate the X coordinate of the next vertical grid line (X coordinate of the next table row)
            int col_x=x1+col_w*i;
            //--- If this is not the very first vertical line, draw it
            //--- (the first vertical line is either the table frame or the panel frame)
            if(i>0)
               this.m_canvas.Line(col_x,y1,col_x,y2,::ColorToARGB(clr,this.m_alpha));
            
            //--- Get the number of created rows from the table data object 
            int total=table.RowsTotal();
            //--- In the loop by table rows
            for(int j=0;j<total;j++)
              {
               //--- get the next row
               CTableRow *row=table.GetRow(j);
               if(row==NULL)
                  continue;
               //--- Create a new table cell 
               CTableCell *cell=new CTableCell(row.Row(),i);
               if(cell==NULL)
                 {
                  ::PrintFormat("%s: Failed to create table cell object at index %lu",(string)__FUNCTION__,i);
                  continue;
                 }
               //--- Add the created cell to the row
               //--- (if adding an object failed, delete the created object)
               if(!row.AddCell(cell))
                 {
                  delete cell;
                  continue;
                 }
               //--- In the created cell object, set its X coordinate and the Y coordinate from the row object 
               cell.SetXY(col_x,row.Y());
              }
           }
      //--- Update the canvas without redrawing the chart
         this.m_canvas.Update(false);
        }
      


      ピクセルをファイルに保存/読み込むメソッドは、コンストラクタで以前に作成したファイル名を適用するようになりました。

      //+------------------------------------------------------------------+
      //| Save the pixel array of the working space to a file              |
      //+------------------------------------------------------------------+
      bool CDashboard::FileSaveWorkspace(void)
        {
      //--- If the saved array is empty, inform of that and return 'false'
         if(this.m_array_wpx.Size()==0)
           {
            ::PrintFormat("%s: Error. The workspace pixel array is empty.",__FUNCTION__);
            return false;
           }
      //--- If the array could not be saved to a file, report this and return 'false'
         if(!::FileSave(this.m_filename_ws,this.m_array_wpx))
           {
            ::PrintFormat("%s: FileSave '%s' failed. Error %lu",__FUNCTION__,this.m_filename_ws,::GetLastError());
            return false;
           }
      //--- Successful, return 'true'
         return true;
        }
      //+------------------------------------------------------------------+
      //| Save the pixel array of the panel background to a file           |
      //+------------------------------------------------------------------+
      bool CDashboard::FileSaveBackground(void)
        {
      //--- If the saved array is empty, inform of that and return 'false'
         if(this.m_array_ppx.Size()==0)
           {
            ::PrintFormat("%s: Error. The background pixel array is empty.",__FUNCTION__);
            return false;
           }
      //--- If the array could not be saved to a file, report this and return 'false'
         if(!::FileSave(this.m_filename_bg,this.m_array_ppx))
           {
            ::PrintFormat("%s: FileSave '%s' failed. Error %lu",__FUNCTION__,this.m_filename_bg,::GetLastError());
            return false;
           }
      //--- Successful, return 'true'
         return true;
        }
      //+------------------------------------------------------------------+
      //| Upload the array of working space pixels from a file             |
      //+------------------------------------------------------------------+
      bool CDashboard::FileLoadWorkspace(void)
        {
      //--- If failed to upload data from the file into the array, report this and return 'false'
         if(::FileLoad(this.m_filename_ws,this.m_array_wpx)==WRONG_VALUE)
           {
            ::PrintFormat("%s: FileLoad '%s' failed. Error %lu",__FUNCTION__,this.m_filename_ws,::GetLastError());
            return false;
           }
      //--- Successful, return 'true'
         return true;
        }
      //+------------------------------------------------------------------+
      //| Upload the array of panel background pixels from a file          |
      //+------------------------------------------------------------------+
      bool CDashboard::FileLoadBackground(void)
        {
         if(::FileLoad(this.m_filename_bg,this.m_array_ppx)==WRONG_VALUE)
           {
            ::PrintFormat("%s: FileLoad '%s' failed. Error %lu",__FUNCTION__,this.m_filename_bg,::GetLastError());
            return false;
           }
      //--- Successful, return 'true'
         return true;
        }
      


      結論

      この記事では、出来高指標とビルウィリアムスの指標のEAへの接続について見てきました。記事で提供されているコードはすべて、カスタムコードに挿入するために「そのまま」使用することができます。次に、最後のカテゴリの指標であるトレンド指標について、その関連性とEAでの使用について考察します。

      すべてのファイル(テストEAとパネルクラス)は、以下の添付ファイルリストからダウンロードできます。パネルクラスは\MQL5\Include\Dashboard\Dashboard.mqhにあります。


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

      添付されたファイル |
      TestVolumeAD.mq5 (30.66 KB)
      TestVolumeMFI.mq5 (35.21 KB)
      TestVolumeOBV.mq5 (30.67 KB)
      TestWilliamsAC.mq5 (30.71 KB)
      TestWilliamsAO.mq5 (32.31 KB)
      Dashboard.mqh (217.85 KB)
      MQL5のALGLIB数値解析ライブラリ MQL5のALGLIB数値解析ライブラリ
      この記事では、ALGLIB3.19数値分析ライブラリ、その応用、金融データ分析の効率を向上させる新しいアルゴリズムについて簡単に説明します。
      時系列マイニング用データラベル(第3回):ラベルデータの利用例 時系列マイニング用データラベル(第3回):ラベルデータの利用例
      この連載では、ほとんどの人工知能モデルに適合するデータを作成できる、いくつかの時系列のラベル付け方法を紹介します。ニーズに応じて的を絞ったデータのラベル付けをおこなうことで、訓練済みの人工知能モデルをより期待通りの設計に近づけ、モデルの精度を向上させ、さらにはモデルの質的飛躍を助けることができます。
      ニューラルネットワークが簡単に(第57回):Stochastic Marginal Actor-Critic (SMAC) ニューラルネットワークが簡単に(第57回):Stochastic Marginal Actor-Critic (SMAC)
      今回は、かなり新しいStochastic Marginal Actor-Critic (SMAC)アルゴリズムを検討します。このアルゴリズムは、エントロピー最大化の枠組みの中で潜在変数方策を構築することができます。
      独自のLLMをEAに統合する(第2部):環境展開例 独自のLLMをEAに統合する(第2部):環境展開例
      今日の人工知能の急速な発展に伴い、言語モデル(LLM)は人工知能の重要な部分となっています。私たちは、強力なLLMをアルゴリズム取引に統合する方法を考える必要があります。ほとんどの人にとって、これらの強力なモデルをニーズに応じて微調整し、ローカルに展開して、アルゴリズム取引に適用することは困難です。本連載では、この目標を達成するために段階的なアプローチをとっていきます。