Download MetaTrader 5

Expert Advisor multiplataforma: Controle de capital

17 agosto 2017, 09:43
Enrico Lambino
0
417

Tabela de conteúdos

  1. Introdução
  2. Objetivos
  3. Classe base
  4. Classes e tipos de controle de capital
  5. Contêiner para objetos de controle de capital
  6. Exemplo
  7. Fim do artigo

Introdução

O controle de capital (money management) é uma função comum nos EAs. Ela permite que o EA determine dinamicamente o tamanho do lote para a próxima transação a ser colocada. Neste artigo, serão apresentadas várias classes de controle de capital que nos permitirão automatizar todo o processo de cálculo do volume de negociações num EA multiplataforma.

Objetivos

  • Compreender e aplicar os métodos de controle de capital mais comuns ​​na negociação
  • Permitir que um EA selecione dinamicamente métodos de controle de capital a partir de uma lista
  • Garantir a compatibilidade com MQL4 e MQL5

Classe base

Neste artigo, todas as classes de controle de capital descritas terão uma classe base, chamada CMoney, derivada da classe CMoneyBase. A classe CMoneyBase é definida no seguinte trecho de código:

class CMoneyBase : public CObject
  {
protected:
   bool              m_active;
   double            m_volume;
   double            m_balance;
   double            m_balance_inc;
   int               m_period;
   bool              m_equity;
   string            m_name;
   CSymbolManager   *m_symbol_man;
   CSymbolInfo      *m_symbol;
   CAccountInfo     *m_account;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CMoneyBase(void);
                    ~CMoneyBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_MONEY;}
   //--- inicialização
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   bool              InitAccount(CAccountInfo*);
   bool              InitSymbol(CSymbolManager*);
   CObject          *GetContainer(void);
   void              SetContainer(CObject*);
   virtual bool      Validate(void);
   //--- métodos de obtenção e inserção
   bool              Active(void) const;
   void              Active(const bool);
   void              Equity(const bool);
   bool              Equity(void) const;
   void              LastUpdate(const datetime);
   datetime          LastUpdate(void) const;
   void              Name(const string);
   string            Name(void) const;
   double            Volume(const string,const double,const ENUM_ORDER_TYPE,const double);
   void              Volume(const double);
   double            Volume(void) const;
protected:
   virtual void      OnLotSizeUpdated(void);
   virtual bool      UpdateLotSize(const string,const double,const ENUM_ORDER_TYPE,const double);
  };

A maioria dos métodos da classe são setters ou getters dos vários membros da classe e, portanto, não precisam de explicações detalhadas Em aplicações práticas, os três métodos que realmente importam são UpdateLotSize, OnLotSizeUpdated e Volume.

No método UpdateLotSize é onde ocorre o cálculo real do volume de negociação. Este é também o método principal, estendido a partir da classe base, e, portanto, a maioria das diferenças entre as classes de controle de capital pode ser encontrada dentro dele. Para a classe base CMoneyBase, o método pode ser considerado virtual, uma vez que não faz nada exceto retornar o valor true:

bool CMoneyBase::UpdateLotSize(const string,const double,const ENUM_ORDER_TYPE,const double)
  {
   return true;
  }

Às vezes, após o cálculo do volume de negociação, é necessário atualizar certos valores que serão ​​usados para cálculos futuros. Nesses casos, é usado o método OnLotSizeUpdated. Ele é chamado automaticamente dentro do método UpdateLotSize:

void CMoneyBase::OnLotSizeUpdated(void)
  {
   m_symbol=m_symbol_man.Get();
   double maxvol=m_symbol.LotsMax();
   double minvol=m_symbol.LotsMin();
   if(m_volume<minvol)
      m_volume=minvol;
   if(m_volume>maxvol)
      m_volume=maxvol;
  }

Para obter o volume de negociação atual já calculado pelo objeto de controle de capital, o EA não precisa chamar UpdateLotSize ou OnLotSizeUpdated. Em vez disso, é chamado o método Volume da classe. Este método chama automaticamente os outros dois métodos dentro de seu código:

double CMoneyBase::Volume(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   if(!Active())
      return 0;
   if(UpdateLotSize(symbol,price,type,sl))
      OnLotSizeUpdated();
   return m_volume;
  }

Métodos de money management


Lote fixo

Este é o método mais comum de dimensionamento de lote, e aquele com o qual a maioria dos traders está familiarizado. Aqui, todas as transações têm um tamanho de negociação constante, independentemente de se o saldo da conta ou capital liquido está diminuindo ou aumentando ao longo do tempo.

Neste tipo de controle de capital, precisamos apenas de um volume fixo. Assim, sua principal diferença com o CMoney / CMoneyBase pode ser encontrada em seu construtor, onde especificamos um tamanho de lote fixo:

CMoneyFixedLotBase::CMoneyFixedLotBase(double volume)
  {
   Volume(volume);
  }

Caso necessitemos alterar dinamicamente a saída deste método de controle de capital, simplesmente alteramos seu membro de classe m_volume ao chamar o método Volume.

Método de risco fixo

O método de risco fixo (ou método de fração fixa) envolve a seleção de uma certa porcentagem do saldo da conta ou do capital liquido para ser o risco em cada transação. Ele é implementado na biblioteca padrão como CmoneyFixedRisk.  Se uma transação sofrer uma perda, o valor da perda não ultrapassará a porcentagem do saldo da conta, no momento de entrada. Neste caso, a perda é definida como a perda máxima, que pode assumir o trader numa transação particular, ou seja, quando os termos da transação atingem o Stop-Loss. A aplicação do método exige que o Stop-Loss não seja igual a zero.

O cálculo da porcentagem de risco é expresso na seguinte fórmula:

Volume = (balance * account_percentage / ticks) / tick_value

onde:

  • balance — saldo da conta ou capital liquido
  • account_percentage — porcentagem de risco máxima (faixa: 0.0-1.0)
  • ticks — valor de Stop-Loss expresso em ticks
  • tick_value — custo do tick na moeda do depósito (para 1 lote completo)

O tick é definido como o menor movimento possível do preço para este instrumento o par de moedas. Por exemplo, o EURUSD - da corretora que usa cotações de cinco dígitos - terá um custo de tick de 0,00001. Pois, esse é o menor movimento possível para este par de moedas. Quando o valor do Stop-Loss é expresso em pontos ou pips, o resultado será a diferença entre o preço de entrada na transação e o Stop-Loss em pontos ou pips.

Para o mesmo par de moedas, o tamanho do tick para a corretora com uma cotação de 4 dígitos será diferente do de uma corretora com uma cotação de 5 dígitos. Isso ocorre porque, ao ter 4 dígitos, 1 tick é equivalente a 1 ponto (ou pip), enquanto para uma corretora usando 5 dígitos, um pip é equivalente a 10 pontos.

Como um exemplo de controle de capital com risco fixo, suponhamos que trabalhamos com uma corretora que usa cotações de 5 dígitos, temos um saldo de US$ 1 000, e o risco especificado é de 5% por transação. Suponhamos que o valor do tick é de 0,1, enquanto o Stop-Loss é de 200 pontos (20 pips):

Volume = (1000 * 0.05 / 200) / 0.1 = 2.5 lote

O tamanho do lote calculado aumenta dependendo da porcentagem de risco e do saldo disponível, e diminui com base no tamanho do Stop-Loss e do valor de tick. Normalmente, o saldo da conta, o risco e o valor do tick são constantes, entretanto que o Stop-Loss muitas vezes é variável (e calculado dinamicamente). Por isso, o risco fixo não é adequado para as estratégias onde não há limite superior na diferença entre o preço de entrada e o Stop-Loss, uma vez que o tamanho do lote pode ser demasiado pequeno e, portanto, rejeitado pela corretora. Por outro lado, um Stop-Loss muito pequeno resultará num tamanho de lote muito grande, o que também pode causar problemas com corretoras que têm uma configuração que limita o lote máximo. Este problema está amplamente resolvida no MetaTrader 5, pois, nele as ordens são divididas em várias transações se o tamanho do lote é muito grande. No entanto, no MetaTrader 4, não há tal recurso, porque o volume da transação deve ser preparado com antecedência (se necessário, dividido em várias transações pequenas), para ela poder ter lugar, mesmo se seu tamanho ultrapassar o nível máximo válido.

A fórmula utilizada nos cálculos está dentro do método UpdateLotSize:

bool CMoneyFixedFractionalBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      double ticks=0;
      if(price==0.0)
        {
         if(type==ORDER_TYPE_BUY)
            ticks=MathAbs(m_symbol.Bid()-sl)/m_symbol.TickSize();
         else if(type==ORDER_TYPE_SELL)
            ticks=MathAbs(m_symbol.Ask()-sl)/m_symbol.TickSize();
        }
      else ticks=MathAbs(price-sl)/m_symbol.TickSize();
      m_volume=((balance*(m_risk/100))/ticks)/m_symbol.TickValue();
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }

Em primeiro lugar, obtemos o valor do Stop-Loss. Depois disso, utilizamos a fórmula atual para atualizar o membro da classe m_volume, que, mais tarde, será usado como resultado final.

Método de proporção fixa

O método de proporção fixa de controle de capital envolve o cálculo do volume do lote em proporção ao saldo atual da conta. Ele pode ser considerado um caso especial do lote fixo, exceto que nele o tamanho do lote é ajustado automaticamente, em vez de manualmente pelo trader. Se a conta estiver aumentando, o tamanho do lote também aumentará após ultrapassar certo limite. Se o tamanho do lote estiver diminuindo, o tamanho do lote também se ajustará em conformidade.

Ao contrário do controle de capital com risco fixo, o método de proporção fixa não requer um Stop-Loss zero. Isso o torna ideal para ser usado em transações que não requerem um Stop-Loss e cujas saídas são gerenciada de maneira diferente (fechamento segundo o lucro/perda na moeda de depósito, etc.).

O volume da transação para este método de controle de capital é calculado da seguinte forma:

Volume = base_volume + (balance / balance_increase) * volume_increment

onde:

  • base_volume — volume a ser adicionado ao volume total, independentemente do tamanho da conta
  • balance — saldo atual na conta
  • balance_increase — limite de aumento do saldo na conta que desencadeará um aumento no tamanho do lote
  • volume_increment — volume incremental a ser adicionado ao lote depois de atingir o limite (ou, respectivamente, subtraído).

Por exemplo, suponhamos que temos um volume base de lote zero, que deve aumentar 0,1 por cada 1 000 dólares na conta. Atualmente, em nossa conta há US$ 2 500. O volume total será calculado como da seguinte forma:

Volume = 0 + (2500 / 1000) * 0.1 = 0.25 do lote

Este método tem muitas variações. Num deles, por exemplo o tamanho do lote é atualizado apenas em certos níveis, gradualmente (ele é implementado em controle de capital com taxa fica). No exemplo acima, o volume calculado do lote é de 0,25, mas, em alguns casos, ele pode permanecer um certo tempo no nível de 0,2 do lote, e aumentar imediatamente para 0,3 (uma vez o saldo alcance US$ 3 000).

Para este caso, o método UpdateLotSize será implementado da seguinte forma:

bool CMoneyFixedRatioBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();      
      m_volume=m_volume_base+((int)(balance/m_balance_inc))*m_volume_inc;
      m_balance=balance;
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }


Risco fixo por ponto

Risco fixo por ponto funciona de tal forma que cada ponto no Stop-Loss vale um certo valor na moeda de depósito. O algoritmo calcula o tamanho do lote com base no valor do tick desejado pelo trader. Por exemplo, se a conta estiver em USD e se o risco fixo por ponto for 2.0, cada ponto na perda de parada valerá US$ 2. Se o Stop-Loss da transação for de 200 pontos, o risco máximo para toda a transação será de US$ 400 (US$ 400 como perda se o mercado atingir o Stop-Loss da transação).

Para um trader comum, o uso deste tipo de controle de capital é mais fácil de entender, uma vez que o valor do risco é expresso na moeda de depósito. O trader simplesmente precisa indicar o valor desejado do tick e, assim, o volume de negociação será calculado automaticamente. O valor do tick ou a mudança no lucro/perda por movimento mínimo no preço permanecerá o mesmo, mas o risco total dependerá da tamanho do Stop-Loss da transação.

Usando a fórmula para este tipo de controle de capital, o método UpdateLotSize será implementado da seguinte maneira:

bool CMoneyFixedRiskPerPointBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      m_volume=(m_risk/m_symbol.TickValue());
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }


Risco fixo (margem fixa)

O risco fixo por margem é o equivalente à classe CMoneyFixedMargin da Biblioteca padrão MQL5. Na verdade, este é um caso especial do método acima descrito de controle de capital, isto é, do risco fixo por ponto. No entanto, ao contrário do risco fixo por ponto, este método considera todo o valor do Stop-Loss no cálculo do volume de negociação, de modo que, independentemente do tamanho do Stop-Loss, o risco permaneça o mesmo. No exemplo anterior, tínhamos 200 pontos no Stop-Loss e US$ 400 como o risco máximo. Se o Stop-Loss fosse reduzido para 100 pontos, o risco máximo por transação, ao usar o risco fixo por ponto, também seria reduzido para metade (US$ 200), enquanto que, ao usar margem fixa, o risco máximo permaneceria constante (US$ 400).

Utilizando esta fórmula, podemos implementar o método UpdateLotSize da seguinte forma:

bool CMoneyFixedRiskBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      double ticks=0;
      if(price==0.0)
        {
         if(type==ORDER_TYPE_BUY)
            ticks=MathAbs(m_symbol.Bid()-sl)/m_symbol.TickSize();
         else if(type==ORDER_TYPE_SELL)
            ticks=MathAbs(m_symbol.Ask()-sl)/m_symbol.TickSize();
        }
      else ticks=MathAbs(price-sl)/m_symbol.TickSize();
      m_volume=(m_risk/m_symbol.TickValue())/ticks;
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }

A fórmula que é usada aqui é substancialmente semelhante à de risco fixo por ponto, exceto pelo fato de que precisamos obter um valor de Stop-Loss de tick e, em seguida, determinar o resultado da fórmula anterior com este valor.


Contêiner para objetos de controle de capital

Como as classes de sinais discutidas no artigo anterior, nossos objetos de controle de capital também serão contêineres. Isso permitirá que o EA selecione dinamicamente na lista de objetos disponíveis de controle de capital que foram adicionados à plataforma. Idealmente, este contêiner atuará como mediador entre as classes de controle de capital e o resto do código do EA. A classe base para este objeto é CMoneysBase, cuja definição é mostrada abaixo:

class CMoneysBase : public CArrayObj
  {
protected:
   bool              m_active;
   int               m_selected;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CMoneysBase(void);
                    ~CMoneysBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_MONEYS;}
   //--- inicialização
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   CObject          *GetContainer(void);
   void              SetContainer(CObject*);
   virtual bool      Validate(void) const;
   //--- métodos de instalação e obtenção
   virtual bool      Active(void) const;
   virtual void      Active(const bool);
   virtual int       Selected(void) const;
   virtual void      Selected(const int);
   virtual bool      Selected(const string);
   //--- cálculo do volume
   virtual double    Volume(const string,const double,const ENUM_ORDER_TYPE,const double);
  };

Como este objeto é projetado para conter vários objetos de controle de capital, são necessários pelo menos dois métodos para torná-lo disponível no EA a ser desenvolvido, isto é:

  1. Seleção ou a capacidade de alternar dinamicamente entre métodos de controle de capital
  2. Uso do objeto selecionado de controle de capital calculado para seu volume de transação
A seleção pode ser implementada de duas maneiras, isto é, através da atribuição do índice do objeto de controle de capital na matriz de objetos (CMoneysBase expande o CArrayObj), ou encontrando o objeto selecionado pelo nome (método Name, que pertence à classe CMoneyBase/CMoney). O seguinte mostra a sobrecarga do método Selected que aceita um argumento inteiro (ou índice):
CMoneysBase::Selected(const int value)
  {
   m_selected=value;
  }

O seguinte mostra o método Selected sobrecarregado que aceita um argumento de string (nome do objeto de controle de capital). Observe que ele requer um nome não-vazio, para o objeto de controle de capital, que pode ser atribuído através do seu método Name.

bool CMoneysBase::Selected(const string select)
  {
   for(int i=0;i<Total();i++)
     {
      CMoney *money=At(i);
      if(!CheckPointer(money))
         continue;
      if(StringCompare(money.Name(),select))
        {
         Selected(i);
         return true;
        }
     }
   return false;
  }

O terceiro método sobrecarregado é um método sem argumentos. Ele simplesmente retorna o índice do objeto de controle de capital selecionado, o que só é útil quando o EA quer saber qual método de controle de capital está selecionado atualmente:

int CMoneysBase::Selected(void) const
  {
   return m_selected;
  }

