![Cómo proteger su Asesor Experto cuando tradea en la Bolsa de Moscú](https://c.mql5.com/i/articles/overlay.png)
Cómo proteger su Asesor Experto cuando tradea en la Bolsa de Moscú
Índice
- INTRODUCCIÓN
- CAPÍTULO 1. DISCONTINUIDAD DE LOS PRECIOS DE FLUJO Y MÉTODOS DE RESISTENCIA A ELLA
- CAPÍTULO 2. ANÁLISIS DE LA LIQUIDEZ DEL MERCADO
- CAPÍTULO 3. MODOS SEGUROS DEL TRADING Y SIMULACIÓN DE LOS EAs
- CONCLUSIÓN
Introducción
El que comerciaba alguna vez en los mercados financieros, se enfrentaba a los riesgos de perder el dinero. La naturaleza de estos riesgos es distinta, sin embargo el resultado final es el mismo: la pérdida del dinero, tiempo y de los nervios. Para evitarlo, es necesario seguir unas sencillas reglas: controlar sus riesgos (Money Management), escribir los algoritmos comerciales fiables y, desde luego, utilizar los sistemas comerciales rentables. Todo lo mencionado atañe a diferentes esferas del trading, pero podemos esperar un resultado positivo estable sólo si aplicamos estos métodos en conjunto.
Actualmente se puede encontrar suficiente información referente a las cuestiones de la gestión del capital (Money Management). Además, hay bastantes libros sobre los sistemas comerciales que pueden ser utilizados en la práctica cotidiana del trading. Pero no hay mucha información sobre las “reglas elementales de seguridad” en los mercados bursátiles.
Este artículo tiene por objetivo cambiar dicha situación y describir más o menos detalladamente estas “reglas de seguridad” que hay que respetar, sobre todo si operamos en la bolsa. Bajo las “reglas de seguridad” se entienden los métodos y técnicas comerciales que le permiten evitar las pérdidas financieras considerables a causa de los saltos bruscos de los precios, escasez de liquidez y otras situaciones de fuerza mayor. Este artículo no comprende el estudio de las estrategias comerciales y las reglas del control de riesgos, dejando estos asuntos para otras fuentes de información y centrándose sólo en uno de los tipos de riesgos, en el riesgo de carácter técnico.
Este artículo es la continuación lógica del artículo “Principios de formación de precios en el mercado bursátil tomando de ejemplo la Sección de Derivados de la Bolsa de Moscú” que contiene los principios teóricos del trading bursátil, pero lleva el carácter más práctico. Si en los “Principios de formación de precios en el mercado bursátil” se describía la teoría y la mecánica de aparición del concepto tal como el precio, pues en este artículo se describen los mecanismos que le protegen a Usted y a su Asesor Experto (EA) de una quiebra accidental causada por algunos momentos peligrosos de la formación de precios en el mercado bursátil.
Capítulo 1. Discontinuidad de los precios de flujo y métodos de resistencia a ella
1.1. Discontinuidad de los precios de flujo. Brechas (gap) de precios
La liquidez es uno de los conceptos más importantes en el mercado bursátil. La liquidez es la capacidad del mercado para comprar a Ud. y venderle un producto por el precio cercano al del mercado. Cuanto más alta sea la liquidez del mercado, los precios siguen más pegados uno detrás del otro. En realidad, el proceso de formación de precios es un proceso discreto. Eso significa que el precio que estamos acostumbrados a observar se compone de varias transacciones que siguen una tras otra a gran velocidad. Este flujo de transacciones se genera por las cotizaciones o gráficos de tick, que luego se reorganizan por las plataformas comerciales en los gráficos más cómodos de velas o barras del período de tiempo aleatorio. Desde el punto de vista del trader, estos gráficos son continuos. En cada momento dado, esta barra o vela tiene un determinado precio. Vamos a ver esta barra en la imagen:
Fig. 1. Barra de precio y su función continua del precio
Independientemente del punto de la barra de precio donde estemos, ella tendrá su propio nivel de precios que se muestra con la línea roja. Precisamente de esta manera se representan las barras en el Probador de Estrategias MetaTrader en el modo “Todos los ticks”. Los precios se generan de una manera continua y consecutiva. Así, si el paso del precio es igual a 1, y el precio ha pasado de 10 a 15, durante el movimiento del precio también tendremos disponibles los precios 11, 12, 13 y 14. En realidad, como ya hemos dicho antes, el precio es discreto y se cambia con saltos pequeños. Estos cambios del precio no siempre pueden ser consecutivos y regulares. A veces el precio puede saltar varios niveles a la vez. Vamos a mostrar la misma barra de arriba, pero esta vez usando un esquema más real (discreto) del cambio del precio:
Fig. 2. Barra de precios y su función discreta del precio
El precio continuo como tal no existe en este esquema. En la imagen 2, este precio condicional (no existente en realidad) se muestra con una línea punteada. ¡En la vida real eso significa que nuestras órdenes del mercado, y sobre todo las órdenes Stop, pueden ser ejecutadas en un lugar diferente del establecido! Es una propiedad muy peligrosa de las órdenes del mercado. Vamos a ver cómo se activa la orden pendiente Buy Stop para esta barra. Supongamos que hemos enviado la solicitud a la bolsa cuando el precio alcanza el nivel 64 203 y más. Marcamos este nivel de forma condicional con una línea azul punteada que cruza nuestra barra ya conocida. Sin embargo, este precio puede simplemente no existir dentro de la barra. En este caso nuestra orden será activada por otro precio que va a superar el nivel 64 203 de forma considerable:
Fig. 3. Ejecución de órdenes pendientes con precios discretos
En este ejemplo la ejecución real tendrá lugar sólo por el precio de 64 220 puntos, lo que es peor a 13 puntes respecto al precio solicitado. La diferencia entre estos precios será nuestro deslizamiento. Si los mercados son bastante líquidos, los precios discretos van en un flujo ajustado, pasando de un nivel a otro suavemente. No obstante, cuando el precio se cambia rápido, pueden surgir las brechas (gap) de precios incluso en los mercados de alta liquidez. Es imposible detectar estas brechas de precios observando los gráficos de precios habituales, pero hay que tomar en consideración la posibilidad de su existencia.
1.2. Picos de precios
Las brechas de precios pueden alcanzar unos valor muy altos. Normalmente, eso se debe a la falta de liquidez. En estos casos ocurren así llamados los picos de precios (en inglés spikes). El spike es una operación realizada por los precios que se desvían mucho de los precios del mercado. Convencionalmente, a los precios del mercado les podemos llamar al flujo de transacciones que siguen una tras otra a una distancia equivalente al paso del precio. Los picos son extremadamente peligrosos tanto para los traders que operan manualmente, como para los sistemas automáticos de trading. Estos picos accionan las órdenes Stop pendientes y las ejecutan por los precios muy desventajosos.
Vamos a ver una simple situación: supongamos que estamos negociando un contrato de futuros de rublo/dólar y hemos colocado una orden Buy Stop de compra por el precio de 64 200. Hemos colocado el Stop Loss para esta orden a 64 100. Esperamos que el precio se mueva hacia arriba, pero si eso no pasa, nuestro Stop Loss en 64 100 reducirá nuestra pérdida a 100 puntos. Parece que nuestro riesgo está limitado, pero no es así. Vamos a considerar la situación cuando ocurre un spike que activa nuestra orden Stop por un precio absolutamente diferente:
Fig. 4. Representación tick de un pico y el esquema de ejecución de la orden BuyStop
En este gráfico se muestra el flujo tick de los precios. Podemos observar que uno de los tick se encuentra a una distancia más grande de los demás. Precisamente este tick forma un “pico”. Este tick activa nuestra orden Buy Stop y la ejecuta por el precio de 64 440. En el siguiente tick el precio vuelve en su diapasón habitual activando nuestra orden Stop por el precio de 64 100. En menos de un segundo nuestra orden pendiente puede ejecutarse y cerrarse por Stop Loss dejándonos con una enormes pérdidas. En vez de una pérdida de 100 puntos que hemos calculado, nuestra orden nos va a traer 340 puntos de pérdidas.
En realidad, los picos pueden alcanzar los tamaños aún más grandes. ¡De esta manera, será suficiente obtener una ejecución de este tipo para arruinar nuestra cuenta por más grande que sea! Para evitar estas situaciones, hay que seguir una sencillas reglas de protección que vamos a considerar más abajo.
Cabe mencionar que en el Probador de Estrategias en el modo “Todos los ticks” la ejecución con estos picos de precios va a realizarse según los precios modelados, que pueden ser mejores que esto sucede en vida real. Si queremos probar nuestra estrategia en este rango de precios, nuestra orden pendiente se ejecutará sin deslizamiento o este deslizamiento será de tamaño mínimo. Nosotros recordamos que en el Probador el flujo de precios dentro de la barra es bastante continuo, entonces el Probador ejecutará nuestra orden por un precio cercano al precio declarado, sin ningún deslizamiento. En realidad, en el Probador de Estrategias se puede tomar en consideración estas situaciones de forma adecuada. Para eso hay que seleccionar un modo de prueba especial. Una sección especial del apartado 3 trata de cómo hacerlo.
1.3. Controlamos el deslizamiento máximo usando las órdenes limitadas
Hemos aclarado que las órdenes de mercado y las órdenes Stop representan un peligro debido al deslizamiento ilimitado. Puede que no haya suficiente liquidez para nuestro pedido, además el mercado puede perder completamente su liquidez por un breve período de tiempo: en este caso los picos de precios serán inevitables. Es más, estas situaciones son constantes en los mercados de poca liquidez, por ejemplo en los mercados de opciones FORTS. No obstante, es posible evitarlas si usamos las órdenes limitadas en vez de las órdenes de mercado y órdenes Stop.
La orden limitada es aquella que se ejecuta por el precio no peor que está indicado en ella. Una característica interesante de las órdenes limitadas en el modo de Ejecución por Bolsa consiste en su capacidad de ejecutarse por el precio actual, incluso si su nivel se encuentra por encima o por debajo del precio especificado en la orden.
Por ejemplo, si el precio actual del contrato de futuros rublo/dólar es de 64 200, podemos colocar la orden Buy Limit por el precio de 64 220. Esta configuración va a significar que estamos dispuestos a comprar si el precio no va a superar 64 220. Puesto que el precio actual 64 200 es mejor que el precio de compra límite especificado, nuestra orden se ejecutará inmediatamente después de su colocación Gracias a esta propiedad, podemos controlar el tamaño de nuestro deslizamiento máximo. Pues, si por alguna razón va a faltar liquidez hasta el nivel de 64 220, el resto de nuestro pedido simplemente no se ejecutará.
Es importante destacar que podemos controlar el deslizamiento sólo usando las órdenes limitadas. Resulta imposible establecer el nivel del deslizamiento máximo para las órdenes de mercado comunes en el modo de Ejecución por Bolsa. Por tanto, el uso de las órdenes limitadas es una táctica obligatoria y única a la hora de negociar en los mercados de poca liquidez.
El uso de este tipo de órdenes será una buena costumbre para entrar y salir del mercado. Utilice las órdenes limitadas incluso si su estrategia requiere las entradas y salidas por los precios actuales del mercado. Sustituya las órdenes Buy y Sell por las Buy Limit y Sell Limit, respectivamente. Por ejemplo, si necesita comprar por el precio actual, coloque una orden limitada con el precio máximo de ejecución un poco más alto que el precio actual del mercado. Lo mismo es cierto para nuestras ventas. En este caso será suficiente colocar nuestra orden Sell Limit con un precio ligeramente menor del actual. La diferencia del precio especificado en la orden limitada y el precio actual va a corresponder al deslizamiento máximo que podemos aceptar para nuestro pedido.
Vamos a ver una situación práctica del uso de una orden limitada como alternativa a la entrada por el mercado. Supongamos que necesitamos comprar un volumen bastante importante del futuro euro/dólar ED-3.15 por el precio de 1,1356. La situación de nuestra compra será un poco extraordinaria. Es que el momento de nuestra compra coincide con el momento de una fuerte escasez de liquidez. Esta situación ha sido escogida a propósito para demostrar las ventajas de la entrada al mercado usando las órdenes limitadas. El momento de la entrada coincide con el “pico de precios” que podemos ver en el gráfico M1:
Fig. 5. Entrada al mercado en el momento del pico de precios, ED-3.15
Es obvio que el momento de la entrada es absolutamente desfavorable. Vamos a analizar el gráfico de ticks para este momento:
Fig. 6. Gráfico de ticks y ejecución de una orden limitada en el momento de la ruptura de liquidez
La ejecución de nuestra orden limitada se muestra con los círculos blancos grandes (ticks): . Los ticks se describen como puntos redondos azules. Si compraramos a mercado por el precio de 1,1356, nuestra orden se ejecutaría con varias transacciones empezando de 1,1356 y terminando con 1,1398. Esto provocaría un importante deslizamiento y nuestro precio medio de entrada sería mucho peor que el precio 1,1356. Cuanto más contratos tuviéramos que comprar, peor sería el precio medio de entrada en nuestra posición.
En este caso, esta enorme diferencia de precios se debe a la liquidez baja, cuando por diferentes razones las órdenes limitadas desaparecen y el precio empieza a oscilarse de forma caótica dentro de una amplia variación. Pero una orden limitada dispone de una “protección incorporada” contra dichos cambios. Simplemente, no será ejecutada si el precio actual supera 1,1356. Por ejemplo, nuestra orden limitada fue ejecutada con siete transacciones: son grandes círculos blancos sobre el gráfico. Había más precios entre estas transacciones, pero todos ellos eran peores que el precio 1,1356, por eso simplemente fueron ignorados. Dentro de un rato el precio se estabilizó nuestra orden se ejecutó por completo.
1.4. Colocación manual de una orden limitada que controla el deslizamiento máximo
Ahora, cuando ya hemos conocido el principio de activación de una orden limitada en teoría, ha llegado la hora de dedicarnos un poco a la practica y ver su funcionamiento en condiciones reales. Para eso vamos a abrir una cuenta conectada a la Bolsa de Moscú y colocar una orden limitada por el precio que es un poco peor que el precio actual. Como instrumento financiero vamos a escoger el futuro más cercano euro/dólar, que en nuestro caso será ED-6.15. Abrimos la ventana de la orden nueva y colocamos la orden Buy Limit cuyo precio estará un poco por encima del precio actual Ask:
Fig. 7. Colocación manual de una orden limitada en el modo de Ejecución por Bolsa
En la imagen se ve que el precio actual Ask es igual a 1,1242, pero nosotros hemos puesto el precio pendiente a 1,1245. La diferencia entre nuestro precio y el precio de la mejor oferta es iguala 0,0003 puntos (1,1245 - 1,1242 = 0,0003). Estos tres puntos equivalen al deslizamiento máximo que podemos aceptar. En el modo de Ejecución por Bolsa, la colocación de una orden limitada de esta manera es equivalente a la colocación de una orden común Buy o Sell con la especificación del deslizamiento máximo (Deviation):
Fig. 8. Ejecución de una orden de mercado con la indicación de la desviación máxima
Puesto que en el modo de Ejecución por Bolsa no se puede establecer el deslizamiento máximo, la única manera de fijar esta desviación límite es la colocación de una orden limitada tal como se muestra en la imagen 7.
1.5. Colocación del deslizamiento máximo en el modo de Ejecución por Bolsa (Exchange Execution) usando el EA.
Ahora, cuando ya hemos aclarado cómo colocar las órdenes limitadas manualmente, vamos a intentar hacer lo mismo usando un robot. Escribiremos un sencillo panel que va a incluir los siguientes elementos:
- Botón “BUY" — al pulsar este botón, entramos en una posición larga usando la orden limitada BuyLimit;
- Botón “SELL” — al pulsar este botón, entramos en una posición corta usando la orden limitada SellLimit;
- Campo para introducir el valor del deslizamiento máximo expresado en puntos (este campo lo añadiremos más tarde);
- Volumen que hace falta comprar o vender (este campo lo añadiremos en la siguiente versión del panel).
En la captura de pantalla de abajo se muestra la apariencia de la primera versión de nuestro panel:
Fig. 9. Colocación del deslizamiento máximo en el panel DevaitionPanel
El panel está escrito con una clase CDevPanel. A continuación va el código fuente de esta clase:
//+------------------------------------------------------------------+ //| Panel.mqh | //| Copyright 2015, Vasiliy Sokolov. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Vasiliy Sokolov." #property link "http://www.mql5.com" #include <Trade\Trade.mqh> #define OP_BUY 0 #define OP_SELL 1 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CDevPanel { private: CTrade Trade; string m_descr_dev; string m_buy_button_name; string m_sell_button_name; string m_deviation_name; string m_volume_name; string m_bg_fon; int m_deviation; void OnObjClick(string sparam); void OnEndEdit(string sparam); double CalcCurrentPrice(int op_type); public: CDevPanel(); ~CDevPanel(); void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam); }; //+------------------------------------------------------------------+ //| CDevPanel class | //+------------------------------------------------------------------+ CDevPanel::CDevPanel(): m_buy_button_name("buy_button"), m_sell_button_name("sell_button"), m_deviation_name("deviation"), m_volume_name("volume"), m_bg_fon("bg_fon"), m_descr_dev("descr_dev"), m_deviation(3) { //--- background ObjectCreate(0,m_bg_fon,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,m_bg_fon,OBJPROP_YSIZE,80); ObjectSetInteger(0,m_bg_fon,OBJPROP_XSIZE,190); ObjectSetInteger(0,m_bg_fon,OBJPROP_BGCOLOR,clrWhiteSmoke); //--- buy button ObjectCreate(0,m_buy_button_name,OBJ_BUTTON,0,0,0); ObjectSetInteger(0,m_buy_button_name,OBJPROP_XDISTANCE,100); ObjectSetInteger(0,m_buy_button_name,OBJPROP_YDISTANCE,50); ObjectSetInteger(0,m_buy_button_name,OBJPROP_XSIZE,80); ObjectSetInteger(0,m_buy_button_name,OBJPROP_BGCOLOR,clrAliceBlue); ObjectSetString(0,m_buy_button_name,OBJPROP_TEXT,"BUY"); //--- sell button ObjectCreate(0,m_sell_button_name,OBJ_BUTTON,0,0,0); ObjectSetInteger(0,m_sell_button_name,OBJPROP_XDISTANCE,10); ObjectSetInteger(0,m_sell_button_name,OBJPROP_YDISTANCE,50); ObjectSetInteger(0,m_sell_button_name,OBJPROP_XSIZE,80); ObjectSetInteger(0,m_sell_button_name,OBJPROP_BGCOLOR,clrPink); ObjectSetString(0,m_sell_button_name,OBJPROP_TEXT,"SELL"); //--- deviation ObjectCreate(0,m_deviation_name,OBJ_EDIT,0,0,0); ObjectSetInteger(0,m_deviation_name,OBJPROP_XDISTANCE,120); ObjectSetInteger(0,m_deviation_name,OBJPROP_YDISTANCE,20); ObjectSetInteger(0,m_deviation_name,OBJPROP_XSIZE,60); ObjectSetInteger(0,m_deviation_name,OBJPROP_BGCOLOR,clrWhite); ObjectSetInteger(0,m_deviation_name,OBJPROP_COLOR,clrBlack); ObjectSetInteger(0,m_deviation_name,OBJPROP_ALIGN,ALIGN_RIGHT); ObjectSetString(0,m_deviation_name,OBJPROP_TEXT,(string)m_deviation); //--- description ObjectCreate(0,m_descr_dev,OBJ_LABEL,0,0,0); ObjectSetInteger(0,m_descr_dev,OBJPROP_XDISTANCE,12); ObjectSetInteger(0,m_descr_dev,OBJPROP_YDISTANCE,20); ObjectSetInteger(0,m_descr_dev,OBJPROP_XSIZE,80); ObjectSetInteger(0,m_descr_dev,OBJPROP_BGCOLOR,clrWhite); ObjectSetString(0,m_descr_dev,OBJPROP_TEXT,"Deviation (pips):"); ObjectSetInteger(0,m_descr_dev,OBJPROP_COLOR,clrBlack); ChartRedraw(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CDevPanel::~CDevPanel(void) { ObjectDelete(0,m_buy_button_name); ObjectDelete(0,m_sell_button_name); ObjectDelete(0,m_bg_fon); ObjectDelete(0,m_deviation_name); ObjectDelete(0,m_descr_dev); } //+------------------------------------------------------------------+ //| Event function | //+------------------------------------------------------------------+ void CDevPanel::OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { switch(id) { case CHARTEVENT_OBJECT_CLICK: OnObjClick(sparam); break; case CHARTEVENT_OBJECT_ENDEDIT: OnEndEdit(sparam); } } //+------------------------------------------------------------------+ //| End edit detect | //+------------------------------------------------------------------+ void CDevPanel::OnEndEdit(string sparam) { if(sparam != m_deviation_name)return; int value = (int)ObjectGetString(0, m_deviation_name, OBJPROP_TEXT); if(value <= 0) ObjectSetString(0,m_deviation_name,OBJPROP_TEXT,(string)m_deviation); else m_deviation=value; ChartRedraw(); } //+------------------------------------------------------------------+ //| End obj click | //+------------------------------------------------------------------+ void CDevPanel::OnObjClick(string sparam) { if(sparam==m_buy_button_name) Trade.BuyLimit(1,CalcCurrentPrice(OP_BUY)); if(sparam==m_sell_button_name) Trade.SellLimit(1,CalcCurrentPrice(OP_SELL)); ObjectSetInteger(0,sparam,OBJPROP_STATE,false); Sleep(100); ChartRedraw(); } //+------------------------------------------------------------------+ //| Calc level price | //+------------------------------------------------------------------+ double CDevPanel::CalcCurrentPrice(int op_type) { if(op_type==OP_BUY) { double ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK); return ask + (m_deviation * Point()); } else if(op_type==OP_SELL) { double bid=SymbolInfoDouble(Symbol(),SYMBOL_BID); return bid - (m_deviation * Point()); } return 0.0; } //+------------------------------------------------------------------+
La particularidad característica de este panel respecto a las prestaciones estándar consiste en el hecho de que permite establecer el deslizamiento máximo permitido en puntos para los mercados con la Ejecución por Bolsa. La entrada y salida reales se realizan a través de las órdenes limitadas.
Es importante mencionar que este panel va a funcionar sólo en los terminales de los brokers que permiten la ejecución bursátil de las órdenes. En los terminales con otros modos de ejecución, este código va a mostrar el error estándar de precios inválidos al introducir los precios de las órdenes limitadas:
2015.04.15 14:08:39.709 Trades '58406864': failed buy limit 0.10 EURUSD at 1.05927 [Invalid price]
1.6. Las órdenes Buy Stop Limit y Sell Stop Limit como alternativa a las órdenes Buy Stop y Sell Stop
Las órdenes limitadas representan un mecanismo conveniente y natural para protegerse contra la ejecución de las órdenes por los precios fuera del mercado. Sin embargo, a veces es necesario utilizar las órdenes pendientes del tipo Stop que se activan al romper un determinado nivel. Por ejemplo, puede tratarse de las órdenes tipo Stop Loss. Aparte de los niveles Stop Loss, muchas estrategias reaccionan a la salida del precio de un determinado pasillo. Para entrar en el mercado, necesitan las órdenes Stop también. Pero como ya sabemos, las órdenes Stop están sujetas al deslizamiento y no están protegidas de los problemas con la liquidez. La imposibilidad de establecer el tamaño del deslizamiento máximo también complica la situación.
En este caso, las órdenes Buy Stop Limit y Sell Stop Limit nos pueden echar una mano. Son órdenes algorítmicas para MetaTrader 5. No son órdenes bursátiles y se implementan en el servidor MetaTrader. Vamos a dirigirnos a la documentación oficial para comprender cómo funcionan:
- Buy Stop Limit — este tipo combina dos primeros tipos (Buy Limit y Buy Stop -nota del autor), siendo una orden Stop para colocar una orden limitada de compra (“Buy Limit”). En cuanto el futuro precio “Ask” alcance el nivel Stop indicado en esta orden (campo “Precio”), se colocará la orden “Buy Limit” en el nivel indicado en el campo “Precio Stop Limit”.
- Sell Stop Limit — es una orden Stop para colocar una orden limitada de venta (“Sell Limit”). En cuanto el futuro precio “Bid” alcance el nivel Stop indicado en esta orden (campo “Precio”), se colocará la orden “Sell Limit” en el nivel indicado en el campo “Precio Stop Limit”.
Además, la documentación ofrece un esquema (Fig. 10) que muestra el principio de funcionamiento de las órdenes en MetaTrader 5. En este esquema nos van a interesar dos tipos de órdenes marcados con los cuadros amarillos.
Fig. 10. Tipos de órdenes en MetaTrader 5
Desde la definición y el esquema de Buy Stop Limit y Sell Stop Limit desprende que se trata de las órdenes limitadas que se colocan en el mercado en el momento cuando el precio alcance un determinado nivel Stop. Para la orden Buy Stop Limit, el nivel Stop se establece por encima del precio actual Ask, y para la orden Sell Stop Limit— por debajo del precio actual Bid. El precio del nivel limitado en el modo de Ejecución por Bolsa puede encontrarse como por encima tanto por debajo del precio Stop de estas órdenes. Esta particularidad nos permite configurar las órdenes Stop especiales con deslizamiento controlado. Veamos el esquema que nos muestra cómo funciona eso:
Fig. 11. Esquema de colocación de la orden Buy Stop Limit para establecer el deslizamiento máximo
Se puede observar que podemos colocar una orden Buy Stop Limit con el precio Limit Price que supere el precio Stop Price. Eso significa que en cuanto se alcance el precio Stop Price, se enviará la orden Buy Limit, que se ejecutará inmediatamente ya que el precio Limit Price va a ser peor que el precio actual Stop Price. La diferencia entre los precios Stop Price y Limit Price será el deslizamiento máximo que decidiremos establecer para nuestras órdenes. Las órdenes Sell Stop Limit funcionan de la misma manera, lo único que para ellas el precio Limit Price tiene que ser más bajo que el precio Stop Price.
Ahora pasamos a la práctica— vamos a intentar colocar una orden Buy Stop Limit manualmente.
1.7. Colocación manual de las órdenes Buy Stop Limit y Sell Stop Limit en vez de los niveles Stop Loss
Supongamos que necesitamos proteger nuestra posición abierta usando la orden Stop. Sin embargo, los mercados con poca liquidez son demasiado peligrosos y impredecibles para trabajar en ellos usando las órdenes Stop o las órdenes de mercado. Una orden Stop (por ejemplo, Stop Loss) puede tener un deslizamiento ilimitado, y por consecuencia ella misma puede ser la fuente de un importante riesgo. En los momentos de fuertes brechas o picos de precios, la activación de Stop Loss por los precios peores que los establecidos puede arruinar nuestra cuenta. Para evitarlo, se puede sustituir la orden Stop en la que se basa Stop Loss por una orden Stop limitada.
Vamos a ver el siguiente ejemplo. Supongamos que tenemos abierta una posición larga para Si-6.15. Su nivel Stop Loss es igual a 56 960. Necesitamos establecer el deslizamiento máximo de 5 puntos, entonces el valor “Stop Limit price” será igual a 56 960 - 5 = 56 955 puntos:
Fig. 12. Colocación de la orden SellStopLimit como nivel Stop para una posición larga
Como vemos, en el modo de Ejecución por Bolsa, esta configuración de la orden Sell Stop Limit se hace posible. Cuando el precio actual alcance el nivel de 56 960, se colocará la orden limitada de venta por el precio de 56 955. Puesto que el precio actual 56 960 es mejor que el precio de la orden limitada, se ejecutará inmediatamente por el precio de 56 960. Si en este nivel no hay liquidez suficiente, la ejecución será realizada a precios subsiguientes, hasta alcanzar el nivel 56 955. Pero al precio peor que este nuestra orden Stop limitada no se ejecutará, garantizándonos así el deslizamiento máximo de 5 puntos: 56 960 - 56 955 = 5.
Ahora intentamos hacer lo mismo para proteger nuestra posición corta. Para cerrarla con Stop Loss, hay que realizar una operación contraria a la corta, es decir hay que comprar enviando una orden Buy Stop Limit. Supongamos que Stop Loss actual para nuestra posición corta será de 56 920, entonces la configuración de nuestra orden Buy Stop Limit con deslizamiento máximo de 5 puntos será la siguiente:
Fig. 13. Colocación de la orden BuyStopLimit como nivel Stop para una posición corta
Como vemos, en este caso el precio “Stop Limit price” es mayor a 5 puntos que el precio “Price” y es igual a 56 925.
1.8. Sustitución de los niveles Stop Loss por las órdenes Buy Stop Limit y Sell Stop Limit en su Asesor Experto
Volveremos de nuevo a nuestro panel descrito en el punto 1.5 del presente artículo. Intentaremos modificarlo de tal manera que aparte de la entrada en el mercado con las órdenes limitadas este panel nos permita colocar las paradas de protección mediante las órdenes Buy Stop Limit y Sell Stop Limit . Para eso vamos a crear un campo más que se llama "Stop Loss Level". Ahora nuestro panel es el siguiente:
Fig. 14. Establecer el nivel Stop Loss en DevaitionPanel
El código que ya conocemos contiene dos cambios más importantes: ahora la clase CDevPanel incluye un nuevo método que se encarga de la colocación de las órdenes Buy Stop Limit y Sell Stop Limit. Además, el método OnObjClick que abre la nueva posición también ha sido modificado. El código fuente de estos métodos es el siguiente:
//+------------------------------------------------------------------+ //| End obj click | //+------------------------------------------------------------------+ void CDevPanel::OnObjClick(string sparam) { if(sparam==m_buy_button_name) { if(Trade.BuyLimit(1,CalcCurrentPrice(OP_BUY))) SendStopLoss(OP_BUY); } if(sparam==m_sell_button_name) { if(Trade.SellLimit(1,CalcCurrentPrice(OP_SELL))) SendStopLoss(OP_SELL); } ObjectSetInteger(0,sparam,OBJPROP_STATE,false); Sleep(100); ChartRedraw(); } //+------------------------------------------------------------------+ //| Send SL order | //+------------------------------------------------------------------+ bool CDevPanel::SendStopLoss(int op_type) { if(op_type==OP_BUY) { double bid=SymbolInfoDouble(Symbol(),SYMBOL_BID); if(m_sl_level>=0.0 && m_sl_level<bid) { MqlTradeRequest request={0}; request.action = TRADE_ACTION_PENDING; request.symbol = Symbol(); request.volume = 1.0; request.price=m_sl_level; request.stoplimit=m_sl_level -(m_deviation*Point()); request.type=ORDER_TYPE_SELL_STOP_LIMIT; request.type_filling=ORDER_FILLING_RETURN; request.type_time=ORDER_TIME_DAY; MqlTradeResult result; bool res=OrderSend(request,result); if(!res) Print("Error set S/L. Reason: "+(string)GetLastError()); return res; } } else if(op_type==OP_SELL) { double ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK); if(m_sl_level>=0.0 && m_sl_level>ask) { MqlTradeRequest request={0}; request.action = TRADE_ACTION_PENDING; request.symbol = Symbol(); request.volume = 1.0; request.price=m_sl_level; request.stoplimit=m_sl_level+(m_deviation*Point()); request.type=ORDER_TYPE_BUY_STOP_LIMIT; request.type_filling=ORDER_FILLING_RETURN; request.type_time=ORDER_TIME_DAY; MqlTradeResult result; bool res=OrderSend(request,result); if(!res) Print("Error set S/L. Reason: "+(string)GetLastError()); return res; } if(CharToStr(StringGetChar(data,strlen-1))=='.') StringSetChar(data,strlen-1,''); } return false; }
Aparte de estos métodos, el código de la clase del panel también incluye la inicialización y configuración del campo correspondiente para la introducción del Stop Loss. Ahora si pulsa el botón “BUY” o “SELL”, rellenando previamente el nivel “Stop Loss”, junto con la nueva orden de mercado se colocará una orden especial de protección Buy Stop Limit o Sell Stop Limit, dependiendo de la dirección de la posición.
Capítulo 2. Análisis de la liquidez del mercado
2.1 Calculamos el deslizamiento antes de entrar en el mercado
Una de las particularidades interesantes del mercado de valores es su negociación centralizada. Por consiguiente, todas las órdenes limitadas de compra y de venta están disponibles desde la Profundidad del Mercado, el término conocido en inglés por las siglas DOM (Depth of Market). De las definiciones descritas en el artículo “Principios de formación de precios en el mercado bursátil tomando de ejemplo la Sección de Derivados de la Bolsa de Moscú” se desprende que las órdenes limitadas ubicados en el DOM determinan la liquidez del mercado, o sea, aseguran la posibilidad de comprar y vender ciertos volúmenes cerca del precio Last de la última transacción.
Cuanto más grande sea el volumen que queremos vender o comprar, más compradores y vendedores tenemos que involucrar desde el DOM. De esta manera, con el aumento del volumen de nuestra transacción, va subiendo el valor del deslizamiento, puesto que con cada nuevo nivel del volumen es necesario involucrar a los proveedores de liquidez a los niveles más lejanos del precio actual. Puede encontrar más detalles sobre el proceso y la mecánica del deslizamiento en el artículo “Principios de formación de precios en el mercado bursátil” que hemos mencionado antes. Nosotros vamos a considerar sólo un breve ejemplo para tener la idea más clara sobre el asunto.
Pues bien, en cualquier momento de tiempo tenemos el DOM que describe los volúmenes a comprar o vender. Como ejemplo, vamos a mostrar la Profundidad del Mercado para el contrato de futuros dólar/rublo Si-6.15:
Fig. 15. Profundidad del Mercado para el contrato de futuros Si-6.15
Nos muestra que si en este momento decidiesemos comprar 2 contratos, lo haríamos sin deslizamiento alguno, adquiriéndolos por el mejor precio de la oferta: 51 931. Pero si nuestro volumen para la compra fuera más grande (por ejemplo, 4 contratos), nuestro precio medio ponderado sería diferente de la mejor oferta (51 931) comprendiendo: (2*51931+2*51932)/4 = 51931,5. Compraríamos dos contratos por 51 931 y otros dos, por el precio 51 932. Nuestro precio 51931,5 va a ser el precio medio ponderado para entrar en el mercado. La diferencia entre este precio y el mejor precio de la oferta será nuestro deslizamiento.
Sabiendo la fórmula del cálculo del precio medio ponderado de la entrada, podemos calcular la tabla de la liquidez que muestra el deslizamiento que vamos a tener al subir el volumen de nuestra transacción. Así ya hemos calculado que si el volumen de la transacción es igual a 1 o 2 contratos, nuestra transacción se realizará por el mejor precio de la oferta (51 931) sin deslizamiento, y si el volumen es de 4 contratos, nuestra transacción nos traerá un deslizamiento de 0,5 punto (51931,5 - 51931,0). La fórmula del cálculo del deslizamiento es sencilla: del precio medio ponderado de la entrada se resta el mejor precio Ask o Bid (dependiendo de la dirección de la operación).
La tabla de liquidez se muestra más abajo:
Volumen | Precio | Volumen de la operación | Precio m/p de entrada | Deslizamiento |
---|---|---|---|---|
2 | 51938 | 25 | 51934,5 | 3,5 |
9 | 51936 | 23 | 51934,2 | 3,2 |
3 | 51935 | 14 | 51933,0 | 2,0 |
7 | 51933 | 11 | 51932,5 | 1,5 |
2 | 51932 | 4 | 51931,5 | 0,5 |
2 | 51931 | 2 | 51931,0 | 0,0 |
Tabla 1. Cálculo del precio medio ponderado de la entrada y el volumen del deslizamiento a su base
Hay que leer esta tabla de arriba abajo, igual que el precio de la oferta del DOM descrito anteriormente. Como podemos ver, la operación de dos contratos no tiene deslizamiento. La operación de cuatro contratos tiene el deslizamiento de 0,5 puntos. La operación de 25 contratos tiene el deslizamiento de 3,5 puntos y su precio medio ponderado de la entrada será igual a 51934,5.
El mercado centralizado y la presencia del DOM nos permiten hacer la siguiente conclusión:
Sabiendo el estado del DOM antes de entrar en el mercado, podemos calcular el deslizamiento potencial de la transacción antes de realizarla.
Este cálculo puede ser sumamente útil en el asunto del control de nuestro riesgo. Independientemente de que si tradeamos manualmente o usamos los robots, podemos conocer la profundidad del mercado antes de realizar nuestra operación. En este caso, surge la comparación con un clavadista. Antes de saltar a la piscina, sería muy conveniente conocer el nivel del agua en la misma. Cuanto más grande sea su cuerpo, más profundidad va a necesitar. Pasando esta analogía al mercado, podemos decir que cuanto más grande sea el volumen con el que operamos, vamos a necesitar un mercado con más liquidez. Está claro que el DOM puede cambiar en el último momento antes de la compra, y nuestro cálculo será obsoleto e incorrecto. Pero el DOM se cambia poco a poco, por eso incluso un cálculo ligeramente obsoleto permanece bastante preciso para evaluar el mercado en el momento de la compra.
2.2. Calculamos el deslizamiento potencial en tiempo real
Después de aprender la teoría, es necesario aplicarla a la práctica. Es imposible calcular el tamaño del deslizamiento potencial manualmente porque los valores en el DOM cambian muy rápido y el propio cálculo es un proceso muy complicado. Por eso vamos a necesitar automatizar nuestros cálculos. Para facilitar los cálculos, vamos a incluir en nuestro proyecto la clase especial CMarketBook para trabajar con el DOM. El desarrollo de una clase de este tipo es una tarea complicada, digna de un artículo separado. No hace falta distraernos describiendo el funcionamiento de esta clase aquí, sólo utilizaremos uno de sus métodos: GetDeviationByVol. Vamos a ver cómo funciona:
//+------------------------------------------------------------------+ //| Get deviation value by volume. Retun -1.0 if deviation is | //| infinity (insufficient liquidity) | //+------------------------------------------------------------------+ double CMarketBook::GetDeviationByVol(long vol,ENUM_MBOOK_SIDE side) { int best_ask = InfoGetInteger(MBOOK_BEST_ASK_INDEX); int last_ask = InfoGetInteger(MBOOK_LAST_ASK_INDEX); int best_bid = InfoGetInteger(MBOOK_BEST_BID_INDEX); int last_bid = InfoGetInteger(MBOOK_LAST_BID_INDEX); double avrg_price=0.0; long volume_exe=vol; if(side==MBOOK_ASK) { for(int i=best_ask; i>=last_ask; i--) { long currVol=MarketBook[i].volume<volume_exe ? MarketBook[i].volume : volume_exe; avrg_price += currVol * MarketBook[i].price; volume_exe -= MarketBook[i].volume; if(volume_exe<=0)break; } } else { for(int i=best_bid; i<=last_bid; i++) { long currVol=MarketBook[i].volume<volume_exe ? MarketBook[i].volume : volume_exe; avrg_price += currVol * MarketBook[i].price; volume_exe -= MarketBook[i].volume; if(volume_exe<=0)break; } } if(volume_exe>0) return -1.0; avrg_price/=(double)vol; double deviation=0.0; if(side==MBOOK_ASK) deviation=avrg_price-MarketBook[best_ask].price; else deviation=MarketBook[best_bid].price-avrg_price; return deviation; }
Cuando se invoca, este método se dirige al DOM. Repasa el DOM empezando desde el mejor precio, y calcula el volumen disponible. En cuanto el volumen disponible sea igual o superior al requerido, el método finaliza la búsqueda y calcula el precio medio ponderado correspondiente al volumen establecido. La diferencia entre este precio medio ponderado y el mejor precio de la demanda (bid) o la oferta (ask) será el valor de nuestro deslizamiento potencial.
Si por alguna razón la liquidez del DOM no es suficiente para el volumen especificado, el método devolverá el valor -1.0 indicándonos que es imposible calcular el deslizamiento potencial.
Ahora, cuando ya tenemos el método del cálculo del deslizamiento potencial, necesitamos visualizar los resultados obtenidosl. Es obvio que el valor del deslizamiento está relacionado con el volumen que hay que comprar o vender en el mercado. Cuanto más grande sea el volumen, más grande será el deslizamiento. De esta manera, hay que añadir en nuestro panel una nueva línea y campo de entrada: “Volumen de la operación” o "Volume":
Fig. 16. Panel con el campo de entrada del volumen necesario
Ahora nuestro panel podrá comprar y vender un volumen arbitrario. Por ejemplo, para comprar 5 contratos a precio de mercado, simplemente tenemos que introducir el valor “5” en el campo "Volume" y pulsar el botón "BUY". No es la única novedad. Como ya hemos dicho, hemos aprendido a controlar el tamaño de nuestro deslizamiento en el momento de la entrada gracias al método GetDeviationVol.
Para que este valor sea más claro, vamos a mostrarlo directamente en los botones “BUY” y “SELL”, respectivamente. Nuestro deslizamiento estará expresado en puntos. Este valor va a calcularse de nuevo con cada cambio del DOM. Si la liquidez se aumenta, el valor del deslizamiento se reduce, y si la liquidezse disminuye, pues al revés, se incrementa. Si queremos comprar o vender sólo un contrato, no habrá ningún deslizamiento ya que el volumen que necesitamos (1 contrato) nunca superará el volumen de la mejor demanda u oferta.
Lo mejor que observe el funcionamiento del panel renovado en tiempo real. En el vídeo de abajo se muestra el cálculo del deslizamiento potencial para el futuro RTS-6.15 en tiempo real:
Al principio, en el campo “Volume” se introduce un contrato. Como era de esperar, los botones “BUY” y “SELL” muestran el valor 0. Eso quiere decir que nuestra entrada en el mercado no supone deslizamiento. Después de aumentar el volumen hasta 100 contratos, el deslizamiento medio para las compras y ventas se aumenta de hasta 10-20 puntos. Cuando el volumen alcanza 500 contratos, el deslizamiento medio sube aún más: 60-80 puntos. Finalmente, después de fijar el volumen en 1500 contratos, empieza a faltar la liquidez de la oferta, y el botón BUY lo muestra visualizando el valor -1.0 (deslizamiento no determinado). La liquidez de la demanda sigue siendo suficiente, aunque la venta de esta cantidad de contratos provocará el deslizamiento de 100-130 puntos.
La clase para trabajar con el DOM, así como la versión final del panel DeviationPanel, están disponibles en los códigos fuente adjuntos al artículo.
2.3. Indicador del spread SpreadRecord como filtro para entrar en la posición
Analizar la liquidez actual antes de entrar en el mercado es una buena práctica comercial. Si delegamos a nuestro Asesor Experto los cálculos complejos de una manera acertada, podemos protegernos contra un deslizamiento destructivo y una entrada en el mercado en un momento inconveniente. Pero no siempre es suficiente.
Otra cuestión problemática es el cálculo fiable del ancho del spread. El spread es la diferencia entre los mejores precios de compra y venta. En gran medida, es un parámetro relativo por el hecho que las operaciones con volúmenes grandes son afectadas sobre todo por la liquidez general del DOM y no por el ancho del spread como tal. Pero habitualmente el trader no puede acceder al historial del DOM por eso es bastante difícil juzgar de la liquidez histórica de un contrato comercial. Por otro lado, el valor del spread está inversamente correlacionado con la liquidez del instrumento financiero. Cuanto más estrecho sea el spread, más alta será la liquidez, y viceversa.
Teniendo está particularidad en la mente, podemos crear nuestro propio indicador del spread que nos mostraría sus valores históricos. Este indicador será sumamente útil para negociar, ya que permite evaluar visualmente los valores históricos de la liquidez y el ancho del spread de un instruemento. Sabiendo el valor medio del spread, podemos limitar nuestro trading en el momento del cambio brusco de la liquidez, cuando el spread se expande significativamente.
Entonces, vamos a crear este indicador. Va a mostrar sus valores en forma de las barras en la ventana inferior del gráfico. El valor medio del spread se mostrará como un punto verde en el nivel correspondiente de la barra. El indicador va a calcular los siguientes valores del spread:
- valor del spread en el momento de la apertura de la barra;
- nivel máximo del spread alcanzado durante la barra;
- nivel mínimo del spread alcanzado durante la barra;
- valor del spread en el momento del cierre de la barra;
- valor medio del spread durante la barra.
Nuestro indicador no va a guardar los valores del spread, y después del reinicio del terminal va a dibujar el spread a partir de la última barra. A continuación va el código fuente de este indicador:
//+------------------------------------------------------------------+ //| Spread Record.mq4 | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Vasiliy Sokolov." #property link "https://www.mql5.com/es/users/c-4" #property version "1.00" #property description "Recording spread and show it." #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 5 #property indicator_type1 DRAW_BARS #property indicator_type2 DRAW_ARROW #property indicator_color1 clrBlack #property indicator_color2 clrBlack double spread_open[]; double spread_high[]; double spread_low[]; double spread_close[]; double spread_avrg[]; int elements; double avrg_current; int count; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,spread_open,INDICATOR_DATA); SetIndexBuffer(1,spread_high,INDICATOR_DATA); SetIndexBuffer(2,spread_low,INDICATOR_DATA); SetIndexBuffer(3,spread_close,INDICATOR_DATA); SetIndexBuffer(4,spread_avrg,INDICATOR_DATA); IndicatorSetInteger(INDICATOR_DIGITS,1); PlotIndexSetInteger(1,PLOT_ARROW,0x9f); PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrRed); PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrGreen); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { printf("DEINIT"); } //+------------------------------------------------------------------+ //| 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[]) { //--- if(prev_calculated==0) { printf("INITIALIZE INDICATORS "+TimeToString(TimeCurrent())); double init_value=EMPTY_VALUE; ArrayInitialize(spread_high,init_value); ArrayInitialize(spread_low,init_value); ArrayInitialize(spread_open,init_value); ArrayInitialize(spread_close,init_value); ArrayInitialize(spread_avrg,init_value); elements=ArraySize(spread_high); InitNewBar(elements-1); } //--- new bar initialization for(; elements<ArraySize(spread_high); elements++) InitNewBar(elements); double d=GetSpread(); for(int i=rates_total-1; i<rates_total; i++) { if(d>spread_high[i]) spread_high[i]=d; if(d<spread_low[i]) spread_low[i]= d; spread_close[i] = d; avrg_current+=d; count++; spread_avrg[i]=avrg_current/count; } //--- return value of prev_calculated for next call return(rates_total-1); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double GetSpread() { double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); return NormalizeDouble((ask-bid)/Point(), 0); } //+------------------------------------------------------------------+ //| Init new bar | //+------------------------------------------------------------------+ void InitNewBar(int index) { spread_open[index] = GetSpread(); spread_high[index] = 0.0; spread_low[index]=DBL_MAX; avrg_current=0.0; count=0; }
Intentamos iniciar este indicador en el gráfico M1 de Si-6.15. Poco después de su inicio, nos muestra los siguientes resultados:
Fig. 17. Indicador SpreadRecord iniciado en el gráfico M1 de Si-6.15
Durante el período analizado, el spread oscilaba entre 1 y 21 puntos. Durante cada minuto, hubo por lo menos un momento cuando el tamaño del spread correspondía al valor mínimo de 1 punto. El valor medio del spread fue de 3 puntos. Como ya ha sido mencionado, este valor se muestra como un punto verde en el gráfico del indicador.
2.4. Limitación manual y automática del trading durante la extensión fuerte del spread
Ahora tenemos que aprender a utilizar este indicador para controlar nuestros riesgos. Lo más simple que podemos hacer es limitar nuestra actividad comercial en el momento cuando los valores del indicador son demasiado elevados. Para el período de tiempo seleccionado, los valores del indicador se encontraban principalmente entre 1 y 9 puntos. Condicionalmente, esta zona puede llamarse la zona “verde”. Para este intervalo el trading estará permitido. Si el valor del spread sube por encima de 9 puntos, pasaremos a la zona roja, donde el trading estará prohibido. En el gráfico, se puede demostrarlo de la siguiente manera:
Fig. 18. Zonas del trading habilitado y deshabilitado determinas por el indicador
Aparte de la limitación manual de la negociación, también tenemos que enseñar a nuestro EA aceptar los valores de este indicador y limitar su actividad comercial cuando el valor del spread actual supera los límites establecidos. Se puede hacerlo mediante la llamada al indicador desde el EA, usando la función iCustom. Ella permite llamar a cualquier indicador personalizado directamente desde su EA, obteniendo los valores de estos indicadores. Abajo se encuentra la plantilla del EA que controla el spread usando este indicador:
//+------------------------------------------------------------------+ //| SpreadRecordControl.mq5 | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" #define OPEN 0 #define HIGH 1 #define LOW 2 #define CLOSE 3 #define AVRG 4 input int MaxSpread=9; int h_spread_record=INVALID_HANDLE; // Handle of SpreadRecord indicator bool print_disable = false; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { h_spread_record=iCustom(Symbol(),Period(),"Spread Record"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinit function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(h_spread_record); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(IsTradeDisable(MaxSpread))return; // // TRADE LOGIC... // } //+------------------------------------------------------------------+ //| Return true if trade disable, otherwise return false | //+------------------------------------------------------------------+ bool IsTradeDisable(int max_spread) { if(h_spread_record==INVALID_HANDLE) return false; double close[]; if(CopyBuffer(h_spread_record, CLOSE, 0, 1, close) < 1)return false; if(close[0]>MaxSpread) { if(!print_disable) printf("trade disable"); print_disable=true; return true; } if(print_disable) printf("trade enable"); print_disable=false; return false; }
La función IsTradeDisable está responsable principalmente de determinar si se puede negociar o no. Devuelve true si el spread es demasiado alto y el trading tiene que estar prohibido. Si el spread se encuentra en un nivel aceptable, devuelve false. La función se basa en la llamada al indicador SpreadRecord mediante el copiado de su valor actual utilizando la función CopyBuffer. El EA contiene el parámetro MaxSpread que representa el valor límite. Si este valor se supera, el EA bloquea su actividad comercial. Si el spread cae por debajo del límite especificado, el EA vuelve a tradear. La función IsTradeDisable avisa sobre el traspaso de un estado al otro mostrando el mensaje correspondiente: "trade enable" y "trade disable":
2015.05.27 16:57:08.238 SpreadRecordControl (Si-6.15,H1) trade enable 2015.05.27 16:57:08.218 SpreadRecordControl (Si-6.15,H1) trade disable 2015.05.27 16:56:49.411 SpreadRecordControl (Si-6.15,H1) trade enable 2015.05.27 16:56:49.401 SpreadRecordControl (Si-6.15,H1) trade disable 2015.05.27 16:56:36.478 SpreadRecordControl (Si-6.15,H1) trade enable 2015.05.27 16:56:36.452 SpreadRecordControl (Si-6.15,H1) trade disable
Usted puede usar este prototipo del EA para sus sistemas de trading evitando así las entradas en los momentos de baja liquidez y fuerte deslizamiento.
El código fuente del EA e indicador SpreadRecord se adjunta a este artículo.
Capítulo 3. Modos seguros del trading y simulación de los EAs
3.1. “Modo de reposo” como alternativa al control tick por tick
Como ha sido dicho en el aparatado 1.1 “Discontinuidad de los precios de flujo. Brechas de precios (Gaps)”, los precios del mercado pueden representarse como un flujo continuo de precios. En esta representación, por ejemplo, el cambio del precio de la acción de $10 a $15 significa que en los momentos intermedios había precios 11, 12, 13 y 14 dólares, respectivamente. No obstante, en el mismo apartado hemos averiguado que eso no siempre es cierto.
A menudo los precios pueden variar a saltos. Pero normalmente nuestros métodos de la negociación se basan en la suposición de que los precios cambian gradual y consecuentemente. Por ejemplo, la colocación del Stop Loss de protección para nuestras estrategias supone que nuestra posición se cerrará en el nivel del Stop Loss antes de alcanzar la pérdida destructiva. Sin embargo, la base de cualquier orden Stop es así llamado pedido Stop: un consentimiento para comprar o vender a cualquier precio disponible si este precio supera un determinado nivel Stop. En caso de precios discretos, esta orden Stop envuelve un riesgo importante, y en vez de proteger nuestra cuenta contra las pérdidas destructivas, es capaz de crea estas mismas pérdidas. Si el precio actual va a ser varias veces peor que el precio indicado en nuestro pedido Stop, Stop Loss se ejecutará igualmente, dejándonos con una pérdida mucho mayor de la calculada.
Por otro lado, si EA comprueba la situación de mercado en cada nuevo tick recibido, también arriesga cerrar la posición a un precio muy diferente del precio del mercado, puesto que la última transacción que genera este tick en caso de baja liquidez puede realizarse por un precio absolutamente increíble provocando la aparición del pico de precios.
Por tanto, en vez de rastrear cada tick, sería más razonable “insensibilizar” la sensibilidad de la estrategia: es decir, no ejecutar la lógica comercial del EA en cada tick, sino hacerlo una vez durante un determinado período de tiempo (por ejemplo, una vez cada minuto). También hay que rechazar el uso de los pedidos Stop.En vez de las órdenes Stop, es mejor utilizar las Stops algorítmicas (virtuales) las condiciones de activación de las cuales también van a comprobarse una vez en un determinado período.
Puede parecer que esta “insensibilidad” de la lógica comercial provocará la distorsión significante de los resultados comerciales, pero no es así. Claro que durante un minuto el precio puede moverse a una distancia considerable desde la salida potencial o entrada en la posición, pero también van a surgir las situaciones más favorables cuando las operaciones no van a realizarse cerca de los giros de precios.
Vamos a mostrar este enfoque en una situación real que tuvo lugar el 28 de mayo con el contrato de futuros Si-6.15 rublo/dólar. A las 10:03 (hora de Moscú) tuvo lugar un pico de precios (spike) bastante fuerte. Supongamos que para este momento teníamos abierta una posición larga por el precio de 53 040 con la parada de protección en 52 740 (300 puntos). En este caso, el spike haría activarse nuestra parada de protección, y el precio de activación sería mucho más bajo que el precio declarado en el nivel Stop.
Como muestra la práctica, en estos casos los pedidos Stop se ejecutan por los precios cercanos a los peores precios. En este caso, el peor precio es de 52 493. Así, debido a la activación del Stop Loss, sufriríamos pérdidas de 53 040 - 52493 = 547 rublos por un contrato (en vez de 300 rublos por contrato especificados en nuestro nivel Stop). Esta situación se muestra en el gráfico A de la imagen de abajo. Si comprobaramos nuestro Stop una vez por minuto, este pico de precios sería ignorado por nuestra estrategia. La estrategia no ejecutaría nuestro Stop Loss, y en adelante podríamos cerra nuestra posición con ganancias. Esta situación se muestra en el gráfico B.
Fig. 19. Diferente comportamiento de estrategias en caso del pedido Stop real y vertual
El pico de precios de este ejemplo es bastante pequeño. Los spikes pueden llegar a unos valores realmente significativos. Se conocen los casos cuando estos picos alcanzaban los límites de precios de un contrato de futuros. Generalmente, los límites de precios se ubican a una distancia de un 5% del precio actual. Eso significa que si usamos el apalancamiento 1:1, podemos perder un 5% del depósito de nuestra cuenta debido a la ejecución del pedido Stop. ¡En caso del trading con el apalancamiento 1:10, las pérdidas alcanzarán un 50%!
3.2. Ejemplo del Asesor Experto basado en las medias móviles que comprueba su lógica una vez durante el período
Un Asesor Experto (EA) que opera en la intersección de dos medias móviles es un buen ejemplo de cómo hacer que la lógica del EA compruebe las condiciones del mercado una vez durante un período. Se sabe que el último valor de la media móvil (MA) se cambia constantemente tras el cambio del precio del cierre de la última barra ya que la última barra siempre se encuentra en el estado de formación.
Muchos traders conocen muy bien la estrategia clásica con dos MAs. El EA compra cuando la MA rápida cruza la MA lenta de abajo arriba, y vente cuando la MA rápida cruza la lenta de arriba abajo. En el gráfico de abajo se muestran las señales de entrada en la posición larga y corta para esta estrategia:
Fig. 20. Señales de entrada en la posición larga y corta para la estrategia MovingAverage
Como se ha mencionado antes, los valores de las MAs de las últimas barras se cambian constantemente. En este caso puede surgir la situación cuando la MA rápida va a cruzar la MA lenta varias veces durante una barra. En estos momentos el EA va a hacer muchas reversas, aunque el precio seguirá siendo casi el mismo. También sabemos que para los mercados de futuros es mejor evitar la comprobación de las condiciones en cada nuevo tick entrante. De esta manera, la elección natural para esta estrategia será el modo de comprobación de la lógica comercial una vez por minuto. En este caso, el EA tendrá que comprobar la barra anterior (ya formada), en vez de la barra actual, por eso le “redibujo” de la MA en la última barra no nos va a afectar.
A continuación, se muestra el código del EA MovingAverage:
//+------------------------------------------------------------------+ //| MovingAverage.mq5 | //| Copyright 2015, Vasiliy Sokolov. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Vasiliy Sokolov." #property link "http://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> input int FastMAPeriod = 10; // Fast MA period input int SlowMAPeriod = 20; // Slow MA period input double Volume = 1.0; // Volume for Trade int FastMA = INVALID_HANDLE; // Handle of fast MA indicator. int SlowMA = INVALID_HANDLE; // Handle of slow MA indicator. datetime TimeLastBar; CTrade Trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { FastMA = iMA(Symbol(), Period(), FastMAPeriod, MODE_SMA, 1, PRICE_CLOSE); SlowMA = iMA(Symbol(), Period(), SlowMAPeriod, MODE_SMA, 1, PRICE_CLOSE); if(FastMA==POINTER_INVALID || SlowMA==POINTER_INVALID) { printf("handle of indicator has not been created"); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(FastMA); IndicatorRelease(SlowMA); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(!NewBarDetect())return; if(CrossOver()) Trade.Buy(GetVolume()); else if(CrossUnder()) Trade.Sell(GetVolume()); } //+------------------------------------------------------------------+ //| Return true if fast ma cross slow ma over. Otherwise return | //| false. | //+------------------------------------------------------------------+ bool CrossOver() { double fast_ma[]; double slow_ma[]; if(CopyBuffer(FastMA, 0, 1, 2, fast_ma) < 1)return false; if(CopyBuffer(SlowMA, 0, 1, 2, slow_ma) < 1)return false; bool is_over=fast_ma[1]>slow_ma[1] && fast_ma[0]<slow_ma[0]; return is_over; } //+------------------------------------------------------------------+ //| Return true if fast ma cross slow ma under. Otherwise return | //| false. | //+------------------------------------------------------------------+ bool CrossUnder() { double fast_ma[]; double slow_ma[]; if(CopyBuffer(FastMA, 0, 1, 2, fast_ma) < 1)return false; if(CopyBuffer(SlowMA, 0, 1, 2, slow_ma) < 1)return false; bool is_under=fast_ma[0]>slow_ma[0] && fast_ma[1]<slow_ma[1]; return is_under; } //+------------------------------------------------------------------+ //| Return count volume for trade/ | //+------------------------------------------------------------------+ double GetVolume() { if(PositionSelect(Symbol()))return Volume*2.0; return Volume; } //+------------------------------------------------------------------+ //| Return true if new bar detect, otherwise return false. | //+------------------------------------------------------------------+ bool NewBarDetect() { datetime times[]; if(CopyTime(Symbol(),Period(),0,1,times)<1) return false; if(times[0] == TimeLastBar)return false; TimeLastBar = times[0]; return true; } //+------------------------------------------------------------------+
La particularidad principal de este EA consiste en las condiciones de comprobación de la llegada de la nueva barra:
void OnTick() { if(!NewBarDetect())return; ... }
Stop Loss no se usa en la versión actual del EA. Sin embargo, si fuera utilizado, la comprobación de la salida de la posición por Stop Loss estaría ubicada detrás de la función de la detección de la nueva barra y sería llamada sólo en el caso de la formación de la nueva barra.
Eso nos permite “saltar” los spikes potenciales en forma de los ticks, analizando la situación del mercado sólo en el momento de la apertura de una nueva barra. Clarro que puede surgir la situación cuando el pico de precios ocurre precisamente en el momento de la apertura de la barra nueva, pero esta probabilidad es cien veces menor que la probabilidad de que ocurra el pico de precios cuando el EA procesa cada tick.
3.2. Prueba del EA en modo de barras formadas como alternativa a la prueba tick por tick
Finalmente, vamos a describir uno de los modos más interesantes de la simulación de los EAs e indicadores en el Probador de Estrategias de MetaTrader 5. Este modo se llama“Sólo precios de apertura”. Para usarlo, es necesario iniciar el Probador de Estrategias seleccionando en el menú el comando “Ver” --> “Probador de Estrategias”. Luego, en la ventana del Probador que se ha abierto, hay que seleccionar este modo entre las opciones de “Modo del trading”.
Fig. 21. Seleccionar el modo del trading “Sólo precios de apertura”
A menudo, a este modo de prueba se le da poca importancia. Pues, eso se debe al hecho de que muchos traders piensan que es un modo de prueba impreciso o de estimación. Además, para este modo valen sólo los EAs escritos de una manera especial. No obstante, pocos saben que en realidad se trata del modo de prueba más preciso y rápido. Por ejemplo, el modo “Todos los ticks” cede bastante ante este modo en cuanto a la precisión y la velocidad de la simulación.
El hecho de que en este modo se utiliza sólo el precio actual de apertura de la barra permite conseguir el alto nivel de precisión de la simulación. Todos los precios de la nueva barra se hacen disponibles sólo después de su completa formación y su traspaso al historial (cuando se ha convertido en la barra anterior en la secuencia histórica de los precios).
Al contrario, el modo de prueba “Todos los ticks” forma cada barra de una manera especial de conseguir los datos desde el menor período de tiempo disponible y utilizando su propio generador de ticks. Tomando en cuenta que MetaTrader 5 no almacena el historial de ticks, este generador no puede simular los picos de precios dentro de la barra de un minuto. Sabiendo esta particularidad, se puede crear (intencionadamente o no) el “Grial” de prueba que va a mostrar excelentes resultados en el Probador de Estrategias pero no va a funcionar en el mercado real.
El modo de prueba tick por tick representa el mayor peligro para las estrategias basadas en la ruptura de algún nivel. Es más, las órdenes pendientes también pueden alterar los resultados reales. Vamos a considerar una estrategia que coloca una orden pendiente Buy Stop y espera un fuerte movimiento alcista. El 25 de mayo de 2015, a las 19:00, justo después de la Compensación de la tarde (Clearing), el contrato de futuros SBRF-6.15 se movía fuertemente durante un minuto hacia arriba de 7 473 a 7 530 rublos. Si tuviéramos una orden pendiente colocada en el nivel de 7 485, se activaría en el Probador de Estrategias por su precio y nos traería ganancias, si cerrásemos la posición unas barras más tarde:
Fig. 22. Esquema de activación de la orden pendiente
Sin embargo, durante la sesión de trading real la situación puede ser absolutamente diferente. No sabemos nada sobre los precios dentro de la barra de un minuto. En otras palabras, la orden puede ejecutarse por un precio mucho peor para nosostros. Vamos a ver cómo se ejecuta la orden en el modo de prueba de cada tick (véase el vídeo de abajo):
Como podemos observar, el Probador ha ejecutado nuestro precio sin problema alguno. Pero vamos a fijarnos en el gráfico de ticks de esta vela de un minuto:
Fig. 23. Gráfico de ticks de la vela de un minuto
El precio pasaba momentos dramáticos durante este minuto. Este gráfico de ticks se caracteriza por unas grandes brechas (gaps) de precio. Los precios se cambian bruscamente, mostrando grandes picos. Es poco probable que nuestra orden Stop podría ejecutarse por el precio solicitado; lo más probable que la ejecución real estaría en el nivel 7 510 - 7 520.
Si analizáramos cada tick y en vez de las órdenes pendientes utilizáramos la entrada de mercado, no se cambiaría nada. El generador de ticks del Probador de Estrategias genera los ticks de forma consecutiva. En cuanto el precio Ask alcance nuestro nivel en el Probador, nuestra orden se ejecutaría. En realidad, no habría posibilidad de ejecutar nuestro pedido por los precios especificados.
Por esta razón, hay que tener cuidado con el uso del modo “Todos los ticks”. Usted debe comprender qué sensible es la estrategia a probar en cuanto a los picos de precios bruscos.
El modo de simulación más seguro es el modo de prueba a base de las barras formadas. Para conseguir la precisión de la estrategias, en este modo no deben utilizarse las órdenes pendientes. Si nuestra estrategia tuviera que entrar en el mercado por el precio 7 495, tendría que comprobar el precio de apretura de cada barra nueva, y en caso cuando el precio superara el nivel necesario, realizar la compra por el precio actual en el momento de la apertura. En el modo de las barras formadas, podríamos saber que el precio se encuentra por encima del precio necesario sólo en el momento de apertura de la barra nueva a las 19:01, porque el precio de apertura de la barra de las 19:00 estaba aún por debajo de 7 495 rublos. En el modo de las barras formadas, nuestra operación sería así en el gráfico:
Fig. 24. La operación real en el modo de las barras formadas
Aunque el resultado final de esta operación haya sido negativo, ella tiene una ventaja indiscutible:
El modo de simulación con barras formadas garantiza que todas las transacciones hayan sido realizadas a precios históricos reales. De esta manera, este modo es el más preciso, y se puede recomendarlo para probar las estrategias en los mercados de baja liquidez.
Si utiliza la estrategia en el período de tiempo mayor que M1, pero resulta inadmisible verificar las condiciones comerciales una vez por período, se puede usar la variante opcional iniciando la simulación en el modo “OHLC de M1”. Este modo genera cada barra a base de los precios memorizados para el gráfico M1. Puesto que todos los precios del gráfico M1 son históricos, este modo también posee la precisión absoluta y puede ser recomendado como un modo de prueba razonable para las estrategias a medio plazo.
No se puede aplicar el modo de prueba “Todos los ticks” para las estrategias que trabajan en los mercados de baja liquidez. Además, estas estrategias no deben usar las órdenes Stop en sus actividades.
Muchos traders pueden replicar en contra del modo de prueba por los precios de apertura, argumentando que la precisión de las entradas es de importancia crítica para los sistemas de trading. La diferencia en sólo unos puntos puede alterar significativamente los resultados finales de la estrategia. A este argumento se puede responder acudiendo a la ley de los grandes números. La diferencia entre la entrada calculada y real en el mercado es un mero componente de ruído. A menudo, la entrada va a realizarse por los precios peores que los precios calculados. Sin embargo, en algunas ocasiones el extremo del precio va a romper el nivel calculado, y luego volver hacia atrás durante la misma barra.
Si probáramos el EA en el modo “Todos los ticks”, tendríamos pérdidas durante estos momentos. A al revés, en el modo de barras formadas podríamos evitar la entrada en el mercado durante estas situaciones. En otras palabras, la entrada en el mercado por los peores precios se compensaría con otros efectos positivos. En general, la diferencia se nivelaría completamente y el resultado de la estrategia se dependería de la idea implementada en ella, y no del nivel momentáneo de la entrada.
Conclusión
Ha llegado la hora de resumir las tesis principales que podemos deducir del material expuesto en este artículo:
El precio del mercado es discreto por su naturaleza. Se compone de múltiples transacciones que forman los gráficos del mercado ya conocidos. Los gráficos ocultan la naturaleza discreta de los precios del mercado. Al analizar una barra de precios, no podemos determinar de una manera cierta qué precios han tenido lugar durante el período de su formación. En la primera aproximación se supone que la liquidez de las barras es infinita y el rango de cada barra se rellena con los precios uniformemente, de modo que en cada potencial nivel de precios existe su precio.
La discontinuidad de los precios del mercado puede ser extremadamente alta en los mercados de baja liquidez. Hay que tomarla en cuenta durante el trading usando las órdenes limitadas para entrar y salir del mercado. Las órdenes limitadas nos permiten superar la naturaleza discreta de los precios del mercado, así como evitar el deslizamiento excesivo.
En MetaTrader 5 existen los tipos especiales de las órdens Buy Stop Limit y Sell Stop Limit que pueden sustituir los niveles clásicos Stop Loss. Son absolutamente seguros, permiten controlar el deslizamiento máximo incluso cuando el terminal no está iniciado.
Los precios del mercado, aparte de su naturaleza discreta, disponen de una determinada liquidez que también hay que tomar en cuenta en algunas ocasiones. La liquidez actual influye en el valor del deslizamiento. Si sabemos el estado actual de la Profundidad del Mercado (DOM), podemos calcular el valor de nuestro deslizamiento potencial.
El control del spread actual es la manera más sencilla para evaluar la liquidez potencial sin usar el DOM. El nivel del spread depende inversamente de la liquidez del instrumento financiero Si el spread es muy alto, es mejor no realizar la actividad comercial y esperar un momento más apropiado para realizar la transacción.
El “modo de reposo” es la protección segura contra los picos de precios para nuestros EAs. En este modo, la lógica del EA se comprueba sólo una vez en el momento de la formación de una barra nueva. Además, los EAs escritos en este modo están compatibles para la prueba en el modo de barras formadas.
El modo de barras formadas es el modo más preciso de la prueba debido al hecho de que utiliza los precios históricos discretos y reales en su trabajo. Aparte de eso, este modo tiene una alta velocidad de la prueba. Los modos de prueba a base de las barras formadas y “OHLC en M1” son los únicos modos de la prueba que se puede utilizar para los mercados de baja liquidez.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1683
![Asesores Expertos basados en sistemas populares de trading, y un poco de alquimia en la optimización de robots (Parte II)](https://c.mql5.com/2/15/576_89.gif)
![MetaEditor: plantillas como punto de apoyo](https://c.mql5.com/2/15/573_135.jpg)
![Análisis comparativo de 30 indicadores y osciladores](https://c.mql5.com/2/15/577_13.gif)
![Asesores Expertos basados en sistemas populares de trading, y un poco de alquimia en la optimización de robots](https://c.mql5.com/2/15/575_71.gif)
![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