//+------------------------------------------------------------------+ //| Demo_iIchimoku.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 "El indicador demuestra cómo hay que obtener los datos" #property description "de los búfers indicadores para el indicador técnico iIchimoku." #property description "El símbolo y el período de tiempo en el que se calcula el indicador" #property description "se establecen mediante los parámetros symbol y period." #property description "El modo de crear el manejador (handle) se establece mediante el parámetro 'type' (tipo de función)." #property description "Todos los demás parámetros son iguales a los del Ichimoku Kinko Hyo estándar." #property indicator_chart_window #property indicator_buffers 5 #property indicator_plots 4 //--- construcción de Tenkan_sen #property indicator_label1 "Tenkan_sen" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- construcción de Kijun_sen #property indicator_label2 "Kijun_sen" #property indicator_type2 DRAW_LINE #property indicator_color2 clrBlue #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- construcción de Senkou_Span #property indicator_label3 "Senkou Span A;Senkou Span B" // en la Data Window se mostrarán dos campos #property indicator_type3 DRAW_FILLING #property indicator_color3 clrSandyBrown, clrThistle #property indicator_style3 STYLE_SOLID #property indicator_width3 1 //--- construcción de Chikou_Span #property indicator_label4 "Chinkou_Span" #property indicator_type4 DRAW_LINE #property indicator_color4 clrLime #property indicator_style4 STYLE_SOLID #property indicator_width4 1 //+------------------------------------------------------------------+ //| Enumeración de modos de crear el manejador | //+------------------------------------------------------------------+ enum Creation { Call_iIchimoku, // usar iIchimoku Call_IndicatorCreate // usar IndicatorCreate }; //--- parámetros de entrada input Creation type=Call_iIchimoku; // tipo de función input int tenkan_sen=9; // período de Tenkan-sen input int kijun_sen=26; // período de Kijun-sen input int senkou_span_b=52; // período de Senkou Span B input string symbol=" "; // símbolo input ENUM_TIMEFRAMES period=PERIOD_CURRENT; // período de tiempo //--- búfer indicador double Tenkan_sen_Buffer[]; double Kijun_sen_Buffer[]; double Senkou_Span_A_Buffer[]; double Senkou_Span_B_Buffer[]; double Chinkou_Span_Buffer[]; //--- variable para guardar el manejador del indicador iIchimoku int handle; //--- variable para guardar string name=symbol; //--- nombre del indicador en el gráfico string short_name; //--- vamos a guardar el número de los valores en el indicador Ichimoku Kinko Hyo int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- vinculación de los arrays a los búfers indicadores SetIndexBuffer(0,Tenkan_sen_Buffer,INDICATOR_DATA); SetIndexBuffer(1,Kijun_sen_Buffer,INDICATOR_DATA); SetIndexBuffer(2,Senkou_Span_A_Buffer,INDICATOR_DATA); SetIndexBuffer(3,Senkou_Span_B_Buffer,INDICATOR_DATA); SetIndexBuffer(4,Chinkou_Span_Buffer,INDICATOR_DATA); //--- estableceremos el desplazamiento para el canal Senkou Span a kijun_sen barras en la dirección del futuro PlotIndexSetInteger(2,PLOT_SHIFT,kijun_sen); //--- no hace falta establecer el desplazamiento para la línea Chikou Span, porque los datos de Chinkou Span //--- se guardan en el indicador iIchimoku con un desplazamiento ya fijado //--- determinamos el símbolo para el que se construye el indicador name=symbol; //--- eliminaremos los espacios del lado izquierdo y derecho StringTrimRight(name); StringTrimLeft(name); //--- si después de eso la longitud de la cadena name obtiene el valor cero, if(StringLen(name)==0) { //--- cogeremos el símbolo del gráfico en el que está iniciado el indicador name=_Symbol; } //--- crearemos el manejador del indicador if(type==Call_iIchimoku) handle=iIchimoku(name,period,tenkan_sen,kijun_sen,senkou_span_b); else { //--- llenaremos la estructura con los valores de los parámetros del indicador MqlParam pars[3]; //--- períodos y desplazamientos de las líneas del Alligator pars[0].type=TYPE_INT; pars[0].integer_value=tenkan_sen; pars[1].type=TYPE_INT; pars[1].integer_value=kijun_sen; pars[2].type=TYPE_INT; pars[2].integer_value=senkou_span_b; //--- crearemos el manejador handle=IndicatorCreate(name,period,IND_ICHIMOKU,3,pars); } //--- si no se puede crear el manejador if(handle==INVALID_HANDLE) { //--- avisaremos sobre el fallo y mostraremos el número del error PrintFormat("Fallo al crear el manejador del indicador iIchimoku para el par %s/%s, código del error %d", name, EnumToString(period), GetLastError()); //--- el trabajo del indicador se finaliza anticipadamente return(INIT_FAILED); } //--- mostraremos sobre qué par símbolo/período ha sido calculado el indicador Ichimoku Kinko Hyo short_name=StringFormat("iIchimoku(%s/%s, %d, %d ,%d)",name,EnumToString(period), tenkan_sen,kijun_sen,senkou_span_b); IndicatorSetString(INDICATOR_SHORTNAME,short_name); //--- inicialización correcta del indicador return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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 desde el indicador iIchimoku int values_to_copy; //--- vamos a averiguar el número de valores calculados en el indicador int calculated=BarsCalculated(handle); if(calculated<=0) { PrintFormat("BarsCalculated() ha devuelto %d, el código del error %d",calculated,GetLastError()); return(0); } //--- si se trata de la primera inicialización de la calculación de nuestro indicador o se ha cambiado el número de valores en el indicador iIchimoku //--- o si es necesario calcular el indicador para dos o más barras (entonces algo se ha cambiado en el historial) if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) { //--- si el array Tenkan_sen_Buffer supera el número de valores en el indicador iIchimoku sobre el par symbol/period, entonces no copiamos todo //--- en caso contrario, copiaremos menos que el tamaño de los búfers indicadores if(calculated>rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { //--- significa que no es la primera vez que se calcula nuestro indicador y desde el momento de la primera llamada de OnCalculate()) //--- se ha añadido no más de una barra para la calculación values_to_copy=(rates_total-prev_calculated)+1; } //--- llenamos los arrays con los valores desde el indicador Ichimoku Kinko Hyo //--- si FillArraysFromBuffer ha devuelto false, significa que los datos aún no están listos - entonces finalizamos el proceso if(!FillArraysFromBuffers(Tenkan_sen_Buffer,Kijun_sen_Buffer,Senkou_Span_A_Buffer,Senkou_Span_B_Buffer,Chinkou_Span_Buffer, kijun_sen,handle,values_to_copy)) return(0); //--- creamos el mensaje string comm=StringFormat("%s ==> Actualizados los valores en el indicador %s: %d", TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS), short_name, values_to_copy); //--- mostraremos en el gráfico un mensaje de servicio Comment(comm); //--- recordaremos el número de valores en el indicador Ichimoku Kinko Hyo bars_calculated=calculated; //--- devolveremos el valor prev_calculated para la siguiente llamada return(rates_total); } //+------------------------------------------------------------------+ //| Llenamos los búfers indicadores desde el indicador iIchimoku | //+------------------------------------------------------------------+ bool FillArraysFromBuffers(double &tenkan_sen_buffer[], // búfer indicador de la línea Tenkan-sen double &kijun_sen_buffer[], // búfer indicador de la línea Kijun_sen double &senkou_span_A_buffer[], // búfer indicador de la línea Senkou Span A double &senkou_span_B_buffer[], // búfer indicador de la línea Senkou Span B double &chinkou_span_buffer[], // búfer indicador Chinkou Span int senkou_span_shift, // desplazamiento de la línea Senkou Span al futuro int ind_handle, // manejador del indicador iIchimoku int amount // número de valores a copiar ) { //--- actualizaremos el código del error ResetLastError(); //--- llenamos una parte del array Tenkan_sen_Buffer con los valores desde el búfer indicador con el índice 0 if(CopyBuffer(ind_handle,0,0,amount,tenkan_sen_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("1.Fallo al copiar los datos desde el indicador iGator, código del error %d",GetLastError()); //--- finalizaremos con el resultado nulo - eso quiere decir que el indicador será considerado como no calculado return(false); } //--- llenamos una parte del array Kijun_sen_Buffer con los valores desde el búfer indicador con el índice 1 if(CopyBuffer(ind_handle,1,0,amount,kijun_sen_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("2.Fallo al copiar los datos desde el indicador iGator, código del error %d",GetLastError()); //--- finalizaremos con el resultado nulo - eso quiere decir que el indicador será considerado como no calculado return(false); } //--- llenamos una parte del array Chinkou_Span_Buffer con los valores desde el búfer indicador con el índice 2 //--- si senkou_span_shift>0 la línea se desplaza hacia el futuro a senkou_span_shift barras if(CopyBuffer(ind_handle,2,-senkou_span_shift,amount,senkou_span_A_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("3.Fallo al copiar los datos desde el indicador iGator, código del error %d",GetLastError()); //--- finalizaremos con el resultado nulo - eso quiere decir que el indicador será considerado como no calculado return(false); } //--- llenamos una parte del array Senkou_Span_A_Buffer con los valores desde el búfer indicador con el índice 3 //--- si senkou_span_shift>0 la línea se desplaza hacia el futuro a senkou_span_shift barras if(CopyBuffer(ind_handle,3,-senkou_span_shift,amount,senkou_span_B_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("4.Fallo al copiar los datos desde el indicador iGator, código del error %d",GetLastError()); //--- finalizaremos con el resultado nulo - eso quiere decir que el indicador será considerado como no calculado return(false); } //--- llenamos una parte del array Senkou_Span_B_Buffer con los valores desde el búfer indicador con el índice 4 //--- cuando copiamos Chinkou Span no hace falta considerar el desplazamiento porque los datos de Chinkou Span //--- se guardan en el indicador iIchimoku con un desplazamiento ya fijado if(CopyBuffer(ind_handle,4,0,amount,chinkou_span_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("5.Fallo al copiar los datos desde el indicador iGator, código del error %d",GetLastError()); //--- finalizaremos con el resultado nulo - eso quiere decir que el indicador será considerado como no calculado return(false); } //--- todo ha salido bien return(true); } //+------------------------------------------------------------------+ //| Indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(handle!=INVALID_HANDLE) IndicatorRelease(handle); //--- limpiaremos el gráfico tras eliminar el indicador Comment(""); } |