Mi primer "Grial"

Сергей Ковалев | 15 febrero, 2016


"...el arte no se puede programar, no se pueden crear
dos sentidos de una poesía. Los talentos no se pueden
plantar
. Nacen. Son riqueza
nacional, como depósitos de radio,
como septiembre en Sigulda, o Bethesda..."
(Andrey Voznesenskiy)


Generalmente se cree que el Santo Grial es la copa de la Cristo bebió en La Última Cena y la que utilizó José de Arimatea para coger su grande cuando estaba colgado en la cruz. Algunos escritores presentan el grial como una piedra que emana una sustancia que evita que quien la tenga, muera en esa semana. Puede leer más aquí o usar cualquier herramienta de búsqueda en internet.

La palabra "grial" se utiliza a menudo irónicamente entre los programadores modernos. Para ellos significa la imposibilidad de crear un programa "universal" para cualquier ocasión. En cuanto a la programación en MQL4, esta palabra significa la imposibilidad de crear un experto que dé buenos resultados en el trading real.

En realidad, forex es el reflejo de un complejo conglomerado de fenómenos económicos y relaciones industriales, caracteres humanos, política, etc. Es más, es tan importante que no se puede formalizar sin más. Los traders con más experiencia recomiendan entrar en el mercado sólo si hay de tres a cinco (o incluso más) señales que indican que un trend es posible.

Al mismo tiempo, las regularidades determinadas hoy en día, no pueden proporcionar una base profunda para los pronósticos de mercado con altas probabilidades de éxito. El pronóstico contradictorio que hacen los principales analistas de los bancos y organizaciones financieras más importantes lo confirman. Todos los analistas, sin excepción, pueden interpretar muy bien los eventos que ya han ocurrido, pero sólo unos cuantos pueden dar una serie de pronósticos seguros.

Vamos a hablar de ellos: Estas personas hacen lo que pueden hacer, la mayoría de ellos tienen mucha experiencia en trading y tienen muchos conocimientos que nosotros querríamos tener. Sin embargo, vamos a llamar a las cosas por su nombre: prácticamente todos ellos se equivocan a menudo. Pueden ver muchas cosas, disfrutar de más o menos popularidad, crear a veces mucho dinero (en el libro de Alexander Elder ,Ganarse la vida haciendo trading: Psicología, tácticas de trading, gestión del dinerose describen muy bien a los "gurús" de distintos tipos) pero el hecho es que, incluso los analistas con más experiencia, se equivocan a menudo.

Así que, teniendo en cuenta estas circunstancias, ¿cuáles son las posibilidades de un programador novel que está dando sus primeros pasos en el trading en Forex? Vamos a marcar el camino que hace el principiante en su búsqueda del "Grial".


1. De qué está formado el "Grial"

En la lógica formal, hacer referencia a una autoridad no se considera una prueba. Sabiendo esto, las razones del primer "grialer" van más o menos en esta dirección: "¿Puedes demostrar que la creación del "grial" es imposible? ¿No? Entonces, ¡es posible!" El principiante no tiene en cuenta que la posibilidad de la creación de algo así tampoco se ha demostrado todavía. Y, por lo tanto, sin considerar o, a menudo, sin estudiar las experiencias de otros "cazadores de tesoros", sino inspirados por el pensamiento de "¡Voy a poder hacerlo!", basándose exclusivamente en su entusiasmo y poca experiencia, empieza a programar.

1,1. Estrategia formal

En la mayoría de los casos, el programador principiante no se otorga la tarea de crear una estrategia de trading con muchos beneficios en poco tiempo. Llevado por el sueño de grandes beneficios en Forex en poco tiempo, sin embargo, se da cuenta de que se requieren una serie de criterios precisos de trading para un experto que dé beneficios.

Para encontrar los buenos criterios, el programados abre la Terminal de Cliente de Meta Trader 4 y mira el gráfico de EURUSD en el periodo de tiempo M1. Es muy fácil darse cuenta que el tipo de moneda varia en curvas: arria y abajo, arriba y abajo. El programador decide sacar beneficio a estas ondas. Pero, para "atrapar" una onda, hay que saber, de alguna manera, que la onda ha parado, por ejemplo, de subir y ha empezado a bajar.

Si se elije el simple movimiento de las divisas como criterio de dirección, no tendrá ningún resultado, ya que las velas blancas y negras se remplazan unas a otras con mucha frecuencia y el rango de esos cambios está dentro del valor de margen o muy cerca de él. Además, sería preferible entrar al mercado en el pico de la curva, no en la pendiente. Y las ondas, afortunadamente, tienen diferentes alturas. Si reflexiona un poco, el programador determina los siguientes criterios:


img 1. Los criterios de trading para el Grial Experto_1 (Grial 1).

La vida siempre nos prepara experiencias increíbles e inesperadas. El programador principiante sólo tardó 3 días en crear su primer "grial".

extern int TP=100; extern int SL=100; extern int lim=1; extern int prodvig=3;
extern double  Prots= 10;
int   total, bb=0,ss=0; double max,min,lmax,lmin,Lot; 
int start(){
total=OrdersTotal(); if (total==0){bb=0;ss=0;}
if (max<Bid) max=Bid;if (min>Ask) min=Ask;
if (((max-Bid)>=lim*Point)&&(Bid>lmax )) { for (int i=total;i>=0;i--) { 
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY)
{OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE); bb=0;}} Strateg(1); } 
if (((Ask-min)>=lim*Point)&&(lmin>Ask )) { for (i=total;i>=0;i--) {
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL)
{OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);ss=0;}}  Strateg(2);}return;}
void Strateg (int vv)                                    
{if (vv==1 && ss==0)                                   
{OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red); ss=1;}
if (vv==2 && bb==0)                                   
{OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);bb=1;}
lmax=Ask+prodvig*Point; lmin=Bid-prodvig*Point;   return;  }
double Lots(){ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   
if (Lot==0 ) Lot=Min_Lot; return(Lot);  }


Eso es lo que hay. Vamos a ser buenos - esta es la primera experiencia del programador principiante, que todavía tiene un estilo sin moldear. Y vamos a respetar este experto, ya que funciona y muestra un resultado fantástico.

Vamos a presentar el código de forma más amena y a intentar llegar al fondo de lo que es. Después de haberlo editado un poco, este experto puede tener este aspecto:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_1.mq4 (Grail 1).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int     TP = 100;                                 // TakeProfit orders
extern int     SL = 100;                                 // StopLoss orders
extern int     lim=   1;                                 // Distance of the rate return
extern int     prodvig=3;                                // Distance of the rate progress
extern double  Prots= 10;                                 // Percentage of the liquid assets
//--------------------------------------------------------------------------------------------
int
   total,                                                // Count of lots
   bb=0,                                                 // 1 = the Buy order is available
   ss=0;                                                 // 1 = the Sell order is available 
//--------------------------------------------------------------------------------------------
double 
   max,                                                  // Maximum price at the peak (abs.)
   min,                                                  // Minimum price in the trough(abs.)
   lmax,                                                 // Limiting price after the exceeding
                                                         // of which we consider selling(abs.)
   lmin,                                                 // The same for buying
   Lot;                                                  // Count of lots
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
   {   
//============================================================================================
   total=OrdersTotal();                                  // Count of lots
   if (total==0)                                         // If there are no orders, ..
      {
      bb=0;                                              // .. no Buys
      ss=0;                                              // .. no Sells
      }
   if (max<Bid) max=Bid;                                 // Calculate the max. price at the peak 
   if (min>Ask) min=Ask;                                 // Calculate the min. price in the trough
//------------------------------------------------------------- The price turns down ----
   if (((max-Bid)>=lim*Point)&&(Bid>lmax ))              // Turn at a high level
      {
      for (int i=total;i>=0;i--)                         // On all orders
         {                                               
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY)
            {
            OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);// Close Buy
            bb=0;                                        // No Buys anymore
            }
         }   
      Strateg(1);                                        // Opening function
      }             
//------------------------------------------------------------ The price turns up ----
   if (((Ask-min)>=lim*Point)&&(lmin>Ask ))              // Turn at the deep bottom
      {
      for (i=total;i>=0;i--)                             // On all orders
         {
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL)
            {         
            OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);// Close Sell   
            ss=0;                                        // No Sells anymore
            }
         }
      Strateg(2);                                        // Opening function
      }
//============================================================================================
   return;

   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Strateg (int vv)                                    // Opening function
   {
//============================================================================================
   if (vv==1 && ss==0)                                   // Sell situation and no Sells
      {
      OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red);// Откр
      ss=1;                                              // Now, there is a Sell
      }
//--------------------------------------------------------------------------------------------
   if (vv==2 && bb==0)                                   // Buy situation and no Buys
      {
      OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);// Откр
      bb=1;                                              // Now, there is a Buy
      }      
//--------------------------------------------------------------------------------------------
   lmax=Ask+prodvig*Point;                               // Redefine the new limiting ..
   lmin=Bid-prodvig*Point;                               // .. levels for open and close 
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                            // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amoung of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum permissible cost of lots
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*


Generalmente, los contenidos del experto son algo incomprensibles.

En la parte superior, antes de la función start(), se recopilan variables. En la función start(), primero se calcula la posición actual de la divisa en la pendiente de un pico, y se analiza la situación para iniciar los criterios de trading. Y, si los criterios se inician, se cierra la orden que ya se ha procesado. En el experto se usan otras dos funciones: Strateg(), para abrir nuevas órdenes; y Lots(), para determinar la cantidad de lotes. Para registrar las órdenes abiertas, se utilizan las variables ss y bb.

El Tester de estrategia es muy importante en la Terminal de Cliente de MetaTrader 4. Nuestro programador ha probado el experto detalladamente para mejorar las entradas y uno de los mejores resultados ha sido el siguiente:




img. 2. Un "Grial" clásico El resultado se ha obtenido en la prueba del experto Grial_1.mp4 (Grial 1), en los datos del historial de marzo de 2005 a junio de 2006 para M1 EURUSD bajo las condiciones de Trading del servidor demo de MetaQuotes Software Corp

Nos podemos imaginar la alegría del programador: ¡Ha creado esta obra de arte con sus propias manos! Aquí está: Nueva, sustancial y brillante con todas sus facetas perfectas, ¡su primer "grial"! Y llega a una conclusión simple: "¡Solo yo!"

No es necesario que resulte ninguna estrategia formal en la creación de un "grial" pero, en nuestros ejemplos, pasa. Vamos a investigar detalladamente lo que llevó al programador a este resultado.

1.2. Gran inversión

El programador no se paró a mitad de camino y decidió intentar y maximizar los valores de las órdenes. Aumentó el valor (en la prueba) hasta un 70% (el valor de la variable externa Prost=70) de liquidez, pero se comprobó que esta aproximación era inefectiva como resultado:


img . 3. Las inversiones agresivas pueden resultar en pérdidas injustificadas


Nuestro héroe estaba muy sorprendido con el resultado. Razonó así: "Si el experto da beneficios, ¡cuanto más inviertas, más consigues!". Pero los resultados del tester muestran que no es así a menudo.

Vamos a examinar qué fue lo que causó este resultado.

1.2.1 Progresión geométrica

Vamos a echar un vistazo a la tecnología del cálculo del valor de las órdenes De acuerdo al código de arriba, el valor de la orden crece en proporción a la cantidad de liquidez:

   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum allowed lot value
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots


Este algoritmo representa una progresión geométrica. La variable de Prots (porcentaje) permite regular el valor de la orden dependiendo de la cantidad actual de liquidez. De este modo, calcular el valor de la orden no es correcto del todo, ya que no tiene en cuenta las llamadas de margen cuando se trabaja con un vendedor específico. Al mismo tiempo, el fragmento del código de arriba permite solucionar el problema principal: el problema de las inversiones proporcionales. Por lo que el valor de cada orden siguiente dependerá proporcionalmente en los resultados obtenidos: el valor crecerá después de cada trade con beneficios y se reducirá después de cada trade sin beneficios. El valor de la orden en del código del Grial_1.mq4 (Grial 1) representa el 10% de la liquidez.

La progresión en sí no es un atributo necesario del "grial". Cualquier otro experto normal se puede crear utilizando esta tecnología. Sin embargo, la progresión geométrica tiene que excluirse del todo para poder investigar el "grial" con más detalle, y centrarse sólo en los resultados de pruebas obtenidos en un valor de orden mínimo constante (igual a un lote de 0.1, si es posible). En este caso, podemos estimar fácilmente la cantidad de puntos que se han ganado.

Vamos a establecer el valor de la variable Prost a 0 y, según el código de abajo,

   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min. lots

vamos a probar el experto en el valor del de la orden constante.

En este caso, el resultado será el siguiente:

img. 4. Resultados de la prueba del experto Graal_1.mq4 (Grial 1) en los valores de lote constante.

La exclusión de los valores progresivos de la orden visualiza la verdadera naturaleza de los cambios de las curvas: aumento, caídas profundas, etc.

1.2.2 Reinversión agresiva

Cualquier experto con beneficios, siempre irá a por su ventana entre beneficio y pérdida. Actualmente, no existe ninguna tecnología que permita realizar sólo trades con beneficios. Los trades con pérdidas son una norma en cualquier estrategia de trading que funcione de verdad. Lo que importa sólo es el proporción entre las operaciones con beneficios y pérdidas.

Por ejemplo, la proporción 3:1 entre beneficio y pérdida se puede considerar bastante aceptable. Esto quiere decir que 100 pedidos abiertos consecutivamente deben contener 75 trades con beneficios y 25 con pérdidas. Al mismo tiempo, nunca se puede predecir cómo se distribuirán las órdenes con pérdidas entre las órdenes con beneficios. Esta distribución tiene, en general, una naturaleza aleatoria.

A. La distribución ideal de los Beneficios y las Pérdidas sería una distribución uniforme por el historial del trading:

B B B P B B B P B B B P B B B P B B B P B B B P B B B P...

Sin embargo, no hay garantías de que la distribución sea siempre tan idónea. Más bien lo contrario, es muy probable que aparezca una serie larga de pérdidas tarde o temprano.


B.
Abajo hay un ejemplo de las situaciones más probables de distribución no uniforme de los trades con beneficios y pérdidas durante trading real:

B B B B B B B B B B B B B B B PPPP B B BP B B B P...


Se muestra una serie de 5 pérdidas consecutivas, aunque estas series pueden ser incluso más largas. Tiene que tener en cuenta que, en este caso, la proporción entre pedidos con beneficios y con pérdidas se ha mantenido en 3: 1.

Entonces, ¿en qué puede resultar esta aleatoriedad regular? La respuesta a esta pregunta depende de la calidad de la estrategia de trading que haya elegido el trader. Una cosa es, si el trader hace trading de forma deliberada, teniendo las precauciones razonables, donde el valor total de sus pedidos no excede el 10 o 15% del depósito; y otra cosa es que el trader permita las inversiones agresivas: invierte la gran parte de su depósito, sólo una vez, pero cada vez que lo hace, gana beneficios.

En el caso de las inversiones agresivas, el historial de la cuenta de trading se desarrollará de forma incalculable. Alguien con "suerte", quizás pueda escapar a estos problemas. Pero, en la mayoría de los casos, el resultado negativo es inminente. Para ilustrar los posibles escenarios de cómo funcionará el experto Graal_1.mq4 (Grial 1), vamos a analizar dos inversiones alternativas, con las mismas condiciones (la misma fase del historia, y las mismas entradas).

Por favor, preste atención al informe de los resultados de la prueba. La cantidad máxima de pérdidas consecutivas (una serie de pedidos con pérdidas) para el experto Grial_1mq4 (Grial 1) es sólo 10. Durante todo el periodo de prueba, ocurrieron otras series de pérdidas, pero la cantidad de pérdidas en cada uno de ellos no sobrepasó 10. Estas series de pérdidas no influenciaron mucho al resultado total del trading en la Alternativa 1, pero han sido desastrosas en la Alternativa 2.

Por lo tanto, una serie corta de pérdidas con las inversiones erróneas puede resultar en un completo desastre. Se ha desarrollado un sistema efectivo para la gestión correcta del capital - Money Management. Según este sistema, el valor de una orden no debería superar el 15% del balance total, y la cantidad total de la inversión no debería superar el 50%. Este sistema ofrece algunas otras reglas útiles que ha leído nuestro programador.

Y ha llegado a la siguiente conclusión: El trading con inversiones agresivas es una auto decepción y, tarde o temprano, resulta en ruina. Cada trader decidirá independientemente dónde poner el límite. Los resultados se obtendrán en relación a eso.

Por lo tanto, una vez que ha probado su "grial" y se ha asegurado de que todo funciona bien, el programador abre una cuenta real y empieza a "hacer dinero". Después de abrir y cerrar satisfactoriamente un número de pedidos, resulta que la balanza no está creciendo, sino descendiendo constantemente. Es más, el equipo del centro de operaciones ha desactivado su cuenta.

El programador está bastante enfadado. Quiere saber las razones de tal injusticia y no está de acuerdo con ninguna explicación. Está perplejo: ¿Qué "limitaciones técnicas"? ¿Qué tiene que ver con "pérdida"? Como resultado de una primera experiencia en trading así, el programador ha llegado a la conclusión de que este es un "mal centro de operaciones", y que le han engañado..Rompe el contacto con el centro de operaciones.


Sin embargo, no se rinde, y decide ver los detalles del proceso, y se pone en contacto con compañeros con más experiencia en el foro especializado en MQL4 donde lo primero que hacen es proponerle que muestre el código. Al principio se lo guarda, pero al final accede, ya que, el experto parece no estar generando beneficios de todos modos... El programador entiende lo siguiente después de las cosas que se han hablado en el foro.


1.3. Errores

El Meta Editor confirmaba constantemente que no había ningún error.
img. 5. No ha habido errores durante la recopilación

pero nunca los hubo.

1.3.1 Digresión de la Estrategia Formal


Aunque hay un poco de conocimiento de la estrategia en la creación del experto, se cambió durante la codificación y la optimización de las variables genéricas. Así que, la idea inicial se presenta ahora en un "grial" bastante reducido. De hecho, la idea era ganar ondas de 15 a 20 puntos de largo, pero este parámetro obtuvo un valor miserable de 3 en la versión actual del "grial". Quién iba a querer hablar aquí de altibajos...

No hay una línea definitiva entre blanco y negro. Todos los estados intermedios se pueden caracterizar por el coeficiente de su blancura o negrura. Pero sólo se puede distinguir que un color es más negro que blanco, o vice versa. En este caso, el ideal inicial de "puramente blanco" se "ennegreció" tanto que se puso tan negro como un deshollinador y perdió toda su fuerza. Podemos considerar esto como la razón del "grial" obtenido.
1.3.2 Programación Incorrecta

Fíjese en cómo se consideran las órdenes en las variables ss y bb. No es la forma correcta de considerarlas. Se considera que el pedido ya está abierto cuando aún se está formando. Pero no se puede saber con antelación si se abrirá o no. Para estar seguro de esto, hay que esperar hasta que el servidor conteste y analizar entonces la disponibilidad de la orden en la terminal. Para el trading real, esta parte del código debería volver a escribirse, aunque las modificaciones que se han hecho funcionarán en la mayoría de los casos, incluso en la prueba de estrategia (ver el artículo Considering Orders ina Large Program ).

1.4. Restricciones de hardware


El experto se probó en el periodo de tiempo para el que estaba destinado: en M1. Hay que prestar mucha atención cuando se moldea el trading de los expertos en el periodo de tiempo M1, sobre todo en los expertos sensibles a los precios.

Si queremos precisar la historia de una barra en un periodo de tiempo más largo, podemos usar la historia de una barra en un periodo de tiempo más pequeño. Pero para M1 no hay periodos de tiempo más pequeños, ya que la historia del tick no se ha guardado o usado en la Terminal de Cliente de MetaTrader 4 (ver Strategy Tester: Modes of Modeling during Testing).

La diferencia principal entre el modelo de prueba y la estrategia de trading real, es que el modo de prueba no provoca desfase ni recotización (cuando el vendedor da otro precio diferente al que está en el pedido del trader).

Los diferentes centros de operaciones trabajan con diferentes proveedores (de los que se hablará después). Cuando más y con más frecuencia cambie la divisa, más probabilidades hay de que el vendedor proponga al trader realizar el pedido con otro precio. Por otro lado, cuanto más "suavizado" parezca el tráfico, menos probable será la recotización, pero menos espacio habrá para el experto que hace trading con frecuencia y con logros pequeños.

