ArrayMaximum

Procura o maior elemento na primeira dimensão de um array numérico multidimensional.

int  ArrayMaximum(
   const void&   array[],             // array para busca
   int           start=0,             // índice a partir do qual começa a verificação
   int           count=WHOLE_ARRAY    // número de elementos verificados
   );

Parâmetros

array[]

[in]  Um array númerico, na qual a busca é feita.

start=0

[in]  Índice a partir do qual começa a verificação.

count=WHOLE_ARRAY

[in]  Número de elementos para busca. Por padrão, busca no array inteiro (count=WHOLE_ARRAY)..

Valor do Retorno

A função retorna um índice de um elemento encontrado levando em consideração a série do array. Em caso de falha, retorna -1.

Observação

O valor da bandeira AS_SERIES É levado em consideração durante a procura de um máximo.

Funções ArrayMaximum e ArrayMinimum aceitam arrays multi-dimensionais como um parâmetro. No entanto, a pesquisa é sempre aplicada à primeira (zero) dimensão.

Exemplo:

#property description "O indicador mostra sobre as barras (candlesticks) um prazo de tempo maior do que o atual."
//--- configurações do indicador
#property indicator_chart_window
#property indicator_buffers 16
#property indicator_plots   8
//---- plot 1
#property indicator_label1  "BearBody"
#property indicator_color1  clrSeaGreen,clrSeaGreen
//---- plot 2
#property indicator_label2  "BearBodyEnd"
#property indicator_color2  clrSeaGreen,clrSeaGreen
//---- plot 3
#property indicator_label3  "BearShadow"
#property indicator_color3  clrSalmon,clrSalmon
//---- plot 4
#property indicator_label4  "BearShadowEnd"
#property indicator_color4  clrSalmon,clrSalmon
//---- plot 5
#property indicator_label5  "BullBody"
#property indicator_color5  clrOlive,clrOlive
//---- plot 6
#property indicator_label6  "BullBodyEnd"
#property indicator_color6  clrOlive,clrOlive
//---- plot 7
#property indicator_label7  "BullShadow"
#property indicator_color7  clrSkyBlue,clrSkyBlue
//---- plot 8
#property indicator_label8  "BullShadowEnd"
#property indicator_color8  clrSkyBlue,clrSkyBlue
//--- constante pré-definida
#define INDICATOR_EMPTY_VALUE 0.0
//--- parâmetros de entrada
input ENUM_TIMEFRAMES InpPeriod=PERIOD_H4;              // Prazo de tempo para calcular o indicador
input datetime        InpDateStart=D'2013.01.01 00:00'; // Analisar a partir desta data
//--- buffers do indicador para candlesticks de baixa
double   ExtBearBodyFirst[];
double   ExtBearBodySecond[];
double   ExtBearBodyEndFirst[];
double   ExtBearBodyEndSecond[];
double   ExtBearShadowFirst[];
double   ExtBearShadowSecond[];
double   ExtBearShadowEndFirst[];
double   ExtBearShadowEndSecond[];
//--- buffers do indicador para candlesticks de alta
double   ExtBullBodyFirst[];
double   ExtBullBodySecond[];
double   ExtBullBodyEndFirst[];
double   ExtBullBodyEndSecond[];
double   ExtBullShadowFirst[];
double   ExtBullShadowSecond[];
double   ExtBullShadowEndFirst[];
double   ExtBullShadowEndSecond[];
//--- variáveis globais
datetime ExtTimeBuff[];      // buffer de tempo para maior periodicidade
int      ExtSize=0;          // tamanho do buffer de tempo
int      ExtCount=0;         // índice dentro do buffer de tempo
int      ExtStartPos=0;      // posição inicial para cálculo do indicador
bool     ExtStartFlag=true;  // sinalizador auxiliar para receber a posição inicial
datetime ExtCurrentTime[1];  // último tempo na geração da barra de maior periodicidade
datetime ExtLastTime;        // último tempo a partir da barra de maior periodicidade, para a execução de cálculos
bool     ExtBearFlag=true;   // flag para definir a ordem de escrita do dados para os buffers de indicador de baixa
bool     ExtBullFlag=true;   // flag para definir a ordem de escrita do dados para os buffers de indicador de alta
int      ExtIndexMax=0;      // índice do elemento máximo do array
int      ExtIndexMin=0;      // índice do elemento mínimo do array
int      ExtDirectionFlag=0; // direção de movimento de preços para o atual candlestick
//--- alternar entre o preço de abertura e fechamento do candlestick para desenhar corretamente
const double ExtEmptyBodySize=0.2*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
//+------------------------------------------------------------------+
//| Preenchendo a parte básica do candlestick                        |
//+------------------------------------------------------------------+
void FillCandleMain(const double &open[],const double &close[],
                    const double &high[],const double &low[],
                    const int start,const int last,const int fill_index,
                    int &index_max,int &index_min)
  {
//--- encontrar o índice dos elementos máximo e mínimo nos arrays
   index_max=ArrayMaximum(high,ExtStartPos,last-start+1); // máximo em Alta
   index_min=ArrayMinimum(low,ExtStartPos,last-start+1);  // mínimo em Baixa
//--- definir quantas barras do período de tempo atual serão preenchidas
   int count=fill_index-start+1;
//--- se o preço de fechamento no primeiro bar é excede ao do último bar, o candlesticks é de baixa
   if(open[start]>close[last])
     {
      //--- antes que o candlestick seja de alta, limpar os valores de alta dos buffers do indicador
      if(ExtDirectionFlag!=-1)
         ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
      //--- candlestick de baixa
      ExtDirectionFlag=-1;
      //--- gerar o candlestick
      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
                     close[last],high[index_max],low[index_min],start,count,ExtBearFlag);
      //--- sair da função
      return;
     }
