Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 575

 

Esta es mi variante para resolver el problema de búsqueda de repeticiones:

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

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

Para que el script funcione, el archivo Dictionary debe ser copiado en MQL5\Include

La búsqueda se realiza en el bucle for de una sola pasada resaltado en amarillo. La lista resultante no contiene repeticiones (si A repite a B y B repite a A, saldrá un conjunto {A, B} en lugar de dos {A, B} y {B, A}). ).

La salida de este script mostró lo siguiente:

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

De la referencia:

Vasiliy Sokolov:

Esta es mi versión de la solución al problema de la búsqueda de repeticiones:


¡¡¡Muchas gracias a todos!!! Intentaré resolverlo todo hoy. Es importante no sólo copiar un trozo de código en Expert Advisor, sino entender por qué está escrito de esta manera, así que tal vez haga más preguntas.
 

Por favor, ayúdenme a encontrar una función para calcular el RSI estándar, los requisitos son simples:

1. Devuelve el valor del RSI en una barra determinada

2. Calcular el índice sólo para las barras (si es necesario), que se solicitan (deseable)

3. Para poder calcular en el TF especificado

4. Funciona a expensas del punto 2 más rápido que el indicador

Quiero integrar la función en el Asesor Experto, si alguien tiene uno listo, por favor compártalo conmigo.

Lo pregunto porque el indicador es muy común y no es un misterio.

 
-Aleks-:

Por favor, ayúdenme a encontrar una función para calcular el RSI estándar, los requisitos son simples:

1. Devuelve el valor del RSI en una barra determinada

2. Calcular el índice sólo para las barras (si es necesario), que se solicitan (deseable)

3. Para poder calcular en el TF especificado

4. Funciona a expensas del punto 2 más rápido que el indicador

Quiero integrar la función en el Asesor Experto, si alguien tiene uno listo, por favor compártalo conmigo.

Lo pregunto porque el indicador es muy común y no es un misterio.

¿Por qué no te gusta el iRSI estándar? ¿No es suficientemente secreto?
 
Vasiliy Sokolov:
¿Qué tiene de malo el iRSI estándar? ¿No es suficientemente secreto?
Hay mis cambios que tendré que hacer en la función...
 
-Aleks-:
Hay mis cambios que tendré que hacer en la función...

Tome uno ya hecho y modifíquelo según sus necesidades:

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

Tome uno ya hecho y modifíquelo según sus necesidades:

Sé que hay un indicador en el código... La pregunta era quién podría haberlo cambiado ya...
 
Vasiliy Sokolov:

Esta es mi variante para resolver el problema de la búsqueda de repeticiones:

Vasily, cuando abro#include <Diccionario.mqh>, se abre lo mismo que en el cuerpo del EA. ¿Debería ser así, o debería haber algún otro código dentro?

Porque en el código, que veo, no está claro cómo busca las repeticiones ((

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

¿Estoy en lo cierto al suponer que se trata de un error tipográfico? Debería ser 0 en lugar de 1.

así:int searchPeriod=(Search_Period<1)?0:Search_Period;

y además en el script ejecutable:

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // el número de velas a copiar

En este caso, probablemente deberíamos utilizar ya una variable: searchPeriod. ¿no?

------

Otra pregunta, ¿qué hace esta línea? He comprobado que cada elemento de la estructura se pone a cero. Y no entiendo qué estamos poniendo a cero aquí si parece que acabamos de escribir estos datos y debemos utilizarlos más.

ZeroMemory(dataCandle); // Puesta a cero de los datos en la estructura

 
Andrey Koldorkin:

¿Estoy en lo cierto al suponer que se trata de un error tipográfico? Debería ser 0 en lugar de 1.

así:int searchPeriod=(Search_Period<1)?0:Search_Period;

y además en el script ejecutable:

int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // el número de velas a copiar

En este caso, probablemente deberíamos utilizar ya una variable: searchPeriod. ¿no?

------

Otra pregunta, ¿qué hace esta línea? He comprobado que cada elemento de la estructura se pone a cero. Y no entiendo qué estamos poniendo a cero aquí si parece que acabamos de escribir estos datos y debemos utilizarlos más.

ZeroMemory(dataCandle); // borrar los datos de la estructura


"...así:int searchPeriod=(Search_Period<1)?0:Search_Period;"

No, no lo es. Así es como se tiene (literalmente): si Search_Period establecido por el usuario en la configuración es menor que uno, entonces searchPeriod será igual a cero; en caso contrario, searchPeriod será igual al valor de Search_Period establecido por el usuario en la configuración. Esto no es correcto. No necesitamos un rango de búsqueda que sea igual a cero. Por lo tanto, si este rango es establecido por el usuario en 0 o menos de cero (menos de uno), entonces estableceremos este rango igual al mínimo - uno.


" int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // número de velas a copiar
aquí ya deberíamos utilizar la variable: searchPeriod. ¿no? "

Sí, es cierto, hay una errata.


"Otra pregunta, ¿qué hace esta línea? ¿Para qué sirve? He comprobado que pone a cero cada elemento de la estructura. Y aquí no puedo entender por qué y qué estamos poniendo a cero si acabamos de escribir estos datos y debemos utilizarlos más. ZeroMemory(dataCandle); // Poner a cero los datos de la estructura".

Lo hacemos antes de llenar la estructura con datos. Primero lo ponemos a cero y luego lo llenamos. Mira - lo ponemos a cero antes del bucle. Y luego en el bucle llenamos la estructura con datos.

Razón de la queja: