//+------------------------------------------------------------------+ //| Demo_iStdDev.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 iStdDev." #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 Standard Deviation." #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 //--- construcción de iStdDev #property indicator_label1 "iStdDev" #property indicator_type1 DRAW_LINE #property indicator_color1 clrMediumSeaGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //+------------------------------------------------------------------+ //| Enumeración de modos de crear el manejador | //+------------------------------------------------------------------+ enum Creation { Call_iStdDev, // usar iStdDev Call_IndicatorCreate // usar IndicatorCreate }; //--- parámetros de entrada input Creation type=Call_iStdDev; // tipo de función input int ma_period=20; // período promedio 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 string symbol=" "; // símbolo input ENUM_TIMEFRAMES period=PERIOD_CURRENT; // período de tiempo //--- búfer indicador double iStdDevBuffer[]; //--- variable para guardar el manejador del indicador iStdDev 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 Standard Deviation int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- vinculación del array al búfer indicador SetIndexBuffer(0,iStdDevBuffer,INDICATOR_DATA); //--- fijaremos el desplazamiento PlotIndexSetInteger(0,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_iStdDev) handle=iStdDev(name,period,ma_period,ma_shift,ma_method,applied_price); else { //--- llenaremos la estructura con los valores de los parámetros del indicador MqlParam pars[4]; //--- período 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; handle=IndicatorCreate(name,period,IND_STDDEV,4,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 iStdDev 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 Standard Deviation short_name=StringFormat("iStdDev(%s/%s, %d, %d, %s, %s)",name,EnumToString(period), ma_period,ma_shift,EnumToString(ma_method),EnumToString(applied_price)); 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 iStdDev 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 del primer arranque del proceso de calculación de nuestro indicador o se ha cambiado el número de valores en el indicador iStdDev //--- 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 iStdDevBuffer supera el número de valores en el indicador iStdDev 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 el array con los valores desde el indicador Standard Deviation //--- si FillArrayFromBuffer ha devuelto false, significa que los datos no están listos - entonces finalizamos el trabajo if(!FillArrayFromBuffer(iStdDevBuffer,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 Standard Deviation bars_calculated=calculated; //--- devolveremos el valor prev_calculated para la siguiente llamada return(rates_total); } //+------------------------------------------------------------------+ //| Llenamos el búfer indicador desde el indicador iStdDev | //+------------------------------------------------------------------+ bool FillArrayFromBuffer(double &std_buffer[], // búfer indicador de la línea Standard Deviation int std_shift, // desplazamiento de la línea Standard Deviation int ind_handle, // manejador del indicador iStdDev int amount // número de valores a copiar ) { //--- actualizaremos el código del error ResetLastError(); //--- llenamos una parte del array iStdDevBuffer con los valores desde el búfer indicador con el índice 0 if(CopyBuffer(ind_handle,0,-std_shift,amount,std_buffer)<0) { //--- si el proceso de copiado ha fallado, comunicaremos el código del error PrintFormat("Fallo al copiar los datos desde el indicador iStdDev, 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(""); } |