O volume atual é calculado através desse objeto por através do método Volume. O método primeiro obtém o ponteiro para o objeto de controle de capital selecionado e, em seguida, chama seu próprio método Volume. O código do método Volume para a classe CMoneysBase é mostrado abaixo:
double CMoneysBase::Volume(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   CMoney *money=At(m_selected);
   if(CheckPointer(money))
      return money.Volume(symbol,price,type,sl);
   return 0;
  }

Aqui, o método acessa o objeto através da matriz de objetos e o armazena no ponteiro. Para evitar erros, é preciso certificar-se de que o elemento atual referido pelo índice realmente existe dentro da matriz de objetos.

Exemplo

Como exemplo, usaremos o último exemplo do artigo anterior. Vamos modificá-lo, para isso, habilitamos nele as classes de controle de capital introduzidas neste artigo, colocamo-las num contêiner separado e, em seguida, adicionamo-las ao gerenciador de ordens. A maioria das adições só tratará a função OnInit do EA, que é mostrada abaixo:

int OnInit()
  {
//--- 
   order_manager=new COrderManager();
   money_manager = new CMoneys();
   CMoney *money_fixed= new CMoneyFixedLot(0.05);
   //CMoney *money_ff= new CMoneyFixedFractional(5);
   CMoney *money_ratio= new CMoneyFixedRatio(0,0.1,1000);
   //CMoney *money_riskperpoint= new CMoneyFixedRiskPerPoint(0.1);
   //CMoney *money_risk= new CMoneyFixedRisk(100);
   
   money_manager.Add(money_fixed);
   //money_manager.Add(money_ff);
   money_manager.Add(money_ratio);
   //money_manager.Add(money_riskperpoint);
   //money_manager.Add(money_risk);
   order_manager.AddMoneys(money_manager);
   //order_manager.Account(money_manager);
   symbol_manager=new CSymbolManager();
   symbol_info=new CSymbolInfo();
   if(!symbol_info.Name(Symbol()))
      Print("symbol not set");
   symbol_manager.Add(GetPointer(symbol_info));
   order_manager.Init(symbol_manager,new CAccountInfo());

   MqlParam params[1];
   params[0].type=TYPE_STRING;
#ifdef __MQL5__
   params[0].string_value="Examples\\Heiken_Ashi";
#else
   params[0].string_value="Heiken Ashi";
#endif
   SignalHA *signal_ha=new SignalHA(Symbol(),0,1,params,signal_bar);
   SignalMA *signal_ma=new SignalMA(Symbol(),(ENUM_TIMEFRAMES) Period(),maperiod,0,mamethod,maapplied,signal_bar);
   signals=new CSignals();
   signals.Add(GetPointer(signal_ha));
   signals.Add(GetPointer(signal_ma));
   signals.Init(GetPointer(symbol_manager),NULL);
//--- 
   return(INIT_SUCCEEDED);
  }

Aqui, incluímos as cadeias de código empregadas para usar métodos de fração fixa, risco fixo e risco fixo por ponto de controle de capital. No entanto, nesse ponto, nosso EA só entra em negociações com Stop-Loss zero, vamos abster-nos de usar esses métodos a partir de agora. Por enquanto, usaremos métodos baseados em lote fixo e proporção fixa de controle de capital. Se estes objetos retornarem um Stop-Loss inválido (inferior a zero), o gerenciador de ordens usara o volume padrão do lote (0.1, disponível no membro m_lotsize da classe CorderManager/COrderManagerBase).

COrderManager tem seu próprio membro de classe, que, por sua vez, é um ponteiro para o contêiner de controle de capital (CMoney). Assim, o uso da COrderManager também fará com que os arquivos de cabeçalho de controle de capital sejam incluídos no código-fonte. Se, no EA, não for usada a COrderManager, a diretiva #include - para as classes de controle de capital - deverá ser indicada no código-fonte.

Para a função OnTick, modificamos o EA de forma que, para posições longas, o EA usará o tamanho fixo de lote, enquanto que para posições curtas, ele usará uma proporção fixa. Isso pode ser conseguido alterando o tipo de controle de capital através do método Selected (classe CMoneys), antes que o método TradeOpen do gerenciador de ordens seja chamado:

