Questions des débutants MQL5 MT5 MetaTrader 5 - page 575

 

Voici ma variante de la résolution du problème de la recherche par répétition :

//+------------------------------------------------------------------+
//|                                              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;
}

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

Pour que le script fonctionne, le fichier Dictionnaire doit être copié dans MQL5\Include

La recherche est effectuée dans la boucle for à passage unique surlignée en jaune. La liste résultante ne contient pas de répétitions (si A répète B et B répète A, un ensemble {A, B} sera produit au lieu de deux {A, B} et {B, A}). ).

Le résultat de ce script est le suivant :

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]
Dossiers :
Dictionary.mqh  18 kb
 
Artyom Trishkin:

De la référence :

Vasiliy Sokolov:

Voici ma version de la solution au problème de la recherche de répétitions :


Merci beaucoup à tous ! !! Je vais essayer de trouver une solution aujourd'hui. Il est important de ne pas se contenter de copier un morceau de code dans Expert Advisor, mais de comprendre pourquoi il est écrit de cette façon, alors peut-être que je poserai plus de questions.
 

Veuillez m'aider à trouver une fonction pour calculer le RSI standard, les exigences sont simples :

1. Retourner la valeur RSI à une barre donnée

2. Calculer l'indice uniquement pour les barres (si nécessaire), qui sont demandées (souhaitable).

3. Être capable de calculer sur le TF spécifié

4. Travaille au détriment du point 2 plus rapidement que l'indicateur

Je veux intégrer la fonction dans l'Expert Advisor, si quelqu'un en a une prête, merci de la partager avec moi.

Je pose la question car cet indicateur est très courant et n'est pas un mystère.

 
-Aleks-:

Veuillez m'aider à trouver une fonction pour calculer le RSI standard, les exigences sont simples :

1. Retourner la valeur RSI à une barre donnée

2. Calculer l'indice uniquement pour les barres (si nécessaire), qui sont demandées (souhaitable).

3. Être capable de calculer sur le TF spécifié

4. Travaille au détriment du point 2 plus rapidement que l'indicateur

Je veux intégrer la fonction dans l'EA, si quelqu'un en a une prête, merci de la partager avec moi.

Je pose la question car cet indicateur est très courant et n'est pas un mystère.

Pourquoi n'aimez-vous pas l'iRSI standard ? Pas assez secret ?
 
Vasiliy Sokolov:
Quel est le problème avec l'iRSI standard ? Pas assez secret ?
Il y a mes changements que je devrai faire à la fonction...
 
-Aleks-:
Il y a mes changements que je devrai faire à la fonction...

Prenez donc un modèle prêt à l'emploi et modifiez-le en fonction de vos besoins :

//+------------------------------------------------------------------+
//|                                                          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:

Prenez donc un modèle prêt à l'emploi et modifiez-le en fonction de vos besoins :

Je sais qu'il y a un indicateur dans le code... La question était de savoir qui aurait pu déjà le changer...
 
Vasiliy Sokolov:

Voici ma variante pour résoudre le problème de la recherche de répétitions :

Vasily, lorsque j'ouvre#include <Dictionary.mqh>, il s'ouvre de la même manière que dans le corps de l'EA. Ça devrait être comme ça, ou il devrait y avoir un autre code à l'intérieur ?

Parce que dans le code, que je vois, il n'est pas clair comment il cherche les répétitions ((

 
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;
// можно расписать точно так же

Ai-je raison de supposer qu'il s'agit d'une erreur de frappe ? Il faudrait que ce soit 0 au lieu de 1.

comme ça :int searchPeriod=(Search_Period<1)?0:Search_Period ;

et plus loin dans le script exécutable :

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())) ; // le nombre de bougies à copier

Dans ce cas, nous devrions probablement déjà utiliser une variable : searchPeriod. non ?

------

Autre question, à quoi sert cette ligne ? J'ai découvert que chaque élément de la structure se remet à zéro. Et je ne comprends pas ce que nous mettons à zéro ici si nous semblons avoir juste écrit ces données et devrions les utiliser plus loin.

ZeroMemory(dataCandle) ; // Remise à zéro des données dans la structure

 
Andrey Koldorkin:

Ai-je raison de supposer qu'il s'agit d'une erreur de frappe ? Il faudrait que ce soit 0 au lieu de 1.

comme ça :int searchPeriod=(Search_Period<1)?0:Search_Period ;

et plus loin dans le script exécutable :

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())) ; // le nombre de bougies à copier

Dans ce cas, nous devrions probablement déjà utiliser une variable : searchPeriod. non ?

------

Autre question, à quoi sert cette ligne ? J'ai découvert que chaque élément de la structure se remet à zéro. Et je ne comprends pas ce que nous mettons à zéro ici si nous semblons avoir juste écrit ces données et devrions les utiliser plus loin.

ZeroMemory(dataCandle) ; // effacement des données dans la structure


"comme ceci :int searchPeriod=(Search_Period<1)?0:Search_Period ;"

Non, ça ne l'est pas. Voici comment procéder (littéralement) : si la période de recherche définie par l'utilisateur dans les paramètres est inférieure à un, alors la période de recherche sera égale à zéro ; sinon, la période de recherche sera égale à la valeur de la période de recherche définie par l'utilisateur dans les paramètres. Ce n'est pas correct. Nous n'avons pas besoin d'une plage de recherche égale à zéro. Ainsi, si cette plage est définie par l'utilisateur comme étant égale à 0 ou inférieure à zéro (inférieure à un), nous la définirons comme étant égale au minimum - un.


"int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())) ; // nombre de chandeliers à copier
ici nous devrions déjà utiliser la variable : searchPeriod. n'est-ce pas ? "

Oui, c'est vrai, c'est une faute de frappe.


"Autre question, à quoi sert cette ligne ? À quoi sert-elle ? J'ai découvert que cela remet à zéro chaque élément de la structure. Et là, je n'arrive pas à comprendre pourquoi et ce que nous mettons à zéro si nous venons d'écrire ces données et que nous devons les utiliser plus tard. ZeroMemory(dataCandle) ; // Mise à zéro des données dans la structure ".

Nous faisons cela avant de remplir la structure avec des données. D'abord on le met à zéro, et ensuite on le remplit. Regarde - on le met à zéro avant la boucle. Et ensuite, dans la boucle, nous remplissons la structure avec des données.