//+------------------------------------------------------------------+ //| Demo_iMACD.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| ;https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property description "O indicador demonstra como obter dados" #property description "de buffers do indicador para o indicador técnico iMACD." #property description "Um símbolo e o prazo utilizado para o cálculo do indicador," #property description "são definidos pelos parâmetros de símbolo e período." #property description "O método de criação do manipulador é definido através do parâmetro "type" (tipo de função)." #property description "Todos os outros parâmetros, assim como no padrão MACD." #property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 //--- plotar MACD #property indicator_label1 "MACD" #property indicator_type1 DRAW_HISTOGRAM #property indicator_color1 clrSilver #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- plotar Signal #property indicator_label2 "Signal" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed #property indicator_style2 STYLE_DOT #property indicator_width2 1 //+------------------------------------------------------------------+ //| Enumerador dos métodos de criação do manipulador | //+------------------------------------------------------------------+ enum Creation { Call_iMACD, // usar iMACD Call_IndicatorCreate // usar IndicatorCreate }; //--- parâmetros de entrada input Creation type=Call_iMACD; // tipo de função input int fast_ema_period=12; // período da Média Móvel Rápida input int slow_ema_period=26; // período da Média Móvel Lenta input int signal_period=9; // período da diferença entre as médias móveis input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE; // tipo de preço input string symbol=" "; // símbolo input ENUM_TIMEFRAMES period=PERIOD_CURRENT; // timeframe //--- buffers do indicador double MACDBuffer[]; double SignalBuffer[]; //--- variável para armazenar o manipulador do indicator iMACD int handle; //--- variável para armazenamento string name=symbol; //--- nome do indicador num gráfico string short_name; //--- manteremos o número de valores no indicador Moving Averages Convergence/Divergence int bars_calculated=0; //+------------------------------------------------------------------+ //| Função de inicialização do indicador customizado | //+------------------------------------------------------------------+ int OnInit() { //--- atribuição de arrays para buffers do indicador SetIndexBuffer(0,MACDBuffer,INDICATOR_DATA); SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); //--- determinar o símbolo do indicador, é desenhado para name=symbol; //--- excluir os espaços à direita e à esquerda StringTrimRight(name); StringTrimLeft(name); //--- se resulta em comprimento zero da string do 'name' if(StringLen(name)==0) { //--- tomar o símbolo do gráfico, o indicador está anexado para name=_Symbol; } //--- criar manipulador do indicador if(type==Call_iMACD) handle=iMACD(name,period,fast_ema_period,slow_ema_period,signal_period,applied_price); else { //--- preencher a estrutura com os parâmetros do indicador MqlParam pars[4]; //--- período da média móvel rápida pars[0].type=TYPE_INT; pars[0].integer_value=fast_ema_period; //--- período lento da média móvel pars[1].type=TYPE_INT; pars[1].integer_value=slow_ema_period; //--- período médio da diferença entre a média móvel rápida e a lenta pars[2].type=TYPE_INT; pars[2].integer_value=signal_period; //--- tipo de preço pars[3].type=TYPE_INT; pars[3].integer_value=applied_price; handle=IndicatorCreate(name,period,IND_MACD,4,pars); } //--- se o manipulador não é criado if(handle==INVALID_HANDLE) { //--- mensagem sobre a falha e a saída do código de erro PrintFormat("Falha ao criar o manipulador do indicador iMACD para o símbolo %s/%s, código de erro %d", name, EnumToString(period), GetLastError()); //--- o indicador é interrompido precocemente return(INIT_FAILED); } //--- mostra que o símbolo/prazo do indicador Moving Average Convergence/Divergence é calculado para short_name=StringFormat("iMACD(%s/%s,%d,%d,%d,%s)",name,EnumToString(period), fast_ema_period,slow_ema_period,signal_period,EnumToString(applied_price)); IndicatorSetString(INDICATOR_SHORTNAME,short_name); //--- inicialização normal do indicador 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[]) { //--- número de valores copiados a partir do indicador iMACD int values_to_copy; //--- determinar o número de valores calculados no indicador int calculated=BarsCalculated(handle); if(calculated<=0) { PrintFormat("BarsCalculated() retornando %d, código de erro %d",calculated,GetLastError()); return(0); } //--- se for o princípio do cálculo do indicador, ou se o número de valores é modificado no indicador iMACD //--- ou se é necessário cálculo do indicador para duas ou mais barras (isso significa que algo mudou no histórico do preço) if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) { //--- se o array MACDBuffer é maior do que o número de valores no indicador iMACD para o símbolo/período, então não copiamos tudo //--- caso contrário, copiamos menor do que o tamanho dos buffers do indicador if(calculated>rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { //--- isso significa que não é a primeira vez do cálculo do indicador, é desde a última chamada de OnCalculate()) //--- para o cálculo não mais do que uma barra é adicionada values_to_copy=(rates_total-prev_calculated)+1; } //--- preencher os arrays com valores do indicador iMACD //--- se FillArraysFromBuffer retorna falso, isto significa que a informação ainda não está pronta, sair da operação if(!FillArraysFromBuffers(MACDBuffer,SignalBuffer,handle,values_to_copy)) return(0); //--- formar a mensagem string comm=StringFormat("%s ==> Valor atualizado no indicador %s: %d", TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS), short_name, values_to_copy); //--- exibir a mensagem de serviço no gráfico Comment(comm); //--- memorizar o número de valores no indicador Moving Averages Convergence/Divergence bars_calculated=calculated; //--- retorna o valor prev_calculated para a próxima chamada return(rates_total); } //+------------------------------------------------------------------+ //| Preencher buffers do indicador a partir do indicador iMACD | //+------------------------------------------------------------------+ bool FillArraysFromBuffers(double &macd_buffer[], // buffer do indicator para valores de MACD double &signal_buffer[], // buffer do indicator da linha de sinal do indicador MACD int ind_handle, // manipulador do indicador iMACD int amount // número de valores copiados ) { //--- redefinir o código de erro ResetLastError(); //--- preencher uma parte do array iMACDBuffer com valores do buffer do indicador que tem índice 0 (zero) if(CopyBuffer(ind_handle,0,0,amount,macd_buffer)<0) { //--- Se a cópia falhar, informe o código de erro PrintFormat("Falha ao copiar dados do indicador iMACD, código de erro %d",GetLastError()); //--- parar com resultado zero - significa que indicador é considerado como não calculado return(false); } //--- preencher uma parte do array SignalBuffer com valores do buffer do indicador que tem índice 1(um) if(CopyBuffer(ind_handle,1,0,amount,signal_buffer)<0) { //--- Se a cópia falhar, informe o código de erro PrintFormat("Falha ao copiar dados do indicador iMACD, código de erro %d",GetLastError()); //--- parar com resultado zero - significa que indicador é considerado como não calculado return(false); } //--- está tudo bem return(true); } //+------------------------------------------------------------------+ //| Função de desinicialização do indicador | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(handle!=INVALID_HANDLE) IndicatorRelease(handle); //--- limpar o gráfico após excluir o indicador Comment(""); } |