//--- se o preço de fechamento no primeiro bar é menor do que último bar, o candlesticks é de alta
   if(open[start]<close[last])
     {
      //--- antes que o candlestick seja de baixa, limpar os valores de baixa dos buffers do indicador
      if(ExtDirectionFlag!=1)
         ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,start,count);
      //--- candlesticks de alta
      ExtDirectionFlag=1;
      //--- gerar o candlestick
      FormCandleMain(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,close[last],
                     open[start],high[index_max],low[index_min],start,count,ExtBullFlag);
      //--- sair da função
      return;
     }
//--- se você está nesta parte da função, o preço de abertura no primeiro bar é igual ao
//--- preço de fechamento no último bar; então o candlestick é considerado de baixa
//--- antes que o candlestick seja de alta, limpar os valores de alta dos buffers do indicador
   if(ExtDirectionFlag!=-1)
      ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
//--- candlestick de baixa
   ExtDirectionFlag=-1;
//--- se os preços de fechamento e de abertura são iguais, use o deslocamento para a exibição correta
   if(high[index_max]!=low[index_min])
      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
                     open[start]-ExtEmptyBodySize,high[index_max],low[index_min],start,count,ExtBearFlag);
   else
      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,
                     open[start],open[start]-ExtEmptyBodySize,high[index_max],
                     high[index_max]-ExtEmptyBodySize,start,count,ExtBearFlag);
  }
//+------------------------------------------------------------------+
//| Preencher o final do candlestick                                 |
//+------------------------------------------------------------------+
void FillCandleEnd(const double &open[],const double &close[],
                   const double &high[],const double &low[],
                   const int start,const int last,const int fill_index,
                   const int index_max,const int index_min)
  {
//--- não desenhar em caso de uma única barra
   if(last-start==0)
      return;
//--- se o preço de fechamento no primeiro bar é excede ao do último bar, o candlesticks é de baixa
   if(open[start]>close[last])
     {
      //--- gerar o final do candelstick
      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,
                    open[start],close[last],high[index_max],low[index_min],fill_index,ExtBearFlag);
      //--- sair da função
      return;
     }
//--- se o preço de fechamento no primeiro bar é menor do que último bar, o candlesticks é de alta
   if(open[start]<close[last])
     {
      //--- gerar o final do candelstick
      FormCandleEnd(ExtBullBodyEndFirst,ExtBullBodyEndSecond,ExtBullShadowEndFirst,ExtBullShadowEndSecond,
                    close[last],open[start],high[index_max],low[index_min],fill_index,ExtBullFlag);
      //--- sair da função
      return;
     }
