Perguntas de Iniciantes MQL5 MT5 MetaTrader 5 - página 575

 

Aqui está a minha variante de resolver o problema da pesquisa de repetição:

//+------------------------------------------------------------------+
//|                                              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 o guião funcione, o ficheiro do Dicionário deve ser copiado para MQL5\Incluir

A pesquisa é realizada na passagem única para laço destacado em amarelo. A lista resultante não contém repetições (se A repete B e B repete A, um conjunto {A, B} será produzido em vez de dois {A, B} e {B, A}). ).

A produção deste guião mostrou o seguinte:

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

A partir da referência:

Vasiliy Sokolov:

Aqui está a minha versão da solução para o problema da procura repetida:


Muito obrigado a todos!!!! Vou tentar descobrir tudo hoje. É importante não só copiar um pedaço de código para o Expert Advisor, mas também compreender porque é que está escrito desta forma, por isso talvez eu faça mais perguntas.
 

Por favor, ajude-me a encontrar uma função para calcular o LER padrão, os requisitos são simples:

1. Devolver valor RSI a uma determinada barra

2. Calcular o índice apenas para as barras (se necessário), que são solicitadas (desejável)

3. Ser capaz de calcular na TF especificada

4. Trabalha à custa do ponto 2 mais rápido do que o indicador

Quero integrar a função no Expert Advisor, se alguém tiver um pronto, por favor partilhe-o comigo.

Pergunto porque o indicador é muito comum e não é um mistério.

 
-Aleks-:

Por favor, ajude-me a encontrar uma função para calcular o LER padrão, os requisitos são simples:

1. Devolver valor RSI a uma determinada barra

2. Calcular o índice apenas para as barras (se necessário), que são solicitadas (desejável)

3. Ser capaz de calcular na TF especificada

4. Trabalha à custa do ponto 2 mais rápido do que o indicador

Quero integrar a função no Expert Advisor, se alguém tiver um pronto, por favor partilhe-o comigo.

Pergunto porque o indicador é muito comum e não é um mistério.

Porque não gosta do iRSI padrão? Não é suficientemente secreto?
 
Vasiliy Sokolov:
O que há de errado com o iRSI padrão? Não é suficientemente secreto?
Há as minhas alterações que terei de fazer à função...
 
-Aleks-:
Há as minhas alterações que terei de fazer à função...

Tome então uma já pronta e modifique-a de acordo com as suas exigências:

//+------------------------------------------------------------------+
//|                                                          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 então uma já pronta e modifique-a de acordo com as suas exigências:

Sei que há um indicador no código... A questão era quem poderia já tê-lo mudado...
 
Vasiliy Sokolov:

Aqui está a minha variante de resolver o problema da procura de repetições:

Vasily, quando eu abro#include <Dictionary.mqh>, abre o mesmo que no corpo da EA. Deveria ser assim, ou deveria haver algum outro código dentro?

Porque no código, que eu vejo, não está claro como procura repetições ((

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

Estou correcto ao assumir que isto é uma gralha? Deveria ser 0 em vez de 1.

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

e ainda no guião executável:

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

Neste caso, provavelmente já deveríamos usar uma variável: searchPeriod. certo?

------

Outra questão, o que faz esta linha? Descobri que cada elemento da estrutura é reposto a zero. E não compreendo o que estamos aqui a zerar se parecemos ter acabado de escrever estes dados e devemos utilizá-los mais.

ZeroMemory(dataCandle); // Zeragem de dados na estrutura

 
Andrey Koldorkin:

Estou correcto ao assumir que isto é uma gralha? Deveria ser 0 em vez de 1.

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

e ainda no guião executável:

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

Neste caso, provavelmente já deveríamos usar uma variável: searchPeriod. certo?

------

Outra questão, o que faz esta linha? Descobri que cada elemento da estrutura é reposto a zero. E não compreendo o que estamos aqui a zerar se parecemos ter acabado de escrever estes dados e devemos utilizá-los mais.

ZeroMemory(dataCandle); // limpar os dados na estrutura


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

Não, não é. É assim que o tem (literalmente): se o Search_Period definido pelo utilizador nas definições for inferior a um, então o SearchPeriod será igual a zero; caso contrário, o SearchPeriod será igual ao valor do Search_Period definido pelo utilizador nas definições. Isto não é correcto. Não precisamos de um intervalo de pesquisa que seja igual a zero. Assim, se este intervalo for definido pelo utilizador para 0 ou menos de zero (menos de um), então definiremos este intervalo igual ao mínimo - um.


"int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period())); // número de candelabros a copiar
aqui, em teoria, já deveríamos usar a variável: searchPeriod. certo? "

Sim, é verdade, é uma gralha.


"Outra questão, o que faz esta linha? Para que serve? Descobri que repõe cada elemento da estrutura a zero. E aqui não consigo compreender porquê e o que estamos a zerar se acabámos de escrever estes dados e devemos utilizá-los mais. ZeroMemory(dataCandle); // Zerando os dados na estrutura".

Fazemo-lo antes de preencher a estrutura com dados. Primeiro zeramo-lo, e depois enchemo-lo. Veja - zeramos antes do laço. E depois, no laço, preenchemos a estrutura com dados.

Razão: