English Русский 中文 Español Deutsch 日本語
Envio de sinais de negociação em um expert advisor universal

Envio de sinais de negociação em um expert advisor universal

MetaTrader 4Exemplos | 18 fevereiro 2016, 15:08
1 014 0
Igor Kim
Igor Kim

Introdução


Há algum tempo, eu decidi tentar universalizar e unitizar um processo de desenvolvimento de expert advisors no tópico "O desenvolvimento de um expert advisor universal". Isso exigiu a criação de um determinado padrão de desenvolvimento de tijolos unitários principais, que mais tarde pudessem ser utilizados na construção de expert advisors, como peças de um kit de construção. Esta tarefa foi parcialmente implementada. Eu forneci a estrutura de um EA universal, e a ideia de um uso universal de sinais de diferentes indicadores. Neste artigo, eu darei prosseguimento a este trabalho: eu vou tentar universalizar o processo de formação e envio de sinais de negociação e gerenciamento de itens nos expert advisors. Neste contexto, um item significa uma operação de compra ou venda. Todas as discussões subsequentes farão referência a este tipo de operação. Este artigo não descreve BUYLIMIT, BUYSTOP, SELLLIMIT e SELLSTOP de pedidos pendentes, mas o fim do artigo eu irei mostrar que a minha abordagem pode facilmente ser aplicada a eles.

Classificação de sinais de negociação


Há vários tipos de sinal de negociação:

  1. Compra;
  2. Venda;
  3. Compra adicional (média);
  4. Venda adicional (média);
  5. Fechamento de compra completa;
  6. Fechamento de venda completa;
  7. Fechamento de compra parcial;
  8. Fechamento de venda parcial;

Caso nós transpusermos a decisão relativa à media e ao fechamento parcial da unidade de formação de sinais de negociação à unidade de gerenciamento de posições e pedidos, esta lista será reduzida à seguinte:

  1. Compra;
  2. Venda;
  3. Fechar compra;
  4. Fechar venda;
  5. Não fazer nada (a operação normal do EA exige um sinal do tipo).

A partir desta suposição, o esquema de operação do EA de ser o seguinte:

  1. Um item de sinal cria um sinal de negociação;
  2. Um sinal de negociação entra na unidade de gerenciamento de posições, que toma as decisões relativas a novas aberturas, média, fechamento parcial ou completo, e envia o sinal de negociação encurtado à unidade do programa de processamento de sinais de negociação.
  3. A unidade de processamento de sinais de negociação realiza diretamente operações de negociação.

Neste artigo, eu gostaria de tratar das diferentes formas de formação de sinais de negociação e dos modos com que eles são enviados à unidade de gerenciamento de posições, ou seja, a interface entre as unidades, mencionada nos pontos 1 e 2.


Negociações de balanço em uma posição


O significado deste tipo de negociação é o seguinte: antes de abrir uma nova posição, a anterior deve ser fechada. A nova posição é oposta à anterior. Caso ela fosse uma compra, nós abrimos uma venda, e vice-versa. Neste caso, os momentos de abertura e fechamento de posições coincidem, e é por isso que sinais de fechamento podem ser omitidos. Portanto, a implementação de negociações de balanço exige o envio de apenas três sinais de negociação: comprar, vender e não fazer nada. Estes sinais podem ser enviados através do uso de uma variável int. Por exemplo:

1 - comprar;
0 - não fazer nada;
-1 - vender.

Então a parte de análise da situação do mercado e criação de um sinal de negociação pode ser escrita em uma função separada como, por exemplo, 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 devolve os supracitados valores de números inteiros. A ativação dessa função é mais facilmente realizada diretamente na unidade de gerenciamento de posições.

//+----------------------------------------------------------------------------+
//|  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);
         }
     }
  }
//+----------------------------------------------------------------------------+

Neste caso, uma única variável local bs do tipo número inteiro age como uma ligação entre as duas unidades do programa. O texto completo do código fonte do exemplo para negociações de balanço em uma posição está localizado no arquivo e-SampleSwing.mq4.