//--- se você está nesta parte da função, o preço de abertura no primeiro bar é igual ao
//--- preço de fechamento no último bar; então o candlestick é considerado de baixa
//--- gerar o final do candelstick
   if(high[index_max]!=low[index_min])
      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
                    open[start]-ExtEmptyBodySize,high[index_max],low[index_min],fill_index,ExtBearFlag);
   else
      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
                    open[start]-ExtEmptyBodySize,high[index_max],high[index_max]-ExtEmptyBodySize,fill_index,ExtBearFlag);
  }
//+------------------------------------------------------------------+
//| Função de inicialização do indicador customizado                 |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- verificar o período do indicador
   if(!CheckPeriod((int)Period(),(int)InpPeriod))
      return(INIT_PARAMETERS_INCORRECT);
//--- exibir dados de preço num primeiro plano
   ChartSetInteger(0,CHART_FOREGROUND,0,1);
//--- vincular buffers do indicador
   SetIndexBuffer(0,ExtBearBodyFirst);
   SetIndexBuffer(1,ExtBearBodySecond);
   SetIndexBuffer(2,ExtBearBodyEndFirst);
   SetIndexBuffer(3,ExtBearBodyEndSecond);
   SetIndexBuffer(4,ExtBearShadowFirst);
   SetIndexBuffer(5,ExtBearShadowSecond);
   SetIndexBuffer(6,ExtBearShadowEndFirst);
   SetIndexBuffer(7,ExtBearShadowEndSecond);
   SetIndexBuffer(8,ExtBullBodyFirst);
   SetIndexBuffer(9,ExtBullBodySecond);
   SetIndexBuffer(10,ExtBullBodyEndFirst);
   SetIndexBuffer(11,ExtBullBodyEndSecond);
   SetIndexBuffer(12,ExtBullShadowFirst);
   SetIndexBuffer(13,ExtBullShadowSecond);
   SetIndexBuffer(14,ExtBullShadowEndFirst);
   SetIndexBuffer(15,ExtBullShadowEndSecond);
//--- definir alguns valores de propriedade para a criação do indicador
   for(int i=0;i<8;i++)
     {
      PlotIndexSetInteger(i,PLOT_DRAW_TYPE,DRAW_FILLING); // tipo de construção gráfica
      PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); // estilo de linha de desenho
      PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1);           // largura de linha de desenho
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Função de iteração do indicador customizado                      |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- neste caso ainda não existe cálculos de barras
   if(prev_calculated==0)
     {
      //--- receber a maior periodicidade das barra no tempo de chegada
      if(!GetTimeData())
         return(0);
     }
//--- definir a indexação direta
   ArraySetAsSeries(time,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(close,false);
//--- iniciar variável para o cálculo das barras
   int start=prev_calculated;
//--- se uma barra é gerada, recalcular o valor do indicador sobre ela
   if(start!=0 && start==rates_total)
      start--;
//--- o loop para cálculos dos valores do indicador
   for(int i=start;i<rates_total;i++)
     {
      //--- preencher i elementos dos buffers do indicador por valores vazios
      FillIndicatorBuffers(i);
      //--- executar cálculos para as barras iniciando a partir dos dados InpDateStart
      if(time[i]>=InpDateStart)
        {
         //--- definir posição, a partir do qual os valores são exibidos pela primeira vez
         if(ExtStartFlag)
           {
            //--- armazenar o número do bar inicial
            ExtStartPos=i;
            //--- definir a primeira data a partir da maior periodicidade excedendo time[i]
            while(time[i]>=ExtTimeBuff[ExtCount])
               if(ExtCount<ExtSize-1)
                  ExtCount++;
            //--- alterar o valor da sinalização em ordem não executada neste bloco novamente
            ExtStartFlag=false;
           }
         //--- verificar se ainda existem quaisquer elementos no array
         if(ExtCount<ExtSize)
           {
            //--- esperar o valor da periodicidade atual para chegar a um maior período de tempo
            if(time[i]>=ExtTimeBuff[ExtCount])
              {
               //--- desenhar a parte principal do candlestick (sem preencher o espaço entre a última e a penúltima barra)
               FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin);
               //--- preencher o final do candlestick(a área entre a última e a penúltima barra)
               FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
               //--- deslocar a posição inicial para desenhar o próximo candlestick
               ExtStartPos=i;
               //--- aumentar o contador de array
               ExtCount++;
              }
            else
               continue;
           }
         else
           {
            //--- redefinir os valores de array
            ResetLastError();
            //--- receber a última data do maior período de tempo
            if(CopyTime(Symbol(),InpPeriod,0,1,ExtCurrentTime)==-1)
              {
               Print("Erro na cópia dos dados, código = ",GetLastError());
               return(0);
              }
            //--- se a nova data for posterior, parar de gerar o candlestick
            if(ExtCurrentTime[0]>ExtLastTime)
              {
               //--- limpar a área entre a última e a penúltima barra nos principais buffers do indicador
               ClearEndOfBodyMain(i-1);
               //--- preencher a área usando buffers auxiliares do indicador
               FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
               //--- deslocar a posição inicial para desenhar o próximo candlestick
               ExtStartPos=i;
               //--- restabelecer flag da direção do preço
               ExtDirectionFlag=0;
               //--- armazenar a nova última data
               ExtLastTime=ExtCurrentTime[0];
              }
            else
              {
               //--- gerar o candlestick
               FillCandleMain(open,close,high,low,ExtStartPos,i,i,ExtIndexMax,ExtIndexMin);
              }
           }
        }
     }