void OnTick()
  {
//--- 
   if(symbol_info.RefreshRates())
     {
      signals.Check();
      if(signals.CheckOpenLong())
        {
         close_last();
         //Print("Entering buy trade..");
         money_manager.Selected(0);
         order_manager.TradeOpen(Symbol(),ORDER_TYPE_BUY,symbol_info.Ask());
        }
      else if(signals.CheckOpenShort())
        {
         close_last();
         //Print("Entering sell trade..");
         money_manager.Selected(1);
         order_manager.TradeOpen(Symbol(),ORDER_TYPE_SELL,symbol_info.Bid());
        }
     }
  }

Como o controle de capital, em essência, é apenas um cálculo puro, esperamos que o lote calculado seja o mesmo nas duas versões do terminal (MT4 e MT5). O que se segue mostra o resultado de teste do EA no MetaTrader 4 (10 primeiras transações):

# Hora Tipo Ordem Volume Preço S / L T / P Lucro saldo da conta
1. 2017.01.02 00:00 venda 1. 1.00 1.05100 0.00000 0.00000
2 2017.01.03 03:00 Fechamento 1. 1.00 1.04679 0.00000 0.00000 419.96 10419.96
3 2017.01.03 03:00 Compra 2 0.05 1.04679 0.00000 0.00000
4 2017.01.03 10:00 Fechamento 2 0.05 1.04597 0.00000 0.00000 -4.10 10415.86
5 2017.01.03 10:00 venda 3 1.00 1.04597 0.00000 0.00000
6 2017.01.03 20:00 Fechamento 3 1.00 1.04285 0.00000 0.00000 312.00 10727.86
7 2017.01.03 20:00 Compra 4 0.05 1.04285 0.00000 0.00000
8 2017.01.03 22:00 Fechamento 4 0.05 1.04102 0.00000 0.00000 -9.15 10718.71
9 2017.01.03 22:00 venda 5 1.00 1.04102 0.00000 0.00000
10 2017.01.04 02:00 Fechamento 5 1.00 1.04190 0.00000 0.00000 -89.04 10629.67
11 2017.01.04 02:00 Compra 6 0.05 1.04190 0.00000 0.00000
12 2017.01.04 03:00 Fechamento 6 0.05 1.03942 0.00000 0.00000 -12.40 10617.27
13 2017.01.04 03:00 venda 7 1.00 1.03942 0.00000 0.00000
14 2017.01.04 06:00 Fechamento 7 1.00 1.04069 0.00000 0.00000 -127.00 10490.27
15 2017.01.04 06:00 Compra 8 0.05 1.04069 0.00000 0.00000
16 2017.01.05 11:00 Fechamento 8 0.05 1.05149 0.00000 0.00000 54.05 10544.32
17 2017.01.05 11:00 venda 9 1.00 1.05149 0.00000 0.00000
18 2017.01.05 16:00 Fechamento 9 1.00 1.05319 0.00000 0.00000 -170.00 10374.32
19 2017.01.05 16:00 Compra 10 0.05 1.05319 0.00000 0.00000
20 2017.01.06 05:00 Fechamento 10 0.05 1.05869 0.00000 0.00000 27.52 10401.84

No MetaTrader 5, podemos ver os seguintes resultados (modo de cobertura, primeiras 10 transações):














Ordens
Tempo de abertura Ordem Símbolo Tipo Volume Preço S / L T / P Hora Estado Comentário
2017.01.02 00:00:00 2 EURUSD venda 1.00 / 1.00 1.05100

2017.01.02 00:00:00 preenchidos
2017.01.03 03:00:00 3 EURUSD Compra 1.00 / 1.00 1.04669

2017.01.03 03:00:00 preenchidos
2017.01.03 03:00:00 4 EURUSD Compra 0.05 / 0.05 1.04669

2017.01.03 03:00:00 preenchidos
2017.01.03 10:00:00 5 EURUSD venda 0.05 / 0.05 1.04597

2017.01.03 10:00:00 preenchidos
2017.01.03 10:00:00 6 EURUSD venda 1.00 / 1.00 1.04597

2017.01.03 10:00:00 preenchidos
2017.01.03 20:00:00 7 EURUSD Compra 1.00 / 1.00 1.04273

2017.01.03 20:00:00 preenchidos
2017.01.03 20:00:00 8 EURUSD Compra 0.05 / 0.05 1.04273

2017.01.03 20:00:00 preenchidos
2017.01.03 22:00:00 9 EURUSD venda 0.05 / 0.05 1.04102

2017.01.03 22:00:00 preenchidos
2017.01.03 22:00:00 10 EURUSD venda 1.00 / 1.00 1.04102

2017.01.03 22:00:00 preenchidos
2017.01.04 02:00:00 11 EURUSD Compra 1.00 / 1.00 1.04180

2017.01.04 02:00:00 preenchidos
2017.01.04 02:00:00 12 EURUSD Compra 0.05 / 0.05 1.04180

2017.01.04 02:00:00 preenchidos
2017.01.04 03:00:00 13 EURUSD venda 0.05 / 0.05 1.03942

2017.01.04 03:00:00 preenchidos
2017.01.04 03:00:00 14 EURUSD venda 1.00 / 1.00 1.03942

2017.01.04 03:00:00 preenchidos
2017.01.04 06:00:00 15 EURUSD Compra 1.00 / 1.00 1.04058

2017.01.04 06:00:00 preenchidos
2017.01.04 06:00:00 16 EURUSD Compra 0.05 / 0.05 1.04058

2017.01.04 06:00:00 preenchidos
2017.01.05 11:00:00 17 EURUSD venda 0.05 / 0.05 1.05149

2017.01.05 11:00:00 preenchidos
2017.01.05 11:00:00 18 EURUSD venda 1.00 / 1.00 1.05149

2017.01.05 11:00:00 preenchidos
2017.01.05 16:00:00 19 EURUSD Compra 1.00 / 1.00 1.05307

2017.01.05 16:00:00 preenchidos
2017.01.05 16:00:00 20 EURUSD Compra 0.05 / 0.05 1.05307

2017.01.05 16:00:00 preenchidos
2017.01.06 05:00:00 21 EURUSD venda 0.05 / 0.05 1.05869

2017.01.06 05:00:00 preenchidos

Como o gerenciador de ordens já cuida da diferença entre as duas plataformas (e idiomas), o método e o resultado do cálculo do tamanho do lote serão os mesmos e as diferenças que possam surgir dependerão do próprio gerenciador de ordens.

Fim do artigo

Este artigo mostra como o controle de capital pode ser aplicado num EA multiplataforma. Apresentados 5 diferentes métodos de controle de capital. Apresentados também o objeto contêiner personalizado dos ponteiros para objetos que são usados para a seleção dinâmica do método de controle de capital.

Traduzido do Inglês por MetaQuotes Software Corp.
Artigo original: https://www.mql5.com/en/articles/3280

Arquivos anexados |
mm_ha_ma.zip (1038.69 KB)
tester_results.zip (292.36 KB)
Indicadores personalizados e infográficos no CCanvas Indicadores personalizados e infográficos no CCanvas

O artigo considera novos tipos de indicadores com uma implementação estrutural mais complexa. Ele também descreve o desenvolvimento de indicadores do tipo pseudo-3D e infográficos dinâmicos.

Expert Advisor multiplataforma: Sinais Expert Advisor multiplataforma: Sinais

No artigo, são discutidas as classes CSignal e CSignals, que serão usadas em Expert Advisors multiplataforma. Além disso, serão examinadas as diferenças entre MQL4 e MQL5 quanto à organização de dados necessários para avaliar os sinais de negociação obtidos. O resultado será um código compatível com os compiladores das duas versões.

Métodos de ordenação e sua visualização usando a MQL5 Métodos de ordenação e sua visualização usando a MQL5

A biblioteca Graphic.mqh foi projetada para trabalhar com gráficos na MQL5. O artigo fornece um exemplo de sua aplicação prática e explica a ideia de ordenação. O conceito geral de ordenação é descrito aqui, pois cada tipo de ordenação já possui pelo menos um artigo separado, enquanto que alguns tipos de ordenação são objetos de estudos detalhados.

Interfaces Gráficas XI: Refatoração do código da biblioteca (build 14.1) Interfaces Gráficas XI: Refatoração do código da biblioteca (build 14.1)

À medida que a biblioteca cresce, seu código deve ser otimizado novamente para reduzir o seu tamanho. A versão da biblioteca descrita neste artigo tornou-se ainda mais orientada a objetos. Isso tornou o código mais amigável para o aprendizado. Uma descrição detalhada das últimas mudanças permitirá que os leitores desenvolvam a biblioteca de maneira independentemente de acordo com suas próprias necessidades.