Negociações simples em uma posição


Este caso é um pouco mais difícil. Ainda que no mercado só haja uma posição em cada ponto do tempo, o seu fechamento não está conectado com a abertura de outra posição. É por isso que um gerenciamento de posições bem sucedido exige o uso de todos os cinco sinais: comprar, vender, fechar posição de compra, fechar posição de venda, e não fazer nada. Eles podem ser enviados em uma variável do tipo número inteiro com os seguintes valores atribuídos:

2 - fechar posição de venda;


1 - comprar;


0 - não fazer nada;


-1 - vender;


-2 - fechar posição de compra.



A unidade de gerenciamento de posições pode ser escrita em uma função:

//+----------------------------------------------------------------------------+
//|  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);
          }
      }
  }
//+----------------------------------------------------------------------------+

O texto completo do código fonte do exemplo para negociações simples em uma posição está localizado no arquivo e-SampleSimple.mq4.

A principal desvantagem de se enviar um sinal de negociação em uma variável é que você não pode enviar vários sinais simultaneamente (desvantagens de uma interface serial). Por exemplo, você não pode abrir em ambas as direções, ou abrir com um fechamento simultâneo de uma posição existente, ou fechar todas as posições. Esta desvantagem pode ser parcialmente eliminada pela divisão de um sinal em dois números inteiros.

Há três modos de dividir um sinal:

  1. Abra em uma variável, feche em outra. Você pode combinar a abertura e o fechamento, ou seja, organizar negociações de balanço, mas não pode abrir em ambas as direções ou fechar posições em direções contrárias.
  2. Posições de compra (abertura e fechamento) ficam em uma variável, e posições de venda (abertura e fechamento) ficam em outra. Você pode abrir posições em ambas as direções e fechar todas as posições de uma só vez, mas você não pode abrir e fechar simultaneamente, por exemplo, uma posição de compra ou venda, ou seja, você não pode reabrir;
  3. Abra uma compra e feche uma venda em uma variável, abra um venda e feche uma compra em outra. Você pode abrir em ambas as direções e fechar todas as posições, mas você não pode organizar as negociações de balanço.

Vamos tentar implementar a segunda opção, pois reaberturas são bastante raras. Ninguém quer perder dinheiro durante o spread. A segunda opção pode ser implementada de diversas maneiras.

1. Dois valores de retorno de funções em duas variáveis locais. Uma função cria sinais para a compra, e a segunda para a venda.

//+----------------------------------------------------------------------------+
//|  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 é uma forma simples e conveniente de criar e enviar um sinal de negociação, mas uma unidade de sinal é dividida em duas funções, o que provavelmente retardaria a sua operação.


2. Duas variáveis globais adquirem valores em uma função.

//+----------------------------------------------------------------------------+
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);
          }
      }
  }
//+----------------------------------------------------------------------------+

Fica claro a partir deste código fonte que a realização com variáveis globais não é muito diferente do primeiro método. A vantagem aparente é que o modo do sinal fica em uma função.



3. Duas variáveis locais são passadas por referência a uma função.

//+----------------------------------------------------------------------------+
//|  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. Uma matriz de dois elementos. Se ela for global, é inicializada dentro da função. Se ela for local, é passada por referência. Tudo aqui é simples: uma matriz ao invés de duas variáveis. Elementos globais e elementos locais por referência foram discutidos anteriormente. Nada de novo.

E, finalmente, nós podemos organizar uma interface paralela plenamente valorizada enviando sinais de negociação, dividindo-a em quatro variáveis. Em relação ao gerenciamento de posições, cada sinal possui dois estados: ele existe ou não. É por isso que é melhor lidarmos com variáveis do tipo lógico. Você pode combinar sinais, enviando-os através do uso de quatro variáveis, sem limite. Aqui temos um exemplo de um código com uma matriz de quatro elementos do 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);
          }
      }
  }
//+----------------------------------------------------------------------------+

A implementação com variáveis locais, passada por referência a uma função, e com variáveis globais, inicializada dentro de uma função, não deve causar nenhum problema. Contudo, a inicialização de quatro variáveis locais através de valores, devolvidas por quatro funções diferentes, não é muito sensata.


Apoio à posição principal


Quando um sinal chega, uma posição é aberta. Ela se torna a posição principal. Todos os outros registros de sinal contra a posição principal são ignorados. Posições adicionais são abertas em sinais, em correspondência com a posição principal. No fechamento da posição principal todas as posições adicionais também são fechadas.

O envio de sinais de negociação para estas táticas pode ser implementado através do uso de uma, duas ou quatro variáveis. Tudo isso foi descrito anteriormente. A dificuldade que você pode encontrar é fornecer a conexão: um sinal - uma posição. No caso de negociações em uma posição, essa questão foi resolvida por uma simples verificação da existência da posição através do uso da função ExistPositions(). Caso uma posição exista, o sinal de entrada é omitido. Caso não exista nenhuma posição, o sinal de entrada é realizado.

Então há diferentes saídas:

  1. Fornecimento de uma pausa entre as entradas. A realização mais fácil;
  2. Uma barra - uma entrada. Uma variação da primeira forma. A realização também é fácil;
  3. Enumerar os sinais e matrizes de controle de sinais e bilhetes de pedidos. Esta é a implementação mais difícil, com baixa confiabilidade.

Este é o exemplo de um código para o primeiro 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);
  }
//+----------------------------------------------------------------------------+

O texto completo do código fonte do exemplo para as táticas com apoio à posição principal está localizado no arquivo e-SampleMain.mq4.


Negociações de balanço com cálculo da média


Quando um sinal de entrada chega, uma posição é aberta. Com base em todos os sinais posteriores na direção da primeira posição, novas posições adicionais são abertas. Quando um sinal chega contra as posições existentes, todas as posições são fechadas e uma posição é aberta na direção do sinal. O sinal de negociação é repetido.

O envio e a execução de sinais de negociação para a negociação de balanço em uma posição já foram discutidos. Vamos adaptar este exemplo para implementar a opção de abertura de posições adicionais. Para fornecer a conexão de um sinal - uma posição, vamos usar a restrição da possibilidade de entrada pelo período de tempo de uma barra. Uma barra - uma 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));
  }
//+----------------------------------------------------------------------------+

O texto completo do código fonte do exemplo para negociações de balanço com cálculo da média está localizado no arquivo e-SampleSwingAdd.mq4.


Táticas de portfólio


Para cada sinal de negociação, uma posição é aberta e apoiada, independentemente das outras.

à primeira vista, essa parece ser a opção mais complexa de execução de sinais de negociação em termos de implementação de software. Aqui, exceto no envio de sinais de negociação, você precisa enviar o conteúdo de um sinal a um ou outro portfólio. Mas se você dividir os sinais em grupos, que constituem um portfólio, você verá que cada grupo separado é uma negociação simples de uma posição. A forma de combinar grupos em um portfólio é evidente: atribua um número único a cada grupo e configura uma busca de todos os grupos em um ciclo. Aqui está um exemplo de quatro grupos de sinais:

//+----------------------------------------------------------------------------+
//|  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);
              }
          }
      }
  }
//+----------------------------------------------------------------------------+

O texto completo do código fonte do exemplo para táticas de perfil está localizado no arquivo e-SampleCase.mq4.


Sinais de negociação para pedidos


Vamos examinar a lista de sinais de negociação necessários para o trabalho com pedidos pendentes.

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

Também seria fácil imaginar que com pedidos pendentes, você poderia querer enviar quatro ou mais sinais de negociação simultaneamente. E se a lógica do EA exija o trabalho tanto com posições quanto com pedidos?

#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

