Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Series array that contains open time of each bar
0 Views
0 Downloads
0 Favorites
Edge_Index
ÿþ//+------------------------------------------------------------------+

//|                                                   Edge_Index.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

//+------------------------------------------------------------------+

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#include <Arrays\ArrayString.mqh>

#include <Arrays\ArrayInt.mqh>



//+------------------------------------------------------------------+

//| ;0AA AGQBG8: B09<5@0                                            |

//+------------------------------------------------------------------+

class CTimerCounter

  {

private:  

   ulong             m_timer_counter;

   ulong             m_timer_step;

   ulong             m_timer_pause;

public:

   void              SetParams(const ulong step,const ulong pause)   { this.m_timer_step=step; this.m_timer_pause=pause;   }

   bool              IsTimeDone(void);

                     CTimerCounter(void) : m_timer_counter(0),m_timer_step(16),m_timer_pause(250){;}

                    ~CTimerCounter(void){;}

  };

//+------------------------------------------------------------------+

//| CTimerCounter ?@>25@O5B >:>=G0=85 ?0C7K                          |

//+------------------------------------------------------------------+

bool CTimerCounter::IsTimeDone(void)

  {

   if(this.m_timer_counter>ULONG_MAX)

      this.m_timer_counter=0;

   if(this.m_timer_counter<this.m_timer_pause)

     {

      this.m_timer_counter+=this.m_timer_step;

      return false;

     }

   this.m_timer_counter=0;

   return true;

  }

//+------------------------------------------------------------------+



//+------------------------------------------------------------------+

//| ;0AA =48:0B>@0                                                 |

//+------------------------------------------------------------------+

#include <Indicators\Indicator.mqh>

class CIndicatorsBase : public CIndicator

  {

protected:

   CTimerCounter     m_counter_time;

   CTimerCounter     m_counter_refresh;

   MqlParam          m_params[];

   string            m_name_indicator;

   bool              m_counter_refresh_done;

   bool              m_counter_time_done;

   int               m_type;

   int               m_num_params;

   int               m_prev_calculated;

   bool              m_handle_success;

   int               m_refresh_flags;

   datetime          Time(const int shift) const { datetime array[]; return(::CopyTime(this.Symbol(),this.Period(),1,1,array)==1 ? array[0]: 0);   }

   string            SetName(const ENUM_INDICATOR type)  const { return ::StringSubstr(::EnumToString(type),4);            }

   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);

public:

   string            TimeframeDescription(void) const { return ::StringSubstr(::EnumToString(this.m_period==PERIOD_CURRENT ? ::Period() : this.m_period),7);   }

   string            Name(void)                 const { return this.m_name_indicator;        }

   int               PrevCalculated(void)       const { return this.m_prev_calculated;       }

   bool              IsCounterRefreshDone(void)       { return this.m_counter_refresh_done;  }

   bool              IsCounterTimeDone(void)          { return this.m_counter_time_done;     }

   void              SetType(const int type)          { this.m_type=type;                    }

   void              SetCounterTime(const uint step,const uint pause);

   void              SetCounterRefresh(const uint step,const uint pause);

   void              SetRefreshFlags(const bool refresh_current,const int refresh_periods=OBJ_ALL_PERIODS);

   bool              CheckLoadHistory(void)           { return CSeries::CheckLoadHistory(this.BufferSize());   }

   bool              Create(const string indicator_name,const int buffers_num);

   bool              Create(const ENUM_INDICATOR indicator_type,const int buffers_num);

   void              Refresh(void);

   template<typename T>

   void              SetParameter(const T value);

   void              OnTimer(void);

   virtual int       Type(void)                 const { return this.m_type;                  }

                     CIndicatorsBase(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int type_id);

                    ~CIndicatorsBase(void);

  };

//+------------------------------------------------------------------+

//| CIndicatorsBase :>=AB@C:B>@                                      |

//+------------------------------------------------------------------+

