//+------------------------------------------------------------------+ //| Demo_iEnvelopes.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 iEnvelopes." #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 indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 //--- construcción de Upper #property indicator_label1 "Upper" #property indicator_type1 DRAW_LINE #property indicator_color1 clrBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- construcción de Lower #property indicator_label2 "Lower" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //+------------------------------------------------------------------+ //| Enumeración de modos de crear el manejador | //+------------------------------------------------------------------+ enum Creation { Call_iEnvelopes, // usar iEnvelopes Call_IndicatorCreate // usar IndicatorCreate }; //--- parámetros de entrada input Creation type=Call_iEnvelopes; // tipo de función input int ma_period=14; // período de la media móvil input int ma_shift=0; // desplazamiento input ENUM_MA_METHOD ma_method=MODE_SMA; // tipo de suavizado input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE; // tipo de precio input double deviation=0.1; // desviación de los márgenes de la media móvil input string symbol=" "; // símbolo input ENUM_TIMEFRAMES period=PERIOD_CURRENT; // período de tiempo //--- búfer indicador double UpperBuffer[]; double LowerBuffer[]; //--- variable para guardar el manejador del indicador iEnvelopes 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 Envelopes int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- vinculación de los arrays a los búfers indicadores SetIndexBuffer(0,UpperBuffer,INDICATOR_DATA); SetIndexBuffer(1,LowerBuffer,INDICATOR_DATA); //--- estableceremos el desplazamiento para cada línea PlotIndexSetInteger(0,PLOT_SHIFT,ma_shift); PlotIndexSetInteger(1,PLOT_SHIFT,ma_shift); //--- 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_iEnvelopes) handle=iEnvelopes(name,period,ma_period,ma_shift,ma_method,applied_price,deviation); else { //--- llenaremos la estructura con los valores de los parámetros del indicador MqlParam pars[5]; //--- período de la media móvil pars[0].type=TYPE_INT; pars[0].integer_value=ma_period; //--- desplazamiento pars[1].type=TYPE_INT; pars[1].integer_value=ma_shift; //--- tipo de suavizado pars[2].type=TYPE_INT; pars[2].integer_value=ma_method; //--- tipo de precio pars[3].type=TYPE_INT; pars[3].integer_value=applied_price; //--- tipo de precio pars[4].type=TYPE_DOUBLE; pars[4].double_value=deviation; handle=IndicatorCreate(name,period,IND_ENVELOPES,5,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 iEnvelopes 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 a base de qué par símbolo/período ha sido calculado el indicador Envelopes short_name=StringFormat("iEnvelopes(%s/%s, %d, %d, %s,%s, %G)",name,EnumToString(period), ma_period,ma_shift,EnumToString(ma_method),EnumToString(applied_price),deviation); 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 iEnvelopes 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 iEnvelopes, //--- 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 UpperBuffer supera el número de valores en el indicador iEnvelopes para 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 UpperBuffer y LowerBuffer con los valores desde el indicador Envelopes //--- si FillArrayFromBuffer ha devuelto false, significa que los datos no están listos - entonces finalizamos el trabajo if(!FillArraysFromBuffers(UpperBuffer,LowerBuffer,ma_shift,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 Envelopes bars_calculated=calculated; //--- devolveremos el valor prev_calculated para la siguiente llamada return(rates_total); } //+------------------------------------------------------------------+ //| Llenamos los búfers indicadores desde el indicador iEnvelopes | //+------------------------------------------------------------------+ bool FillArraysFromBuffers(double &upper_values[], // búfer indicador del borde superior double &lower_values[], // búfer indicador del borde inferior int shift, // desplazamiento int ind_handle, // manejador del indicador iEnvelopes int amount // número de valores a copiar ) { //--- actualizaremos el código del error ResetLastError(); //--- llenamos una parte del array UpperBuffer con los valores desde el búfer indicador con el índice 0 if(CopyBuffer(ind_handle,0,-shift,amount,upper_values)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("Fallo al copiar los datos desde el indicador iEnvelopes, 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 LowerBuffer con los valores desde el búfer indicador con el índice 1 if(CopyBuffer(ind_handle,1,-shift,amount,lower_values)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("Fallo al copiar los datos desde el indicador iEnvelopes, 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(""); } |