KeyFinder 2.0 – script MetaTrader 5

This script finds DeMark pivot points, displays them on the chart and indicates their dimensions.

This script has practically the same functionality as KeyFinder. It doesn’t have any visual differences except the button which deletes the script and all associated objects from the chart.

Fig. 1. RTS index futures chart after applying KeyFinder 2.0 script

Fig. 1. RTS index futures chart after applying KeyFinder 2.0 script

Although the script hasn’t been changed both visually and functionally, it’s code has been significantly modified.

CKeyFinder class has been created for the script.

Fig. 2. CKeyFinder class

Fig. 2. CKeyFinder class

The code of the class is provided below. As I tried to make comments as detailed as possible, you shouldn’t face any problems.

//+------------------------------------------------------------------+
//|                                                    KeyFinder.mqh |
//|                                                   Trofimov Pavel |
//|                                               trofimovpp@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Trofimov Pavel"
#property link      "trofimovpp@mail.ru"
//+------------------------------------------------------------------+
//| Class for KeyFinder 2.0                                          |
//+------------------------------------------------------------------+
class CKeyFinder
  {
private:
   // Class variables
   int               MinDimension;  //Minimum dimension of points
   int               MaxBars;       //The number of bars to process
protected:
   // Class methods for internal use
   // Determining the upper points dimensions
   int               getHighDimension(MqlRates &tmpRates[],int tmp_i,int tmp_iCod);
   // Determining the lower points dimensions
   int               getLowDimension(MqlRates &tmpRates[],int tmp_i,int tmp_iCod);
public:
   // Class constructor
                     CKeyFinder();
   // Class destructor
                    ~CKeyFinder();
   // Property method for getting the dimension   
   int               GetMinDimension();
   // Property method for setting the dimension
   void              SetMinDimension(int temp_Val);
   // Property method for getting the number of bars to process
   int               GetMaxBars();
   // Property method for setting the number of bars to process
   void              SetMaxBars(int temp_Val);
   // Method for finding upper pivot points
   void              FindUpKeyPoints(int temp_iCod,MqlRates &temp_rates[]);
   // Method for finding lower pivot points
   void              FindLowKeyPoints(int temp_iCod,MqlRates &temp_rates[]);
   // Clearing the chart from the script objects.
   int               CleanChart();
  };
//+------------------------------------------------------------------+
//|                Determining the upper point dimension             |
//+------------------------------------------------------------------+
int CKeyFinder::getHighDimension(MqlRates &tmpRates[],int tmp_i,int tmp_iCod)// The method receives an array of MqlRates type data, a number of a processed bar in the array and a maximum index of the array
  {
   int k=1;
   while((tmpRates[tmp_i].high>tmpRates[tmp_i+k].high) && (tmpRates[tmp_i].high>tmpRates[tmp_i-k].high) && ((tmp_i+k)<(tmp_iCod)) && ((tmp_i-k)>0)) k++;
   if(((tmp_i+k)==tmp_iCod) || ((tmp_i-k)==0)) k=-1;
   return(k);
  };
//+------------------------------------------------------------------+
//|                Determining the lower point dimension             |
//+------------------------------------------------------------------+
int CKeyFinder::getLowDimension(MqlRates &tmpRates[],int tmp_i,int tmp_iCod)// The method receives an array of MqlRates type data, a number of a processed bar in the array and a maximum index of the array
  {
   int k=1;
   while((tmpRates[tmp_i].low<tmpRates[tmp_i+k].low) && (tmpRates[tmp_i].low<tmpRates[tmp_i-k].low) && ((tmp_i+k)<(tmp_iCod)) && ((tmp_i-k)>0)) k++;
   if(((tmp_i+k)==tmp_iCod) || ((tmp_i-k)==0)) k=-1;
   return(k);
  };
//+------------------------------------------------------------------+
//| Method GetMinDimension                                           |
//+------------------------------------------------------------------+
int CKeyFinder::GetMinDimension(){return(MinDimension);};
//+------------------------------------------------------------------+
//| Method SetMinDimension                                           |
//+------------------------------------------------------------------+
void CKeyFinder::SetMinDimension(int temp_Val)
  {
   if(temp_Val>1) MinDimension=temp_Val;
   else
     {
      MessageBox("The set dimension is too low."+"\n"+"The default dimension of 5 will be used","Warning!",MB_OK+MB_ICONWARNING);
      MinDimension=5;
     };
  };
