![Utilidad para la selección y navegación en MQL5 y MQL4: aumentando la informatividad de los gráficos](https://c.mql5.com/i/articles/overlay.png)
Utilidad para la selección y navegación en MQL5 y MQL4: aumentando la informatividad de los gráficos
Introducción
En los artículos anteriores (Utilidad para la selección y navegación en MQL5 y MQL4: añadiendo la búsqueda automática de patrones y visualización de símbolos encontrados, Utilidad para la selección y navegación en MQL5 y MQL4: añadiendo las pestañas de «recordatorios» y guardando objetos gráficos, Desarrollando una utilidad para la selección y navegación de instrumentos en los lenguajes MQL5 y MQL4) ya hicimos bastante sobre este asunto. Pero aún así, eso no es suficiente para una negociación intradía de calidad. Hoy, añadiremos una nueva funcionalidad que permitirá encontrar los puntos de entrada en la transacción, o los puntos de salida de ella.
Cada elemento de la nueva funcionalidad será descrito en un apartado separado del artículo. Primero, vamos a considerar, ¿para qué es necesario eso? Luego, se mostrará la función o el código que hace eso, para el caso si Usted quiere implementar lo mismo en sus proyectos.
Ocultar símbolos cuya tendencia actual se diferencia de la tendencia del día anterior
Parámetro de entrada: Ocultar si la tendencia de hoy != ayer
Área: Configuraciones de la filtración
Muchos gurús del trading recomiendan para la negociación intradía seleccionar sólo las acciones para las cuales la tendencia de hoy
coincide con la tendencia de ayer. Simplificando, si el precio de una acción crecía ayer, entonces, hoy también tiene que crecer.
Consecuentemente, el trading este día es posible sólo en Long, y viceversa.
Para filtrar esos símbolos, se usa la siguiente función:
/* Devuelve true si la tendencia de hoy no es igual a la de ayer symname - nombre del símbolo para la verificación */ bool check_no_trend(string symname){ MqlRates rates2[]; ArraySetAsSeries(rates2, true); if(CopyRates(symname, PERIOD_D1, 0, 2, rates2)==2){ if( rates2[0].close>rates2[0].open && rates2[1].close>rates2[1].open ){ return false; } if( rates2[0].close<rates2[0].open && rates2[1].close<rates2[1].open ){ return false; } } return true; }
Mostrar el inicio de la sesión
Parámetro de entrada: Mostrar el comienzo del día (en los períodos hasta el día)
Área: Configuraciones
de los gráficos
El comienzo de la sección de trading es el momento cuando se abren los mercados de acciones, si se trata de las acciones. Например, 16:30
para el mercado de acciones americano, 10:00 para el mercado europeo y ruso. Si se trata del mercado Forex, tomamos la medianoche como el
inicio de la sesión.
En los marcos temporales (timeframe) pequeños, por ejemplo M5, resulta difícil determinar inmediatamente el inicio de la sesión
actual. Por ejemplo, para ver rápidamente si una acción está subiendo o cayendo hoy. Por tanto, vamos a añadir una configuración que nos
permita ver inmediatamente a partir de qué barra ha comenzado el día de trading actual del instrumento.
Función para visualizar el inicio de la sesión:
/* Muestra el comienzo del día en el gráfico currChart - id del gráfico day - número del día (0 - actual) */ void showNdays(long currChart, int day){ MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(ChartSymbol(currChart), PERIOD_D1, day, 1, rates)>0){ ObjectCreate(currChart, exprefix+"_Nday", OBJ_VLINE, 0, rates[0].time, 0); ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_RAY,true); ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_BACK,true); } }
En el gráfico, eso se ve como una línea vertical roja:
Tal vez, alguien note que una funcionalidad semejante ya existe en MetaTrader. Además, se puede observar no sólo el inicio de la última sesión, sino también, en general, el inicio de cada sesión. Para eso, basta con marcar la casilla Mostrar separadores de períodos en las propiedades del gráfico. Pero, en la práctica, en algunas ocasiones y en determinados timeframes, esta funcionalidad es redundante y hace que el gráfico sea muy colorido e inconveniente para la lectura. Por ejemplo:
Mostrar Low y High del día de ayer y anteayer
Parámetro de entrada: Mostrar low y high del día de ayer y Mostrar low y high del día de anteayer
Área: Configuraciones de los gráficos
Al trabajar dentro del día, High y Low de ayer y anteayer son los niveles muy populares de soporte y resistencia. La situación cuando el precio baja, alcanza High de ayer/anteayer y rebota, tiene lugar muy a menudo. De acuerdo con mis propias observaciones, puedo decir que el precio en los casos de 70% o más no rompe High/Low desde la primera vez tanto ayer, como anteayer.
Por eso, nunca hay que despreciar estos niveles de soporte y resistencia.
Para mostrar Low y High del día seleccionado, se usa la siguiente función:
/* Mostrar Low y High del día especificado en el gráfico currChart - id del gráfico day - número del día mostrado */ void showHOBeforeDay(long currChart, int day=1){ MqlRates rates[]; ArraySetAsSeries(rates, true); color curColor=clrAquamarine; switch(day){ case 2: curColor=clrOlive; break; } if(CopyRates(ChartSymbol(currChart), PERIOD_D1, day, 1, rates)>0){ ObjectCreate(currChart, exprefix+"_beforeday_high_line"+(string) day, OBJ_HLINE, 0, 0, rates[0].high); ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_COLOR,curColor); ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_beforeday_low_line"+(string) day, OBJ_HLINE, 0, 0, rates[0].low); ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_COLOR,curColor); ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_BACK,true); } }
En el gráfico, Low y High de ayer se muestran con líneas horizontales claras, mientras que Low y High de anteayer, con líneas de color
glauco:
Mostrar precios redondos más cercanos
Parámetro de entrada: Mostrar precios redondos más cercanos (período < 1day)
Área: Configuraciones
de los gráficos
Otros niveles naturales de soporte/resistencia son los precios redondos. Es decir, son los precios de los instrumentos que se terminan en .00 o .50. Muchos traders a menudo buscan los segmentos planos cerca de los niveles redondos semejantes.
Los precios terminados en .25 y .75 también tienen las mismas propiedades. Pero ellos actúan como niveles con probabilidad menor, por
eso, no vamos a monitarearlos para no «embasurar» el gráfico.
Para mostrar los precios redondos, se usa la siguiente función:
/* Mostrar en el gráfico 3 niveles redondos más próximos al precio actual. currChart - id del gráfico */ void showRoundPrice(long currChart){ string name=ChartSymbol(currChart); int tmpPrice; MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(name, PERIOD_D1, 0, 1, rates)==1){ switch((int) SymbolInfoInteger(name, SYMBOL_DIGITS)){ case 0: break; case 2: case 3: case 5: tmpPrice=(int) rates[0].close; ObjectCreate(currChart, exprefix+"_round_line_00_0", OBJ_HLINE, 0, 0, (double) tmpPrice-1 ); ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_round_line_05_0", OBJ_HLINE, 0, 0, (double) tmpPrice-0.5 ); ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_round_line_00_1", OBJ_HLINE, 0, 0, (double) tmpPrice ); ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_round_line_05_1", OBJ_HLINE, 0, 0, (double) tmpPrice+0.5 ); ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_round_line_00_2", OBJ_HLINE, 0, 0, (double) tmpPrice+1 ); ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_round_line_05_2", OBJ_HLINE, 0, 0, (double) tmpPrice+1.5 ); ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_COLOR,clrCadetBlue); ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_BACK,true); break; } } }
En el gráfico, los niveles redondos se muestran con líneas horizontales punteadas:
Mostrar el cierre de la hora
Parámetro de entrada: Mostrar el cierre de la hora (período < 1hour)
Área: Configuraciones de los
gráficos
Continuando el tema de los niveles naturales de soporte/resistencia, se puede mencionar los niveles del cierre de la hora. Se considera que el precio de cierre de la hora también puede actuar como un nivel de soporte/resistencia en los timeframes más pequeños. La verdad es que no lo he notado en la práctica. No obstante, vamos a implementar la posibilidad de visualizar un modelo semejante por lo menos para las últimas 4 horas.
Función para destacar el cierre de la hora en el gráfico:
/* Mostrar el cierre de las últimas 4 horas en el gráfico currChart - id del gráfico */ void showCloseHour(long currChart){ MqlDateTime tmpTime; int tmpOffset=0; MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(ChartSymbol(currChart), PERIOD_M30, 0, 9, rates)>0){ tmpOffset=0; TimeToStruct(rates[tmpOffset].time, tmpTime); if(tmpTime.min!=0){ tmpOffset++; } ObjectCreate(currChart, exprefix+"_hour_0", OBJ_VLINE, 0, rates[tmpOffset].time, 0); ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_RAY,true); ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_COLOR,clrYellow); ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_BACK,true); tmpOffset++; TimeToStruct(rates[tmpOffset].time, tmpTime); if(tmpTime.min!=0){ tmpOffset++; } ObjectCreate(currChart, exprefix+"_hour_1", OBJ_VLINE, 0, rates[tmpOffset].time, 0); ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_RAY,true); ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_COLOR,clrYellow); ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_BACK,true); tmpOffset++; TimeToStruct(rates[tmpOffset].time, tmpTime); if(tmpTime.min!=0){ tmpOffset++; } ObjectCreate(currChart, exprefix+"_hour_2", OBJ_VLINE, 0, rates[tmpOffset].time, 0); ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_RAY,true); ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_COLOR,clrYellow); ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_BACK,true); tmpOffset++; TimeToStruct(rates[tmpOffset].time, tmpTime); if(tmpTime.min!=0){ tmpOffset++; } ObjectCreate(currChart, exprefix+"_hour_3", OBJ_VLINE, 0, rates[tmpOffset].time, 0); ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_RAY,true); ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_COLOR,clrYellow); ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_BACK,true); } }
En el gráfico, el cierre de las últimas 4 horas se muestra como las líneas verticales amarillas:
Mostrar el precio máximo y mínimo del año
Parámetro de entrada: Mostrar el precio máx./min. del año
Área: Configuraciones de los gráficos
Además, entre los traders son populares los precios máximos y mínimos. Vamos a mostrarlos en el gráfico.
Para mostrar los precios límite del año, se usa la siguiente función:
/* Mostrar el precio máximo y mínimo del último año en el gráfico. currChart - id del gráfico. */ void showMaxPrice(long currChart){ MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(ChartSymbol(currChart), PERIOD_MN1, 0, 12, rates)==12){ double maxPrice=0; double minPrice=0; for(int j=0; j<12; j++){ if( maxPrice==0 || maxPrice<rates[j].high ){ maxPrice=rates[j].high; } if( minPrice==0 || minPrice>rates[j].low ){ minPrice=rates[j].low; } } ObjectCreate(currChart, exprefix+"_maxprice_line", OBJ_HLINE, 0, 0, maxPrice); ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_COLOR,clrMagenta); ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_BACK,true); ObjectCreate(currChart, exprefix+"_minprice_line", OBJ_HLINE, 0, 0, minPrice); ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_COLOR,clrMagenta); ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_SELECTABLE,false); ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_BACK,true); } }
Los precios máximos/mínimos de los últimos 12 meses se muestran a través de las líneas horizontales de color violeta:
Mostrar spread al abrir el gráfico
Parámetro de entrada: Mostrar spread al abrir el gráfico
Área: Configuraciones de los gráficos
Si Usted negocia con los Stop los pequeños, el spread actual del instrumento para Ud. es uno de los factores clave para entrar en la transacción. Por eso, es importante saberlo de inmediato en el momento de la apertura del gráfico. Pues, vamos a aumentar la informatividad de nuestros gráficos.
Sólo hay que recordar que mostramos el spread exactamente en el momento de la apertura del gráfico. Tal vez, dentro de un rato el spread del
gráfico cambie. El nivel del spread no se muestra en tiempo real, sino se usa sólo para estimar el intervalo actual de los spreads del
instrumento.
El spread es devuelto por la siguiente pequeña función:
/* Devuelve la cadena con el spread actual para el símbolo especificado. symname - nombre del símbolo */ string getmespread_symbol(string symname){ double curSpread=SymbolInfoDouble(symname, SYMBOL_ASK)-SymbolInfoDouble(symname, SYMBOL_BID); return "Spread: "+(string) DoubleToString(curSpread, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+" ("+DoubleToString(curSpread/SymbolInfoDouble(symname, SYMBOL_POINT), 0)+" p)"; }
El spread se muestra en el comentario para el gráfico abierto, entre otra información adicional:
Aplicar una plantilla con el nombre al gráfico
Parámetro de entrada: Aplicar una plantilla con el nombre al gráfico
Área: Configuraciones de los
gráficos
Las plantillas en MetaTrader se usan para poder aplicar rápidamente las configuraciones preferidas, EAs al gráfico, y lo más importante para nosotros, los indicadores utilizados por Ud. con parámetros preferidos.
Pero «rápido» es un concepto elástico. Para aplicar la plantilla al gráfico, seleccione el elemento Plantilla / «Nombre de plantilla» en el menú contextual. ¿Pero qué pasa si algún indicador, por ejemplo, la media móvil, es importante para Ud. a la hora de tomar decisiones y desea verlo en cada gráfico que abre? Imagine que Ud. abre centenares de gráficos de varios instrumentos al día. ¿Entonces, debería hacer clic en cada uno ellos?
Sería mucho más fácil si se pudiera aplicar automáticamente una determinada plantilla con un conjunto de indicadores a cada gráfico a
abrir. Vamos a implementar este recurso.
Para aplicar una plantilla al gráfico, basta con usar el comando ChartApplyTemplate que funciona de la misma
manera tanto en MQL5, como en MQL4:
ChartApplyTemplate(curChartID[ArraySize(curChartID)-1], allApplyTemplate+".tpl");
Mostrar ATR según el método de Gerchik
Parámetro de entrada: Mostrar ATR según el método de Gerchik
Área: Configuraciones de los gráficos
ATR, o sea, el movimiento medio diario del instrumento durante un cierto período, es un importante parámetro en la determinación del rango de la acción del instrumento. Se usa para diferentes propósitos.
Por ejemplo, para decidir si merece la pena entrar en la transacción durante la transacción intradía. Si Ud. espera a hacer un movimiento de 100 puntos en el instrumento, y en media el instrumento recorre 50 puntos, sus posibilidades son pequeñas y es mejor abstenerse de negociar.
Además, se considera que si el instrumento ya ha pasado más de 80% de su ATR diario en una dirección, no tiene sentido abrir transacciones en la misma dirección y se puede trabajar sólo en la dirección opuesta.
ATR según el método de Gerching se diferencia de ATR habitual sólo en que no se toman en cuenta las barras paranormales. Es decir, las barras que son 2 veces más grandes que la media o 0,3 veces más pequeños en comparación con las barras medio estadísticas.
Generalmente, ATR se calcula durante 5 o 3 días.
La siguiente función se encarga de mostrar ATR según el método de Gerchik:
/* Devolver la cadena con ATR según Gerchik para el símbolo especializado: symname - nombre del símbolo */ string getmeatr_symbol(string symname){ string msg=""; MqlRates rates[]; ArraySetAsSeries(rates, true); double atr=0; double pre_atr=0; int curDigits=(int) SymbolInfoInteger(symname, SYMBOL_DIGITS); string currencyS=SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT); int count=0; int copied=CopyRates(symname, PERIOD_D1, 0, 8, rates); if(copied>1){ for(int j=1; j<copied; j++){ pre_atr+=rates[j].high-rates[j].low; } pre_atr/=(copied-1); } if(pre_atr>0){ for(int j=1; j<copied; j++){ if( rates[j].high-rates[j].low > pre_atr*2 ) continue; if( rates[j].high-rates[j].low < pre_atr*0.3 ) continue; if( ++count > 5 ){ break; } atr+=rates[j].high-rates[j].low; } if( count > 5 ){ count=5; } atr= NormalizeDouble(atr/count, curDigits ); } if(atr>0){ StringAdd(msg, "ATR: "+(string) DoubleToString(atr, curDigits)+" "+currencyS+", today: "+DoubleToString(rates[0].high-rates[0].low, curDigits)+" "+currencyS+" ("+(string) (int) (((rates[0].high-rates[0].low)/atr)*100) +"%)"); } return msg; }
Nuestra utilidad mustra ATR en el comentario para el gráfico, igual como el spread considerado en el apartado anterior. Así que se puede ver ATR en la captura de pantalla anterior.
Mostramos las direcciones de los símbolos guías
Parámetro de entrada: Mostrar las direcciones del símbolo #N
Área: Mostrar información
adicional
A juzgar por el material ya publicado en este artículo, la negociación intradía es una cosa bastante complicada, ya que es necesario tener en la mente y acompañar muchas cosas. Y como resulta, eso no es todo.
Muchos traders recomiendan observar la dirección actual de los llamados símbolos guías antes de negociar.
Por ejemplo, si Usted opera en el mercado de acciones de los EE.UU., es necesario monitorear:
- los principales índices americanos, por lo menos Dow Jones o SP500;
- uno de los índices de otros países: China, Europa, Japón;
- empresas con capitalización grande en diferentes sectores del mercado: JPMorgan en el sector bancario, Apple en tecnologías, ExxonMobil en energética, IBM y algunos otros.
Además, se puede monitorear el estado de las cotizaciones del petróleo, oro, dólar.
Sería mejor que todos los símbolos guías sigan la misma dirección. Como Ud. probablemente haya adivinado, es mejor negociar sólo en la dirección en la que van los símbolos guías.
Puesto que diferentes brókers tienen el mismo instrumento con nombre diferente, es imposible especificar programaticamente los
instrumentos a monitorear. Pero podemos añadir los parámetros de entrada del tipo string, en los cuales el mismo usuario
escribirá los tickets de los símbolos necesarios de tal amanera como se lleman en el lado del bróker. Para este propósito, han sido
añadidos 7 parámetros a la utilidad.
La dirección del símbolo especificado se devuelve por la siguiente función:
/* Devolver la cadena con la dirección del movimiento del precio para el símbolo especificado: symname - nombre del símbolo show - mostrar la etiqueta con el nombre del símbolo en la cadena */ string getmeinfo_symbol(string symname, bool show=true){ MqlRates rates2[]; ArraySetAsSeries(rates2, true); string msg=""; if(CopyRates(symname, PERIOD_D1, 0, 1, rates2)>0){ if(show){ StringAdd(msg, (string) symname+": "); } StringAdd(msg, "D1 "); if( rates2[0].close > rates2[0].open ){ StringAdd(msg, "+"+DoubleToString(((rates2[0].close-rates2[0].open)/rates2[0].close)*100, 2) +"% (+"+DoubleToString(rates2[0].close-rates2[0].open, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")"); }else{ if( rates2[0].close < rates2[0].open ){ StringAdd(msg, "-"+DoubleToString(((rates2[0].open-rates2[0].close)/rates2[0].close)*100, 2) +"% (-"+DoubleToString(rates2[0].open-rates2[0].close, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")"); }else{ StringAdd(msg, "0%"); } } } if(CopyRates(symname, PERIOD_H1, 0, 1, rates2)>0){ StringAdd(msg, ", H1 "); if( rates2[0].close > rates2[0].open ){ StringAdd(msg, "+"+DoubleToString(((rates2[0].close-rates2[0].open)/rates2[0].close)*100, 2)+"% (+"+DoubleToString(rates2[0].close-rates2[0].open, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")"); }else{ if( rates2[0].close < rates2[0].open ){ StringAdd(msg, "-"+DoubleToString(((rates2[0].open-rates2[0].close)/rates2[0].close)*100, 2)+"% (-"+DoubleToString(rates2[0].open-rates2[0].close, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")"); }else{ StringAdd(msg, "0%"); } } } return msg; }
Las direcciones se muestran en el comentario para el gráfico en el que se ejecuta la utilidad. El elemento tiene la siguiente
apariencia.
Nótese que la dirección del movimiento de los símbolos guías no se actualiza automáticamente. Para que la información sobre ellos se
actualice, es necesario ir a una de las pestañas deferente de la que está abierta en este moemento, o hacer clic en la tecla
R. Por otra parte, podemos simplificar eso usando un nuevo parámetro de entrada.
Actualización automática de las pestañas de la utilidad
Parámetro de entrada: Actualizar automáticamente la pestaña abierta cada, segundos
Área:Mostrar
información adicional
Si quiere que el contenido de la pestaña abierta en este momento se actualice automáticamente, y no sólo cuando se pulsa la tecla R,
entonces, simplemente especifique el número de segundos transcurridos los cuales la actualización debe realizarse. El valor de
este parámetro más de 0 informa a la utilidad que si ha pasado más del número de segundos especificado desde el momento de la
visualización de la pestaña, hay que actualizar esta pestaña. Es decir, eso no significa que la pestaña va a actualizarse
estrictamente cada N segundos. Lo más probable, eso significa que será actualizada aproximadamente dentro de N más uno o dos
segundos.
El código que implementa esta funcionalidad se encuentra dentro de la función OnTimer y es bastante simple:
// actualizar el contenido de la pestaña en segundos if( autoUpdateAfter>0 && TimeCurrent()-lastUpd >= autoUpdateAfter ){ start_symbols(); lastUpd=TimeCurrent(); }
Naturalmente, cuando la utilidad se inicia, inicializaremos el valor de la variable lastUpd con la hora
actual en la función
OnInit.
Mostrar la información financiera de la acción
Parámetro de entrada: Mostrar la información sobre la empresa
Área: Datos externos
Si Ud. sigue los indicadores fundamentales de la empresa antes de comprar o vender sus acciones, tal vez, haya soñado desde hace tiempo en que todos estos indicadores se visualicen directamente en la ventana de MetaTrader, para no tener que navegar por diferentes sitios web en busca de los indicadores de cada acción.
Vamos a intentar que eso sea así. Para no complicar mucho, visualizaremos los indicadores en la pestaña Asesores
Expertos del terminal inmediatamente después de que el gráfico de alguna acción haya sido abierto a través de nuestra
utilidad.
Los indicadores financieros no se sacarán de su caletre. Primero, quería «envolverlos» directamente en el EA, pero el error de la falta de la memoria impidió hacerme eso. Por tanto, todos los indicadores financieros se almacenan separadamente, en la carpeta finder adjunta al artículo. Para que esta funcionalidad opere, descargue el archivo comprimido con esta carpeta, descomprímelo y coloque la carpeta finder dentro de la carpeta Files de su terminal.
Para encontrar la carpeta Files, abra el menú Archivo en la ventana de MetaTrader, y haga clic en el
elemento
Abrir carpeta de datos. Después de eso, vaya a la carpeta MQL4 o MQL5 en la ventana del
navegador que se abre.
Estos indicadores financieros son relevantes en el momento de la escritura de este artículo y, tal vez, a lo largo de algunos meses
posteriores. Si en el futuro, necesitará los datos actuales, envíe un mensaje privado.
Pero volvamos a nuestra función de la salida de datos. Esta función limpia el ticket de la empresa de todo lo innecesario que su bróker puede añadir a él, a saber, del prefijo #, así como, de los sufijos .us y .eu que se añaden por algunos brókers. Si su broker añade otra cosa a su tiket, tendrá que añadir al código de la utilidad sus filtros que eliminan estos símbolos.
Si por el ticket no ha sido encontrada ninguna información necesaria en la carpeta finder, se realiza la
búsqueda por el nombre de la empresa.
void printTicker(string ticker, string name){ bool isYes=false; int filehandle; // limpiamos el ticket de los sufijos y prefijos sobrantes // también lo pasamos a las minúsculas StringToLower(ticker); StringReplace(ticker, "#", ""); StringReplace(ticker, ".us", ""); StringReplace(ticker, ".eu", ""); // pasamos el nombre de la empresa en las minúsculas StringToLower(name); ResetLastError(); // si la carpeta finder contiene la información sobre esta empresa, la mostramos if( FileIsExist("finder\\"+ticker+".dat") ){ isYes=true; filehandle=FileOpen("finder\\"+ticker+".dat",FILE_READ|FILE_TXT); if(filehandle!=INVALID_HANDLE){ int str_size; string str; Print("----------------"); while(!FileIsEnding(filehandle)){ str_size=FileReadInteger(filehandle,INT_VALUE); str=FileReadString(filehandle,str_size); Print(str); } FileClose(filehandle); } }else if( FileIsExist("finder\\"+name+".dat") ){ isYes=true; filehandle=FileOpen("finder\\"+name+".dat",FILE_READ|FILE_TXT); if(filehandle!=INVALID_HANDLE){ int str_size; string str; Print("----------------"); while(!FileIsEnding(filehandle)){ str_size=FileReadInteger(filehandle,INT_VALUE); str=FileReadString(filehandle,str_size); Print(str); } FileClose(filehandle); } } // en caso contrario, escribimos que la información no ha sido encontrada if(!isYes){ Print("No hay datos sobre el símbolo"); } }
Como resultado, al abrir el gráfico de cualquier acción con la ayuda de esta utilidad, la información sobre esta empresa se mostrará en la pestaña Asesor Experto. Aproximadamente, así:
Mostrar el beneficio de hoy
Parámetro de entrada: Mostrar el beneficio de hoy
Área: Mostrar información adicional
Finalmente, vamos a añadir un indicador al gráfico que nos permitirá parar a tiempo durante nuestra negociación diaria, es decir, el
número de ganancias o pérdidas obtenidas en un día, así como, el número total de transacciones por día, número de
transacciones rentables y no rentables (se muestra en el gráfico precisamente en este orden).
Para MQL4, se puede obtener el beneficio actual usando la función personalizada getmetoday_profit() cuyo código se muestra más abajo. Pero para MQL5, esta función no es suficiente.
En MQL5, primero, comprobamos si es necesario actualizar los datos sobre las posiciones cerradas. Para eso, se utiliza la
variable
needHistory declarada globalmente. En la función estándar OnInit(), a esta función se le asigna el
valor true. Por tanto, al ejecutar la función
getmetoday_profit() por primera vez, se carga adicionalmente la información sobre las transacciones desde el
historial. Después de eso, el valor de la variable
needHistory se hace igual a false.
A continuación, usamos la función estándar de MQL5 OnTrade() para cargar adicionalmente el historial de
las transacciones cada vez que cierre alguna posición abierta.
Como resultado, obtenemos el siguiente código:
#ifdef __MQL5__ void OnTrade(){ if(orders_total==PositionsTotal()){ return; } if(orders_total>PositionsTotal()){ needHistory=true; } orders_total=(ushort) PositionsTotal(); } #endif /* Devuelve la cadena con el tamaño de la ganancia/pérdida de hoy. */ string getmetoday_profit(){ string msg=""; double curProfit=0; int tradeAll=0; int tradeMinus=0; int tradePlus=0; MqlDateTime curD; TimeCurrent(curD); curD.hour=0; curD.min=0; curD.sec=0; #ifdef __MQL5__ if( needHistory ){ HistorySelect(StructToTime(curD),TimeCurrent()); } uint totalHistory=HistoryDealsTotal(); double currHistory=0; ulong ticket_history; for(uint j=0;j<totalHistory;j++){ if((ticket_history=HistoryDealGetTicket(j))>0 ){ double profitHistory=HistoryDealGetDouble(ticket_history,DEAL_PROFIT); profitHistory+=HistoryDealGetDouble(ticket_history,DEAL_COMMISSION); profitHistory+=HistoryDealGetDouble(ticket_history,DEAL_SWAP); if(profitHistory!=0){ currHistory+=profitHistory; } } } #else int cntMyPos=OrdersHistoryTotal(); if(cntMyPos>0){ for(int ti=cntMyPos-1; ti>=0; ti--){ if(OrderSelect(ti,SELECT_BY_POS,MODE_HISTORY)==false) continue; if( OrderCloseTime()<StructToTime(curD) ){ continue; } double tmpProfit=OrderProfit(); tmpProfit+=OrderSwap(); tmpProfit+=OrderCommission(); tradeAll++; if(tmpProfit>0){ tradePlus++; }else if(tmpProfit<0){ tradeMinus++; } curProfit+=tmpProfit; } } #endif if(tradeAll>0){ StringAdd(msg, "Today: "+DoubleToString(curProfit, 2)+" "+AccountInfoString(ACCOUNT_CURRENCY)+" ("+(string) tradeAll+";+"+(string) tradePlus+";-"+(string) tradeMinus+")"); } return msg; }
El beneficio también se muestra en el gráfico en el que se ejecuta la utilidad. Será así:
Nótese que el beneficio diario no se recalcula automáticamente. Para que la información sobre el beneficio actual se actualice, es necesario ir a una de las pestañas deferente de la que está abierta en este momento, o hacer clic en la tecla R.
Conclusiones
Probablemente, éste es el último artículo de esta serie. Espero que la utilidad resultante sea útil para Usted.
Pero si le falta alguna funcionalidad, escríbame de ello. Si estas dudas serán suficientes para un nuevo artículo, el desarrollo de la
utilidad continuará.
En conclusión, vamos a hacer un resumen y revisemos brevemente la funcionalidad que hemos implementado en este artículo.
Pues bien, después de iniciar la utilidad, veremos una lista de instrumentos que satisfacen nuestras condiciones. Por encima de esta lista,
veremos los botones de las pestañas:
All, LONG, SHORT, Range, así como, las pestañas de filtración automática. Por defecto, la pestaña All
está abierta:
Además, en el comentario para el gráfico, podemos observar una línea que comienza con la palabra update. Ahí se muestra la hora de la última actualización del contenido de la pestaña. Usted puede pulsar la tecla R para actualizar la pestaña actual manualmente. Adicionalmente, en los ajustes de la utilidad, se puede indicar la frecuencia en segundos, con la que el contenido de la pestaña actual abierta va a actualizarse.
Por cierto, sobre los ajustes de la utilidad. Si analizamos estos ajustes, será más simple comprender la funcionalidad de nuestra utilidad.
La lista de los instrumentos que se muestran en la pestaña All depende de los ajustes en el grupo Configuraciones de filtración:
Si hacemos clic en el botón de algún instrumento mostrado por la utilidad, verá el gráfico de este instrumento con la información adicional sobre él:
En primer lugar, son los botones de navegación que saltan a la vista en este gráfico. Puede usarlos para alternar los instrumentos filtrados por la utilidad. Además, utilice estos botones para añadir el instrumento a las pestañas «Recordatorios» ( LONG, SHORT, Range), o bien, eliminarlos de ahí.
También se puede notar que en el comentario para el gráfico ha sido insertada diversa información sobre el instrumento. Y desde luego, se puede
notar diferentes líneas horizontales trazadas en el gráfico.
La línea violeta indica en el máximo y mínimo del año.
La línea roja representa el nivel que he trazado antes manualmente. La utilidad puede guardar y recuperar todos los niveles trazados anteriormente en este instrumento.
Como ya ha sido dicho antes en este artículo, la línea de color glauco representa el precio de cierre/apertura del día anteayer. Mientras que la última línea mostrada en la captura de pantalla representa el precio del cierre/apertura del día de ayer.
Los ajustes del grupo Configuraciones de gráficos determinan las líneas y la información a mostrar en el gráfico:
El timeframe y la escala que se usa para visualizar los gráficos también es ejustable. Eso se hace por separado para la pestaña All, pestañas de Recordatorios y para algunas pestañas de filtración automática.
El timeframe para la pestaña All se ajusta en el grupo Mostrar información adicional:
Por defecto, para todos los botones de los instrumentos en la pestaña All se usa el timeframe D1. Por ejemplo, vamos a cambiarlo por M15:
Lo hemos hecho para ver más líneas en el gráfico que la utilidad puede mostrar, ya que estas líneas se muestran sólo en lo períodos de menos de 1
día.
La línea vertical roja muestra la barra del comienzo de la sesión actual, y permite determinar fácilmente de manera visual si el instrumento sube o baja hoy.
La línea horizontal punteada muestra los niveles redondos, es decir, los precios que se terminan en .00 o .50 para las cotizaciones de dos
dígitos. O como en nuestro caso, en 0.x1000 o 0.xx500 para las cotizaciones de 4 y 5 dígitos.
Pero volvamos a los ajustes. Las pestañas de la filtración automática también tienen sus ajustes. Los globales se encuentran en el grupo Pestañas adicionales. Además, para algunas pestañas hay grupos separados con los ajustes:
Los últimos grupos de ajustes: Abrir gráfico en ventana nueva y Datos externos.
Los ajustes del grupo Abrir gráfico en ventana nueva afectan el período y la escala de los gráficos que se abren al pulsar
el botón
New windows.
En suma, eso es todo. La funcionalidad completa de la utilidad ha sido discutida con más detalles en los artículos anteriores de esta serie.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/5614
![Web scraping de datos sobre la rentabilidad de los bonos](https://c.mql5.com/2/35/MQL5-avatar-web_scraping.png)
![Cómo escribir una biblioteca DLL para MQL5 en 10 minutos (Parte II): Escribiendo en el entorno de Visual Studio 2017](https://c.mql5.com/2/35/logo__2.png)
![Aplicando OLAP en el trading (parte 1): Fundamentos del análisis corriente de datos multidimensionales](https://c.mql5.com/2/36/OLAP_02.png)
![Estudio de técnicas de análisis de velas (Parte III): Biblioteca para el trabajo con patrones](https://c.mql5.com/2/35/Pattern_I__4.png)
![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso