Consideração de pedidos em um programa amplo

18 fevereiro 2016, 10:03
Сергей Ковалев
0
416

Caso a estratégia de transações pressuponha o trabalho com uma pequena quantidade de pedidos (por exemplo, com apenas um pedido de compra e um pedido de venda), o expert que executa essa estratégia pode fazê-lo sem registrar os pedidos. Ele simplesmente toma as decisões relativas às transações com base em sua própria ideologia, ou seja, no fato de que não pode haver mais de um pedido unilateral no terminal.

Essa abordagem é basicamente aceitável, mas só é adequada a programas pequenos, e não pode ser classificada como universal. Mas o que esse expert deve fazer caso haja dois ou mais pedidos do mesmo tipo para o mesmo símbolo? Poderia-se argumentar que a estratégia de transações não prevê esse tipo de situação, e que elas não poderiam ocorrer. Isso é verdade, mas também revela o quão deficiente e limitado é esse conceito.

Assim que o trader passa a ter experiência suficiente para realizar transações usando vários pedidos (incluindo pedidos pendentes), torna-se necessário levar em consideração todos os pedidos disponíveis, pois pedidos pendentes podem se transformar em pedidos abertos. Além disso, sabe-se que o trader pode sempre abrir manualmente um pedido deixado pelo expert que trabalha no terminal. Também é possível que vários traders realizem transações usando a mesma conta. E, em um caso mais geral, a própria estratégia de transações pode pressupor o uso de grande quantidade de pedidos.

Vamos tentar explorar os detalhes das formas pelas quais podemos considerar melhor os pedidos em um programa amplo.

1. Característica de ambiente e generalidades

Vamos descrever brevemente as características do ambiente no qual o nosso programa irá trabalhar.

1. Antes de tudo, nós certamente queremos saber (considere que os dados serão colhidos pelo programa) quantos pedidos teremos. Apenas mencionar que temos, digamos, 3 pedidos de venda e 4 pedidos de compra não é suficiente. É bastante provável que qualquer sistema de transação de dados possua um algoritmo para controlar as características dos pedidos - os níveis de StopLoss e TakeProfit e o OpenPrice de pedidos pendentes. Além disso, nós precisaremos saber qual é o custo de cada pedido, qual é o seu tempo de expiração e qual programa foi usado para fazê-lo.

2. Ticks. Qualquer informação faz sentido caso seja considerada a tempo. Qualquer expert lida com cotações que chegam ao terminal. Evidentemente o estado dos pedidos pode mudar com qualquer mudança de preço, o que significa que pedidos devem ser "reconsiderados" a cada tick.

3. O símbolo localizado na janela à qual o expert foi conectado pode ser considerado uma "característica geral".

Com base nesses dados simples, nós podemos determinar os princípios gerais de como se construir o programa para considerar pedidos.

Em primeiro lugar, exceto em relação à consideração de pedidos, o sistema de transações pode e deve resolver alguns outros problemas. Por exemplo, ele pode analisar a disponibilidade e a qualidade dos pedidos e, com base nesses dados, tomar decisões relativas às transações.. Qualquer análise da situação atual é possível caso a situação seja conhecida. Isso significa que o código do programa que é responsável por considerar os pedidos deve ser executado antes dos outros códigos. O ideal seria formar este código de consideração como uma função separada. Vamos chamá-lo de Terminal(), pois a sua tarefa principal será observar os pedidos no terminal.

Em segundo lugar, os dados acumulados pela função Terminal() devem ser disponibilizados às outras funções. É por isso que as variáveis que possuam informações úteis sobre os pedidos deve ser declaradas no nível global (não confundir com o GlobalVariables).

Em terceiro lugar, dado que nós lidamos com conjuntos de informações, seria lógico organizar as considerações com base nas matrizes de pedidos.

2. Estrutura do programa

O raciocínio acima nos permite projetar uma estrutura geral do programa que contém os pedidos considerando que:

// My_expert.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
#include ...
#include <Peremen.mq4>    // Description of the expert's variables.   
#include <Terminal.mq4>   // Attach the Terminal function.
#include <Sobytiya.mq4>   // Attach the Sobytiya function.
#include ...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
// 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
   ...                    // Function code init()
   return;
   } 
//=================================================================
int start() 
   {
   Terminal();            // This function is the first in 
                          // the sequence of functions
   ...                    // The posterior start()function code
   Sobytiya();            // Events processing function
   ...                    // The posterior start()function code
   return;                                                                 
   }
//=================================================================
int deinit() 
   {   
   ...                    // The deinit() function code
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

O arquivo Peremen.mq4 que descreve variáveis deve conter a descrição das matrizes que fornecem dados sobre os pedidos.

//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//==================================================================
int
...
//==================================================================
double
...
Mas_Ord_Tek[31][8], Mas_Ord_Old[31][8], 
// The current and the old array of orders
// the 1st index = the order number in this array
// [][0] not defined
// [][1] order open rate  (absolute value of the rate)
// [][2] StopLoss orders  (absolute value of the rate)
// [][3] TakeProfit orders(absolute value of the rate)
// [][4] order number        
// [][5] lots in the order(absolute value of the rate)
// [][6] order type 1=B,2=S,3=BL,4=SL,5=BS,6=SS
// [][7] Magic Number of the order
...
//=================================================================
string 
...
//=================================================================
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Quado as variáveis globais são definidas em programas pequenos, elas são geralmente escritas antes da função de primeira chegada. Em programas médios e grandes, é adequado coletar todas as variáveis globais em um arquivo e anexar este arquivo ao expert, usando a

instrução

#include Em termos de eficiência do código, as diferenças entre os métodos não são importantes, mas em termos de usabilidade, a anexação do arquivo é preferível. É assim que o arquivo

Peremen.mq4

foi anexado ao expert no exemplo acima.


3. Matrizes

No arquivo Peremen.mq4, duas matrizes são definidas como variáveis globais:

Mas_Ord_Tek[31][8] - a matriz atual de pedidos;

Mas_Ord_Old[31][8] - a antiga matriz de pedidos.

Por que precisamos de duas, e não apenas de uma matriz? Para sermos capazes de monitorar os eventos. Nós discutiremos mais tarde o que esses eventos podem vir a ser. Por enquanto, vamos apenas dizer que um evento em si é identificado com base na comparação de seu estado inicial ao seu estado atual. Caso não haja dados em relação a nenhum dos estados, é impossível identificar o evento. Neste caso, são usadas matrizes de pedidos para se obter informações a respeito do status do espaço de transações antes e depois do tick.

Por que nós usamos uma matriz 2D? Porque nós vamos considerar vários pedidos simultaneamente, e armazenar informações sobre cada um deles em relação a várias características. O primeiro índice é o número do pedido na matriz, o segundo é a característica do pedido em relação a um dado critério. No exemplo acima, o primeiro índice não permite que mais de 30 pedidos estejam disponíveis no terminal. Você pode alterar essa quantidade livremente, permitindo que 50 ou 100 pedidos, por exemplo, sejam considerados no terminal simultaneamente. Obviamente isso faz sentido apenas caso o seu sistema de transações for projetado para trabalhar com essa quantidade de pedidos. Em situações padrão, são usados 1 ou 2 pedidos. Em casos mais raros, 4. 30, na minha opinião, é um número excessivo.

Por que 31 e 8, e não 30 e 7, são os números apresentados nos colchetes indexados das matrizes? A questão é que no MQL4 as matrizes começam a contar o índice a partir do zero. O uso de células zero para elementos comuns nem sempre é justificável. Na minha opinião, seria lógico fazer com que o número do pedido correspondesse ao número do elemento da matriz. Por exemplo, o terceiro pedido deveria estar alinhado ao índice 3. Na realidade, essa linha será a quarta, mas o seu índice será 3, pois a primeira linha possui um índice de 0.

Vamos examinar a tabela abaixo, que exibe o interior das matrizes. Vamos supor que há apenas 3 pedidos: Comprar, vender e BuyStop de qualidades diferentes:



As informações sobre os pedidos estão localizadas nas células da matriz, numeradas de [1][1] a [7][30]. Além disso, nós colocaremos a quantidade total de pedidos na matriz na célula indexada como [0][0]. Neste caso, 3. Nos cálculos subsequentes, este número será usado para organizar ciclos, nos quais o estado atual será analisado.

Deste modo, nós podemos armazenar informações sobre 30 pedidos, cada um sendo marcado por 7 características.

Caso a sua estratégia de transações pressuponha a realização de transações simultâneas em vários símbolos, você pode abrir várias matrizes e ordená-las de acordo com os pares cambiais. Esse método é bastante aceitável, mas não é muito conveniente. Caso a consideração dos pedidos for organizada desse modo, é necessário abrir outra matriz para armazenar os nomes das matrizes que contêm as informações sobre os pedidos.

Uma solução mais conveniente é usar uma matriz grande (uma antiga e uma nova) para considerar todos os pedidos. Essa é a melhor escolha pois, ao se processar essa matriz no código subsequente, não haverá necessidade de procurar os nomes das matrizes de pedidos de símbolo. Bastará organizar a busca no ciclo de uma variável numérica formal através de um dos índices da matriz.

A matriz que contém informações sobre todos os pedidos pode ser organizada da seguinte maneira:



Informações a respeito de pedidos relativos a cada símbolo são armazenadas no mesmo plano do índice, como no exemplo acima. A diferença consiste no fato de que, neste caso, há vários desses planos (na figura, há 3 deles: amarelo, rosa e verde). A sua quantidade total é igual à quantidade de pares cambiais com os quais iremos trabalhar, mais um, o zero. Nesse plano do índice (cinza), o único valor, a quantidade total de pedidos, é armazenado na célula indexada como [0][0][0].

A dimensão da matriz para, digamos, 25 símbolos, será de 26 para o primeiro índice. Neste caso, o arquivo

Peremen.mq4

que descreve matrizes irá ter a seguinte aparência:


//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//===========================================================================
int
...
//===========================================================================
double
...
Mas_Ord_Tek[26][31][8], Mas_Ord_Old[26][31][8], 
//The current and the new array of orders
// the 1st index = symbol number
// the 2nd index = order number ...
// ... on the plane of the symbol
// [][][0] not defined
// [][][1] order open rate     (absolute value of the rate)
// [][][2] StopLoss orders     (absolute value of the rate)
// [][][3] TakeProfit orders   (absolute value of the rate)
// [][][4] order number        
// [][][5] lots of the order   (absolute value of the rate)
// [][][6] order type 1=B,2=S,3=BL,4=SL,5=BS,6=SS
// [][][7] MagicNumber of the order
//=================================================================
string 
      Instrument[26];                   // Array of symbol names
...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Predopred()
   {
//================================================= Predefinitions =
   Instrument[1] = "EURUSD";
   Instrument[2] = "GBPUSD";
   ...
   Instrument[25]= "AUDCAD";
//==================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж


Na parte inferior do bloco de variáveis de abertura deste arquivo, a matriz Instrument[26] foi aberta.

Um programa grande geralmente possui muitas variáveis, cujos valores não mudam durante a execução do programa. No nosso caso, elas são elementos da matriz Instrument[]. De modo a tornar a programação mais confortável, seria melhor agrupar essas variáveis em uma função. Essa função também pode ser formada como um arquivo separado anexado ao programa através de #include.

No exemplo abaixo, podemos ver a pré-definição dos elementos da matriz Instrument[] na função Predopred() contida no mesmo arquivo Peremen.mq4. Basta executar essa função uma única vez, portanto faz sentido incluí-la no programa dentro da função especial chamada init():

int init()  
   {
   Predopred();         // Predefinition of some variables
   return;
   }

Desse modo, alguns números inteiros contidos, no nosso caso, nos valores índice da matriz Instrument[] são criados em correspondência com os símbolos.


4. Função para a consideração dos pedidos

Vamos agora examinar a função Terminal() de considerar pedidos em relação a um símbolo. Essa função também é organizada como um arquivo separado chamado Terminal.mq4, e é anexada ao expert através da instrução #include.

A primeira coisa a ser feita após o sistema ter passado o controle à função Terminal() é salvar o estado anterior dos pedidos. Ele está na matriz Mas_Ord_Tek[][], mas não está atualizado no momento, pois reflete o estado dos pedidos formados no tick anterior. O estado atual ainda não é conhecido pelo movimento inicial.
// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//================================================ Predefinition ==
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);// Save the preceding history
   int Kol=0;                       // Zeroization of orders counter
   ArrayInitialize(Mas_Ord_Tek,0);     // Zeroization of the array
//=============================================== Анализ ордеров ==
   for (int i=0; i<OrdersTotal(); i++) 
// For all orders in the terminal
     {
      if((OrderSelect(i, SELECT_BY_POS)==true) && 
                      (OrderSymbol()==Symbol()))
                        //If there is the next and our currency pair
       {                                                                     
        Kol++;                   // Count the total amount of orders
//---------------------------  Forming of the new array of orders --
        Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                              Digits); 
// Order open rate
        Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(),
                                              Digits); 
// SL rate
        Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                              Digits); 
// ТР rate
        Mas_Ord_Tek[Kol][4] = OrderTicket();      // Order number
        Mas_Ord_Tek[Kol][5] = OrderLots();        // Count of lots
        Mas_Ord_Tek[Kol][6] = OrderType();        // Order type
        Mas_Ord_Tek[Kol][7] = OrderMagicNumber(); // Magic number 
//-----------------------------------------------------------------
       }
     }
   Mas_Ord_Tek[0][0] = Kol;     // Save to the zero cell
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж



Na linha

   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek); 
// Save the preceding history


O último estado conhecido dos pedidos é passado à matriz Mas_Ord_Old[][].

A função usa a variável local chamada Kol e reflete a quantidade nova e atual de pedidos. A necessidade de usar essa variável surgiu porque o MQL4 não permite o uso de índices indexados. Como você pode ver a partir do código, ela é usada como o valor índice. Vamos usar a função "zeroize" nessa variável, assim como em toda a matriz do estado atual, e focar no estado real das coisas.

Para fazer isso, vamos organizar um ciclo para o terminal, ou seja, chamar todos os pedidos disponíveis de forma consecutiva e descobrir as suas características.


   for (int i=0; i<OrdersTotal(); i++) 
// For all orders in the terminal

Por favor, note:

OrdersTotal()

determina a quantidade de pedidos, e a contagem dos números de pedidos no terminal começa com 0. É por isso que o sinal "<" é usado na linha do ciclo e a mudança da variável interna do ciclo começa com zero: i=0.



No código subsequente, a ordem do símbolo ao qual o expert está ligado é enfatizada. Após o uso de funções que determinam várias características do pedido, a informação obtida é colocada nos elementos correspondentes da matriz Mas_Ord_Tek[][].

//--------------------------- Forming of the new array of orders --
       Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                             Digits); 
// Order open rate
       Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss() ,
                                             Digits); 
// SL rate
       Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                             Digits); 
// ТР rate
       Mas_Ord_Tek[Kol][4] = OrderTicket();      // Order number
       Mas_Ord_Tek[Kol][5] = OrderLots();        // Count 
                                                 // of lots
       Mas_Ord_Tek[Kol][6] = OrderType();        // Order type
       Mas_Ord_Tek[Kol][7] = OrderMagicNumber(); // Magic number 
//------------------------------------------------------------------


O contador que é preenchido de passagem irá passar o seu valor ao elemento zero da matriz ao fim do ciclo.

   Mas_Ord_Tek[0][0] = Kol;        // Save to the zero cell


Para a realização de transações simultâneas em vários símbolos, a função Terminal() pode ser construída da seguinte maneira:

// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//================================================== Predefinitions =
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek); 
// Save the preceding history
   ArrayInitialize(Mas_Ord_Tek,0);  
// Zeroization of array of the current orders
//================================================== Анализ ордеров =
   for (int i=0; i<OrdersTotal(); i++)  
// For all orders of the terminal
      {
      if(OrderSelect(i, SELECT_BY_POS)==true) 
// If there is a "living" order
         {
//--------------------------------------- Symbol index definition -
         string Symb=OrderSymbol();
// Determine the current order currency
         for (int ind=1; ind<=25; ind++)
// Search in the array of symbols
            {
            if (Symb==Instrument[ind])
// Index found, the search is complete
               break;            // Quit the loop by ind
            }
//------------------------ Forming of the new array of orders ----
         Mas_Ord_Tek[0][0][0]++; 
// Count the total amount of orders
         Mas_Ord_Tek[ind][0][0]++; 
// Count the amount of orders for a symbol
         int k=Mas_Ord_Tek[ind][0][0];   // Formal variable
         
         Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                                  Digits); 
// Order open rate
         Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),
                                                  Digits); 
// SL rate
         Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),
                                                  Digits); 
// ТР rate
         Mas_Ord_Tek[ind][k][4] = OrderTicket(); // Order number
         Mas_Ord_Tek[ind][k][5] = OrderLots();   // Count of lots
         Mas_Ord_Tek[ind][k][6] = OrderType();   // Order type
         Mas_Ord_Tek[ind][k][7] = OrderMagicNumber(); // Magic
                                                      // number 
         
//-----------------------------------------------------------------
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж


O algoritmo de consideração de pedidos para vários símbolos difere daquele para apenas um símbolo por conta de um pequeno bloco que determina o índice do símbolo.

//----------------------------------- Symbol index definition ----
         string Symb=OrderSymbol(); 
// Determine the current order currency
         for (int ind=1; ind<=25; ind++) 
// Search in the array of symbols
            {
            if (Symb==Instrument[ind]) 
// Index found, the search is complete
               break;              // Quit the loop by ind
            }


Nas linhas consecutivas da função

Terminal()

o valor encontrado do índice do símbolo

ind

determina o índice do plano da matriz que contém dados sobre pedidos em relação ao símbolo correspondente.



Nos exemplos acima da execução da função Terminal(), a normalização é usada no cálculo de algumas variáveis:

Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                         Digits); 
// Order open rate
Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),
                                         Digits); 
// SL rate
Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),
                                         Digits); 
// ТР rate


A necessidade desses cálculos é determinada pela intenção de se usar valores normalizados de variáveis em operadores em cálculos futuros. Além disso, a quantidade de dígitos válidos é determinada com base na variável predefinida Digits.

Um sistema de transações pode levar em consideração outros recursos e características dos pedidos. Mas, no exemplo acima, são apresentados apenas princípios gerais de consideração de pedidos em um programa grande. Por exemplo, a consideração de pedidos fechados e deletados não é discutida aqui, e algumas características de pedidos não são levadas em consideração, como o tempo de expiração de um pedido pendente, por exemplo. Caso você precise processar os recursos acima, você pode reconfigurar facilmente matrizes de modo que elas armazenem dados adicionais. Por exemplo, você pode aumentar a quantidade de elementos do último índice para armazenar valores de tempo de expiração de relação pedidos pendentes.

5. Processamento de eventos

Bem, chegamos a um novo tick, e a função Terminal() foi acionada. O controle será passado aos operadores que estão localizados imediatamente após a função Terminal(). Não é possível prever em que parte da função especial start() uma determinada função personalizada de processamento de eventos deve ser colocada. Isso depende da ideia na qual o sistema de transações é baseado. Em um caso simples, alguns eventos podem ser processados imediatamente.

Antes de apresentar o exemplo de como processar eventos, eu gostaria de lhe lembrar que há casos específicos nos quais a ordem de eventos instintivamente prevista não ocorrerá.

Em primeiro lugar, há alguns fornecedores (bancos, por exemplo, com a sua contabilidade específica) que fecham forçosamente todos os pedidos abertos no fim do dia, e abrem os mesmos pedidos no início do próximo dia, mas a taxas que diferem da atual por alguns décimos de ponto. Esse décimos de ponto realizam a conversão na economia do pedido. A conversão em si é exibida como um zero no terminal. Em termos de economia, fornecedores não estão quebrando nenhuma regra. Para nós, nessa situação é importante que os pedidos abertos recentemente recebam novos números, que são absolutamente diferentes dos anteriores.

Em segundo lugar, o fechamento parcial de um pedido separado (em todos os fornecedores) é realizado em dois estágios. No primeiro estágio, o pedido é fechado completamente. No segundo estágio, um novo pedido, com um preço reduzido e um novo número, é aberto. Além disso, o número de pedido inicial é escrito nos comentários do novo pedido.

Em terceiro lugar, uma especificidade semelhante ocorre quando um pedido é fechado através do uso de outro, caso esses pedidos possuam preços diferentes. Na prática, nesse caso a situação de fechamento parcial de um pedido é repetida.

A única oportunidade para que o pedido seja identificado é iniciar uma característica sua que não mude ou se repita. De todas as oportunidades oferecidas pelo MQL4, eu pude encontrar apenas um parâmetro do tipo: o MagicNumber. Mas, mesmo nesse caso, o programador não pode assumir que possui controle total sobre a situação durante a criação. A questão é que o MagicNumber não pode ser alterado através de programação. Por outro lado, ele possui uma vantagem inegável: Nós podemos ter certeza de que este parâmetro não irá mudar, mesmo que acidentalmente, enquanto o pedido existir. Mas, por outro lado, seria desejável ter um parâmetro ajustável, que pudesse ser acessado por um programa. Na situação atual, tal oportunidade não existe. Portanto, caso um pedido (ou mais de um) não tiver sido aberto pelo nosso sistema de transações, mas tiver sido aberto por outro programa ou manualmente, não há possibilidade de fazer algum tipo de marcação neles para que haja um identificador que os diferencie dos "nossos" pedidos e uns dos outros.

Uma possível alternativa fraca a um identificador único é o momento da abertura do pedido. Mas esse critério não pode ser considerado confiável e universal, pois é teoricamente possível que vários pedidos sejam abertos simultaneamente (no mesmo segundo). Por exemplo, dois pedidos pedentes em símbolos diferentes podem abrir ao mesmo tempo caso o preço se mova rapidamente.



Vamos estudar o exemplo de execução da função

Sobytiya()

contida no arquivo Sobytiya.mq4. Vamos assistir a um evento simples, a deleção ou fechamento de um pedido. Nós já sabemos que o número do pedido nem sempre é adequado para isso, portanto iremos analisar o MagicNumber.



// Sobytiya.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya()
   {
//==================================== Search for lost orders ====
   for (int oo=1;oo<=Mas_Ord_Old[0][0];oo++)     
// Take the order number from an old array
      {   
      int Sovpadenie=0; 
// Begin with zeroizing of the match condition mark
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)     
// Try to find this order in the current array 
         {
         if (Mas_Ord_Tek[i][7]==Mas_Ord_Old[oo][7]) 
// If the order MagicNumber matches, then remember, i.e., it's 
// still there and quit the internal loop
            {
            Sovpadenie=1;
            break; 
            }
         }      
      if (Sovpadenie==1) continue;                  
// Go to the next old array
      Alert("Закрыт ордер ",Mas_Ord_Old[oo][4]);   
// Inform about this with a screen text
      PlaySound( "Close_order.wav" );  // And music.
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж


Como você pode ver, você facilmente assistir ao evento caso você possua os critérios que o descrevem à sua disposição. Basta comparar os pedidos disponíveis de forma sequencial antes do tick com aqueles disponíveis após o tick. E aí está a diferença, assim como o fato confirmando que o evento ocorreu.

No próximo exemplo, abaixo, nós consideramos a busca por outro evento, a modificação do tipo de pedido. Aqui, o mesmo princípio é usado, mas ele se aplica a outro critério. É totalmente aceitável aplicar a análise de números e tipos de pedidos.

// Sobytiya_2.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya_2()
   {
//============ Search for orders that have changed their types ====
   for(int oo=1;oo<=Mas_Ord_Old[0][0]; oo++)               
// Go through the old array
      {
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)               
// Search for the order in the current array 
         {
         if (Mas_Ord_Tek[i][4] == Mas_Ord_Old[oo][4] &&
// If the old array contained the same order but of an other type, 
// then: The pending order becomes actual
             Mas_Ord_Tek[i][6] != Mas_Ord_Old[oo][6])      
            {   
            Alert("Трансформировался ордер",Mas_Ord_Tek[i][4]);
// Inform about this with a screen text
            PlaySound("Transform.wav" );   // And music
            }
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж


Dependendo da área programada no expert pelo programador, eventos podem ser assistidos em diferentes partes do programa. Caso seja necessário, a análise de todos os eventos de interesse pode ser formada em um arquivo. Além disso, o código deve ser modificado várias vezes para que ele não execute buscas de matrizes frequentemente de modo separado para cada critério. Também é fácil compor um algoritmo para extrair o número inicial dos comentários do pedido parcialmente fechado para análise futura. Para fazer isso, basta usar a função OrderComment().

Além dos recursos acima que dizem respeito à consideração de pedidos, há alguns outros. O exame detalhado destes pode nos ajudar a aumentar parcialmente a nossa consciência de realidade e nos salvar de trabalhos desnecessários e erros infelizes. Vamos voltar aos fornecedores que fecham pedidos ao fim do dia de transações.

O valor da conversão geralmente não é divisível pelo ponto, e como resultado disso a quantidade de coeficientes no valor da taxa aberta do pedido aumentará em 1. Para levar essa característica em consideração, é necessário normalizar este valor com precisão a 1 mais do que o Digits:


Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                         Digits+1); 
// Order open rate


Além disso, essa situação é significativa porque a taxa do pedido aberto pode essencialmente alterar o seu status. Caso um fornecedor use um sistema de transações que tome decisões de transações relativas a taxas abertas de pedidos, esse sistema pode simplesmente sair de controle no fim do dia. Após um exame mais detalhado, nós podemos chegar à conclusão de que a taxa aberta do pedido não tem qualquer importância! O fator importante é a tendência de desenvolvimento da situação, e caso ela esteja contra nós, nós temos que fechar o pedido, não importando onde ele esteja.

As discussões sobre a influência dos critérios sobre as decisões de transações comerciais não poderiam ser abarcadas por esse artigo. Contudo, ainda é necessário dizer que a escolha correta do critério a ser usado no programa é o fator chave para qualquer estratégia.


Traduzido do russo pela MetaQuotes Software Corp.
Artigo original: https://www.mql5.com/ru/articles/1390

Trabalhando com arquivos. Um exemplo de visualização de eventos de mercado importantes Trabalhando com arquivos. Um exemplo de visualização de eventos de mercado importantes

O artigo trata das perspectivas do uso do MQL4 para a realização de trabalhos mais produtivos nos mercados FOREX.

Expert Advisor gráfico: AutoGraf Expert Advisor gráfico: AutoGraf

O artigo mostra a operacionalidade de gráficos na criação de uma interface conveniente para o gerenciamento de transações.

Sincronização de Expert Advisors, scripts e indicadores Sincronização de Expert Advisors, scripts e indicadores

O artigo considera a necessidade e os princípios gerais do desenvolvimento de um pacote de programas que incluiria um Expert Advisor, um script e um indicador.

Eventos no MetaTrader 4 Eventos no MetaTrader 4

O artigo trata do monitoramento programado de eventos no terminal do cliente do MetaTrader 4, como a abertura/fechamento/modificação de pedidos, e é destinado a um usuário que possua habilidades básicas no trabalho com o terminal e em programação em MQL4.