Aqui está a lista completa e expandida de todos os sinais de negociação.

  1. Abrir compra;
  2. Abrir venda;
  3. Configurar BuyLimit;
  4. Configurar SellLimit;
  5. Configurar BuyStop;
  6. Configurar SellStop;
  7. Fechar compra;
  8. Fechar venda;
  9. Deletar BuyLimit;
  10. Deletar SellLimit;
  11. Deletar BuyStop;
  12. Deletar SellStop;
  13. Modificar BuyLimit;
  14. Modificar SellLimit;
  15. Modificar BuyStop;
  16. Modificar SellStop.

Dezesseis sinais de negociação! Dois bytes! Também existia a ideia de enviar sinais como um número binário, mas em sequência. Por exemplo, 00101..., sendo que a posição do zero ou do um seria responsável por um sinal definido. Mas isso causaria muita confusão com os subconjuntos e a decodificação de sinais. Portanto, a saída mais conveniente é uma matriz com o número de elementos igual ao número de sinais. Além disso, para maior conveniência na referência aos elementos da matriz, índices podem ser definidos como constantes. O MQL4 já contém OP_BUY, OP_SELL, etc. Nós podemos continuar com facilidade:

e consultar os elementos da matriz: ms[OP_BUY] ou ms[OP_MODIFYSELLLIMIT] ao invés de ms[0] e ms[13]. Ainda assim, trata-se de uma questão de gosto. Eu prefiro códigos concisos e simples, e é por isso que eu opto por figuras.

Vamos prosseguir. Tudo parece estar indo bem! Mas nós também precisamos dos níveis de preço da configuração de pedidos, paradas e níveis de takeprofit de posições, pois cada sinal de negociação pode carregar informações a respeito de certas paradas e takeprofit e certos níveis de preço para se configurar um pedido. Mas como nós podemos passar estas informações com o sinal de negociação? Em ofereço a seguinte opção:

  1. Declare uma matriz bidimensional com um número de linhas igual ao número de sinais, e três colunas;
  2. A primeira coluna irá apontar para o valor zero na ausência de um sinal, e para o valor não-zero na presença de um sinal para uma posição (um nível de preço de configuração de um pedido);
  3. A segunda coluna - paradas;
  4. A terceira coluna - níveis de takeprofit.

O texto completo do código fonte do exemplo para negociações com pedidos está localizado no arquivo e-SampleOrders.mq4.

E se nós precisarmos configurar vários BuyLimit ou vários SellStio? E abrir posições? Neste caso nós faremos como descrito na seção "Táticas de portfólio" deste artigo, ou seja, usar táticas de perfil com identificação de posição e pedido através de números mágicos.

Conclusão


É hora de resumir todas as informações:

  1. O envio de sinais através do uso de uma variável apresenta algumas desvantagens de uma interface serial: apenas um sinal pode ser enviado em cada ponto do tempo;
  2. A implementação de uma interface paralela leva a um número maior de variáveis e complica o seu gerenciamento, mas permite o envio simultâneo de dúzias de sinais.

Portanto, o uso de um ou outro método de envio de sinais de negociação deve ser determinado pela conveniência.


Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1436

Arquivos anexados |
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)
Psicologia individual de um trader Psicologia individual de um trader
Um retrato do comportamento de um trader no mercado financeiro. O menu do próprio autor, do livro "Как играть и выигрывать на бирже" ("Como especular e lucrar na bolsa de valores"), de A. Elder.
Como não cair em armadilhas de otimização? Como não cair em armadilhas de otimização?
O artigo descreve os métodos para se entender melhor os resultados da otimização do provador. Ele também fornece algumas dicas que ajudam a evitar a "otimização prejudicial".
Negociações com o uso do Linux Negociações com o uso do Linux
O artigo descreve como usar indicadores para monitorar a situação dos mercados financeiros online.
Execução do terminal do cliente MetaTrader 4 em Linux-Desktop Execução do terminal do cliente MetaTrader 4 em Linux-Desktop
Descrição de uma configuração passo a passo em desktop Linux usando um wine não emulador para executar o terminal do cliente MetaTrader4.