//--- valor retorno de prev_calculated para a próxima chamada
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Verificar a exatidão do período do indicador determinado         |
//+------------------------------------------------------------------+
bool CheckPeriod(int current_period,int high_period)
  {
//--- o período do indicador deve ultrapassar o período de tempo que é exibido sobre
   if(current_period>=high_period)
     {
      Print("Erro! O valor do período do indicador deve exceder o valor do intervalo do tempo atual!");
      return(false);
     }
//--- se o período do indicador é de uma semana ou um mês, o período está correto
   if(high_period>32768)
      return(true);
//--- converter valores do período para minutos
   if(high_period>30)
      high_period=(high_period-16384)*60;
   if(current_period>30)
      current_period=(current_period-16384)*60;
//--- o período do indicador deve ser múltiplo do período de tempo, é exibido sobre
   if(high_period%current_period!=0)
     {
      Print("Erro! O valor do período do indicador deve ser múltiplo ao valor do atual período de tempo!");
      return(false);
     }
//--- o período do indicador deve exceder o prazo de tempo quando apresentado de 3 ou mais vezes
   if(high_period/current_period<3)
     {
      Print("Erro! O período do indicador deve exceder o prazo atual de 3 ou mais vezes!");
      return(false);
     }
//--- O período do indicador é o correto para a atual periodicidade
   return(true);
  }
//+------------------------------------------------------------------+
//| Receber dados de tempo a partir da maior prazo de tempo          |
//+------------------------------------------------------------------+
bool GetTimeData(void)
  {
//--- redefine o valor de erro
   ResetLastError();
//--- copiar todos os dados para o tempo atual
   if(CopyTime(Symbol(),InpPeriod,InpDateStart,TimeCurrent(),ExtTimeBuff)==-1)
     {
      //--- receber o código de erro
      int code=GetLastError();
      //--- imprimir a mensagem de erro
      PrintFormat("Erro de cópia de dados! %s",code==4401
                  ? "Histórico ainda está sendo carregado!"
                  : "Código = "+IntegerToString(code));
      //--- retornar falso para fazer uma tentativa de repetir o download de dados
      return(false);
     }
//--- recebe o tamanho do array
   ExtSize=ArraySize(ExtTimeBuff);
//--- definir o índice do loop para o array zero
   ExtCount=0;
//--- definir a posição atual do candlestick no período de tempo para zero
   ExtStartPos=0;
   ExtStartFlag=true;
//--- armazenar o último valor de tempo a partir da maior periodicidade
   ExtLastTime=ExtTimeBuff[ExtSize-1];
//--- sucesso na execução
   return(true);
  }
//+------------------------------------------------------------------------------+
//| Função constitui a parte principal do candlestick. Dependendo do sinalizador |
//| valor, a função define quais dados e arrays serão                        |
//| usados para exibição correta.                                                |
//+------------------------------------------------------------------------------+
void FormCandleMain(double &body_fst[],double &body_snd[],
                    double &shadow_fst[],double &shadow_snd[],
                    const double fst_value,const double snd_value,
                    const double fst_extremum,const double snd_extremum,
                    const int start,const int count,const bool flag)
  {
//--- verificar o valor do flag
   if(flag)
     {
      //--- gerar o corpo do candlestick
      FormMain(body_fst,body_snd,fst_value,snd_value,start,count);
      //--- gerar a sombra do candlestick
      FormMain(shadow_fst,shadow_snd,fst_extremum,snd_extremum,start,count);
     }
   else
     {
      //--- gerar o corpo do candlestick
      FormMain(body_fst,body_snd,snd_value,fst_value,start,count);
      //--- gerar a sombra do candlestick
      FormMain(shadow_fst,shadow_snd,snd_extremum,fst_extremum,start,count);
     }
  }
