Descargar MetaTrader 5

Enviando señales de trading en un asesor experto universal

15 febrero 2016, 12:56
Igor Kim
0
127

Introducción


Hace algún tiempo decidí intentar universalizar y unificar un proceso para el desarrollo de asesores expertos en el tema "El desarrollo de un asesor experto universal". Esto supuso resolver un cierto estándar de desarrollo de fragmentos unitarios que luego pudieran utilizarse para construir asesores expertos como las piezas de un kit de construcción. En parte, esta tarea se implementó. Ofrecí una estructura de un asesor experto universal y una idea del uso universal de señales de distintos indicadores. En este artículo continuaré este trabajo. Intentaré universalizar el proceso de formación y envío de señales de trading y la gestión de elementos en asesores expertos. En este contexto, un elemento es una operación, COMPRAR o VENDER, todo el diálogo posterior hará referencia a dichas operaciones. Este artículo no describe las órdenes pendientes BUYLIMIT, BUYSTOP, SELLLIMIT and SELLSTOP, pero al final del artículo mostraré que mi método puede ser aplicado fácilmente en ellas.

Clasificación de las señales de trading


Hay varios tipos de señales de trading:

  1. Compra;
  2. Venta;
  3. Compra adicional (promediación);
  4. Venta adicional (promediación);
  5. Cierre de compra total;
  6. Cierre de venta total;
  7. Cierre de compra parcial;
  8. Cierre de venta parcial;

Si trasladamos la decisión sobre promediación y cierre parcial desde la unidad de formación de señales de trading a la unidad de gestión de posiciones y órdenes, esta lista quedaría reducida a la siguiente:

  1. Compra;
  2. Venta;
  3. Cierre de compra;
  4. Cierre de venta;
  5. No hacer nada (el funcionamiento normal del AE requiere dicha señal).

Asumiendo esto, el esquema de funcionamiento del AE debería ser el siguiente:

  1. Un elemento de señal crea una señal de trading;
  2. Una señal de trading entra en la unidad de gestión de posiciones, que decide sobre las nuevas aperturas, promediación y cierre parcial o total, y envía la señal de trading acortada a la unidad del programa de procesamiento de señales de trading;
  3. La unidad de procesamiento de señales de trading realiza directamente las operaciones de trading.

En este artículo me gustaría hacer hincapié sobre las distintas formas de crear señales de trading y las formas de envío de estas a la unidad de gestión de posiciones, es decir, la interfaz entre las unidades mencionada en los puntos 1 y 2.


Trading oscilante sobre una posición


El significado de dicho trading es el siguiente: antes de abrir una nueva posición, debe cerrarse la anterior. La nueva posición es la opuesta a la anterior. Si era comprar, abrimos vender y viceversa. En este caso, los momentos de apertura y cierre de la posición coinciden en el tiempo y por esta razón podemos omitir el cierre de las señales. Por tanto, la implementación del trading oscilante requiere el envío de solo tres señales de trading: comprar, vender y no hacer nada. Estas señales pueden enviarse usando una variable int. Por ejemplo:

1 - comprar;
0 - no hacer nada;
-1 - vender.

Luego, la parte de análisis de la situación del mercado y creación de una señal de trading puede escribirse en una función separada, por ejemplo GetTradeSignal(),

//+----------------------------------------------------------------------------+
//|  Returns trading signal:                                                   |
//|     1 - buy                                                                |
//|     0 - do nothing                                                         |
//|    -1 - sell                                                               |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignal(string sym="", int tf=0) 
  {
   int bs=0;
   if (sym=="") sym=Symbol();
 
   // Block of analysis assigning a value to the variable bs
 
   return(bs);
  }
//+----------------------------------------------------------------------------+

que devuelve los valores enteros mencionados anteriormente. La activación de esta función se realiza con mayor facilidad directamente en la unidad de gestión de posiciones.


//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
   double sl=0, tp=0;
   int    bs=GetTradeSignal();
 
   if(bs>0) 
     {
      if(ExistPositions("", OP_SELL)) 
          ClosePositions("", OP_SELL);
      if(!ExistPositions("", OP_BUY)) 
        {
          if(StopLoss!=0) 
              sl=Ask-StopLoss*Point;
          if(TakeProfit!=0) 
              tp=Ask+TakeProfit*Point;
          OpenPosition("", OP_BUY, sl, tp);
        }
     }
   if(bs<0) 
     {
       if(ExistPositions("", OP_BUY)) 
           ClosePositions("", OP_BUY);
       if(!ExistPositions("", OP_SELL)) 
         {
           if(StopLoss!=0) 
               sl=Bid+StopLoss*Point;
           if(TakeProfit!=0) 
               tp=Bid-TakeProfit*Point;
           OpenPosition("", OP_SELL, sl, tp);
         }
     }
  }
//+----------------------------------------------------------------------------+

En este caso, una sola variable local bs de tipo entero actúa como enlace entre dos unidades del programa. El texto completo del ejemplo del código fuente para el trading oscilante por una posición se encuentra en el archivo e-SampleSwing.mq4.



Trading simple sobre una posición


Este caso es un poco más difícil. Aunque en el mercado solo hay una posición en cada momento en el tiempo, su cierre no está conectado con la apertura de ninguna otra. Por esta razón, una gestión de posiciones de éxito requiere usar las cinco señales: comprar, vender, cierre de posición comprar, cierre de posición vender y no hacer nada. Pueden enviarse en una variable de tipo entero con los siguientes valores asignados:

2 - cerrar posición de venta;


1 - comprar;


0 - no hacer nada;


-1 - vender;


-2 - cerrar posición de compra;



La unidad de gestión de posiciones puede escribirse en una función:

//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignal();
 
    if(ExistPositions()) 
      {
        if(bs==2) 
            ClosePositions("", OP_SELL);
        if(bs==-2) 
            ClosePositions("", OP_BUY);
      } 
    else 
      {
        if(bs==1) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(bs==-1) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

El texto completo del ejemplo del código fuente para el trading simple por una posición se encuentra en el archivo e-SampleSimple.mq4.

El principal inconveniente de enviar una señal de trading en una variable es que no es posible enviar varias señales simultáneamente (inconvenientes de una interfaz serie). Por ejemplo, no puedes abrir en ambas direcciones o abrir con un cierre simultáneo de una posición existente, o cerrar todas las posiciones. En parte, este inconveniente puede eliminarse dividiendo una señal en dos enteros.

Hay tres formas de dividir una señal:

  1. Abrir en una variable y cerrar en otra. Es posible combinar la apertura y el cierre, por ejemplo organizando un trading oscilante, pero no es posible abrir en ambas direcciones o cerrar posiciones en dirección contraria;
  2. Las posiciones BUY (abrir y cerrar) están en una variable, y las posiciones SELL (abrir y cerrar) están en otra. Es posible abrir posiciones en ambas direcciones y cerrar todas las posiciones a la vez, pero no es posible abrir y cerrar simultáneamente, por ejemplo, la posición comprar o vender, es decir, no es posible reabrir;
  3. Abrir BUY y cerrar SELL en una variable, abrir SELL y cerrar BUY en otra. Es posible abrir en ambas direcciones y cerrar todas las posiciones, pero no es posible organizar el trading oscilante.

Intentemos implementar una segunda variante, ya que la reapertura es bastante rara. Nadie quiere perder dinero en el diferencial. La segunda variante puede implementarse de varias formas.

1. Dos funciones devuelven valores en dos variables locales. Una función crea señales para la compra y la segunda para la venta.

//+----------------------------------------------------------------------------+
//|  Returns trading signal for long positions:                                |
//|     1 - buy                                                                |
//|     0 - do nothing                                                         |
//|    -1 - close BUY                                                          |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignalBuy(string sym="", int tf=0) 
  {
    int bs=0;
    if(sym=="") 
        sym=Symbol();
 
    // Block of analysis assigning a value to the variable bs
 
    return(bs);
  }
 
//+----------------------------------------------------------------------------+
//|  Returns trading signal for short positions:                               |
//|     1 - sell                                                               |
//|     0 - do nothing                                                         |
//|    -1 - close SELL                                                         |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignalSell(string sym="", int tf=0) 
  {
    int bs=0;
    if(sym=="") 
        sym=Symbol();
 
    // Block of analysis assigning a value to the variable bs
 
    return(bs);
  }
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignalBuy();
    int    ss=GetTradeSignalSell();
 
    if(ExistPositions()) 
      {
        if(bs<0) 
            ClosePositions("", OP_BUY);
        if(ss<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(bs>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ss>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

Esta es una forma simple y cómoda de crear y vender una señal de trading, pero una unidad de señal se divide en dos funciones que probablemente ralentizaría su funcionamiento.



2. Dos variables globales adquieren valores en una función.

//+----------------------------------------------------------------------------+
BuySignal=0;
SellSignal=0;
 
//+----------------------------------------------------------------------------+
//|  Creates trading signals.                                                  |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe              ( 0 - current timeframe)                   |
//+----------------------------------------------------------------------------+
void FormTradeSignals(string sym="", int tf=0) 
  {
    if(sym=="") sym=Symbol();
 
    // Block of analysis assigning a value to the variable BuySignal and SellSignal
  }
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
 
    FormTradeSignals();
    if(ExistPositions()) 
      {
        if(BuySignal<0) 
            ClosePositions("", OP_BUY);
        if(SellSignal<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(BuySignal>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(SellSignal>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

Está claro a partir de este código fuente, que la realización con variables globales no se diferencia mucho del primer método. La ventaja aparente es que el modo de la señal está en una función.



3. Se pasan dos variables locales por referencia a una función.

//+----------------------------------------------------------------------------+
//|  Returns trading signals.                                                  |
//|  Parameters:                                                               |
//|    bs  - BUY signal                                                        |
//|    ss  - SELL signal                                                       |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//+----------------------------------------------------------------------------+
void GetTradeSignals(int& bs, int& ss, string sym="", int tf=0) 
  {
    if(sym=="") 
        sym=Symbol();
 
    // Block of analysis assigning a value to variables bs and ss
  }
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=0, ss=0;
 
    GetTradeSignals(bs, ss);
    if(ExistPositions()) 
      {
        if(bs<0) 
            ClosePositions("", OP_BUY);
        if(ss<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(bs>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ss>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

4. Una matriz de dos elementos. Si es global, se inicializa dentro de la función. Si es local, se pasa por referencia. Aquí todo es fácil: una matriz en lugar de dos variables. Los elementos globales y los locales por referencia fueron discutidos anteriormente. Nada nuevo.

Y, por último, podemos organizar una interfaz paralela con valores completos enviando señales de trading y dividiéndola en cuatro variables. Para la gestión de posiciones, cada señal tiene dos estados: existe o no. Esta es la razón por la que debemos utilizar variables de tipo lógico. Podemos combinar señales, enviarlas usando cuatro variables sin límite. Este es un ejemplo de código con una matriz de cuatro elementos de tipo lógico.

//+----------------------------------------------------------------------------+
//|  Returns trading signals.                                                  |
//|  Parameters:                                                               |
//|    ms  - array of signals                                                  |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//+----------------------------------------------------------------------------+
void GetTradeSignals(bool& ms[], string sym="", int tf=0) 
  {
    if(sym=="") 
        sym=Symbol();
 
    // Block of analysis filling ms array:
    // ms[0]=True;   // Buy
    // ms[1]=True;   // Sell
    // ms[2]=True;   // Close Buy
    // ms[3]=True;   // Close Sell
  }
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4]={False, False, False, False};
    double sl=0, tp=0;
 
    GetTradeSignals(ms);
    if(ExistPositions()) 
      {
        if(ms[2]) 
            ClosePositions("", OP_BUY);
        if(ms[3]) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(ms[0]) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ms[1]) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

La implementación con variables locales pasadas por referencia a una función y con variables globales inicializadas dentro de una función, no debe dar ningún problema. No obstante, la inicialización de cuatro variables locales por valores, devueltos por cuatro funciones distintas es algo difícilmente razonable.



Apoyando la posición principal


Cuando llega una señal, se abre una posición. Esta se convierte en la posición principal. Todas las demás entradas de señales contra la posición principal son ignoradas. Se abren posiciones adicionales en las señales que se corresponden con la posición principal. Al cierre de la posición principal, todas las posiciones adicionales también se cierran.

El envío de señales de trading para esta táctica puede implementarse usando una, dos o cuatro variables. Todo ello ya se ha descrito anteriormente. La dificultad, con la que podemos encontrarnos, es proporcionar la conexión: una señal con una posición. En caso de trading en una posición esta cuestión se resolvió simplemente comprobando la existencia de la posición usando la función ExistPositions(). Si hay una posición, la señal de entrada se omite y si no hay posición la señal de entrada se materializa.

Por tanto, hay diferentes formas:

  1. Proporcionar una pausa entre entradas. La realización más fácil;
  2. Una barra para una entrada. Una variedad del primer modo. La realización también es fácil;
  3. Numerar señales y controlar matrices de señales y tiques de órdenes. Esta es la implementación más difícil con una dudosa fiabilidad.

Este es el ejemplo de un código para el primer método:

//+----------------------------------------------------------------------------+
extern int PauseBetweenEntrys=3600;    // Pause between entrances in seconds
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4]={False, False, False, False};
    double sl=0, tp=0;
 
    GetTradeSignals(ms);
    if(ExistPositions()) 
      {
        if(ms[2]) 
            ClosePositions("", OP_BUY);
        if(ms[3]) 
            ClosePositions("", OP_SELL);
      }
    if(SecondsAfterOpenLastPos()>=PauseBetweenEntrys) 
      {
        if(ms[0]) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ms[1]) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
 
//+----------------------------------------------------------------------------+
//|  Returns number of seconds after the last position is opened.              |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    op  - operation              (-1 - any position)                        |
//|    mn  - MagicNumber            (-1 - any magic number)                    |
//+----------------------------------------------------------------------------+
datetime SecondsAfterOpenLastPos(string sym="", int op=-1, int mn=-1) 
  {
    datetime oot;
    int      i, k=OrdersTotal();
 
    if(sym=="") sym=Symbol();
        for(i=0; ik; i++) 
          {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
              {
                if(OrderSymbol()==sym) 
                  {
                    if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
                      {
                        if(op0 || OrderType()==op) 
                          {
                            if(mn0 || OrderMagicNumber()==mn) 
                              {
                                if(ootOrderOpenTime()) 
                                    oot=OrderOpenTime();
                              }
                          }
                      }
                 }
             }
        }
      return(CurTime()-oot);
  }
//+----------------------------------------------------------------------------+

El texto completo del ejemplo del código fuente para las tácticas apoyando la posición principal se encuentra en el archivo e-SampleMain.mq4.


Trading oscilante con promediación


Cuando llega una señal de entrada, se abre una posición. Se abren nuevas posiciones adicionales en base a todas las demás señales en la dirección de la primera posición. Cuando una señal llega contra las posiciones existentes, todas las posiciones se cierran y se abre una posición en la dirección de la señal. La señal de trading se repite.

El envío y la ejecución de señales de trading para el trading oscilante en una posición ya ha sido discutido. Adaptemos este ejemplo para implementar la opción de la apertura de posiciones adicionales. Para proporcionar la conexión de una señal con una posición, usaremos la restricción de posibilidad de entrada por un periodo de tiempo de una barra. Una barra para una entrada.

//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignal();
 
    if(bs>0) 
      {
        if(ExistPositions("", OP_SELL)) 
            ClosePositions("", OP_SELL);
        if(NumberOfBarLastPos()>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
      }
    if(bs<0) 
      {
        if(ExistPositions("", OP_BUY)) 
            ClosePositions("", OP_BUY);
        if(NumberOfBarLastPos()>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
 
//+----------------------------------------------------------------------------+
//|  Returns the bar number of the last position opening or -1.                |
//|  Parameters:                                                               |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe                ( 0 - current timeframe)                 |
//|    op  - operation                (-1 - any position)                      |
//|    mn  - MagicNumber              (-1 - any magic number)                  |
//+----------------------------------------------------------------------------+
int NumberOfBarLastPos(string sym="", int tf=0, int op=-1, int mn=-1) 
  {
    datetime oot;
    int      i, k=OrdersTotal();
 
    if(sym=="") 
        sym=Symbol();
    for(i=0; ik; i++) 
      {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
          {
            if(OrderSymbol()==sym) 
              {
                if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
                  {
                    if(op0 || OrderType()==op) 
                      {
                        if(mn0 || OrderMagicNumber()==mn) 
                          {
                            if(ootOrderOpenTime()) oot=OrderOpenTime();
                          }
                      }
                  }
             }
         }
     }
   return(iBarShift(sym, tf, oot, True));
  }
//+----------------------------------------------------------------------------+

El texto completo del ejemplo del código fuente para el trading oscilante con promediación se encuentra en el archivo e-SampleSwingAdd.mq4.


Tácticas de la cartera de valores


Para cada señal de trading se abre y se apoya una posición con independencia de las demás.

A primera vista, esta es la variante más complicada de la ejecución de señales de trading en términos de la implementación del software. Aquí, excepto el envío de señales de trading, necesitamos enviar la correspondiente de una señal a una cartera u otra. Pero si dividimos las señales en grupos, que constituyen una cartera, veremos que cada grupo por separado es un trading sencillo de una posición. La forma de combinar grupos en una cartera es evidente: asignar un número único a cada grupo y hacer una búsqueda de todos los grupos en un ciclo. Este es un ejemplo de grupos de cuatro señales:

//+----------------------------------------------------------------------------+
//|  Returns trading signals.                                                  |
//|  Parameters:                                                               |
//|    ms  - array of signals                                                  |
//|    ns  - number of a signal                                                |
//|    sym - name of the instrument ("" - current symbol)                      |
//|    tf  - timeframe              ( 0 - current timeframe)                   |
//+----------------------------------------------------------------------------+
void GetTradeSignals(bool& ms[], int ns, string sym="", int tf=0) 
  {
    if (sym=="") sym=Symbol();
 
    // Switching signal groups using operators switch or if
    // Block of analysis fulfilling the array ms:
    // ms[0]=True;   // Buy
    // ms[1]=True;   // Sell
    // ms[2]=True;   // Close Buy
    // ms[3]=True;   // Close Sell
  }
 
//+----------------------------------------------------------------------------+
//|  Positions management                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4];
    double sl=0, tp=0;
    int    i;
 
    for(i=0; i4; i++) 
      {
        ArrayInitialize(ms, False);
        GetTradeSignals(ms, i);
        if(ExistPositions("", -1, MAGIC+i)) 
          {
            if(ms[2]) ClosePositions("", OP_BUY, MAGIC+i);
            if(ms[3]) ClosePositions("", OP_SELL, MAGIC+i);
          }
        if(!ExistPositions("", -1, MAGIC+i)) 
          {
            if(ms[0]) 
              {
                if(StopLoss!=0) 
                    sl=Ask-StopLoss*Point;
                if(TakeProfit!=0) 
                    tp=Ask+TakeProfit*Point;
                OpenPosition("", OP_BUY, sl, tp, MAGIC+i);
              }
            if(ms[1]) 
              {
                if(StopLoss!=0) 
                    sl=Bid+StopLoss*Point;
                if(TakeProfit!=0) 
                    tp=Bid-TakeProfit*Point;
                OpenPosition("", OP_SELL, sl, tp, MAGIC+i);
              }
          }
      }
  }
//+----------------------------------------------------------------------------+

El texto completo del ejemplo del código fuente para las tácticas de perfil se encuentra en el archivo e-SampleCase.mq4.


Señales de trading para órdenes


Veamos la lista de señales de trading necesaria para trabajar con órdenes pendientes.

  1. Establecer BuyLimit;
  2. Establecer SellLimit;
  3. Establecer BuyStop;
  4. Establecer SellStop;
  5. Borrar BuyLimit;
  6. Borrar SellLimit;
  7. Borrar BuyStop;
  8. Borrar SellStop;
  9. Modificar BuyLimit;
  10. Modificar SellLimit;
  11. Modificar BuyStop;
  12. Modificar SellStop.

Podemos adivinar fácilmente que con las órdenes pendientes podríamos desear enviar simultáneamente cuatro o más señales de trading. ¿Y qué ocurriría si la lógica del AE requiere trabajar con las posiciones y las órdenes?

Esta es la lista completa ampliada de todas las señales de trading.

  1. Abrir Buy;
  2. Abrir Sell;
  3. Establecer BuyLimit;
  4. Establecer SellLimit;
  5. Establecer BuyStop;
  6. Establecer SellStop;
  7. Cerrar Buy;
  8. Cerrar Sell;
  9. Borrar BuyLimit;
  10. Borrar SellLimit;
  11. Borrar BuyStop;
  12. Borrar SellStop;
  13. Modificar BuyLimit;
  14. Modificar SellLimit;
  15. Modificar BuyStop;
  16. Modificar SellStop.

¡Dieciséis señales de trading! ¡Dos bytes! Estaba también la idea de enviar señales como número binario, pero en un string. Por ejemplo, 00101..., donde la posición cero o uno estaría a cargo de una señal definitiva. Pero habría mucha agitación con los substrings y la decodificación de señales. Por tanto, podemos ver que la forma más conveniente es una matriz con el número de elementos igual al número de señales. Además, para una mayor comodidad de referencia a los elementos de la matriz, los índices pueden definirse como constantes. MQL4 ya contiene OP_BUY, OP_SELL y así sucesivamente. Podemos continuar fácilmente:

#define OP_CLOSEBUY         6
#define OP_CLOSESELL        7
#define OP_DELETEBUYLIMIT   8
#define OP_DELETESELLLIMIT  9
#define OP_DELETEBUYSTOP   10
#define OP_DELETESELLSTOP  11
#define OP_MODIFYBUYLIMIT  12
#define OP_MODIFYSELLLIMIT 13
#define OP_MODIFYBUYSTOP   14
#define OP_MODIFYSELLSTOP  15

y hacer referencia a los elementos de la matriz: ms[OP_BUY] o ms[OP_MODIFYSELLLIMIT] en lugar de ms[0] y ms[13]. Aún así, es cuestión de gustos. Yo prefiero los códigos concisos y simples y por ello elijo las cifras.

Sigamos. ¡Todo parece fácil y bonito! Pero también necesitamos niveles de precio para establecer órdenes, niveles de stops y takeprofit para las posiciones, ya que cada señal de trading puede llevar la información sobre un determinado stop o takeprofit y un cierto nivel de precio al establecer una orden. Pero ¿cómo podemos pasar esta información junto con una señal de trading? Yo ofrezco la siguiente forma:

  1. Declarar una matriz de dos dimensiones con un número de líneas igual al número de señales y tres columnas;
  2. La primera columna apuntará con el valor cero en ausencia de una señal, con el valor no cero cuando exista una señal para una posición (un nivel de precio al establecer una orden);
  3. La segunda columna: stops;
  4. La tercera columna: niveles de takeprofit.

El texto completo del ejemplo del código fuente para el trading con órdenes se encuentra en el archivo e-SampleOrders.mq4.

Y ¿qué ocurriría si necesitamos establecer varias BuyLimit o varias SellStop? ¿Y abrir posiciones? En esta caso haremos lo que se describe en la parte "Tácticas de cartera" de este artículo, es decir, usar una táctica de perfil con identificación de la posición y la orden por los número mágicos.

Conclusión


Es el momento de resumirlo todo:

  1. Enviar señales usando una variable tiene algunos inconvenientes de una interfaz serie: solo puede enviarse una señal en cada momento en el tiempo;
  2. Implementar una interfaz paralelo conduce al mayor número de variables y complica su gestión, pero permite enviar simultáneamente docenas de señales.

Por tanto, el uso de uno u otro método para el envío de señales de trading debe determinarse por conveniencia.

Traducción del ruso hecha por MetaQuotes Software Corp.
Artículo original: https://www.mql5.com/ru/articles/1436

Archivos adjuntos |
b-Positions.mqh (20.13 KB)
e-SampleCase.mq4 (7.12 KB)
e-SampleMain.mq4 (7.94 KB)
e-SampleOrders.mq4 (14.71 KB)
e-SampleSimple.mq4 (6.88 KB)
¿Cómo no caer en las trampas de la optimización? ¿Cómo no caer en las trampas de la optimización?

El artículo describe los métodos para conocer mejor los resultados de la optimización del probador. También da algunos ejemplos que ayudan a evitar la "optimización perjudicial".

Ejecutando el terminal de cliente de MetaTrader 4 en el escritorio de Linux Ejecutando el terminal de cliente de MetaTrader 4 en el escritorio de Linux

Descripción paso a paso de la configuración del escritorio de Linux usando un emulador de Windows (wine) no emulador para ejecutar el terminal de cliente de MetaTrader 4 en él.

Psicología individual de un trader Psicología individual de un trader

Un retrato del comportamiento de un trader en el mercado financiero. Menú propio del autor extraído del libro "Как играть и выигрывать на бирже" ("Cómo especular en el mercado bursátil y ganar") por A. Elder.

Trading Usando Linux Trading Usando Linux

The article describes how to use indicators to watch the situation on financial markets online.