CIndicatorsBase::CIndicatorsBase(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int type_id) : m_refresh_flags(OBJ_ALL_PERIODS),

                                                                                                               m_prev_calculated(WRONG_VALUE),

                                                                                                               m_handle_success(false),

                                                                                                               m_num_params(0),

                                                                                                               m_counter_refresh_done(false),

                                                                                                               m_counter_time_done(false),

                                                                                                               m_type(type_id)

  {

   this.SetSymbolPeriod(symbol_name,timeframe);

   this.m_refresh_current=false;

   this.SetCounterRefresh(16,250);

   this.SetCounterTime(16,90000);

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase 45AB@C:B>@                                       |

//+------------------------------------------------------------------+

CIndicatorsBase::~CIndicatorsBase(void)

  {

   this.m_handle_success=false;

   this.m_handle=INVALID_HANDLE;

   this.m_buffers_total=0;

   this.m_prev_calculated=0;

   this.m_num_params=0;

   this.m_counter_time_done=false;

   this.m_counter_refresh_done=false;

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase "09<5@                                           |

//+------------------------------------------------------------------+

void CIndicatorsBase::OnTimer(void)

  {

   this.m_counter_time_done=this.m_counter_time.IsTimeDone();

   if(this.m_counter_time_done)

      this.Time(1);

   this.m_counter_refresh_done=this.m_counter_refresh.IsTimeDone();

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase #AB0=>2:0 AGQBG8:0 B09<5@0 2@5<5=8               |

//+------------------------------------------------------------------+

void CIndicatorsBase::SetCounterTime(const uint step,const uint pause)

  {

   this.m_counter_time.SetParams(step,pause);

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase #AB0=>2:0 AGQBG8:0 B09<5@0 >1=>2;5=8O            |

//+------------------------------------------------------------------+

void CIndicatorsBase::SetCounterRefresh(const uint step,const uint pause)

  {

   this.m_counter_refresh.SetParams(step,pause);

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase !>740QB 8=48:0B>@ ?> 8<5=8                       |

//+------------------------------------------------------------------+

bool CIndicatorsBase::Create(const string indicator_name,const int buffers_num)

  {

   if(this.m_num_params==0)

     {

      ::Print(__FUNCSIG__,": Error. First, you need to set the indicator parameters: SetParameter()");

      this.m_handle_success=false;

      this.m_handle=INVALID_HANDLE;

      this.m_buffers_total=0;

      this.m_num_params=0;

      return false;

     }

   //---

   this.m_name_indicator=indicator_name;

   this.m_buffers_total=(buffers_num<1 ? 1 : buffers_num>512 ? 512 : buffers_num);

   int size=::ArraySize(this.m_params);

   ::ArrayResize(this.m_params,size+1);

   for(int i=size;i>0;i--)

     {

      this.m_params[i].type=this.m_params[i-1].type;

      this.m_params[i].double_value=this.m_params[i-1].double_value;

      this.m_params[i].integer_value=this.m_params[i-1].integer_value;

      this.m_params[i].string_value=this.m_params[i-1].string_value;

     }

   this.m_params[0].type=TYPE_STRING;

   this.m_params[0].string_value=this.m_name_indicator;

   this.m_num_params++;

   //---

   ::ResetLastError();

   this.m_handle_success=CIndicator::Create(this.m_symbol,this.m_period,IND_CUSTOM,this.m_num_params,this.m_params);

   if(!this.m_handle_success)

     {

      ::Print(__FUNCSIG__,": Error creating ",this.Name(),": ",::GetLastError());

      this.m_handle_success=false;

      this.m_handle=INVALID_HANDLE;

      this.m_buffers_total=0;

      this.m_num_params=0;

      return false;

     }

   return this.m_handle_success;

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase !>740QB 8=48:0B>@ ?> B8?C                        |

//+------------------------------------------------------------------+

bool CIndicatorsBase::Create(const ENUM_INDICATOR indicator_type,const int buffers_num)

  {

   if(this.m_num_params==0)

     {

      ::Print(__FUNCSIG__,": Error. First, you need to set the indicator parameters: SetParameter()");

      this.m_handle_success=false;

      this.m_handle=INVALID_HANDLE;

      this.m_buffers_total=0;

      this.m_num_params=0;

      return false;

     }

   if(indicator_type==IND_CUSTOM)

     {

      ::Print(__FUNCSIG__,": Error. To create a custom indicator, use the Create(const string indicator_name,const int buffers_num) method.");

      this.m_handle_success=false;

      this.m_handle=INVALID_HANDLE;

      this.m_buffers_total=0;

      this.m_num_params=0;

      return false;

     }

   //---

   this.m_name_indicator=this.SetName(indicator_type);

   CSeries::m_buffers_total=(buffers_num<1 ? 1 : buffers_num>512 ? 512 : buffers_num);

   //---

   ::ResetLastError();

   this.m_handle_success=CIndicator::Create(this.m_symbol,this.m_period,indicator_type,this.m_num_params,this.m_params);

   if(!this.m_handle_success)

     {

      ::Print(__FUNCSIG__,": Error creating ",this.Name(),": ",::GetLastError());

      this.m_handle_success=false;

      this.m_handle=INVALID_HANDLE;

      this.m_buffers_total=0;

      this.m_num_params=0;

      return false;

     }

   return this.m_handle_success;

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase 8=8F80;870F8O                                    |

//+------------------------------------------------------------------+

bool CIndicatorsBase::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])

  {

   if(CIndicator::CreateBuffers(symbol,period,m_buffers_total))

     {

      //--- string of status of drawing

      CSeries::m_name=this.m_name_indicator+" "+symbol+" "+this.TimeframeDescription()+" "+params[0].string_value;

      CIndicator::m_status="("+this.m_name_indicator+" "+symbol+" "+this.TimeframeDescription();

      for(int i=(this.m_type==IND_CUSTOM ? 1 : 0);i<num_params;i++)

        {

         switch(params[i].type)

           {

            case TYPE_BOOL    : CIndicator::m_status+=","+((params[i].integer_value) ? "true" : "false");  break;

            case TYPE_CHAR    : case TYPE_UCHAR: case TYPE_SHORT: case TYPE_USHORT: 

            case TYPE_INT     : case TYPE_UINT:  case TYPE_LONG:

            case TYPE_ULONG   : CIndicator::m_status+=","+IntegerToString(params[i].integer_value);         break;

            case TYPE_COLOR   : CIndicator::m_status+=","+ColorToString((color)params[i].integer_value);    break;

            case TYPE_DATETIME: CIndicator::m_status+=","+TimeToString(params[i].integer_value);            break;

            case TYPE_FLOAT   :

            case TYPE_DOUBLE  : CIndicator::m_status+=","+DoubleToString(params[i].double_value,2);         break;

            case TYPE_STRING  : CIndicator::m_status+=",'"+params[i].string_value+"'";                      break;

            default           : break;

           }

        }

      CIndicator::m_status+=") Handle="+IntegerToString(CIndicator::m_handle);

      //--- create buffers

      for(int i=0;i<m_buffers_total;i++)

         ((CIndicatorBuffer*)At(i)).Name("LINE "+IntegerToString(i));

      //--- ok

      return true;

     }

//--- error

   return false;

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase 1=>2;O5B 8=48:0B>@                              |

//+------------------------------------------------------------------+

void CIndicatorsBase::Refresh(void)

  {

   this.SetRefreshFlags(CIndicator::BarsCalculated()==this.m_prev_calculated,this.m_refresh_flags);

   if(this.m_prev_calculated!=CIndicator::BarsCalculated())

     {

      this.m_prev_calculated=CIndicator::BarsCalculated();

     }

   CIndicator::Refresh(this.m_refresh_flags);

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase CAB0=>2:0 D;03>2 >1=>2;5=8O                      |

//+------------------------------------------------------------------+

void CIndicatorsBase::SetRefreshFlags(const bool refresh_current,const int refresh_periods=OBJ_ALL_PERIODS)

  {

   CSeries::RefreshCurrent(refresh_current);

   this.m_refresh_flags=refresh_periods;

  }

//+------------------------------------------------------------------+

//| CIndicatorsBase #AB0=>2:0 >4=>3> ?0@0<5B@0                       |

//+------------------------------------------------------------------+

template<typename T>

void CIndicatorsBase::SetParameter(const T value)

  {

   string type=typename(value);

   this.m_num_params++;

   if(::ArraySize(this.m_params)<this.m_num_params)

      ::ArrayResize(this.m_params,this.m_num_params);

   if(type=="string")

     {

      this.m_params[this.m_num_params-1].type=TYPE_STRING;

      this.m_params[this.m_num_params-1].string_value=(string)value;

     }

   else if(type=="bool")

     {

      this.m_params[this.m_num_params-1].type=TYPE_BOOL;

      this.m_params[this.m_num_params-1].integer_value=(bool)value;

     }

   else if(type=="char")

     {

      this.m_params[this.m_num_params-1].type=TYPE_CHAR;

      this.m_params[this.m_num_params-1].integer_value=(char)value;

     }

   else if(type=="uchar")

     {

      this.m_params[this.m_num_params-1].type=TYPE_UCHAR;

      this.m_params[this.m_num_params-1].integer_value=(uchar)value;

     }

   else if(type=="short")

     {

      this.m_params[this.m_num_params-1].type=TYPE_SHORT;

      this.m_params[this.m_num_params-1].integer_value=(short)value;

     }

   else if(type=="ushort")

     {

      this.m_params[this.m_num_params-1].type=TYPE_USHORT;

      this.m_params[this.m_num_params-1].integer_value=(ushort)value;

     }

   else if(type=="color")

     {

      this.m_params[this.m_num_params-1].type=TYPE_COLOR;

      this.m_params[this.m_num_params-1].integer_value=(color)value;

     }

   else if(type=="int")

     {

      this.m_params[this.m_num_params-1].type=TYPE_INT;

      this.m_params[this.m_num_params-1].integer_value=(int)value;

     }

   else if(type=="uint")

     {

      this.m_params[this.m_num_params-1].type=TYPE_UINT;

      this.m_params[this.m_num_params-1].integer_value=(uint)value;

     }

   else if(type=="datetime")

     {

      this.m_params[this.m_num_params-1].type=TYPE_DATETIME;

      this.m_params[this.m_num_params-1].integer_value=(datetime)value;

     }

   else if(type=="long")

     {

      this.m_params[this.m_num_params-1].type=TYPE_LONG;

      this.m_params[this.m_num_params-1].integer_value=(long)value;

     }

   else if(type=="ulong")

     {

      this.m_params[this.m_num_params-1].type=TYPE_ULONG;

      this.m_params[this.m_num_params-1].integer_value=(long)value;

     }

   else if(type=="float")

     {

      this.m_params[this.m_num_params-1].type=TYPE_FLOAT;

      this.m_params[this.m_num_params-1].double_value=(float)value;

     }

   else if(type=="double")

     {

      this.m_params[this.m_num_params-1].type=TYPE_DOUBLE;

      this.m_params[this.m_num_params-1].double_value=(double)value;

     }

  }

//+------------------------------------------------------------------+

//| ;0AA-:>;;5:F8O 8=48:0B>@>2                                      |

//+------------------------------------------------------------------+

class CIndCollection : public CObject

  {

protected:

   CTimerCounter     m_counter_time;

   CTimerCounter     m_counter_refresh;

   CArrayObj         m_list_ind;

   string            m_symbol;

   string            m_first_in_pair;

   string            m_second_in_pair;

   ENUM_TIMEFRAMES   m_timeframe;

   bool              m_counter_refresh_done;

   bool              m_counter_time_done;

   int               m_index_x;

   int               m_index_y;

   int               m_digits;

   double            m_point;

   datetime          Time(const int shift) const { datetime array[]; return(::CopyTime(this.m_symbol,this.m_timeframe,1,1,array)==1 ? array[0]: 0);   }

public:

   CIndicatorsBase*  GetIndByID(const int ind_id);

   CArrayObj*        GetList(void)                    { return &m_list_ind;                  }

   bool              Add(CIndicatorsBase* ind)        { return this.m_list_ind.Add(ind);     }

   void              SetIndexX(const int x)           { this.m_index_x=x;                    }

   void              SetIndexY(const int y)           { this.m_index_y=y;                    }

   bool              IsCounterRefreshDone(void)       { return this.m_counter_refresh_done;  }

   bool              IsCounterTimeDone(void)          { return this.m_counter_time_done;     }

   double            Point(void)                const { return this.m_point;                 }

   int               Digits(void)               const { return this.m_digits;                }

   int               IndexX(void)               const { return this.m_index_x;               }

   int               IndexY(void)               const { return this.m_index_y;               }

   string            Symbol(void)               const { return this.m_symbol;                }

   string            FirstInPair(void)          const { return this.m_first_in_pair;         }

   string            SecondInPair(void)         const { return this.m_second_in_pair;        }

   ENUM_TIMEFRAMES   Timeframe(void)            const { return this.m_timeframe;             }

   string            TimeframeDescription(void) const { return ::StringSubstr(::EnumToString(this.m_timeframe),7);}

   void              SetCounterTime(const uint step,const uint pause);

   void              SetCounterRefresh(const uint step,const uint pause);

   void              OnTimer(void);

   void              Refresh(void);

                     CIndCollection(const string symbol_name,const ENUM_TIMEFRAMES timeframe);

                    ~CIndCollection(void);

  };

//+------------------------------------------------------------------+

//| CIndCollection :>=AB@C:B>@                                       |

//+------------------------------------------------------------------+

CIndCollection::CIndCollection(const string symbol_name,const ENUM_TIMEFRAMES timeframe) : m_index_x(0),

                                                                                           m_index_y(0),

                                                                                           m_counter_refresh_done(false),

                                                                                           m_counter_time_done(false)

  {

   this.m_symbol=(symbol_name=="" || symbol_name==NULL ? ::Symbol() : symbol_name);

   this.m_timeframe=(timeframe==PERIOD_CURRENT ? ::Period() : timeframe);

   this.m_digits=(int)::SymbolInfoInteger(this.m_symbol,SYMBOL_DIGITS);

   this.m_point=::SymbolInfoDouble(this.m_symbol,SYMBOL_POINT);

   this.SetCounterRefresh(16,250);

   this.SetCounterTime(16,90000);

   this.m_first_in_pair=::StringSubstr(this.m_symbol,0,3);

   this.m_second_in_pair=::StringSubstr(this.m_symbol,3,3);

  }

//+------------------------------------------------------------------+

//| CIndCollection 45AB@C:B>@                                        |

//+------------------------------------------------------------------+

CIndCollection::~CIndCollection(void)

  {

   this.m_counter_time_done=false;

   this.m_counter_refresh_done=false;

  }

//+------------------------------------------------------------------+

//| CIndCollection 1=>2;O5B :>;;5:F8N 8=48:0B>@>2                   |

//+------------------------------------------------------------------+

void CIndCollection::Refresh(void)

  {

   int total=this.m_list_ind.Total();

   for(int i=0;i<total;i++)

     {

      CIndicatorsBase* ind=this.m_list_ind.At(i);

      if(ind==NULL)

         continue;

      ind.Refresh();

     }

  }

//+------------------------------------------------------------------+

//| CIndCollection "09<5@                                            |

//+------------------------------------------------------------------+

void CIndCollection::OnTimer(void)

  {

   this.m_counter_time_done=this.m_counter_time.IsTimeDone();

   if(this.m_counter_time_done)

     {

      this.Time(1);

     }

   this.m_counter_refresh_done=this.m_counter_refresh.IsTimeDone();

  }

//+------------------------------------------------------------------+

//| CIndCollection #AB0=>2:0 AGQBG8:0 B09<5@0 2@5<5=8                |

//+------------------------------------------------------------------+

void CIndCollection::SetCounterTime(const uint step,const uint pause)

  {

   this.m_counter_time.SetParams(step,pause);

  }

//+------------------------------------------------------------------+

//| CIndCollection #AB0=>2:0 AGQBG8:0 B09<5@0 >1=>2;5=8O             |

//+------------------------------------------------------------------+

void CIndCollection::SetCounterRefresh(const uint step,const uint pause)

  {

   this.m_counter_refresh.SetParams(step,pause);

  }

//+------------------------------------------------------------------+

//| CIndCollection 2>72@0I05B C:070B5;L =0 8=48:0B>@ ?> B8?C         |

//+------------------------------------------------------------------+

CIndicatorsBase* CIndCollection::GetIndByID(const int ind_id)

  {

   int total=this.m_list_ind.Total();

   for(int i=0;i<total;i++)

     {

      CIndicatorsBase* ind=this.m_list_ind.At(i);

      if(ind.Type()==ind_id)

         return ind;

     }

   return NULL;

  }



//+------------------------------------------------------------------+

//| =48:0B>@                                                        |

//+------------------------------------------------------------------+

#property version   "1.00"

#property description "Edge Index indicator"

#property indicator_separate_window

#property indicator_buffers 8

#property indicator_plots   8

//--- plot AUD

#property indicator_label1  "AUD"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrDodgerBlue

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- plot CAD

#property indicator_label2  "CAD"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrDimGray

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- plot CHF

#property indicator_label3  "CHF"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrGold

#property indicator_style3  STYLE_SOLID

#property indicator_width3  1

//--- plot EUR

#property indicator_label4  "EUR"

#property indicator_type4   DRAW_LINE

#property indicator_color4  clrDarkOrange

#property indicator_style4  STYLE_SOLID

#property indicator_width4  1

//--- plot GBP

#property indicator_label5  "GBP"

#property indicator_type5   DRAW_LINE

#property indicator_color5  clrLimeGreen

#property indicator_style5  STYLE_SOLID

#property indicator_width5  1

//--- plot JPY

#property indicator_label6  "JPY"

#property indicator_type6   DRAW_LINE

#property indicator_color6  clrAqua

#property indicator_style6  STYLE_SOLID

#property indicator_width6  1

//--- plot NZD

#property indicator_label7  "NZD"

#property indicator_type7   DRAW_LINE

#property indicator_color7  clrBlue

#property indicator_style7  STYLE_SOLID

#property indicator_width7  1

//--- plot USD

#property indicator_label8  "USD"

#property indicator_type8   DRAW_LINE

#property indicator_color8  clrRed

#property indicator_style8  STYLE_SOLID

#property indicator_width8  1

//--- defines

#define   IND_ID_ROC_SIG   IND_CUSTOM+1

#define   IND_ID_MA_FAST   IND_CUSTOM+2

#define   IND_ID_MA_MED    IND_CUSTOM+3

#define   IND_ID_MA_SLOW   IND_CUSTOM+4

//--- enums

enum ENUM_INPUT_YES_NO

  {

   INPUT_YES   =  1,       // Yes

   INPUT_NO    =  0        // No

  };

//--- input parameters

input uint                 InpPeriodFast     =  8;             // Fast MA period

input ENUM_MA_METHOD       InpMethodFast     =  MODE_EMA;      // Fast MA method

input ENUM_APPLIED_PRICE   InpPriceFast      =  PRICE_CLOSE;   // Fast MA applied price

input uint                 InpPeriodMedium   =  21;            // Medium MA period

input ENUM_MA_METHOD       InpMethodMedium   =  MODE_EMA;      // Medium MA method

input ENUM_APPLIED_PRICE   InpPriceMedium    =  PRICE_CLOSE;   // Medium MA applied price

input uint                 InpPeriodSlow     =  55;            // Slow MA period

input ENUM_MA_METHOD       InpMethodSlow     =  MODE_EMA;      // Slow MA method

input ENUM_APPLIED_PRICE   InpPriceSlow      =  PRICE_CLOSE;   // Slow MA applied price

input uint                 InpPeriodROC      =  8;             // ROC period

input uint                 InpPeriodSig      =  8;             // ROC signal MA period

input ENUM_MA_METHOD       InpMethodROC      =  MODE_EMA;      // ROC signal MA method

//--- indicator buffers

double         BufferAUD[];

double         BufferCAD[];

double         BufferCHF[];

double         BufferEUR[];

double         BufferGBP[];

double         BufferJPY[];

double         BufferNZD[];

double         BufferUSD[];

//--- global variables

CArrayString   list_symbols;

CArrayInt      list_timeframes;

CArrayObj      list_ind;

//---

string         custom_ind_name;

string         array_symbols[];

string         gv_name;

//--- Edge Index

string         InpSymbols;

int            period_fast;

int            period_medium;

int            period_slow;

int            period_roc;

int            period_sig;

int            period_max;

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- timer

   EventSetMillisecondTimer(16);

//--- setting indicator parameters

   gv_name="";

   custom_ind_name="ROC_with_Signal_MA";

//--- Edge Index

   period_fast=int(InpPeriodFast<1 ? 1 : InpPeriodFast);

   period_medium=int(InpPeriodMedium<1 ? 1 : InpPeriodMedium);

   period_slow=int(InpPeriodSlow<1 ? 1 : InpPeriodSlow);

   period_roc=int(InpPeriodROC<1 ? 1 : InpPeriodROC);

   period_sig=int(InpPeriodSig<1 ? 1 : InpPeriodSig);

   period_max=fmax(period_fast,fmax(period_medium,period_slow));

   InpSymbols="AUDCAD,AUDNZD,EURAUD,GBPAUD,AUDUSD,AUDCHF,AUDJPY,EURNZD,GBPNZD,NZDUSD,NZDCAD,NZDCHF,NZDJPY,EURGBP,EURUSD,EURCAD,EURCHF,EURJPY,GBPUSD,GBPCAD,GBPCHF,GBPJPY,USDCAD,USDCHF,USDJPY,CADCHF,CADJPY,CHFJPY";

//---

   if(!ArraysPreparing())

     {

      Print("Error. Failed to prepare working arrays.");

      return INIT_FAILED;

     }

//---

   list_ind.Clear();

   int total_sym=list_symbols.Total();

   int total_tfs=list_timeframes.Total();

   for(int s=0;s<total_sym;s++)

     {

      for(int t=0;t<total_tfs;t++)

        {

         ENUM_TIMEFRAMES timeframe=(ENUM_TIMEFRAMES)list_timeframes.At(t);

         string symbol=list_symbols.At(s);

         CIndCollection* collection=new CIndCollection(symbol,timeframe);

         if(collection==NULL)

            continue;

         //--- Add MA Fast into array_obj list

         CIndicatorsBase* maf=new CIndicatorsBase(symbol,timeframe,IND_ID_MA_FAST);

         if(maf!=NULL)

           {

            collection.Add(maf);

            maf.SetParameter(period_fast);         // Set MA Fast Period

            maf.SetParameter(0);                   // Set MA Fast Shift

            maf.SetParameter((int)InpMethodFast);  // Set MA Fast Method

            maf.SetParameter((int)InpPriceFast);   // Set MA Fast Applied price

            if(!maf.Create(IND_MA,1))

              {

               Print(maf.Symbol()," ",maf.TimeframeDescription(),": Failed to create ",maf.Name(),"'s handle. Please restart the indicator");

               delete maf;

               return INIT_FAILED;

              }

            else

              {

               maf.SetRefreshFlags(true,OBJ_ALL_PERIODS);

               maf.Refresh();

              }

           }

         //--- Add MA Medium into array_obj list

         CIndicatorsBase* mam=new CIndicatorsBase(symbol,timeframe,IND_ID_MA_MED);

         if(mam!=NULL)

           {

            collection.Add(mam);

            mam.SetParameter(period_medium);          // Set MA Medium Period

            mam.SetParameter(0);                      // Set MA Medium Shift

            mam.SetParameter((int)InpMethodMedium);   // Set MA Medium Method

            mam.SetParameter((int)InpPriceMedium);    // Set MA Medium Applied price

            if(!mam.Create(IND_MA,1))

              {

               Print(mam.Symbol()," ",mam.TimeframeDescription(),": Failed to create ",mam.Name(),"'s handle. Please restart the indicator");

               delete mam;

               return INIT_FAILED;

              }

            else

              {

               mam.SetRefreshFlags(true,OBJ_ALL_PERIODS);

               mam.Refresh();

              }

           }

         //--- Add MA Slow into array_obj list

         CIndicatorsBase* mas=new CIndicatorsBase(symbol,timeframe,IND_ID_MA_SLOW);

         if(mas!=NULL)

           {

            collection.Add(mas);

            mas.SetParameter(period_slow);         // Set MA Medium Period

            mas.SetParameter(0);                   // Set MA Medium Shift

            mas.SetParameter((int)InpMethodSlow);  // Set MA Medium Method

            mas.SetParameter((int)InpPriceSlow);   // Set MA Medium Applied price

            if(!mas.Create(IND_MA,1))

              {

               Print(mas.Symbol()," ",mas.TimeframeDescription(),": Failed to create ",mas.Name(),"'s handle. Please restart the indicator");

               delete mas;

               return INIT_FAILED;

              }

            else

              {

               mas.SetRefreshFlags(true,OBJ_ALL_PERIODS);

               mas.Refresh();

              }

           }

         //--- Add ROC Signal into array_obj list

         CIndicatorsBase* roc=new CIndicatorsBase(symbol,timeframe,IND_ID_ROC_SIG);

         if(roc!=NULL)

           {

            collection.Add(roc);

            roc.SetParameter(period_roc);          // Set ROC Signal Period

            roc.SetParameter(period_sig);          // Set ROC Signal MA period

            roc.SetParameter((int)InpMethodROC);   // Set ROC Signal MA Method

            if(!roc.Create(custom_ind_name,2))

              {

               Print(roc.Symbol()," ",roc.TimeframeDescription(),": Failed to create ",roc.Name(),"'s handle. Please restart the indicator");

               delete roc;

               return INIT_FAILED;

              }

            else

              {

               roc.SetRefreshFlags(true,OBJ_ALL_PERIODS);

               roc.Refresh();

              }

           }

         

         //--- Add collection to the indicators list

         list_ind.Add(collection);

        }

     }

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferAUD,INDICATOR_DATA);

   SetIndexBuffer(1,BufferCAD,INDICATOR_DATA);

   SetIndexBuffer(2,BufferCHF,INDICATOR_DATA);

   SetIndexBuffer(3,BufferEUR,INDICATOR_DATA);

   SetIndexBuffer(4,BufferGBP,INDICATOR_DATA);

   SetIndexBuffer(5,BufferJPY,INDICATOR_DATA);

   SetIndexBuffer(6,BufferNZD,INDICATOR_DATA);

   SetIndexBuffer(7,BufferUSD,INDICATOR_DATA);

//--- setting indicator parameters

   IndicatorSetString(INDICATOR_SHORTNAME,"Edge Index ("+(string)period_fast+","+(string)period_medium+","+(string)period_slow+","+(string)period_roc+","+(string)period_sig+")");

   IndicatorSetInteger(INDICATOR_DIGITS,0);

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferAUD,true);

   ArraySetAsSeries(BufferCAD,true);

   ArraySetAsSeries(BufferCHF,true);

   ArraySetAsSeries(BufferEUR,true);

   ArraySetAsSeries(BufferGBP,true);

   ArraySetAsSeries(BufferJPY,true);

   ArraySetAsSeries(BufferNZD,true);

   ArraySetAsSeries(BufferUSD,true);

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Custom indicator iteration function                              |

//+------------------------------------------------------------------+

int OnCalculate(const int rates_total,

                const int prev_calculated,

                const datetime &time[],

                const double &open[],

                const double &high[],

                const double &low[],

                const double &close[],

                const long &tick_volume[],

                const long &volume[],

                const int &spread[])

  {

//---

   if(rates_total<fmax(period_sig,4)) return 0;

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-period_sig-2;

      ArrayInitialize(BufferAUD,EMPTY_VALUE);

      ArrayInitialize(BufferCAD,EMPTY_VALUE);

      ArrayInitialize(BufferCHF,EMPTY_VALUE);

      ArrayInitialize(BufferEUR,EMPTY_VALUE);

      ArrayInitialize(BufferGBP,EMPTY_VALUE);

      ArrayInitialize(BufferJPY,EMPTY_VALUE);

      ArrayInitialize(BufferNZD,EMPTY_VALUE);

      ArrayInitialize(BufferUSD,EMPTY_VALUE);

     }



//---  0AGQB 8=48:0B>@0

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      double sum_aud=0,sum_cad=0,sum_chf=0,sum_eur=0,sum_gbp=0,sum_jpy=0,sum_nzd=0,sum_usd=0,pair1=0,pair2=0;

      int row=list_symbols.Total();

      int col=list_timeframes.Total();

   //---

      int total=list_ind.Total();

      for(int j=0;j<total;j++)

        {

         CIndCollection* collection=list_ind.At(j);

         if(collection==NULL)

            continue;

         collection.Refresh();

   

      //--- MA Fast

         double maf0=0;

         CIndicatorsBase* maf=collection.GetIndByID(IND_ID_MA_FAST);

         if(maf!=NULL)

           {

            maf0=maf.GetData(0,i);

           }

      //--- MA Medium

         double mam0=0;

         CIndicatorsBase* mam=collection.GetIndByID(IND_ID_MA_MED);

         if(mam!=NULL)

           {

            mam0=mam.GetData(0,i);

           }

      //--- MA Slow

         double mas0=0;

         CIndicatorsBase* mas=collection.GetIndByID(IND_ID_MA_SLOW);

         if(mas!=NULL)

           {

            mas0=mas.GetData(0,i);

           }

      //--- ROC Signal

         double roc0=0,sig0=0;

         CIndicatorsBase* roc=collection.GetIndByID(IND_ID_ROC_SIG);

         if(roc!=NULL)

           {

            roc0=roc.GetData(0,i);

            sig0=roc.GetData(1,i);

           }

         if(maf0!=EMPTY_VALUE && mam0!=EMPTY_VALUE && mas0!=EMPTY_VALUE && roc0!=EMPTY_VALUE && sig0!=EMPTY_VALUE)

           {

            if(maf0>mam0 && mam0>mas0) { pair1+=3; pair2-=3; }

            if(maf0<mam0 && mam0>mas0) { pair1+=2; pair2-=1; }

            if(maf0<mam0 && mam0<mas0) { pair1-=3; pair2+=3; }

            if(maf0>mam0 && mam0<mas0) { pair1-=1; pair2+=2; }

   

            if(roc0>sig0 && sig0>0) { pair1+=3; pair2-=3; }

            if(roc0<sig0 && sig0>0) { pair1+=2; pair2-=1; }

            if(roc0<sig0 && sig0<0) { pair1-=3; pair2+=3; }

            if(roc0>sig0 && sig0<0) { pair1-=1; pair2+=2; }

   

            if(collection.FirstInPair()=="AUD") sum_aud+=pair1;

            if(collection.FirstInPair()=="CAD") sum_cad+=pair1;

            if(collection.FirstInPair()=="CHF") sum_chf+=pair1;

            if(collection.FirstInPair()=="EUR") sum_eur+=pair1;

            if(collection.FirstInPair()=="GBP") sum_gbp+=pair1;

            if(collection.FirstInPair()=="JPY") sum_jpy+=pair1;

            if(collection.FirstInPair()=="NZD") sum_nzd+=pair1;

            if(collection.FirstInPair()=="USD") sum_usd+=pair1;

   

            if(collection.SecondInPair()=="AUD") sum_aud+=pair2;

            if(collection.SecondInPair()=="CAD") sum_cad+=pair2;

            if(collection.SecondInPair()=="CHF") sum_chf+=pair2;

            if(collection.SecondInPair()=="EUR") sum_eur+=pair2;

            if(collection.SecondInPair()=="GBP") sum_gbp+=pair2;

            if(collection.SecondInPair()=="JPY") sum_jpy+=pair2;

            if(collection.SecondInPair()=="NZD") sum_nzd+=pair2;

            if(collection.SecondInPair()=="USD") sum_usd+=pair2;

           }

         BufferAUD[i]=sum_aud;

         BufferCAD[i]=sum_cad;

         BufferCHF[i]=sum_chf;

         BufferEUR[i]=sum_eur;

         BufferGBP[i]=sum_gbp;

         BufferJPY[i]=sum_jpy;

         BufferNZD[i]=sum_nzd;

         BufferUSD[i]=sum_usd;

        }

     }



//--- return value of prev_calculated for next call

   return(rates_total);

  }

//+------------------------------------------------------------------+

//| Timer function                                                   |

//+------------------------------------------------------------------+

void OnTimer()

  {

   static long last_time=0;

   MqlTick tick;

   bool refresh=false;

   int total=list_ind.Total();

   for(int i=0;i<total;i++)

     {

      CIndCollection* collection=list_ind.At(i);

      if(collection==NULL)

         continue;

      collection.OnTimer();

     }

  }

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+

//| $C=:F88                                                          |

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+

//| @>25@:0 A8<2>;0                                                 |

//+------------------------------------------------------------------+

bool SymbolCheck(const string symbol_name)

  {

   long select=0;

   ResetLastError();

   if(!SymbolInfoInteger(symbol_name,SYMBOL_SELECT,select))

     {

      int err=GetLastError();

      Print("Error: ",err," Symbol ",symbol_name," does not exist");

      return false;

     }

   else

     {

      if(select) return true;

      ResetLastError();

      if(!SymbolSelect(symbol_name,true))

        {

         int err=GetLastError();

         Print("Error selected ",symbol_name,": ",err);

        }

     }

   return false;

  }

//+------------------------------------------------------------------+

//| >72@0I05B D0:B =0;8G8O A8<2>;0 2 A?8A:5                         |

//+------------------------------------------------------------------+

bool IsPresentSymbol(const string symbol)

  {

   list_symbols.Sort();

   return(list_symbols.Search(symbol)>WRONG_VALUE);

  }

//+------------------------------------------------------------------+

//| >72@0I05B 8=45:A A8<2>;0 2 A?8A:5                               |

//+------------------------------------------------------------------+

int IndexSymbol(const string symbol_name)

  {

   int total=list_symbols.Total();

   for(int i=0;i<total;i++)

      if(list_symbols.At(i)==symbol_name)

         return i;

   return WRONG_VALUE;

  }

//+------------------------------------------------------------------+

//| >72@0I05B 8=45:A B09<D@59<0 2 A?8A:5                            |

//+------------------------------------------------------------------+

int IndexTimeframe(const ENUM_TIMEFRAMES timeframe)

  {

   int total=list_timeframes.Total();

   for(int i=0;i<total;i++)

      if((ENUM_TIMEFRAMES)list_timeframes.At(i)==timeframe)

         return i;

   return WRONG_VALUE;

  }

//+------------------------------------------------------------------+

//| >43>B>2:0 <0AA82>2 2E>4=KE ?0@0<5B@>2                           |

//+------------------------------------------------------------------+

bool ArraysPreparing(void)

  {

   if(InpSymbols=="" || InpSymbols==NULL)

     {

      ArrayResize(array_symbols,1);

      array_symbols[0]=Symbol();

     }

   else

     {

      string value=","+InpSymbols;

      int total=StringSplit(InpSymbols,StringGetCharacter(value,0),array_symbols);

      ResetLastError();

      if(total<=0)

        {

         string end=(total==0 ? "Symbols string is empty." : "Error: "+(string)GetLastError());

         Print("Failed to get the array of symbols. ",end);

         return false;

        }

      for(int i=0;i<total;i++)

         SymbolCheck(array_symbols[i]);

     }

   int total=ArraySize(array_symbols);

   list_symbols.Clear();

   for(int i=0;i<total;i++)

     {

      if(!IsPresentSymbol(array_symbols[i]))

         if(SymbolCheck(array_symbols[i]))

            list_symbols.Add(array_symbols[i]);

     }

//---

   list_timeframes.Clear();

   if(list_timeframes.Total()==0)

      list_timeframes.Add(Period());

   return true;

  }

//+------------------------------------------------------------------+

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---