//+------------------------------------------------------------------+
//| Method GetMaxBars                                                |
//+------------------------------------------------------------------+
int CKeyFinder::GetMaxBars() {return(MaxBars);};
//+------------------------------------------------------------------+
//| Method SetMaxBars                                                |
//+------------------------------------------------------------------+
void CKeyFinder::SetMaxBars(int temp_Val)
  {
// Checking the availability of history for the set number of bars
   int SMaxBars=Bars(Symbol(),0);
   if(SMaxBars<temp_Val)
     {
      temp_Val=SMaxBars;// Setting the maximum available number of bars
      MessageBox("The MaxBars parameter is too high."+"\n"+"Only "+IntegerToString(temp_Val)+" bars will be used for calculation.","Warning!",MB_OK+MB_ICONWARNING);
     };

// Checking if the number of bars is not too low
   if(temp_Val<(2*MinDimension))
     {
      MessageBox("The set number of bars is too low."+"\n"+"The default number of 300 will be used","Warning!",MB_OK+MB_ICONWARNING);
      temp_Val=300;
     };
   MaxBars=temp_Val;
  };
//+------------------------------------------------------------------+
//| Method FindKeyPoints - Finding upper key points                  |
//+------------------------------------------------------------------+
void CKeyFinder::FindUpKeyPoints(int temp_iCod,MqlRates &temp_rates[])// The method receives an index of the maximum array element and the MqlRates array
  {
   int HD=1;   //initializing points dimensions
   for(int i=temp_iCod-MinDimension; i>(MinDimension-1); i--)// A loop from the last bar - MinDimension to the zero bar + MinDimension
     {
      HD=getHighDimension(temp_rates,i,temp_iCod);//Getting points dimensions
      if((HD>=MinDimension) || (HD==-1))
        {//Creating a mark if MinDimension condition is met
         string Ob_Name="KF_Label"+IntegerToString(i);
         if(HD!=-1)
           {
            ObjectCreate(0,Ob_Name,OBJ_TEXT,0,temp_rates[i].time,temp_rates[i].high);
            ObjectSetInteger(0,Ob_Name,OBJPROP_ANCHOR,0,ANCHOR_LOWER);
            ObjectSetString(0,Ob_Name,OBJPROP_TEXT,0,IntegerToString(HD));
            ObjectSetInteger(0,Ob_Name,OBJPROP_COLOR,clrRed);
           }
         else
           { //If the dimension can't be determined, use a ball mark
            ObjectCreate(0,Ob_Name,OBJ_ARROW,0,temp_rates[i].time,temp_rates[i].high);
            ObjectSetInteger(0,Ob_Name,OBJPROP_ARROWCODE,0,159);
            ObjectSetInteger(0,Ob_Name,OBJPROP_ANCHOR,0,ANCHOR_BOTTOM);
            ObjectSetInteger(0,Ob_Name,OBJPROP_COLOR,clrRed);
           };
        };
     };
  };
//+------------------------------------------------------------------+
//| Method FindLowKeyPoints - Finding lower key points            |
//+------------------------------------------------------------------+   
void CKeyFinder::FindLowKeyPoints(int temp_iCod,MqlRates &temp_rates[])// The method receives an index of the maximum array element and the MqlRates array
  {
   int LD=1;//initializing points dimensions
   bool iCreate;
   for(int i=temp_iCod-MinDimension; i>(MinDimension-1); i--)// A loop from the last bar - MinDimension to the zero bar + MinDimension
     {
      LD=getLowDimension(temp_rates,i,temp_iCod);
      if((LD>=MinDimension) || (LD==-1))
        {
         string Ob_Name="KF_Label"+IntegerToString(i)+"_1";//Avoiding the bars there Low and High can be key points
         if(LD!=-1)
           {
            iCreate=ObjectCreate(0,Ob_Name,OBJ_TEXT,0,temp_rates[i].time,temp_rates[i].low);
            if(iCreate)
              {
               ObjectSetInteger(0,Ob_Name,OBJPROP_ANCHOR,0,ANCHOR_UPPER);
               ObjectSetString(0,Ob_Name,OBJPROP_TEXT,0,IntegerToString(LD));
               ObjectSetInteger(0,Ob_Name,OBJPROP_COLOR,clrGreen);
              }
            else Comment("Cannot create the object");
           }
         else
           {
            iCreate=ObjectCreate(0,Ob_Name,OBJ_ARROW,0,temp_rates[i].time,temp_rates[i].low);
            if(iCreate)
              {
               ObjectSetInteger(0,Ob_Name,OBJPROP_ARROWCODE,0,159);
               ObjectSetInteger(0,Ob_Name,OBJPROP_ANCHOR,0,ANCHOR_TOP);
               ObjectSetInteger(0,Ob_Name,OBJPROP_COLOR,clrGreen);
              }
            else Comment("Cannot create the object");
           };
        };
     };
  };
//+------------------------------------------------------------------+
//| Method CleanChart - Clearing the chart from objects              |
//+------------------------------------------------------------------+   
int CKeyFinder::CleanChart(void)
  {
   string Label="KF_Label";
   int obj_total=ObjectsTotal(0,0,-1),n=0;
   for(int obj=obj_total-1; obj>=0; obj--) //Clearing the objects created by the script by the name mask
     {
      string objname=ObjectName(0,obj,0,-1);
      if(StringFind(objname,Label)>=0) ObjectDelete(0,objname);
      n++;
     }
   return(n);
  }
//+------------------------------------------------------------------+
//| Class constructor                                                |
//+------------------------------------------------------------------+
CKeyFinder::CKeyFinder(){};
//+------------------------------------------------------------------+
//| Class destructor                                                 |
//+------------------------------------------------------------------+
CKeyFinder::~CKeyFinder(){};
//+---------------------------------------------------------------------+

Because most of the code has been moved to the class, the main script code is very compact.

Alternative:  RVI_Histogram_HTF - indicator MetaTrader 5
//+------------------------------------------------------------------+
//|                                                   KeyFinder2.mq5 |
//|                                                   Trofimov Pavel |
//|                                               trofimovpp@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Trofimov Pavel"
#property link      "trofimovpp@mail.ru"
#property version   "2.00"
#property description "Warning! This algorithm uses loops for calculations!"
#property description "It is recommended so set not more than 1000 to process!"
#property script_show_inputs
//--- input parameters
input int      MinDimesion=5; //Minimum dimension of points
input int      MaxBars=300;   //The number of bars to process
#include       "KeyFinder.mqh"
#include       <ChartObjects\ChartObjectsTxtControls.mqh>
//+------------------------------------------------------------------+
//| Script variables                                                 |
//+------------------------------------------------------------------+
CKeyFinder           m_keyfinder;      //Declaring СKeyFinder class variable
CChartObjectButton   m_button_close;   //Declaring CChartObjectButton class variable
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//-Initializing variables
   MqlRates  rates_array[];
   string Com="\n\n\n";
   int iCod=CopyRates(Symbol(),Period(),0,MaxBars,rates_array);// The number of elements in MqlRates array that we were able to copy
   int sy=10;//Button position
   if(ChartGetInteger(0,CHART_SHOW_OHLC))
      sy+=16;
//-Setting the necessary parameters   
   m_keyfinder.SetMaxBars(MaxBars);
   m_keyfinder.SetMinDimension(MinDimesion);
   m_keyfinder.CleanChart();//Clearing the chart from objects in case of a second use 
   iCod=iCod-1;//An index of the maximum element in rates_array[]
   Com+="Working...Please, wait!";
//-Creating the button and setting its properties
   m_button_close.Create(0,"ButtonClose",0,10,sy,100,20);
   m_button_close.Description("Close Script");
   m_button_close.Color(Blue);
   m_button_close.FontSize(8);
   Comment(Com);
//-Processing the bars using the CKeyFinder class methods   
   if(iCod>0)
     {
      m_keyfinder.FindUpKeyPoints(iCod,rates_array);//Searching for upper key points
      Com+="\nUpper points have been processed.\n";
      Comment(Com);
      m_keyfinder.FindLowKeyPoints(iCod,rates_array);//Searching for lower key points
      Comment("\n\n\nProcessing is complete");
     }
   else Comment("\n\n\nNo bars to process!!!");
   m_button_close.State(false);
//-Looping the script until the button is pressed
   while(!(m_button_close.State()))
     {
      //--- redraw chart
      ChartRedraw();
      Sleep(250);
     };
//-Clearing the chart by a press of the button
   m_keyfinder.CleanChart();
   Comment("");
  }

And finally, I provided several helpful links and explanations:

Alternative:  VTS_Float_Pivot_Smoothed_HTF - indicator MetaTrader 5
  • How to load the code directly from MetaEditor
  • To use the script in MetaTrader 4 you need to change the extension of the file KeyFinder2.mq5 to mq4 and recompile it in MetaEditor. The KeyFinder.mqh file containing the class code should be stored in the same folder (for example, MQL5\Scripts) as the main script file.

I am looking forward to reading your comments, feedback and suggestions. Good luck in trading!



📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks