English Русский 中文 Español Deutsch 日本語
Análise de gráficos de Balanço/Capital líquido ("equity") de acordo com os símbolos e Expert Advisors ORDER_MAGIC

Análise de gráficos de Balanço/Capital líquido ("equity") de acordo com os símbolos e Expert Advisors ORDER_MAGIC

MetaTrader 5Estatística e análise | 29 maio 2017, 10:09
2 416 0
Vladimir Karputov
Vladimir Karputov

Conteúdo


Estabelecimento de objetivos

Introduzida a cobertura no MetaTrader 5, surgiu a grande possibilidade de negociar simultaneamente usando Expert Advisors (ou várias estratégias) numa só conta de negociação. No serviço Sinais, é possível monitorizar toda a conta de negociação e obter estatísticas graças a ele. Há uma questão muito importante para mim que ainda permanece sem solução, isto é, como visualizar a contribuição de cada estratégia para os gráficos de Balanço e Capital líquido?

Afinal, na negociação é muito provável de acontecer uma primeira estratégia rentável, uma segunda não-rentável, e, como resultado, o monitoramento exiba uma turbulência perto do zero. Nesse caso, é altamente desejável construir gráficos de Balanço e Capital líquido ("equity") para cada estratégia de negociação separadamente.


1. Comissão, Swap, Lucro

O resultado financeiro total da transação é gerado pela soma de três parâmetros:

 Result=Deal commission +Cumulative swap on close+ Deal profit

Estas propriedades de transação são preparadas pelo HistoryDealGetDouble() com os seguintes identificadores:

DEAL_COMMISSION

Deal commission

double

DEAL_SWAP

Cumulative swap on close

double

DEAL_PROFIT

Deal profit

double


Exemplo de obtenção de propriedades de transação a partir do histórico de negociação para o período especificado no script "HistoryDealGetTicket.mq5".

Resultados do script (excluídas as transações com o tipo DEAL_ENTRY_IN, já que não há resultado financeiro nelas):

...
  4: deal #36774600 at 2017.02.15 10:17:50 Entry out, sell vol: 0.01 comm: 0 swap: 0.02 profit: 1.52 NZDUSD.m (order #47802989, position ID 47770449)
...
12: deal #36798157 at 2017.02.15 16:44:17 Entry out, buy vol: 0.01 comm: 0 swap: -0.01 profit: 2.98 EURUSD.m (order #47827771, position ID 47685190)
13: deal #36798161 at 2017.02.15 16:44:17 Entry out, buy vol: 0.01 comm: 0 swap: -0.02 profit: 5.99 EURUSD.m (order #47827785, position ID 47665575)
14: deal #36798176 at 2017.02.15 16:44:17 Entry out, buy vol: 0.01 comm: 0 swap: -0.02 profit: 5.93 EURUSD.m (order #47827805, position ID 47605603)
15: deal #36798185 at 2017.02.15 16:44:18 Entry out, buy vol: 0.01 comm: 0 swap: -0.03 profit: 5.98 EURUSD.m (order #47827821, position ID 47502789)
16: deal #36798196 at 2017.02.15 16:44:18 Entry out, buy vol: 0.01 comm: 0 swap: -0.03 profit: 8.96 EURUSD.m (order #47827832, position ID 47419515)
17: deal #36798203 at 2017.02.15 16:44:18 Entry out, buy vol: 0.01 comm: 0 swap: -0.06 profit: 8.92 EURUSD.m (order #47827835, position ID 47130461)
18: deal #36798212 at 2017.02.15 16:44:19 Entry out, sell vol: 0.01 comm: 0 swap: -0.48 profit: -21.07 EURUSD.m (order #47827845, position ID 46868574)
...
25: deal #36824799 at 2017.02.15 19:57:57 Entry out, sell vol: 0.01 comm: 0 swap: 0 profit: 2.96 NZDUSD.m (order #47855548, position ID 47817757)
26: deal #36824800 at 2017.02.15 19:57:58 Entry out, sell vol: 0.01 comm: 0 swap: 0 profit: 3.01 NZDUSD.m (order #47855549, position ID 47790966)
27: deal #36824801 at 2017.02.15 19:57:58 Entry out, sell vol: 0.01 comm: 0 swap: 0.02 profit: 3.07 NZDUSD.m (order #47855550, position ID 47777495)
28: deal #36824802 at 2017.02.15 19:57:58 Entry out, sell vol: 0.01 comm: 0 swap: 0.02 profit: 3 NZDUSD.m (order #47855551, position ID 47759307)
29: deal #36824803 at 2017.02.15 19:57:59 Entry out, sell vol: 0.01 comm: 0 swap: 0.02 profit: 1.52 NZDUSD.m (order #47855552, position ID 47682775)
...
33: deal #36832775 at 2017.02.16 00:58:41 Entry out, sell vol: 0.01 comm: 0 swap: 0.05 profit: 2.96 NZDUSD.m (order #47863883, position ID 47826616)
34: deal #36832776 at 2017.02.16 00:58:41 Entry out, sell vol: 0.01 comm: 0 swap: 0.05 profit: 3.05 NZDUSD.m (order #47863884, position ID 47803010)
35: deal #36832777 at 2017.02.16 00:58:41 Entry out, sell vol: 0.01 comm: 0 swap: 0.05 profit: 2.98 NZDUSD.m (order #47863885, position ID 47792294)
36: deal #36832778 at 2017.02.16 00:58:42 Entry out, sell vol: 0.01 comm: 0 swap: 0.07 profit: 2.88 NZDUSD.m (order #47863886, position ID 47713741)
...

Como você pode ver, o swap e o lucro podem ter tanto o sinal "+" quanto o sinal "-". Portanto, na fórmula do resultado financeiro final, para o swap e lucro, são usados outros mais complicados.


2. Cálculo de Capital líquido ("equity") e balanço no histórico

Esquema de trabalho geral: geramos uma lista "posições abertas", dividimos o histórico de negociação em segmentos de 5-15 minutos (mais tarde, tiraremos dúvidas sobre esse parâmetro). Em seguida, sucessivamente, para cada segmento:

  • buscamos transações de saída do mercado. Se forem encontrados esses tipos de transações, com base no resultado financeiro final delas, recalculamos o valor para os gráficos "Balanço" e "Capital líquido". Ajustamso a lista "Posições abertas".
  • de acordo com as posições abertas calculamos o valor para o gráfico "Capital líquido". 

2.1. Lista "Posições abertas"

Para realizar a classe de inventário de posições abertas no intervalo selecionado, é necessária uma classe de transações. Implementamos isto na classe "CHistoryDeal" — no arquivo anexado "HistoryDeal.mqh":

Método Valor
TicketDeal Obtém/define a propriedade de transação "Bilhete de transação"
PosIDDeal Obtém/define a propriedade de transação "Identificador de posição"
SymbolDeal Obtém/define a propriedade de transação "Símbolo de transação"
TypeDeal Obtém/define a propriedade de transação "Tipo de transação" a partir da enumeração ENUM_DEAL_TYPE
EntryDeal Obtém/define a propriedade de transação "Direção de transação" a partir da enumeração ENUM_DEAL_ENTRY
VolumeDeal Obtém/define a propriedade de transação "Volume de transação"
PriceDeal Obtém/define a propriedade de transação "Preço de abertura de transação"


2.2. Fórmula de lucro flutuante

Tomamos a fórmula de lucro na descrição da enumeração ENUM_SYMBOL_CALC_MODE. Ao fazer isto, sempre é necessário lembrar em qual moeda é calculado o lucro para esse instrumento. A moeda na qual é calculado o lucro das transações pode ser obtida:

SymbolInfoString(m_name,SYMBOL_CURRENCY_BASE);

  • ou simplesmente abrindo a especificação do símbolo no terminal:

rts specification

Fig. 1. Especificação RTS-3.17

2.3. Seguro: todos os símbolos disponíveis

Possíveis problemas: 

  • o símbolo do histórico de negociação não está na "Observação do mercado" (a pesquisa continua segundo a lista de símbolos geral);
  • a moeda de lucro do símbolo não pode ser recalculada na moeda do depósito, ou seja, na "Observação do mercado" não há nenhum símbolo para a recálculo.

Para o monitoramento de possíveis erros, no EA, no nível das variáveis globais do programa (atenção do programa, e não do terminal!), é introduzida a matriz para os símbolos "maus" ausentes na "Observação do mercado" ou para os quais é impossível recalcular a moeda de lucro na moeda do depósito:

string m_arr_defective_symbols[];                        // array for defective symbols

Sequência para passar pela cobertura de seguros (todas as fases ocorrem na função "SearchDefectiveSymbols"):

  1. criamos uma matriz temporária (auxiliar) a partir de todos os símbolos disponíveis na "Observação do mercado";
  2. criamos uma matriz temporária (auxiliar) a partir de todos os símbolos do histórico de negociação (no intervalo de datas especificado de ... a ... );
  3. procuramos os símbolos a partir do histórico de negociação na "Observação do mercado". Se qualquer um dos símbolos não existir, ele será armazenado numa matriz de símbolos "maus";
  4. adicionamos (exibimos) os símbolos do histórico de negociação à "Observação do mercado". Se a operação falhar, o símbolo será armazenado na matriz de símbolos "maus";
  5. a partir das propriedades do símbolo obtemos a moeda de lucro. Se a moeda de lucro do símbolo for diferente da moeda de depósito, passaremos para a subseção 5.1.
    1. Estamos tentando encontrar na "Observação do mercado" um símbolo - para recálculo - que corresponda à "moeda de depósito" + "moeda de lucro" ou "moeda de lucro" + "moeda depósito." Se a operação falhar, o símbolo será armazenado na matriz de símbolos "maus"

Processada a função "SearchDefectiveSymbols", será formada a matriz com símbolos "maus" a partir do histórico de negociação. Nos cálculos futuros (ao calcular o gráfico "Balanço" e o gráfico "Capital líquido"), os "maus" símbolos não participarão mais.

2.4. Monitoramento de posições abertas e fechadas no histórico

Exibimos na matriz bidimensional "m_arr_balance_equity" todas as alterações do balanço.

Pedimos o histórico no intervalo das datas "from date" e "to date" (trata-se do parâmetro de entrada do Expert Advisor) e dividimo-lo pelo número de ciclos cuja duração seja "timer (minutes)". O trabalho é realizado na função "CreateBalanceEquity". Registramos todas as transações na matriz dinâmica de ponteiros "ArrOpenPositions". Depois trabalhamos com esta matriz, isto é, adicionamos e excluímos transações.

Dependendo do parâmetro de transação de negociação "Direção da transação" — ENUM_DEAL_ENTRY — estimaremos de maneiras diferentes os gráficos "Balanço" e "Capital líquido" ("equity"). Se - nas contas de cobertura e de compensação - você quiser verificar o comportamento de abertura, fechamento, fechamento parcial ou inversão de posições, você pode executar o script "HistorySelect.mq5".

  • ‌DEAL_ENTRY_IN — Entrar no mercado. Registramos a transação na matriz "ArrOpenPositions"
  • DEAL_ENTRY_OUT — Sair do mercado. Procuramos na matriz "ArrOpenPositions" a transação com o tipo DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se a busca retornar false, não realizaremos alterações no gráficos "Balanço" e "Capital líquido ("equity")"
    • se a busca retornar true, verificaremos o volume (em lotes)
      • se os volumes forem iguais, removeremos a transação na matriz "ArrOpenPositions" e faremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")
      • se o volume da transação na matriz "ArrOpenPositions" for maior, ajustaremos o volume da transação na matriz "ArrOpenPositions" e realizaremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")
      • se o volume da transação na matriz "ArrOpenPositions" for menor, apagaremos a transação na matriz "ArrOpenPositions" e realizaremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")
  • DEAL_ENTRY_INOUT — Inversão. Procuramos na matriz "ArrOpenPositions" a transação com o tipo  DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se a busca retornar false, não realizaremos alterações no gráficos "Balanço" e "Capital líquido" ("equity")
    • se a busca retornar true, ajustaremos o volume de transação na matriz "ArrOpenPositions", ajustaremos o tipo de transação na matriz "ArrOpenPositions" e realizaremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")
  • DEAL_ENTRY_OUT_BY — Fechamento usando a posição oposta. Procuramos na matriz "ArrOpenPositions" a transação com o tipo  DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se os volumes forem iguais, removeremos a transação na matriz "ArrOpenPositions" e realizaremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")
    • se os volumes forem diferentes, ajustaremos o volume de transação na matriz "ArrOpenPositions" e realizaremos alterações na coluna "Balanço" (matriz "m_arr_balance_equity")

2.5. Como calcular o lucro flutuante (Capital líquido ("equity"))

É necessário percorrer toda a matriz "ArrOpenPositions" e calcular o lucro flutuante de todas as transações na matriz. Se a transação se encontrar a matriz "ArrOpenPositions", teremos os seguintes dados para cada transação, dos quais precisaremos:

  • símbolo
  • tipo (BUY or SELL)
  • volume
  • preço (preço pelo qual a transação foi aberta)

Também temos uma data final em que pedido o histórico de negociação. Só faltam os preços do símbolo da transação para a data final, na qual solicitado o histórico de negociação. Obteremos o preço usando CopyTicks em "CalculationFloatingProfit". Lembre-se que tomaremos as formulas de lucro na descrição da enumeração ENUM_SYMBOL_CALC_MODE

No processo de criação de perfis, descobriu-se que o método CopyTicks é muito demorado, especialmente quando na matriz "CalculationFloatingProfit" existem várias transações para um único símbolo. Nesses casos, verifica-se que serão solicitados os mesmos dados várias vezes, quer dizer, o símbolo é o mesmo e a data é a mesma. Para acelerar, foram introduzidos os resultados de cache CopyTicks 

//--- caching results "CopyTicks"
   static string arr_name[];
   static double arr_ask[];
   static double arr_bid[];
   static datetime prev_time=0;
   int number=-1;
   if(time>prev_time)
     {
      prev_time=time;
      ArrayFree(arr_name);
      ArrayFree(arr_ask);
      ArrayFree(arr_bid);
     }
   found=false;
   size=ArraySize(arr_name);
   if(size>0)
      for(int i=0;i<size;i++)
        {
         if(name==arr_name[i])
           {
            number=i;
            found=true;
            break;
           }
        }
   if(found)
     {
      ArrayResize(ticks_array,1);
      ticks_array[0].ask=arr_ask[number];
      ticks_array[0].bid=arr_bid[number];
     }
   else
     {
      //---
      int copy_ticks=-1;
      int count=0;
      while(copy_ticks==-1 && count<5)
        {
         copy_ticks=CopyTicks(name,ticks_array,COPY_TICKS_INFO,1000*(ulong)time,1);
         //if(copy_ticks==-1)

— os resultados bid e ask são armazenados nas matrizes locais: se, num intervalo de tempo, para o símbolo, forem obtidos os ticks, estes ticks são tomados a partir das matrizes locais. Esta abordagem permite acelerar o trabalho 10-15 vezes. 


3. Integramos o Expert Advisor no painel de diálogo

Agora, que a base do Expert Advisor é operável, é possível proporcionar ao Expert Advisor uma interface fácil de usar. A partir do título do artigo "Análise de gráficos de Balanço/Capital líquido ("equity") de acordo com os símbolos e Expert Advisors ORDER_MAGIC", devem existir alguns recursos de filtragem:

  • mostrar todos os símbolos/mostrar um ou mais dos símbolos selecionados;
  • mostrar em todos os magics/mostrar apenas num ou vários dos símbolos selecionados.

Para cálculo de todos os símbolos de negociação, temos a matriz "m_arr_all_trade_symbols". Ela é declarada ao nível de programa global. É necessário introduzir mais uma matriz — "m_arr_all_magics" — para calcular todos os magics. Para fazer isto, atualizamos a função "FillArrayTradeSymbols", agora nela será preenchida mais uma matriz "m_arr_all_magics".

3.1. Vista geral do painel de diálogo

panel

Fig. 2. Vista geral do painel

Após a formação de matrizes de símbolos "maus", de todos os símbolos de negociação e magics, no painel são preenchidas duas listas (elementos com base na classe CComboBox): a lista esquerda contém todos os símbolos de negociação, a lista da direita, todos os magics. No primeiro lugar das listas, aparece a escolha de todos os símbolos e todos os magics:

panel combo box

Fig. 3. Listas suspensas

O Expert Advisor no painel terá a seguinte lógica: só após pressionado o botão "Start", verificar-se-á se foi selecionado nas duas listas suspensas. Dependendo dos parâmetros selecionados, nestas listas será realizada a plotagem dos gráficos de Balanço / Capital líquido ("equity") com base no histórico de negociação.

3.2. Interação com o painel

Achei que a transferência de todo o código do Expert Advisor para a classe do painel ("APHDialog.mqh") leva muito tempo. A solução alternativa consiste em introduzir as variáveis internas m_ready, m_symbol e m_magic na classe do painel:

//+------------------------------------------------------------------+
//| Class CAPHDialog                                                 |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CAPHDialog : public CAppDialog
  {
private:
   CLabel            m_label_symbols;                 // the label object
   CComboBox         m_combo_box_symbols;             // the combo boxp object
   CLabel            m_label_magics;                  // the label object
   CComboBox         m_combo_box_magics;              // the combo box object
   CButton           m_button_start;                  // the button object
   //---
   bool              m_ready;                         // true -> you can build graphics
   string            m_symbol;
   ulong             m_magic;

public:

Será durante o processamento de clique no botão "Start" que será tomada a decisão sobre o estado da variável m_ready:

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CAPHDialog::OnClickButtonStart(void)
  {
   if(m_combo_box_symbols.Select()!=" " && m_combo_box_magics.Select()!=" ")
      m_ready=true;
   else
      m_ready=false;
//Comment(__FUNCTION__+" ButtonStartclick"+"\n"+
//        "Symbols: "+"\""+m_combo_box_symbols.Select()+"\""+"\n"+
//        "Magic: "+"\""+m_combo_box_magics.Select()+"\""+"\n"+
//        "m_ready: "+IntegerToString(m_ready));
  }

Observe que, na cadeia de caracteres selecionada, imediatamente após criar e preencher as listas suspensas (no nosso caso, são os elementos m_combo_box_symbolsm_combo_box_magics), nas listas é definido o elemento com valor " ", ou seja, um caractere de tabulação.

Será durante o processamento de clique nas listas suspensas adequadas que será tomada a decisão sobre o estado das variáveis m_symbol m_magic:

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CAPHDialog::OnChangeComboBoxSymbols(void)
  {
//Comment(__FUNCTION__+" \""+m_combo_box_symbols.Select()+"\"");
   if(m_combo_box_symbols.Select()=="All symbols")
      m_symbol="";
   else
      m_symbol=m_combo_box_symbols.Select();
  }
//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CAPHDialog::OnChangeComboBoxMagics(void)
  {
//Comment(__FUNCTION__+" \""+m_combo_box_magics.Select()+"\"");
   if(m_combo_box_magics.Select()=="All magics")
      m_magic=-1;
   else
      m_magic=StringToInteger(m_combo_box_magics.Select());
  }

Assim, após um clique no botão "Start" serão preenchidas três variáveis, isto é: m_ready, m_symbol m_magic. Resta descobrir como informar ao Expert Advisor que no painel realizada a seleção de parâmetros. A solução é simples: no EA, executamos um temporizador, a intervalos de 3 segundos, que consultará o painel. Para este fim, no painel escrevemos o método "CAPHDialog::IsReady"

//+------------------------------------------------------------------+
//| On the panel there are chosen parameters                         |
//+------------------------------------------------------------------+
bool CAPHDialog::IsReady(string &symbol,ulong &magic)
  {
   if(m_ready)
     {
      symbol=m_symbol;
      magic=m_magic;
      m_ready=false;
      return(true);
     }
   else
      return(false);
  }

Neste método, registramos o valor das variáveis internas nas variáveis enviadas segundo referência e redefinimos a variável interna m_ready.

3.3. Pequeno ajuste no cálculo do magic selecionado

Seleção de transações ocorre de acordo com as condições especificadas, isto é: segundo símbolo ou todos os símbolos, ora segundo magic ou todos os magics, no "GetHistory":

//--- for all deals 
   for(int i=0;i<deals;i++)
     {
      deal_ticket          = HistoryDealGetTicket(i);
      deal_position_ID     = HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
      deal_symbol          = HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
      deal_type            = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
      deal_entry           = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
      deal_volume          = HistoryDealGetDouble(deal_ticket,DEAL_VOLUME);
      deal_price           = HistoryDealGetDouble(deal_ticket,DEAL_PRICE);
      deal_commission      = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
      deal_swap            = HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
      deal_profit          = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
      deal_magic           = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
      if(sSymbol!="")

         if(deal_symbol!=sSymbol)
            continue;
      if(uMagic!=ULONG_MAX)
         if(deal_magic!=uMagic)
            continue;
      //--- onle BUY or SELL

Note que, para a variável uMagic, o valor ULONG_MAX indica "todos magics", enquanto, para a variável sSymbol, o valor "" indica "Todos os símbolos".

Vídeo sobre a construção do balanço e lucro flutuante com base no histórico de negociação (em primeiro lugar para todos os símbolos, depois, apenas para um único símbolo):


Vídeo


4. Gráficos de distribuição MFE e MAE

Para cada posição aberta, durante sua existência, são registrados os valores de lucro máximo (MFE) e perda máxima (MAE). Estes indicadores caracterizam adicionalmente cada posição fechada através dos valores de potencial máximo não realizado e o risco máximo autorizado. Nos gráficos de distribuição MFE/Profit e MAE/Profit, a cada posição corresponde um ponto, na horizontal, é dado o valor do lucro/perda obtida, e, na vertical, os valores máximos mostrados quanto ao lucro potencial ("Maximum Favorable Excursion" MFE) e à perda potencial ("Maximum Adverse Excursion" MAE).

4.1. Principio de monitoramento de MFE e MAE

No nível global de programa, são declaradas duas matrizes, isto é, "m_arr_pos_id" para monitoramento de posições e "m_arr_mfe_mae" para inventário do MFE, resultado financeiro final e MAE: 

long   m_arr_pos_id[];
double m_arr_mfe_mae[][3];  // [][0] - mfe, [][1] - final financial result,[][2] - mae

Após isto, na matriz base "m_arr_mfe_mae", serão construídos os gráficos de dispersão de MFE e MAE.

As matrizes "m_arr_pos_id" - para inventário de posições - e "m_arr_mfe_mae" - para inventário de mfe - sempre têm o mesmo tamanho na primeira dimensão, assim, para posições com índice "i" (m_arr_pos_id[i]) sempre existirá a correspondência m_arr_mfe_mae[i][][][]. As dimensões destas duas matrizes são definidas em "GetHistory":

         if(deal_symbol=="")
            DebugBreak();
         ArrOpenPositions.Add(HistoryDeal);
         //--- mfe, mae
         int size=ArraySize(m_arr_pos_id);
         ArrayResize(m_arr_pos_id,size+1,10);
         ArrayResize(m_arr_mfe_mae,size+1,10);
         m_arr_pos_id[size]=deal_position_ID;
         // [][0] - mfe, [][1] - final financial result,[][2] - mae
         m_arr_mfe_mae[size][0]=0.0;
         m_arr_mfe_mae[size][1]=0.0;
         m_arr_mfe_mae[size][2]=0.0;
         continue;
        }
      //--- 
      if(deal_entry==DEAL_ENTRY_OUT)

Função que é responsável pela monitoramento do lucro máximo e perda máxima para cada posição:

//+------------------------------------------------------------------+
//| Add Result Mfe Mae                                               |
//+------------------------------------------------------------------+
void AddResultMfeMae(const long pos_id,const double floating_profit,const double financial_result)
  {
// [][0] - mfe (profit), [][1] - final financial result,[][2] - mae (loss)
//--- search pos_id
   int position=-1;
   int size=ArraySize(m_arr_pos_id);
   for(int i=0;i<size;i++)
      if(m_arr_pos_id[i]==pos_id)
        {
         position=i;
         break;
        }
   if(position==-1)
      return;

//---
   if(floating_profit==0.0)
      return;

   if(floating_profit>0.0) // profit
     {
      if(m_arr_mfe_mae[position][0]<floating_profit)
         m_arr_mfe_mae[position][0]=floating_profit;
     }
   else // loss
     {
      if(m_arr_mfe_mae[position][2]>floating_profit)
         m_arr_mfe_mae[position][2]=floating_profit;
     }
   m_arr_mfe_mae[position][1]=financial_result;
  }

Aqui a regra é passar todos os três parâmetros. Ou seja, se nossa posição virtual ainda não se encontrar na lista de posições abertas "ArrOpenPositions" e seu lucro flutuante for igual a "-20.2", a chamada será algo do tipo:

    AddResultMfeMae(pos_id,-20.2,0.0);

se nossa posição virtual ainda não se encontrar na lista de posições abertas "ArrOpenPositions" e seu lucro flutuante for igual a "+5.81", a chamada será algo do tipo:

    AddResultMfeMae(pos_id,5.81,0.0);

se nossa posição virtual for excluída na lista de posições abertas "ArrOpenPositions" e seu resultado financeiro final for igual a "+3.06", a chamada será algo do tipo:

    AddResultMfeMae(pos_id,0.0,-3.06);

Ou seja, se houver um lucro flutuante, o resultado financeiro final será igual a "0", se a posição for fechada, o lucro flutuante será igual a "0".

4.2. Processamento de posições

  • ‌DEAL_ENTRY_IN - Entrada no mercado. Registramos a transação na matriz "ArrOpenPositions". Criamos o novo elemento nas matrizes "m_arr_pos_id" e "m_arr_mfe_mae"
  • DEAL_ENTRY_OUT - Saída do mercado. Procuramos na matriz "ArrOpenPositions" a transação com o tipo DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se a busca retornar false, não realizaremos alterações no gráficos "Balanço" e "Capital líquido" ("equity")
    • se a busca retornar true, verificaremos o volume (em lotes)
      • se os volumes forem iguais, removeremos a transação na matriz "ArrOpenPositions" e faremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0][resultado financeiro final].
      • se o volume da transação na matriz "ArrOpenPositions" for maior - ajustaremos o volume de transação na matriz "ArrOpenPositions" e realizaremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0] [resultado financeiro final].
      • se o volume da transação na matriz "ArrOpenPositions" for inferior - excluiremos a transação na matriz "ArrOpenPositions" e realizaremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0] [resultado financeiro final].
  • DEAL_ENTRY_INOUT - Inversão. Procuramos na matriz "ArrOpenPositions" a transação com o tipo  DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se a busca retornar false, não realizaremos alterações no gráficos "Balanço" e "Capital líquido" ("equity")
    • se a busca retornar true, ajustarmos o volume da transação na matriz "ArrOpenPositions", ajustaremos o tipo de transação na matriz "ArrOpenPositions" e realizaremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0] [resultado financeiro final].
  • DEAL_ENTRY_OUT_BY - Fechamento usando a posição oposta. Procuramos na matriz "ArrOpenPositions" a transação com o tipo DEAL_ENTRY_IN com o mesmo DEAL_POSITION_ID
    • se os volumes forem iguais, removeremos a transação na matriz "ArrOpenPositions" e faremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0][resultado financeiro final].
    • se os volumes forem diferentes, ajustaremos a transação na matriz "ArrOpenPositions" e faremos alterações na matriz "m_arr_balance_equity" - na coluna "Balanço". Na matriz "m_arr_mfe_mae" registramos [lucro flutuante 0.0][resultado financeiro final].

Além disso, em "GetHistory", se for necessário recalcular o lucro flutuante, para cada posição na matriz "m_arr_mfe_mae" registramos [lucro flutuante] [resultado financeiro final 0.0].

4.3. Painel modificado

Para exibir o gráfico de Balanço / Capital líquido ("equity") e MFE e MAE, o painel evolui de forma:

panel 2

Fig. 4. Painel modificado

Gráficos de MFE (lucro máximo) e de MAE (perda máxima) são baseados em duas coordenadas, isto é: coordenada "X" - valor do resultado financeiro final de posição, enquanto no eixo "Y" - valor de MFE ou de MAE, respectivamente.

MFE

Fig. 5. MFE

MAE

Fig. 6 MAE


Conclusão

Agora nas contas de cobertura ("hedge"), ao EAs negociarem simultaneamente, é possível visualizar as estatísticas do balanço e capital liquido ("equity") de cada símbolo e cada magic, quer dizer, identificar visualmente a contribuição de um determinado Expert Advisor (ORDER_MAGIC) para o balanço geral e, mais importante, qual o abaixamento em cada Expert Advisor.

Programas utilizados no artigo:

#
 Nome
Tipo
Descrição
1
HistoryDeal.mqh Biblioteca  Classe de inventário de posições abertas no intervalo selecionado
2
HistoryDealGetTicket.mq5 Expert Advisor  Exemplo de obtenção de propriedades de transação a partir do histórico de negociação para o período especificado
3
APHDialog.mqh Biblioteca  Classe de painel de diálogo do Expert Advisor
4
Accounting_positions_on_history.mq5 Expert Advisor  Expert Advisor principal - com base no artigo
5
MQL5.zip Arquivo  Arquivo com o Expert Advisor principal e seus arquivos incorporados.


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

Arquivos anexados |
APHDialog.mqh (28.62 KB)
HistoryDeal.mqh (6.66 KB)
MQL5.zip (26.34 KB)
Criação de documentos com base em códigos-fonte MQL5 Criação de documentos com base em códigos-fonte MQL5
No artigo é estudada a criação de documentação para um código em linguagem MQL5, partindo da automação de tags (marcação). Além disso, quanto ao programa Doxygen, é descrito seu funcionamento, adequada configuração e obtenção de resultados em vários formatos (HTML, HtmlHelp e PDF).
Ondas de Wolfe Ondas de Wolfe
Este método gráfico, proposto por Bill Wolfe, torna possível não só identificar a forma e, assim, determinar o tempo e a direção de entrada, mas também prever o alvo, que deve atingir o preço, e o tempo para alcançá-lo. Este artigo descreve como criar, com a base no indicador ZigZag, um indicador para procurar ondas de Wolfe e um Expert Advisor simples que opere de acordo com seus sinais.
Sistema de negociação DiNapoli Sistema de negociação DiNapoli
No artigo, é examinado o sistema de negociação com níveis de Fibonacci desenvolvido e descrito por Joe DiNapoli. Além disso, são explicados os conceitos básicos e a essência do sistema, e é fornecido um exemplo de um indicador simples.
Receitas MQL5 - Criamos um buffer circular para calcular rapidamente indicadores numa janela deslizante Receitas MQL5 - Criamos um buffer circular para calcular rapidamente indicadores numa janela deslizante
O buffer circular é a maneira mais simples e eficaz de organizar os dados para os cálculos numa janela deslizante. Este artigo descreve como está construído este algoritmo e mostra como usá-lo para fazer o cálculo numa janela deslizante usando um processo simples e eficiente.