El programador probó el Grial_1 (Grial 1) en un historial de 1-minuto de otro centro de operaciones (con la misma extensión) y vio con sus propios ojos que el resultado depende muchísimo del tipo de tráfico.


img. 6. Los resultados de la prueba del Grial_1.mq4 (Grial 1) en el historial M1 de EURUSD del 4 de abril al 26 de julio de 2006 en los términos de trading del servidor demo FX_Integralbank con pedidos de ódenes constantes

La presencia de caídas profundas, el desarollo inestable de los beneficios, muestran las balances del experto al límite de la pérdida.

Como norma general, la los precios de la recotización varían 1 o 2 puntos (aunque pueden ser más en un mercado rápido). Este fenómeno no puede influir esencialmente en el éxito del experto si se esperan recompensas mucho más grandes, por ejemplo, entre 10/15. Pero si se espera que la recompensa de un experto sea pequeña, especialmente si es menos de 2, no se puede esperar un éxito general, ya que depende mucho de la naturaleza de la cotización y la recotización en cuestión.

Que el vendedor recotice o no el tick actual, es una cuestión a parte que sólo puede responder él. Pero, al empezar a trabajar en el mercado real, hay que asumir que la recotización es algo normal, un fenómeno natural, y que la tecnología de trading que trabaje en una cuenta real, tiene que tenerlo en cuenta.



1.5. Aspectos económicos

Esta situación es más común cuando la atención del trader está totalmente enfocada a su cuenta de trading y sus eventos, como estrategias, expertos, etc. Sin embargo, a parte de la preocupación del trader, también hay una preocupación económica por parte del vendedor.

En el trading "normal", las dos partes pueden salir ganando: el trader que usa una buena estrategia, y el vendedor, que obtiene intereses de la operación que realice el trader. En este caso, ambas partes se preocupan la una de la otra y ambas están preparadas para apoyarse mutuamente.

Sin embargo, puede ocurrir que las actividades de una de las partes sea contraria a los intereses de la otra. Por ejemplo, si el vendedor aumenta la difusión, deshabilita el trading automático, o no abre pedidos (cerrados) al primer momento del precio, etc. esto va contra los intereses del trader.

Al mismo tiempo, el trader puede hacer algunas cosas que vayan contra los intereses económicos del vendedor. Una de ellas son las operaciones de trade frecuentes con cantidades pequeñas de dinero.

La tecnología de trabajo del vendedor es más bien siemple. El vendedor recoge las órdenes del trader para comprar y vender, y se relaciona con un banco u otra institución financiera para procesar las diferencias en los precios. Vamos a examinar un ejemplo muy simple. Suponga que el vendedor tiene un total de 100 trades, 60 de los cuales han comprado por 1 lote EURUSD, y los otros 40 han vendido por 1 lote el mismo par de divisas. En este caso, el vendedor debe comprar 20 lotes (la diferencia entre 60 y 40) al banco. En ese momento, da lo mismo en qué dirección mueva el vendedor los precios. En cualquier caso, el vendedor obtendrá la extensión completa por 80 lotes (40+40) y una extensión parcial de 20 lotes (una parte se le dará al banco por sus servicios).

En este caso, la fuente de beneficios/pérdidas para 40 traders es la pérdida/beneficio de otros 40 traders. La fuente de beneficio/pérdida del los otros 20 traders es el banco o, para ser más exactos, las personas legales proporcionadas por el banco, y las monedas de venta/compra de sus operaciones de exportación-importación. Esta es la forma normal de interacción entre los participantes del mercado del dinero.

Pero hay un detalle raro más en la forma de interactuar del vendedor con el banco o la institución financiera. El problema es que el vendedor no interactúa con el banco en cada operación de compra o venta, si el trader vende o compra una cantidad de dinero insignificante. Las operaciones de trade entre el vendedor y el banco se hacen con menos frecuencia que los clics que hace el trader en la terminal de MT4. Normalmente, la cantidad mínima de relaciones entre el vendedor y el banco no excede los 50 000 dólares americanos, que se traduce en el precio de la orden con un aprovechamiento de 1:100 por un lote de 0,5. Es por esto que, si el trader trabaja siempre con una cantidad pequeña de dinero, de hecho, hace el trading con el vendedor. En este caso, la fuente del beneficio del trader es el dinero del vendedor.

El vendedor es tan participante del dinero del mercado como los demás. El vendedor debe observar y analizar el trabajo de todos los traders. Por supuesto, los vendedores, en su preocupación económica, pueden hacer la vista gorda con las inversiones irregulares repetidas si resultan en pérdidas evidentes para el trader, o su resultado total durante un periodo de tiempo concreto (por ejemplo, el resultado diario) es neutral. Pero ningún vendedor razonable permitirá que continúen estas interrelaciones si éstas resultan en pérdidas para él. En este caso, el vendedor tiene que reaccionar de alguna manera, sino no hay nada para él en el territorio económico del mercado monetario.

Por favor, tenga en cuenta que la rutina moderna del mercado monetario no es la mala voluntad de los vendedores. Las relaciones del vendedor con el banco también son contraídas. Y el vendedor se esfuerza por ganar la extensión de manera justa (en este artículo no se habla de los abusos de los vendedores). El vendedor se alegrará, probablemente, de hacer trading con el banco a cada segundo, pero no existe esa posibilidad en este momento.

Bajo las condiciones de operaciones frecuentes de trade pequeñas que realiza un trader, el vendedor tiene que tomar ciertas medidas. Puede enviar una notificación al trader en la que le diga que su trabajo es de locos. El vendedor también puede deshabilitar el trading automático de este trader o aumentar la cantidad de las operaciones recotizadas.

Hay una limitación más que diferencia el trading real de las pruebas o el trading en las cuentas demo. El valor máximo del precio del lote. Ningún centro de operaciones, ya sea un banco, la oficina de un corredor de apuestas, o una institución financiera, puede hacer operaciones con cantidades muy grandes de dinero.

Si las órdenes cuestan de 10 000 a 20 000 dólares americanos (por favor, tenga en cuenta que hay un aprovechamiento que normalmente es igual a 100), el centro de operaciones venderá/comprará a 1 000 000 dólares americanos. Esta cantidad es muy grande, pero los vendedores han aprendido a trabajar con cantidades así de grandes y tienen bastante éxito.

En una institución financiera pequeña o mediana, pueden surgir algunas dificultades si el precio de la orden supera los 50 000 o incluso los 100 000 dólares americanos. En este caso, en el mercado intebancario, la cantidad que aparece es de 5 a 10 millones de dólares americanos. Esta cantidad de dinero no es fácil de vender/comprar en un sólo movimiento.

Pueden ocurrir situaciones difíciles si el precio de la orden supera los 300 000 a 500 000 dólares americanos. En este caso, el centro de operaciones trabajará individualmente con el trader. 50 millones de dólares es muchísimo dinero en cualquier situación.

En el caso de precios muy elevados, la firma de garantía del centro de operaciones no se cuestiona, y el trading se realiza basándose en que el trader lo entiende y lo acepta. (De hecho, ¿qué vendedor puede tomarse la libertad de abrir una orden que cueste tanto dinero en el primer contacto, con el riesgo de movimientos del mercado grandes e inesperados?)

Por este motivo, los expertos en trading que especulan con millones, son una prueba de un gran error del trader y no tiene nada que ver con la vida real.

Este razonamiento sugirió al programador ganar los 100 000 "pavos" iniciales y luego encontrar "la peor oficina". El programador se queda callado y piensa "todo está controlado".

No olvidemos que los vendedores son gente normal con su cultura y su educación, y que tienen sus negocios funcionando de una u otra forma. La misma tecnología, que no es beneficiosa para los vendedores, se puede detectar inmediatamente cuando el trabajo del analista es eficiente, y los vendedores que trabajan con mitades, que no tienen mucha experiencia, o que no poseen el software necesario, no pueden detectarla fácilmente. Pero en la mayoría de los casos, los vendedores son antiguos "grialers", tienen experiencia en trading y generalmente se agarran muy bien a todos los detalles del trading en el mercado monetario, por lo que saben qué es la progresión geométrica, la preocupación económica, las reinversiones agresivas, y precios de pedidos pequeños y grandes. Generalmente, cada trader tiene que actuar sabiendo que las cualificaciones del vendedor son más altas que las suyas, y que la posición del vendedor en prácticamente cualquier tema está justificada.

Juzguen ustedes mismos: ¿Cuáles pueden ser los resultados (bajo las condiciones técnicas y económicas explicadas arriba) del trabajo de un experto que abre más de 20 000 pedidos en un año?



img. 7. Informe de la prueba del experto Grial_1 (Grial 1).


El cerebro del programador está dando vueltas con todos estos ticks, barras, puntos, extensiones, vendedores y bancos. Decide que no quiere entrar detalles o "preguntas sencillas". Está satisfecho con lo que entiende por "los resultados de la prueba no coinciden con el trading real". Y decide que construirá la tecnología adecuada basada en pedidos pendientes. "¡No me pillarán!", piensa.

2. El segundo "Grial"

2.1 Estrategia

La idea de construir un experto de pedidos abiertos llega a la mente del programador después de que haya estudiado el comportamiento de los tipos de cambio cruzado EURGBP y EURCHF en gráficos de 1-minuto.



img. 8. Historial de tipos de cambio cruzado en regiones con importantes desvíos en los precios (picos)

Por muy fácil que parezca, cuando la sesión europea ya ha terminado, y la asiática aún no ha empezado, algunos símbolos de los gráficos tienen barras con precios inesperados que son totalmente diferentes del flujo "normal" de precios. Desde la lógica formal, basta con colocar las órdenes pendientes en el tipo Límite un tanto arriba y un tanto abajo de la corriente principal, y parte de ellos se abrirán con unas posibilidades de éxito bastante altas. Para que las órdenes pendientes reaccionen de forma adecuada a los cambios de la corriente principal, deben "arrastrarse" por alguna línea mediana y soportar constantemente cierta distancia de la línea MP (Movimiento Promedio). El programador ha escrito un experto para comprender la idea:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_2.mq4 (Grail 2).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int TakeProfit=5;                            // TakeProfit orders
extern int StopLoss= 29;                            // StopLoss orders
extern int Distan   = 2;                            // Distance from the МА line
extern int Cls      = 2;                            // Close at ** points of profit
extern int period_MA=16;                            // MA period 
//extern int Time_1   = 0;                          // Starting time 
//extern int Time_2   = 0;                          // Finishing time
extern int Prots    = 0;                            // Percentage of free assets
 
//--------------------------------------------------------------------------------------------
int
   Nom_bl,                                          // BuyLimit order number
   Nom_sl,                                          // SellLimit
   total,                                           // Count of lots
   bl = 0,                                          // 1 = BuyLimit order availability
   sl = 0,                                          // 1 = SellLimit order availability
   b  = 0,                                          // 1 = Buy order availability
   s  = 0;                                          // 1 = Sell order availability
//--------------------------------------------------------------------------------------------
double 
   OP,                                              // OpenPrice (absolute points)
   SL,                                              // StopLoss orders (relative points)
   TP,                                              // TakeProfit orders (relative points)
   dist,                                            // Distance from МА (relative points)
   Level,                                           // Min.allowed distance of a pending order
   OP_bl,                                           // OpenPrice BuyLimit (absolute points)
   OP_sl,                                           // OpenPrice SellLimit(absolute points)
   cls,                                             // Close at ** profit (absolute points)
   MA,                                              // MA value (rate)
   spred,                                           // Spread (absolute points)
   Lot;                                             // Count of lots
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()
   {   
   Level=MarketInfo(Symbol(),MODE_STOPLEVEL);       // Check what the server shows us
   Level=(Level+1)*Point;                           // ?:)
   SL=StopLoss*Point;                               // StopLoss orders (relative points)
   TP=TakeProfit*Point;                             // TakeProfit orders (relative points)
   dist=Distan*Point;                               // Distance from the MA line(relative points)
   cls=Cls*Point;                                   // Close at ** profit (absolute points)
   spred=Ask-Bid;                                   // Spread (absolute points)
   return;
   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
   {   
//============================================================================================
   total=OrdersTotal();                             // Count of lots
   bl=0;                                            // Zeroize at the start of the pass
   sl=0;                                            // Zeroize at the start of the pass
   b=0;                                             // Zeroize at the start of the pass
   s=0;                                             // Zeroize at the start of the pass
//--------------------------------------------------------------------------------------------
   for (int i=total; i>=0; i--)                     // For all orders
      {                                             
      if (OrderSelect(i,SELECT_BY_POS)==true &&     // Select an order
         OrderSymbol()==Symbol())
         {
      
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_BUY)                   // Buy order
            {
            b =1;                                   // The order found
            Close_B(OrderTicket(),OrderLots());     // Close the order (the function decides
                                                    // whether it is necessary)
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_SELL)                   // Sell order
            {
            s =1;                                   // The order found
            Close_S(OrderTicket(),OrderLots());     // Close the order (if necessary)
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_BUYLIMIT)              // BuyLimit order
            {
            OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(absolute points)
            Nom_bl=OrderTicket();
            bl=1;                                   // The order found
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_SELLLIMIT)             // SellLimit order
            {
            OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(absolute points)
            Nom_sl=OrderTicket();
            sl=1;                                   // The order found
            }
//--------------------------------------------------------------------------------------------
         }
      }   
//--------------------------------------------------------------------------------------------
   MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// The MA current value
   Modify_order();                                  // Activate modification
   Open_order() ;                                   // Activate opening
//============================================================================================
   return;
   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_B(int Nomber, double lots)               // Close Buy orders
   {
//============================================================================================
   if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// If the preset profit is reached
      {
      OrderClose( Nomber, lots, Bid, 1, Yellow);    // Close
      b = 0;                                        // No Buy order anymore
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_S(int Nomber, double lots)               // Close Sell orders
   {
//============================================================================================
   if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// If the preset order is reached
      {
      OrderClose( Nomber, lots, Ask, 1, Yellow);    // Close
      s = 0;                                        // No Sell order anymore
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Modify_order()                                 // Modification of orders
   {
//============================================================================================
   if (bl==1)                                       // If there is BuyLimit
      {
      OP=MA-dist;                                   // it must be located here
      if (MathAbs(OP_bl-OP)>0.5*Point)              // if it is not located here
         {
         OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// The order modification 
         }
      }
//--------------------------------------------------------------------------------------------
   if (sl==1)                                       // If there is SeelLimit
      {
      OP=MA+spred+dist;                             // It must be located here
      if (MathAbs(OP_sl-OP)>0.5*Point)              // If it is not located here
         {
         OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// The order modification 
         }
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Open_order()                                   // An opening function
   {
//   int Tek_Time=TimeHour(CurTime());              // To test by the time
//   if (Tek_Time>Time_2 && Tek_Time>
//============================================================================================
   if (b==0 && bl==0)                               // No Buy orders, open bl
      {
      OP=MA-dist;                                   // bl order open rate      
      if(OP>Ask-Level) OP=Ask-Level;                // OP precision according to the tolerance
      OP=NormalizeDouble(OP,Digits);                // Normalizing (MA gives the 5th digit) 
      OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Open
      bl=1;                                         // Now there is a Buy order b1
      }      
//--------------------------------------------------------------------------------------------
   if (s==0 && sl==0)                               // No Sell orders, open sl
      {
      OP=MA+spred+dist;                             // sl order open rate    
      if(OP<Bid+Level) OP=Bid+Level;                // OP precision according to the tolerance
      OP=NormalizeDouble(OP,Digits);                // Normalizing (MA gives the 5th digit) 
      OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Open
      sl=1;                                         // Now there is a Sell order sl
      }
///============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                       // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum lot values
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

StopLoss, TakeProfit, Distan (distancia a la que se mantiene la orden por la corriente principal), CIs (cantidad mínima de los puntos ganados en la orden, que debe cerrarse cuando los puntos alcancen este valor), periodo_MA (el periodo MA; el MA aquí es la línea media de divisas del último historial), y Prots (el porcentaje de activos, el precio de la orden) se han elegido como variables ajustables. Esto es más que suficiente para comprender la idea.
En la escritura del programa, el programador se ha dado cuenta de que puede ser ilimitado, y decidió que la escritura no puede terminarse, ¡sólo tiene que detenerse! Las pruebas del experto en EURCHF tuvieron como resultado lo siguiente (estudiaremos este ejemplo, aunque se pueden obtener ejemplos similares en EURGBP).


img. 9. Los resultados de la prueba en Graal_2.mq4 (Grial 2) en el historial de marzo 2005 a junio de 2006, en el gráfico M1 EURUSD bajo las condiciones de trading de la compañía MIG_Investments

2.2. Progresión geométrica
En este experto, igual que en el anterior, se utiliza la tecnología de inversión progresiva. Para los precios constantes de las órdenes, el gráfico del balance tendrá este aspecto:


img.10. Los resultados de la prueba en Graal_2.mq4 (Grial 2) en el historial de marzo 2005 a junio de 2006, en el gráfico M1 EURUSD bajo las condiciones de trading de la compañía MIG_Investments con precios constantes de las órdenes.

Originalmente, el programador quería ganar dinero sólo por la noche, pero luego se sorprendió de que el experto trabajara satisfactoriamente durante todo el día. ¿Vale de algo decir que después de haber visto esto, el programador decide de nuevo: "¡Yo solo!" y empieza a "crear dinero" de nuevo? Pero no pasa nada de eso... Esta vez, el programador tiene que familiarizarse con los "picos".

2.3. Errores

En el ejemplo de experto anterior, hay una gran catidad de defectos y soluciones de programación incorrectas. En la función Modify_order(), la distancia mínima permitida para las órdenes pendientes no se tiene en cuenta, las órdenes abiertas que se tienen en cuenta están organizadas de forma incorrecta; TakeProfit no se modifica por separado para "fomentar" el beneficio de CIs, la parte analítica del experto se "desvanece" por todo el código, etc.

La programación incorrecta y, lo que es más, la programación descuidada, a menudo resulta en errores que no pueden distinguirse y, a veces, en réplicas de errores que se integra con otros expertos.

2.4. Restricciones técnicas (Picos)

Por norma general, todas las restricciones, ya sean téncnias o de organización, se convertirán al final en pérdidas económicas. La pregunta es, a costa de qué se cubrirán estas pérdidas.

Cuando el trader ve un gráfico de velas normal en el monitor, es un resultado medio del desarrollo del mercado en un territorio específico (entre los bancos europeos, por ejemplo). Se puede analizar el comportamiento de la divisa en un periodo de historia con diferentes vendedores. En este momento, es fácil ver que todos los gráficos van a ser diferentes unos de otros, aunque sea ligeramente. Los gráficos de algunos vendedores contendrán lotes de velas largas en varias direcciones, mientras que los gráfios de otros vendedores mostrarán "silencio y tranquilidad".

Un gráfico de tick también es un objeto de venta. Es el resultado del trabajo de algún programa de procesamiento que filtra precios de ticks excesivos e innaturales. Y aparecen (los "ticks innaturales"). Esto ocurre cuando una persona en un banco, por algún motivo personal (puede pasar cualquier cosa, ¿no?) ha comprado o vendido una cantidad a un precio que difiere bastante del precio del mercado. El programa de procesamiento acepta esta información y, si una transacción así sólo ocurre una vez, no lo considera a la hora de crear el gráfico final. En algunas ocasiones, el programa tiene dificultades en comprender qué precios son "normales" y cuáles no. Por este motivo, las velas simples de diferentes longitudes (dependiendo del algoritmo del programa de procesamiento) aparecen a veces en el gráfico. Estos son los picos. Esto aparece de formas diferentes, pero no muestran la situación real del mercado monetario.

No es muy difícil hacer un experto que pille estos picos y las órdenes abiertas cuando los precios son más beneficiosos. Pero hay que entender que, en los contratos determinados entre el vendedor y el banco, normalmente el banco no paga una transacción así al vendedor. Esto quiere decir que la fuente de beneficio del trader es, de nuevo, el bolsillo del vendedor. Y el vendedor no quiere que esto ocurra, claro, así que pelea con los traders para realizar operaciones de trading con precios de mercado "normales".

Como una medida para generar esta oportunidad para el vendedor, el contrato entre el vendedor y el trader suele contener cláusulas sobre los derechos del vendedor, en las que se incluyen la posible recotización, apertura no garantizada de pedidos con precios elevados, apertura de pedidos pendientes en una segunda vuelta, y otras precauciones. En algunos casos, el vendedor puede cancelar una orden que ya se ha abierto si, según su opinión, el pedido se ha abierto en un pico.

Esto es lo que le ocurrió al programador. Por muy bien que aparezca en la cuenta demo, el grial se corrigió de nuevo. Esta vez, el programador no cierra el receptor y escucha atentamente a los vendedores cada vez que explican las razones por las que se ha forzado el cierre de las órdenes. Pero cuando el vendedor deshabilita los expertos, el programador no pudo soportarlo y rompió de nuevo el contrato.

Ahora, el programador cree que el perioodo de tiempo de 1-minuto es el culpable de sus continuos fracasos. Una vez que ha leído los posts en los foros, y ha hablado con otros traders, el programador ve que la mayoría de ellos trabajan en periodos de tiempo más largos con los mismos símbolos. "Esto tiene sentido", piensa. Poco a poco, el programador llega a la conclusión de "Mozart y yo" y se quita el abrigo para desarrollar su tercera creación: ya no la hará en los gráficos M1, ("¡Nunca, nuca más!").

3. El tercer "Grial"

3.1 Estrategia formal

Después de estudiar con detenimiento el gráfico EURUSD H1 y utilizando diferentes indicadores para analizarlo, el programador ha descubierto una regularidad muy atractiva: Si el MP (Movimiento Promedio) de un periodo de tiempo más corto se encuentra con el MP de un periodo más largo, el mercado suele moverse en la misma dirección que el MP del periodo más corto.

img. 11. La representación gráfica de la estrategia basada en el intercruzado de MPs con periodos diferentes

El programador también se ha dado cuenta de que esta interrelación aparece en todos los periodos de tiempo, pero ha decidido trabajar sólo con los largos. Sólo le queda traducir el conocimiento adquirido en MQL4 para poder informar al experto de la dirección y las condiciones en las que tiene que abrir las órdenes. Y, cuando el experto esté listo, es necesario mejorar sus parámetros: escoger las duraciones de MP más efectivas y colocar adecuadamente StopLoss y TakeProfit.

Esta vez, ha nacido este experto:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_3.mq4 (Grail 3).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int    MA1 = 11;                                  // Period of the first MA
extern int    MA2 = 23;                                  // Period of the second MA
extern double TP =  50;                                  // TakeProfit orders
extern double SL =  15;                                  // StopLoss orders
extern double Prots= 0;                                  // Percentage of free assets
//--------------------------------------------------------------------------------------------
int
   ret,                                                  // Direction of intersection
   total;                                                // Count of open orders
//--------------------------------------------------------------------------------------------
double 
   Lot,                                                  // Count of lots
   Pred,                                                 // Preceding value of the 1st MA(red)
   Tek,                                                  // Current value of the 1st MA (red)
   Golub;                                                // Current value of the 2nd MA (blue)
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
//============================================================================================
   SL = SL*Point;                                        // StopLoss in points
   TP = TP*Point;                                        // TakeProfit in points
   return;
//============================================================================================
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()  
   {
//============================================================================================
   total=OrdersTotal();                                  // Total amount of orders
   if (total==2)return;                                  // Both orders are already open
//--------------------------------------------------------------------------------------------
   Tek  =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA
   Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Preceding value of the 2nd MA
   Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA
//--------------------------------------------------------------------------------------------
   if (Peresechenie()==1) Open_Buy();                    // Movement bottom-up = open Buy
   if (Peresechenie()==2) Open_Sell();                   // Movement top-down  = open Sell
//============================================================================================
   return;
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()                                       // Function determining intersection
   {
//============================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Intersection bottom-up       
//--------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Intersection top-down
//============================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Buy()                                           // Function opening Buy
   {
//============================================================================================
   if (total==1)                                         // If there is only one order...
      {                                                  // ... it means another can be opened
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==0)return;                         // If it is Buy, do not open
      }
   OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// open
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Sell()                                          // Function opening Sell
   {
//============================================================================================
   if (total==1)                                         // If there is only one order...
      {                                                  // ... it means another can be opened
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==1)return;                         // If it is Sell, do not open
      }
   OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                            // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum lot values
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const. min. lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

Este experto, como los anteriores, era más bien simple.

Empieza con el bloque que describe las variables. En la función start() se definen la cantidad total de pedidos, y los valores de MP para los periodos más largos y más cortos. Si se encuentran los MPs, se llama a la función correspondiente para que abra las órdenes: Open_*() Para especificar que los MP se han encontraro, se utiliza la función Peresechenie(), y para averiguar el valor de los lotes, se utiliza la función Lots().

El programador revisa una vez más en su experto, no ve ningún defecto ("Es simple, ¡pero está bien!") y empieza la prueba. Después de la optimización de las variables, el resultado fue maravilloso:

img. 12. Los resultados de la prueba en Graal_3.mq4 (Grial 3) en el historial de marzo 2005 a julio de 2005,
en el gráfico H1 EURUSD bajo las condiciones de trading del servidor demo de la compañía
MetaQuotes Software Corp.

¡Tres millones en cinco meses! ¡Maravilloso! Pero hay algo en este gráfico que al programador le recuerda la amargura de las experiencias anteriores. Y decide ir un poco más despacio.

3.2. Progresión

Después de haber probaro el mismo experto con precios de pedidos constantes, mostró un gráfico de balance bastante aceptable:



img alt="". 13.Los resultados de la prueba en Graal_3.mq4 (Grial 3) en el historial de marzo 2005 a julio de 2005 en el gráfico H1 EURUSD
bajo las condiciones de trading del servidor demo con lotes de precios constantes de la compañía
MetaQuotes Software Corp.

Seis mil puntos en cinco meeses; se podría cortar con un cuchillo, ¡Más de mil puntos al mes! Pero el programador duda si configurar o no el experto para el trading real. Después de todo, se ha equivocado ya dos veeces...

Luego el programador decidió revisar más detenidamente los periodos de tiempo con marcas de apertura y cierre de pedidos y, para su sorpresa descubrió que el experto no sólo abría pedidos en las intersecciones de los MPs, sino que también lo hacía en otros puntos, ¡sin motivo!

img. 14. Apertura de pedidos por el experto Graal_3 (Grial 3) en situaciones que no se han previsto en la estrategia inicial.

3.3. Errores

"¡Qué extraño! ¡Debe pasarle algo al MetaEditor!" fue lo primero que pensó. Pero luego, una vez que analizó el código sucesivamente, volvió a encontrar errores. Vamos a hablar de ellos.

3.3.1 Desviaciones de la estrategia inicial - Errores algorítmicos

Mire a la siguiente función:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()                                       // Function that detects the intersection
   {
//=================================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Bottom-up intersection       
//-------------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Top-down intersection
//=================================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Parece que todo está bastante claro, ¿qué podemos encontrar? Pero sigue habiendo un error. Es en ese momento, cuando se usa la variable global ret, cuando el valor se guarda igual al último que se ha calculado, es decir, 1 o 2. Por este motivo, la función Peresechenie(), sin tener en cuenta la situación actual, vuelve al último valor calculado. Por eso se le ordena abrirse constantemente en la función start():

   if (Peresechenie()==1) Open_Buy();                    // Bottom-up movement = open Buy
   if (Peresechenie()==2) Open_Sell();                   // Top-down movement  = open Sell

Para cambiarlo, es suficiente con darle valor cero a la variable ret al principio de la función Peresechenie(). Una vez que ha encontrado el error algorítmico, el programador lo corrije y escribe un fragmento al mismo tiempo, que permite abrir sólo una barra. Ahora el experto tiene este aspecto:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_31.mq4 (Grail 31)
// Used as an example in the article My First "Grail"
// Sergey Kovalyov, Dnepropetrovsk, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/.
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int    MA1 = 11;                                  // Period of the 1st MA
extern int    MA2 = 23;                                  // Period of the 2nd MA
extern double TP =  50;                                  // TakeProfit orders
extern double SL =  15;                                  // StopLoss orders
extern double Prots= 0;                                  // Percentage of free assets
//--------------------------------------------------------------------------------------------
int
   New_Bar,                                              // 0/1 The fact of new bar forming
   Time_0,                                               // The new bar beginning time
   ret,                                                  // Intersection direction
   total;                                                // Count of open orders
//--------------------------------------------------------------------------------------------
double 
   Lot,                                                  // Count of lots
   Pred,                                                 // Previous value of the 1st MA (red)
   Tek,                                                  // Current value of the 1st MA (red)
   Golub;                                                // Current value of the 2nd MA (blue)
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
//============================================================================================
   SL = SL*Point;                                        // SL in points
   TP = TP*Point;                                        // ТР in points
   return;
//============================================================================================
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()  
   {
//============================================================================================
   total=OrdersTotal();                                  // Total count of orders
   if (total==2)return;                                  // Both orders already opened
 
//----------------------------------------------------------------------------- New bar ------
   New_Bar=0;                                            // First zeroize
   if (Time_0 != Time[0])                                // If the bar beginning time changed
      {
      New_Bar= 1;                                        // Here we have a new bar
      Time_0 = Time[0];                                  // Remember the new bar beginning time
      } 
      
//--------------------------------------------------------------------------------------------
   Tek  =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA
   Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Previous value of the 2nd MA
   Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA
   
//--------------------------------------------------------------------------------------------
   if (Peresechenie()==1 && New_Bar==1) Open_Buy();      // Bottom-up movement = open Buy
   if (Peresechenie()==2 && New_Bar==1) Open_Sell();     // Top-down movement  = open Sell
//============================================================================================
   return;
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()
   {
   ret=0;                                                // That's the heart of the matter!:)
//============================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Bottom-up intersection       
//--------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Top-down intersection
//============================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Buy()  
   {
   if (total==1)
      {
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==0)return;                         // If it is buy, don't open
      }
   OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// Open
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Sell() 
   {
   if (total==1)
      {
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==1)return;                         // If it is sell, don't open
      }
   OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()
   {
   Lot = NormalizeDouble( AccountEquity()*Prots/100/1000, 1);// Calculate the amount of lots  
   if (Lot<0.1)Lot = 0.1;                                // For testing on const. min. lots
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

La prueba de este experto con lotes de precios constantes sólo ha obtenido un éxito limitado:

img. 15. Los resultados de la prueba en Graal_3.mq4 (Grial 31) en el historial de marzo 2005 a julio de 2005, en el gráfico H1 EURUSD
bajo las condiciones de trading del servidor demo con lotes de precios constantes de la compañía
MetaQuotes Software Corp.


El programador está bastante desanimado. Tanto trabajo en vano... Con el tiempo limitado, el programador fue a buscar el "grial". Después de un par de meses, decide volver al experto Graal_3.mq4 (Grial 3). "Sí, había un error, pero dio buenos resultados. ¡Puede que sea cuestión de rutina! "Que el experto abra las órdenes como quiera si sólo mantiene los buenos resultados". Y empieza a prorbar de nuevo.

Cuál fue su sorpresa al ver que el experto empezó a perder depósito de forma monótona, por sí solo, sin hacer ningún cambio al código.

img. 16. Los resultados de la prueba en Graal_3.mq4 (Grial 3) en el historial de marzo 2005 a julio de 2006,en el gráfico H1 EURUSD
bajo las condiciones de trading del servidor demo con lotes de precios constantes de la compañía
MetaQuotes Software Corp.

3.4. Adaptación de los resultados

El programador se da cuenta que es él quien está creando los problemas. Comprueba que no hay ninguna dificultad para adaptar los mejores parámetros de un experto poco efectivo en un segmento del historial. El mismo experto dará siempre diferentes resultados en diferentes periodos del historial.

Toda la cuestión se reduce a la pregunta de cómo encontrar las mejores entradas para el experto, si es posible, y qué fluctuaciones en la velocidad de precio de pequeño mercado no influiría en el funcionamiento y eficacia del experto. Generalmente, hay que centrarse en una estrategia que sea resistente a cualquier cambio en el mercado; y la optimización de los parámetros debe ayudar a algunos alcances a obtener los mejores resultados posibles.

La búsqueda de los ajustes ideales para el experto Graal_3.mq4 (Grial 3) no ha tenido ningún resultado. La prueba del experto con diferentes valores de las variables externas tampoco ha mostrado pérdidas ni resultados en bastantes ajustes diferentes para diferentes periodos del historial. Por este motivo, el programador no ha tenido éxito buscando la mejor configuración. Por eso ha llegado a la conclusión de que esta estrategia no tiene una configuración universal para todas las ocasiones.

El programador ha vuelto al experto Graal_31.mq4 (Grial 31) y quiere obtener desesperadamente los resultados deseados. Pero los mejores tienen este aspecto:




img. 17. Los resultados de la prueba en Graal_3.mq4 (Grial 31) en el historial de marzo 2005 a julio de 2006,en el gráfico H1 EURUSD
bajo las condiciones de trading del servidor demo con lotes de precios constantes de la compañía
MetaQuotes Software Corp.


Eso que el programador ve arriba no se parece para nada a un "grial". El experto no se puede utilizar para trabajar en una cuenta real por la caída profunda en mitad del gráfico. Pero aún así, es un experto que funciona y que muestra un resultado positivo, aunque muy lejos de ser fantástico.

Esto hace que el programador se anime.

4. Conclusión


La decepción siempre es dolorosa, especialmente si las ilusiones son tan optimistas. Pero la vida pone a todos y a todo en su sitio tarde o temprano. Los problemas del mundo se llevaron el brillo del programador: Ha estropeado las relaciones con dos centros de operaciones, ha perdido dinero que ganó con su trabajo... Después de haber obtenido experiencias incalculables (para sí) en programación y trading en Forex, el programador casi llegó a la conclusión de "Sólo Mozart...", pero paró a tiempo y decidió que nunca sacaría conclusiones precipitadas.

En su lugar, el programador cogió una hoja de papel en blanco y formuló varias conclusiones basadas en las lecciones aprendidas: