Questions from Beginners MQL5 MT5 MetaTrader 5 - page 575

 

Here is my variant of solving the repetition search problem:

//+------------------------------------------------------------------+
//|                                              FindRetryPrices.mq5 |
//|                                 Copyright 2016, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include <Dictionary.mqh>

input int RatesPeriod = 10;                        // Период за который ищутся повторения
input int RoundPoints = 10;                        // Загрубление цены в прайсстепах
class CBar : public CObject
{
private:
   MqlRates m_bar;
public:
            CBar(MqlRates& bar){m_bar = bar;}
   datetime Date(){return m_bar.time;}
   double Open(){return m_bar.open;}
   double High(){return m_bar.high;}
   double Low(){return m_bar.low;}
   double Close(){return m_bar.close;}
};
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   // Нахождение повторяющихся баров
   MqlRates rates[];
   int total = CopyRates(Symbol(), Period(), 0, RoundPoints, rates);
   CDictionary* BarsCollections = new CDictionary(total);
   for(int i = 0; i < total; i++)
   {
      double price = PriceToLevel(rates[i].high);
      CBar* bar = new CBar(rates[i]);
      if(!BarsCollections.ContainsKey(price))
         BarsCollections.AddObject(price, new CList());
      CList* equal_bars = BarsCollections.GetObjectByKey(price);
      equal_bars.Add(bar);
   }
   // Вывод повторов
   FOREACH_DICT(BarsCollections)
   {
      CList* list = node;
      if(list.Total() < 2)continue;
      string retry_bars = "";
      for(CBar* bar = list.GetFirstNode(); bar != NULL; bar = list.GetNextNode())
         retry_bars += " [" + TimeToString(bar.Date()) + ", " + DoubleToString(bar.High(), Digits()) + "]";
      printf("Обнаружено совпадение баров:" + retry_bars);
   }
   delete BarsCollections;
}
//+------------------------------------------------------------------+
//| Округляет цену в соответствии с параметром RoundPoints           |
//+------------------------------------------------------------------+
double PriceToLevel(double price)
{
   double price_step = RoundPoints*Point();
   double mn = MathFloor(price/price_step);
   return mn * price_step;
}

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

For the script to work, the Dictionary file must be copied into MQL5\Include

The search is performed in the one-pass for loop highlighted in yellow. The resulting list contains no repetitions (if A repeats B and B repeats A, one set {A, B} will be output instead of two {A, B} and {B, A}). ).

The output of this script showed the following:

2016.05.10 11:09:06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [2016.05.10 11:02, 67149] [2016.05.10 11:03, 67147] [2016.05.10 11:04, 67144]
2016.05.10 11:09:06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [2016.05.10 11:01, 67160] [2016.05.10 11:05, 67161]
2016.05.10 11:09:06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [2016.05.10 11:00, 67132] [2016.05.10 11:06, 67139]
Files:
Dictionary.mqh  18 kb
 
Artyom Trishkin:

From the reference:

Vasiliy Sokolov:

Here is my version of the solution to the repetition search problem:


Thank you all very much!!! I will try to figure it all out today. It is important not just to copy a piece of code into Expert Advisor, but to understand why it is written this way, so maybe I will ask more questions.
 

Please help me find a function to calculate the standard RSI, the requirements are simple:

1. Return RSI value at a given bar

2. Calculate index only for those bars (if necessary), which are requested (desirable)

3. To be able to calculate on the specified TF

4. Works at the expense of point 2 faster than the indicator

I want to integrate the function into the Expert Advisor, if anyone has a ready one, please share it with me.

I am asking as the indicator is very common and is not a mystery.

 
-Aleks-:

Please help me find a function to calculate the standard RSI, the requirements are simple:

1. Return RSI value at a given bar

2. Calculate index only for those bars (if necessary), which are requested (desirable)

3. To be able to calculate on the specified TF

4. Works at the expense of point 2 faster than the indicator

I want to integrate the function into the Expert Advisor, if anyone has a ready one, please share it with me.

I am asking as the indicator is very common and is not a mystery.

Why don't you like the standard iRSI? Not secret enough?
 
Vasiliy Sokolov:
What's wrong with the standard iRSI? Not secret enough?
There are my changes that I will need to make to the function...
 
-Aleks-:
There are my changes that I will need to make to the function...

Take a ready-made one then and modify it according to your requirements:

//+------------------------------------------------------------------+
//|                                                          RSI.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "2009, MetaQuotes Software Corp."
#property link        "http://www.mql5.com"
#property description "Relative Strength Index"
//--- indicator settings
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property  indicator_level1 30
#property  indicator_level2 70
#property indicator_buffers 3
#property indicator_plots   1
#property  indicator_type1   DRAW_LINE
#property  indicator_color1  DodgerBlue
//--- input parameters
input int InpPeriodRSI=14; // Period
//--- indicator buffers
double    ExtRSIBuffer[];
double    ExtPosBuffer[];
double    ExtNegBuffer[];
//--- global variable
int       ExtPeriodRSI;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- check for input
   if(InpPeriodRSI<1)
     {
      ExtPeriodRSI=12;
      Print("Incorrect value for input variable InpPeriodRSI =",InpPeriodRSI,
            "Indicator will use value =",ExtPeriodRSI,"for calculations.");
     }
   else ExtPeriodRSI=InpPeriodRSI;
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtRSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtPosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,ExtNegBuffer,INDICATOR_CALCULATIONS);
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPeriodRSI);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"RSI("+string(ExtPeriodRSI)+")");
//--- initialization done
  }
//+------------------------------------------------------------------+
//| Relative Strength Index                                          |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   int    i;
   double diff;
//--- check for rates count
   if(rates_total<=ExtPeriodRSI)
      return(0);
//--- preliminary calculations
   int pos=prev_calculated-1;
   if(pos<=ExtPeriodRSI)
     {
      //--- first RSIPeriod values of the indicator are not calculated
      ExtRSIBuffer[0]=0.0;
      ExtPosBuffer[0]=0.0;
      ExtNegBuffer[0]=0.0;
      double SumP=0.0;
      double SumN=0.0;
      for(i=1;i<=ExtPeriodRSI;i++)
        {
         ExtRSIBuffer[i]=0.0;
         ExtPosBuffer[i]=0.0;
         ExtNegBuffer[i]=0.0;
         diff=price[i]-price[i-1];
         SumP+=(diff>0?diff:0);
         SumN+=(diff<0?-diff:0);
        }
      //--- calculate first visible value
      ExtPosBuffer[ExtPeriodRSI]=SumP/ExtPeriodRSI;
      ExtNegBuffer[ExtPeriodRSI]=SumN/ExtPeriodRSI;
      if(ExtNegBuffer[ExtPeriodRSI]!=0.0)
         ExtRSIBuffer[ExtPeriodRSI]=100.0-(100.0/(1.0+ExtPosBuffer[ExtPeriodRSI]/ExtNegBuffer[ExtPeriodRSI]));
      else
        {
         if(ExtPosBuffer[ExtPeriodRSI]!=0.0)
            ExtRSIBuffer[ExtPeriodRSI]=100.0;
         else
            ExtRSIBuffer[ExtPeriodRSI]=50.0;
        }
      //--- prepare the position value for main calculation
      pos=ExtPeriodRSI+1;
     }
//--- the main loop of calculations
   for(i=pos;i<rates_total && !IsStopped();i++)
     {
      diff=price[i]-price[i-1];
      ExtPosBuffer[i]=(ExtPosBuffer[i-1]*(ExtPeriodRSI-1)+(diff>0.0?diff:0.0))/ExtPeriodRSI;
      ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(ExtPeriodRSI-1)+(diff<0.0?-diff:0.0))/ExtPeriodRSI;
      if(ExtNegBuffer[i]!=0.0)
         ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]);
      else
        {
         if(ExtPosBuffer[i]!=0.0)
            ExtRSIBuffer[i]=100.0;
         else
            ExtRSIBuffer[i]=50.0;
        }
     }
//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Vasiliy Sokolov:

Take a ready-made one then and modify it according to your requirements:

I know there is an indicator in the code... The question was who might have already changed it...
 
Vasiliy Sokolov:

Here is my variant of solving the problem of searching for repetitions:

Vasily, when I open#include <Dictionary.mqh>, it opens the same as in the EA body. It should be like this, or there should be some other code inside?

Because in the code, that I see, it's not clear how it searches for repetitions ((

 
Artyom Trishkin:

// строку int searchPeriod=(Search_Period<1)?1:Search_Period;
// можно расписать так:

input int Search_Period=10; // Количество копируемых свечей ... эту строку вы видите в настройках
int searchPeriod;           // Сюда будем записывать входной параметр
if(Search_Period<1) searchPeriod=1; // Если во входном параметре ввели ноль или меньше нуля, то параметр будет равен нулю
else searchPeriod=Search_Period;    // иначе примем входной параметр

// соответственно и строку int delta=(Delta<0)?0:Delta;
// можно расписать точно так же

Am I correct in assuming this is a typo? It should be 0 instead of 1.

like this:int searchPeriod=(Search_Period<1)?0:Search_Period;

and further in the executable script:

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // the number of candles to copy

In this case, we should probably already use a variable: searchPeriod. right?

------

Another question, what does this line do? I found that each element of the structure resets to zero. And I don't understand what we are zeroing here if we seem to have just written this data and should use it further.

ZeroMemory(dataCandle); // Zeroing data in the structure

 
Andrey Koldorkin:

Am I correct in assuming this is a typo? It should be 0 instead of 1.

like this:int searchPeriod=(Search_Period<1)?0:Search_Period;

and further in the executable script:

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // the number of candles to copy

In this case, we should probably already use a variable: searchPeriod. right?

------

Another question, what does this line do? I found that each element of the structure resets to zero. And I don't understand what we are zeroing here if we seem to have just written this data and should use it further.

ZeroMemory(dataCandle); // clearing the data in the structure


"like this:int searchPeriod=(Search_Period<1)?0:Search_Period;"

No, it's not. This is how you have it (literally): if Search_Period set by the user in the settings is less than one, then searchPeriod will be equal to zero; otherwise, searchPeriod will be equal to the value of Search_Period set by the user in the settings. This is not correct. We don't need a search range that equals zero. So, if this range is set by the user to 0 or less than zero (less than one), then we'll set this range equal to the minimum - one.


"int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // number of candlesticks to copy
here we should already use the variable: searchPeriod. right? "

Yes, that's right, there's a typo.


"Another question, what does this line do? What is it for? I found that it resets each element of the structure to zero. And here I cannot understand why and what we are zeroing if we have just written this data and should use it further. ZeroMemory(dataCandle); // Zeroing the data in the structure".

We do this before filling the structure with data. First we zero it, and then we fill it. Look - we zero it before the loop. And then in the loop we fill the structure with data.