
Análisis de spread Bid/Ask en MetaTrader 5
Introducción
Si usted no usa órdenes Limit o Stop tanto para la entrada como para la salida, entonces usará las órdenes de mercado y, por supuesto, estas dependen del tamaño del spread Bid/Ask para determinar los precios que obtenemos.
Cuando presionamos el botón de compra, en realidad compramos al precio ASK, que supone un tamaño de margen superior al precio bid que probablemente utilizamos para decidirnos a comprar.
Al presionar el botón de venta, en realidad vendemos al precio BID, que supone un tamaño de margen inferior al precio ask.
Por supuesto, cuando presionamos el botón de cierre para cerrar una posición que habíamos comprado anteriormente, en realidad estamos vendiendo al precio BID actual.
Y lo contrario es cierto, cuando presionamos el botón de cierre para cerrar una posición que previamente habíamos acortado, en realidad estamos comprando o cubriendo al precio ASK actual.
Ahora podremos usar los datos de ticks de MetaTrader 5 para analizar cuál ha sido realmente el promedio histórico real del spread Bid/Ask reciente.
No deberíamos necesitar mirar el spread actual, porque está disponible si mostramos las líneas de precio Bid/Ask.
Veamos por qué y cómo
Al mirar estos gráficos, podemos ver que este bróker dice que la mayoría de los spreads son de 5 puntos.
Si ese fuera el caso, el proceso completo de apertura y cierre de una transacción debería costarle a usted 1 pip.
Por consiguiente, para una transacción con una ratio de riesgo-recompensa de 1/1 con un Stop Loss de 10 pips y un Take Profit de 10 pips, debería costarle el 10% de su riesgo/apuesta.
Este tipo de margen es bastante justo; por ejemplo, el total de un libro de apuestas es típicamente del 15%, el margen de beneficio de los casinos es de alrededor del 4%.
Pero, los spreads promedio reales (la línea roja), en comparación con el margen documentado de los brókeres (línea discontinua negra), son en su mayoría dos veces más grandes que el margen declarado, como lo confirma la ventana de datos a continuación. Usando el ejemplo anterior con el mismo SL y TP, vemos que el coste para usted es normalmente de al menos 2 pips o un 20%.
Si es usted un scalper a menor escala, y usa, por ejemplo, un SL de 5 pips y un TP de 5 pips, o si decide salir antes de que se alcancen los ejemplos anteriores, de 10 pips de SL o TP, digamos, con una pérdida de 5 pips, entonces el coste supondrá los mismos 2 pips, pero como ha jugado seguro después de que la transacción comenzara a ir en su contra, el coste porcentual será ahora del 40% de su apuesta/riesgo.
Cuando era un tráder novato, comencé usando 5 pips de S/l y 10 pips de T/P para una relación riesgo/recompensa de 2:1, (como sospecho que hacen muchos tráders nuevos). No tenía mucho éxito, por cierto.
Así que hice un análisis profundo del gráfico EURUSD M1 con un indicador Zig Zag fiable. Lo puse en 5 pips como tamaño mínimo del lado, lo cual significaba para mí un tipo de retroceso con el que podría lidiar.
Los resultados parecen sugerir que la mayoría de los cambios pequeños fueron de alrededor de 7 pips y los lados de 10 pips fueron relativamente raros en comparación. Por supuesto, permití el uso de noticias y los mercados volátiles, por lo que los resultados fueron principalmente de periodos promedio únicamente de las sesiones comerciales.
Entonces, en consecuencia, comencé a usar un stop loss de 10 pips y dejé abierto el take profit, para poder monitorear la transacción de cerca y decidir cuándo salir si esta ya había alcanzado unas pérdidas o ganancias de 7 pips. Esto redundó en una mejora, pero, aún así, me quedé sin beneficios. Solo entonces me di cuenta de los altos spreads Bid/Ask contra los que estaba comerciando con ese bróker, así que, obviamente, busqué un bróker mejor.
Si comerciamos cuando surgen noticias o el mercado se vuelve volátil, podremos ver que el spread promedio real sube a alrededor de 15 puntos o 3 veces los 5 puntos estándar, por lo que deberemos pagar 3 pips o el 60% de nuestra apuesta.
Ni siquiera debemos considerar comerciar después de las 20:30 hora del Reino Unido (21:30 hora del servidor de gráficos), porque podría ser 4, 5, 6 veces mayor o incluso mucho más, especialmente si decidimos mantener nuestra posición comercial durante el fin de semana, lo cual, como podemos ver a continuación, es casi 10 veces el margen estándar de 5 puntos; a menos, claro, que tengamos niveles de stop loss y take profit extremadamente grandes.
Ejemplo de código de OnInit()
#property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 //--- plots #property indicator_label1 "ActSpread" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #property indicator_label2 "DeclaredSpread" #property indicator_type2 DRAW_LINE #property indicator_color2 clrBlack #property indicator_style2 STYLE_DASH #property indicator_width2 2 //--- indicator parameters input int numRecentBarsBack=100; //#RecentBarsBack M30+~100, M5~200, M1~500 input bool doPrint=true; //true=prints to the toolbox\experts log //--- indicator buffers double ActSpreadBuf[], DeclaredSpreadBuf[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { int numBars=iBars(_Symbol,PERIOD_CURRENT)-2; // Check we have enough data for the request before we begin if(numRecentBarsBack>numBars) { Alert("Can't Do ", numRecentBarsBack, "! Only ", numBars, " Bars are Available", " try 100 or so for 30+ minute charts,", " 200 for 5 minute, or 500 for 1 minute charts.", " Otherwise the indicator may be too slow" ); return(INIT_PARAMETERS_INCORRECT); } double sumPrice=0; double avgPrice=0; // Get the standard 5 point spread for the standard EURUSD currency double stdSpread=0.00005/iClose("EURUSD",PERIOD_M1,1); // 1.2 ~= EURUSD std price //Find out the current average price of the instrument we are using, so we can standardise the spread and _Point int CheckAvgPriceBars=MathMin(numRecentBarsBack, 200); int i=0; for(; i<CheckAvgPriceBars; i++) { sumPrice+=iClose(_Symbol,PERIOD_CURRENT,i); } avgPrice=sumPrice/(i? i: 1.0); //convert the stdSpread to stdPoint by dividing by 5, so we compare apples with apples, not oranges double stdPoint=StringToDouble(DoubleToString(avgPrice*stdSpread/5.0,6)); Print(i, "=bars done, avgPrice=", DoubleToString(avgPrice,6), " std=", DoubleToString(1.2*stdSpread, 6), " stdPoint=", DoubleToString(stdPoint, 6) ); SetIndexBuffer(0,ActSpreadBuf,INDICATOR_DATA); SetIndexBuffer(1,DeclaredSpreadBuf,INDICATOR_DATA); string indName ="BAS("+_Symbol; indName+=" TF="+string(_Period); indName+=" stdPoint="+DoubleToString(stdPoint, 6); indName+=") Last("+string(numRecentBarsBack)+") Bars"; IndicatorSetString(INDICATOR_SHORTNAME, indName); IndicatorSetInteger(INDICATOR_DIGITS,6); IndicatorSetDouble(INDICATOR_MINIMUM, 0.0); IndicatorSetInteger(INDICATOR_LEVELS, 20); //mark out each standard EURUSD 5 point spread, to compare this currencies spread with EURUSD IndicatorSetDouble(INDICATOR_LEVELVALUE,0, 0.000000); IndicatorSetDouble(INDICATOR_LEVELVALUE,1, 5*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,2, 10*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,3, 15*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,4, 20*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,5, 25*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,6, 30*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,7, 35*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,8, 40*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,9, 45*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,10,50*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,11,55*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,12,60*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,13,65*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,14,70*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,15,75*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,16,80*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,17,85*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,18,90*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,19,95*stdPoint); return(INIT_SUCCEEDED); }
Para este indicador simple con 2 gráficas, solo hay 2 parámetros, el primero, 'numRecentBarsBack', es para el número de barras que queremos analizar.
Lo primero que hacemos en OnInit() es comprobar que tenemos suficientes datos para satisfacer la solicitud; si no los tenemos, alertaremos al usuario y sugeriremos algunos valores realistas que utilizar. Luego saldremos del indicador con un error.
El resto de OnInit() es bastante estándar, salvo por los niveles usados en la subventana del indicador, que se establecen en valores que se correspondan con múltiplos del margen estándar de 5 puntos EURUSD.
Este es un paso bastante importante porque, además de querer ver la comparación entre los valores promedios de spread declarados y reales, también queremos ver cómo de grande es el spread de diferentes divisas en comparación con el EURUSD estándar, que normalmente muestra el spread más bajo disponible de todas las divisas.
Este es un método bastante complicado porque tenemos que obtener el precio actual de EURUSD (y sustituir 1.2, si no existe) y usar 5 puntos de EURUSD divididos por ese precio para construir un spread estándar. Luego, iteramos a través de los precios numRecentBarsBack del instrumento Fórex actual (no lo he probado con instrumentos que no sean Fórex) para obtener el precio promedio de ese instrumento.
Una vez tenemos el precio promedio de los instrumentos, podemos construir un punto estándar redondeado multiplicando el precio promedio de los instrumentos por el spread estándar previamente construido y dividiendo por 5, el punto de spread estándar de EURUSD.
Este punto estándar redondeado se usa en cada valor de nivel y también se incluye en el nombre breve de los indicadores, como podemos ver en el nombre de los indicadores en el gráfico USDMXN "exótico" a continuación.
En este ejemplo de USDMXN el spread declarado durante el día comercial es de alrededor de 0.0025, es decir, aproximadamente 3 niveles de spread desde cero, por lo que se corresponde con alrededor de 15 puntos en un gráfico de EURUSD. También debemos considerar que el spread promedio real varía ampliamente incluso por encima de ese nivel alto para este bróker.
El gráfico de GBPAUD a continuación, muestra que el spread declarado durante el día comercial es de alrededor de 0.00019, es decir, aproximadamente 2.5 niveles de spread por encima de cero, por lo que se corresponde con alrededor de 12 puntos en el gráfico EURUSD. También debemos tener en cuenta que en este gráfico los valores de spread promedio reales están bastante cerca de los valores declarados para este bróker.
El gráfico de GBPJPY a continuación, muestra que el spread declarado durante el día comercial es de alrededor de 0.020, es decir, aproximadamente 3 niveles de spread por encima de cero, por lo que se corresponde con alrededor de 15 puntos en el gráfico EURUSD. También debemos tener en cuenta que en este gráfico los valores de spread promedio reales están bastante cerca de los valores declarados para este bróker.
El gráfico de USDJPY a continuación, muestra que el spread declarado durante el día comercial es de alrededor de 0.0050, es decir, aproximadamente 1 nivel de spread por encima de cero, por lo que se corresponde con alrededor de 5 puntos en el gráfico EURUSD. También debemos considerar que en este gráfico los valores de spread promedio reales están de nuevo bastante cerca del doble de los valores declarados para este bróker, por lo que los mismos comentarios sobre los niveles de porcentaje de riesgo/recompensa de EURUSD también se aplican aquí.
Aquí tenemos algunos ejemplos más, así que podrá hacer sus propias valoraciones sobre las relaciones entre los niveles de spread.
El segundo parámetro es el 'doPrint' booleano, marcado en el código y que, si es verdadero, imprimirá las estadísticas de las barras individuales en el diario de expertos, como lo muestran los ejemplos a continuación. Esto puede ralentizar el indicador si el valor de 'numRecentBarsBack' es demasiado elevado, por lo que el valor por defecto es 100.
Si establecemos el parámetro 'doPrint' en true y 'numRecentBarsBack' en un valor razonable de alrededor de 100 para un gráfico de 30 minutos, o de 300 para un gráfico de 1 minuto, podremos copiar las entradas del diario y enviarlas a nuestro bróker como prueba de sus verdaderos spreads Bid/Ask.
Ejemplo de código de OnCalculate()
//--- Global variables //--- Set the date formatting for printing to the log const uint dtFormat=uint(TIME_DATE|TIME_MINUTES); //+------------------------------------------------------------------+ //| 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[]) { //--- Check for no data or Stop flag before we begin if(_StopFlag || rates_total<2) { Alert("Error, StopFlag=", _StopFlag, " #Bars=", rates_total); return(rates_total); } //only do the report at indicator start up or refresh if(prev_calculated>2) { // if we have already nulled the ActSpreadBuf just do the DeclaredSpreadBuf[] and return. if(prev_calculated==rates_total) { int currBar=rates_total-1; DeclaredSpreadBuf[currBar]=spread[currBar]*_Point; return(rates_total); } // else its the start of a new bar so null the ActSpreadBuf else { int currBar=rates_total-1; ActSpreadBuf[currBar]=EMPTY_VALUE; return(rates_total); } } static int start=rates_total-numRecentBarsBack; MqlTick tickBuf[]; double sumSpread=0; double thisSpread=0; int ticks=0; int bid_tick=0; int ask_tick=0; int k=0; ArrayInitialize(ActSpreadBuf, EMPTY_VALUE); ArrayInitialize(DeclaredSpreadBuf, EMPTY_VALUE); for(int i=start; i<rates_total; i++) { sumSpread=0; thisSpread=0; bid_tick=0; ask_tick=0; k=0; ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // Only bid and ask changes are required time[i-1]*1000, // Start time of previous bar time[i ]*1000 // End time of previous bar ); while(k<ticks) { if((tickBuf[k].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) ask_tick++; if((tickBuf[k].flags&TICK_FLAG_BID)==TICK_FLAG_BID) bid_tick++; sumSpread+=tickBuf[k].ask-tickBuf[k].bid; k++; } // Ensure no divide by zero errors for any missing tick data if(ticks>0) { thisSpread=sumSpread/ticks; ActSpreadBuf[i-1]=thisSpread; } else { thisSpread=0.0; ActSpreadBuf[i-1]=EMPTY_VALUE; } DeclaredSpreadBuf[i-1]=spread[i-1]*_Point; if(doPrint) { Print(TimeToString(time[i-1], dtFormat), " NumTicks="+string(ticks), " b="+string(bid_tick), " a="+string(ask_tick), " AvgSpread=", DoubleToString(thisSpread/_Point, 1), " DeclaredSpread=", string(spread[i-1]) ); } } //don't do stats for incomplete current bar, but can do DeclaredSpread if it has a value DeclaredSpreadBuf[rates_total-1]=(spread[rates_total-1]*_Point); //--- return value of prev_calculated for next call return(rates_total); }
Del ejemplo anterior de OnCalculate(), el punto principal a tener en cuenta es el uso de CopyTicksRange() para obtener solo los datos de ticks entre el inicio de la barra/vela de los índices anteriores y el inicio de la barra/vela de los índices actuales. También debemos considerar que tenemos que convertir la matriz time[] a milisegundos multiplicándola por 1000, porque los datos de fecha y hora solo son precisos hasta el segundo, y CopyTicksRange() requiere milisegundos.
ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // Only bid and ask changes are required time[i-1]*1000, // Start time of previous bar time[i ]*1000 // End time of previous bar );
También debemos tener en cuenta que acumulamos los ticks Bid/Ask, aunque no los usamos en las gráficas. El valor de los ticks de la oferta debe coincidir con el valor de la matriz tick_volume[], y funciona como se muestra en la ventana de datos.
Nota adicional sobre la descarga de ticks...
Si desea verificar una divisa que no usa normalmente, deberá añadir dicha divisa desde el elemento de menú Ver\Símbolos, clicando dos veces en ella para Mostrar el símbolo. Mientras esté en esta ventana, también deberá ir a la pestaña de ticks y solicitar en Todos los Ticks una fecha o un mes antes de hoy en el menú de la primera fecha, y luego configurar el segundo menú de fecha en "mañana" para generar su base de datos local de ticks.
Conclusión
Antes de comerciar con una divisa, deberemos saber cuáles son nuestros porcentajes de riesgo para el tipo de transacción (scalping, swing, posición...) que estamos considerando, y también comparar nuestras divisas favoritas con otras disponibles usando un tamaño de margen estándar común.
Usando mis estudios como base, recomendaría a los tráders que se ciñan a las principales divisas directamente vinculadas al dólar americano, a saber, USDCAD, USDCHF, USDJPY, EURUSD y GBPUSD, ya que tienen los spreads generales más bajos.
Todos debemos informar a nuestros brókeres de que ahora podemos ver sus verdaderos spreads Bid/Ask, incluso si estamos comerciando solo con comisiones, si aumentan sus diferenciales a niveles muy altos. Buena suerte y recuerde que es mejor no comerciar si no puede encontrar un bróker con spreads Bid/Ask razonables durante las horas comerciales, ¡ya que usted NO PUEDE ganar!
Antes de que alguien pregunte, este proceso solo se puede ejecutar en MetaTrader 5, porque los datos de ticks no están disponibles en MetaTrader 4, así que ahí tiene una buena razón para actualizarse.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/9804





- 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