//+-------------------------------------------------------------------------------+
//| A função para formar o final do candlestick. Depende do valor do sinalizador, |
//| a função define quais dados e arrays são                                      |
//| usados para exibição correta.                                                 |
//+-------------------------------------------------------------------------------+
void FormCandleEnd(double &body_fst[],double &body_snd[],
                   double &shadow_fst[],double &shadow_snd[],
                   const double fst_value,const double snd_value,
                   const double fst_extremum,const double snd_extremum,
                   const int end,bool &flag)
  {
//--- verificar o valor do flag
   if(flag)
     {
      //--- gerar o final do corpo do candlestick
      FormEnd(body_fst,body_snd,fst_value,snd_value,end);
      //--- gerar o final da sombra do candlestick
      FormEnd(shadow_fst,shadow_snd,fst_extremum,snd_extremum,end);
      //--- alterar o valor do sinalizador para o oposto
      flag=false;
     }
   else
     {
      //--- gerar o final do corpo do candlestick
      FormEnd(body_fst,body_snd,snd_value,fst_value,end);
      //--- gerar o final da sombra do candlestick
      FormEnd(shadow_fst,shadow_snd,snd_extremum,fst_extremum,end);
      //--- alterar o valor do sinalizador para o oposto
      flag=true;
     }
  }
//+---------------------------------------------------------------------------------+
//| Limpar o fim do candlestick (a área entre a última e a penúltima                |
//| barra)                                                                          |
//+---------------------------------------------------------------------------------+
void ClearEndOfBodyMain(const int ind)
  {
   ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,ind,1);
   ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,ind,1);
  }
//+--------------------------------------------------------------------------+
//| Limpar o candlestick                                                     |
//+--------------------------------------------------------------------------+
void ClearCandle(double &body_fst[],double &body_snd[],double &shadow_fst[],
                 double &shadow_snd[],const int start,const int count)
  {
//--- verificar
   if(count!=0)
     {
      //--- preencher buffers do indicador com valores vazios
      ArrayFill(body_fst,start,count,INDICATOR_EMPTY_VALUE);
      ArrayFill(body_snd,start,count,INDICATOR_EMPTY_VALUE);
      ArrayFill(shadow_fst,start,count,INDICATOR_EMPTY_VALUE);
      ArrayFill(shadow_snd,start,count,INDICATOR_EMPTY_VALUE);
     }
  }
//+--------------------------------------------------------------------------+
//| Gerar a parte principal do candlestick                                   |
//+--------------------------------------------------------------------------+
void FormMain(double &fst[],double &snd[],const double fst_value,
              const double snd_value,const int start,const int count)
  {
//--- verificar
   if(count!=0)
     {
      //--- preencher o buffer do indicador com valores
      ArrayFill(fst,start,count,fst_value);
      ArrayFill(snd,start,count,snd_value);
     }
  }
//+-----------------------------------------------------------------------------+
//| Gerar o final do candlestick                                                |
//+-----------------------------------------------------------------------------+
void FormEnd(double &fst[],double &snd[],const double fst_value,
             const double snd_value,const int last)
  {
//--- preencher o buffer do indicador com valores
   ArrayFill(fst,last-1,2,fst_value);
   ArrayFill(snd,last-1,2,snd_value);
  }
//+------------------------------------------------------------------+
//| Preencher i elemento dos buffers do indicador por valores vazios |
//+------------------------------------------------------------------+
void FillIndicatorBuffers(const int i)
  {
//--- definir um valor vazio na célula dos buffers do indicador
   ExtBearBodyFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBearBodySecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBearShadowFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBearShadowSecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBearBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBearBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBearShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBearShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBullBodyFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBullBodySecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBullShadowFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBullShadowSecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBullBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBullBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
   ExtBullShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
   ExtBullShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
  }