English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
O uso de bibliotecas de classe de negócio padrão MQL5 ao escrever um Expert Advisor

O uso de bibliotecas de classe de negócio padrão MQL5 ao escrever um Expert Advisor

MetaTrader 5Sistemas de negociação | 5 fevereiro 2014, 12:40
9 153 0
Samuel Olowoyo
Samuel Olowoyo

Introdução

O novo programa MQL5 vem com muitas bibliotecas de classe padrão destinadas a fazer o desenvolvimento do Consultor Especialista MQL5, Indicadores e Scripts o mais fácil possível para negociadores e desenvolvedores.

Estas classes de bibliotecas estão disponíveis na pasta \Include\ localizada dentro da pasta MQL5 dentro da pasta terminal do cliente MetaTrader 5. As bibliotecas de classe estão divididas em várias categorias – classes Arrays (arranjos), ChartObjects, Gráficos, Arquivos, Indicadores, Cadeias e Negócio.

Neste artigo, iremos descrever em detalhes como podemos usar as classes de negócios integradas para escrever um Consultor Especialista. O Consultor Especialista será baseado em uma estratégia que incluirá o fechamento e a modificação de posições abertas quando uma condição estipulada é satisfeita.

Se você já tem uma ideia do que são classes e como elas podem ser usadas, então você é bem-vindo para outro mundo de oportunidade que a nova linguagem MQL5 pode oferecer.

Se, por outro lado, você é completamente novo para o MQL5; sugiro que você leia estes dois artigos para começar Guia Passo-A-Passo para escrever um Consultor Especialista em MQL5 para iniciantes, Escrevendo um Consultor Especialista usando a abordagem Objeto-Orientada MQL5 de programação ou qualquer outro artigo que te dará uma introdução para a nova linguagem MQL5. Há muitos artigos que foram escritos que te darão o conhecimento requerido.


1. As Classes de Negócios

A pasta de classes de negócios consiste em diferentes classes que tem o propósito de fazer a vida mais fácil para negociadores que querem desenvolver um CE para uso pessoal ou para programadores que não terão que reinventar a roda quando desenvolvendo seus Consultores Especializados (CE).

Ao usar uma classe, você não tem que saber o funcionamento interno da classe (isso é, como ela realiza o que o desenvolvedor diz), tudo em que você precisa se concentrar é em como a classe pode ser usada para resolver seu problema. Por isso usar uma biblioteca de classe incorporada faz as coisas bem fáceis para qualquer um que queira usá-las. Neste artigo iremos cobrir as maiores classes que serão necessárias no curso de desenvolver um desenvolver um Consultor Especialista.

Ao discutir as classes, nós não iremos nos preocupar com os detalhes internos das classes, mas iremos discutir em detalhes o que a classe pode fazer e como nós podemos usá-la para realizar nossa missão em desenvolver um CA muito lucrativo. Vamos discutí-las uma após a outra.

1.1 A classe СAccountInfo

A CAccountInfo é uma classe que torna fácil para o usuário ter acesso a todas as propriedades da conta ou informações para a conta de negócios atual aberta no terminal do cliente.

Para entender melhor, veremos as funções do membro principal dessa classe que provavelmente utilizaremos em nosso CE. Antes de podermos usar uma classe, primeiro precisamos criar um objeto daquela classe, para usar a classe CAccountInfo, devemos criar um objeto da classe.

Vamos chamá-lo myaccount:

//--- The AccountInfo Class Object
CAccountInfo myaccount;

Lembre-se que para criar um objeto de uma classe, você vai usar o nome da classe seguido pelo nome que você quer dar ao objeto.

Nós agora podemos usar nosso objeto myaccount para acessar as funções de membros públicos da classe CAccountInfo .

Método
Descrição
Exemplo de uso
myaccount.Login()

Esta função é usada quando você quer obter o número da conta para a negociação atualmente aberta no terminal.

// returns account number, example 7770
long accountno = myaccount.Login()
myaccount.TradeModeDescription()Esta função é usada para obter a descrição do modo de negociação para a conta atualmente ativa no terminal.
// returns Demo trading account, 
// or Real trading account or Contest trading account
string  acc_trading_mode = myaccount.TradeModeDescription();
myaccount.Leverage()

Esta função é usada para obter a descrição do modo de negociação para a conta atualmente ativa no terminal.

// returns leverage given to the active account
long acc_leverage = myaccount.Leverage(); 
myaccount.TradeAllowed()

Esta função é usada para checar se a negociação é permitida na conta ativa no terminal. Se a negociação não é permitida, a conta não pode negociar.

if (myaccount.TradeAllowed())
{
    // trade is allowed
}
else
{
  // trade is not allowed
}
myaccount.TradeExpert()Esta função é usada para checar se Consultores Especializados são permitidos para negociar na conta atualmente ativa no terminal.
if (myaccount.TradeExpert())
{
   // Expert Advisor trade is allowed
}
else
{
   // Expert Advisor trade is not allowed
}
myaccount.Balance()Esta função fornece o saldo em conta para a conta ativa no terminal.
// returns account balance in the deposit currency
double acс_balance =  myaccount.Balance(); 
myaccount.Profit()

Esta função é usada para obter o lucro atual da conta ativa no terminal.

// returns account profit in deposit currency
double acс_profit =  myaccount.Profit();
myaccount.FreeMargin()

Esta função é usada para obter a margem livre da conta ativa no terminal.

// returns free margin for active account
double acс_free_margin = myaccount.FreeMargin();
myaccount.Currency()

Esta função é usada para obter a moeda de depósito para a conta ativa no terminal.

string acс_currency = myaccount.Currency();
myaccount.OrderProfitCheck(const string symbol, ENUM_ORDER_TYPE trade_operation, double volume, double price_open, double price_close)Esta função obtém o lucro avaliado, baseado em parâmetros passados. Os parâmetros de entrada são: símbolo, tipo de operação de negócio, volume e preços de abertura/fechamento.
double op_profit=myaccount.OrderProfitCheck(_Symbol,ORDER_TYPE_BUY,
1.0,1.2950,1.3235);
Print("The amount of Profit for deal buy EURUSD",
"at 1.2950 and sell at 1.3235 is: ",op_profit);
myaccount.MarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price)Esta função é usada para obter a margem necessária para abrir uma ordem. Esta função tem quatro parâmetros de entrada que são : o símbolo (pareamento-moeda), tipo de ordem, os lotes (ou volume) para negociação e o preço da ordem. Esta função é muito importante quando efetuando uma negociação.
// depending on the type of position to open - in our case buy
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
double margin_req=myaccount.MarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
 
myaccount.FreeMarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price)Esta função é usada para obter a quantidade de margem livre restante naquela conta ativa quando uma ordem é efetuada. Ela tem quatro parâmetros de entrada que são : o símbolo (pareamento-moeda), tipo de ordem, lotes (ou volume) para negociar e o preço da ordem.
double acс_fm=myaccount.FreeMarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.MaxLotCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double price)

Esta função é usada para obter o lote máximo possível para efetuar uma ordem na conta ativa no terminal. Ela tem três parâmetros de entrada que são : o símbolo, o tipo de ordem e o preço de abertura da ordem.

double max_lot=myaccount.MaxLotCheck(_Symbol,ORDER_TYPE_BUY,price);

1.2 A Classe СSymbolInfo

A classe CSymbolInfo facilita para que o usuário rapidamente tenha acesso a todas as propriedades do símbolo atual.

Para usar a classe, precisamos criar um objeto da classe, neste caso iremos chamá-lo mysymbol.

// the CSymbolInfo Class object CSymbolInfo mysymbol;

Vamos dar uma olhada na maioria das funções desta classe que pode ser usada no processo de escrever nosso Consultor Especialista:

Método DescriçãoExemplo de uso
mysymbol.Name (nome da string)

Esta função é usada para definir o símbolo para o objeto de classe. Ela toma o nome do símbolo como um parâmetro de entrada.

// set the symbol name for our CSymbolInfo class Object
mysymbol.Name(_Symbol);
mysymbol.Refresh() Esta função é usada para atualizar todos os dados dos símbolos. é também chamada automaticamente quando você define um novo nome do símbolo para a classe.
mysymbol.Refresh();
mysmbol.RefreshRates()Esta função é usada para checar os últimos dados de cotações. Ela retorna verdadeiro nos sucessos e falso nas falhas. Esta é uma função útil que não pode faltar.
//--- Get the last price quote using the CSymbolInfo 
// class object function
   if (!mysymbol.RefreshRates())
   {
      // error getting latest price quotes 
}
mysymbol.IsSynchronized()

Esta função é usada para checar se os dados atuais do símbolo definido no terminal está sincronizado com os dados do servidor. Ele retorna verdadeiro se os dados estão sincronizados e falso quando não estão.

// check if symbol data are synchronized with server
  if (!mysymbol.IsSynchronized())
   {
     // error! Symbol data aren't synchronized with server
   }
mysymbol.VolumeHigh()

Esta função é usada para obter o volume máximo do dia para o símbolo definido.

long max_vol = mysymbol.VolumeHigh();
mysymbol.VolumeLow()

Esta função é usada para obter o volume mínimo do dia para o símbolo definido.

long min_vol = mysymbol.VolumeLow();
mysymbol.Time()

Esta função é usada para obter o horário da última cotação de preço para o símbolo definido.

datetime qtime = mysymbol.Time();
mysymbol.Spread()Esta função é usada para obter o valor do spread (em pontos) para o símbolo definido.
int spread = mysymbol.Spread();
mysymbol.StopsLevel()Esta função é usada para obter o nível mínimo (em pontos) para o preço atual de fechamento para o qual parar perdas pode ser colocado para o símbolo definido. Uma função muito útil para uso se você estiver considerando usar o Limite Móvel ou ordenar uma modificação de /posição.
int stp_level = mysymbol.StopsLevel();
mysymbol.FreezeLevel()Esta função é usada para obter a distância (em pontos) de congelamento da operação de negociação para o símbolo definido.
int frz_level = mysymbol.FreezeLevel();
mysymbol.Bid()

Esta função é usada para obter o preço de COMPRA atual para o símbolo definido.

double bid =  mysymbol.Bid();
mysymbol.BidHigh()Esta função é usada para obter o preço máximo/maior de COMPRA para o dia.
double max_bid = mysymbol.BidHigh();
mysymbol.BidLow()Esta função é usada para obter o preço mínimo/menor de COMPRA para o dia para o símbolo definido.
double min_bid = mysymbol.BidLow();
msymbol.Ask()Esta função é usada para obter o preço de VENDA para o símbolo definido.
double ask = mysymbol.Ask();
mysymbol.AskHigh()Esta função é usada para o obter o preço máximo/maior de VENDA para o dia para o símbolo definido.
double max_ask = mysymbol.AskHigh();
mysymbol.AskLow()Esta função é usada para obter o preço mínimo/menor de VENDA para o dia.
double min_ask = mysymbol.AskLow();
mysymbol.CurrencyBase()Esta função é usada para obter a moeda base para o símbolo definido.
// returns "USD" for USDJPY or USDCAD
string base_currency = mysymbol.CurrencyBase();
mysymbol.ContractSize()Esta função é usada para obter a quantia para o tamanho do contrato para negociar o símbolo definido.
double cont_size =  mysymbol.ContractSize();
mysymbol.Digits() Esta função é usada para obter o número de dígitos depois do ponto decimal para o símbolo definido.
int s_digits = mysymbol.Digits();
mysymbol.Point()Esta função é usada para obter o valor de um ponto para o símbolo definido.
double s_point =  mysymbol.Point();
mysymbol.LotsMin()Esta função é usada para obter o volume mínimo necessário para fechar um negócio com o símbolo.
double min_lot =  mysymbol.LotsMin();
mysymbol.LotsMax()Esta função é usada para obter o máximo volume necessário para fechar um negócio para o símbolo.
double max_lot =  mysymbol.LotsMax();
mysymbol.LotsStep()Esta função é usada para obter a mudança mínima no passo de volume para fechar um negócio para o símbolo.
double lot_step = mysymbol.LotsStep();
mysymbol.NormalizePrice(double price) Esta função é usada para obter um preço normalizado para os dígitos corretos do símbolo definido.
// A normalized current Ask price
double n_price = mysymbol.NormalizePrice(mysymbol.Ask()); 
mysymbol.Select()Esta função é utilizada para determinar se um símbolo foi selecionado na janela de observação do mercado. Ela retorna verdadeiro se o símbolo foi selecionado caso contrário ela retorna falso.
if (mysymbol.Select())
{
  //Symbol successfully selected
}
else
{
  // Symbol could not be selected
}
mysymbol.Select(bool select)Esta função é usada para selecionar um símbolo na janela de observação do Mercado ou para remover um símbolo na janela de observação do mercado. é necessário notar que remover um símbolo da janela de observação do mercado quando o gráfico está aberto de quando ele já tem uma posição aberta irá retornar falso.
if (!mysymbol.Select())
{
   //Symbol not selected, Select the symbol
    mysymbol.Select(true);
}
else
{
 // Symbol already selected, 
 // remove Symbol from market watch window
    mysymbol.Select(false);
}
mysymbol.MarginInitial()Esta função é usada para obter a quantia necessária para abrir uma posição com o volume de um lote na moeda de margem.
double init_margin = mysymbol.MarginInitial() ; 
mysymbol.TradeMode()Esta função é usada para obter o tipo de ordem de execução permitida para o símbolo.
if (mysymbol.TradeMode() == SYMBOL_TRADE_MODE_FULL)
{
 // Full trade allowed for this symbol,
 // no trade restrictions 
}
mysymbol.TradeModeDescription()Esta função é usada para obter a descrição do tipo de ordem de execução permitida para o símbolo.
Print("The trade mode for this symbol is",
       mysymbol.TradeModeDescription());

1.3 A classe СHistoryOrderInfo

A CHistoryOrderInfo é outra classe que torna mais fácil processar propriedades de histórico de ordem.

Uma vez que é criado um objeto desta classe nós podemos então usá-lo para acessa importantes funções de membro público que precisamos para solucionar um problema imediato.

Vamos nomear o objeto de classe myhistory.

// The CHistoryOrderInfo Class object
CHistoryOrderInfo myhistory;

Vamos olhar para algumas das maiores funções desta classe.

Ao usar esta classe para obter detalhes de ordens no histórico, precisamos primeiro de tudo obter o total de ordens no histórico e então passar o ticket de ordem para nosso objeto de classe, myhistory.

//Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))  // get all history orders
{
// Get total orders in history
int tot_hist_orders = HistoryOrdersTotal(); 

Nós vamos agora percorrer pelo histórico total de ordens disponíveis e obter os detalhes de cada ordem de histórico com nosso objeto de classe.

ulong h_ticket; // Order ticket

for (int j=0; j<tot_hist_orders; j++)
{
  h_ticket = HistoryOrderGetTicket(j));

  if (h_ticket>0)
  {
    // First thing is to now set the order Ticket to work with by our class object 
Método
DescriçãoExemplo de uso
myhistory.Ticket(ulong ticket)Esta função é usada para selecionar o ticket de ordem do qual queremos obter suas propriedades ou detalhes.
myhistory.Ticket(h_ticket);
myhistory.Ticket() Esta função é utilizada para obter o ticket de ordem para uma ordem.
ulong o_ticket = myhistory.Ticket();
myhistory.TimeSetup()Esta função é utilizada para obter o Horário em que a ordem foi executada ou configurada.
datetime os_time = myhistory.TimeSetup();
myhistory.OrderType()Esta função é usada para obter o tipo de ordem (ORDER_TYPE_BUY, etc).
if (myhistory.OrderType() == ORDER_TYPE_BUY)
{
// This is a buy order
}
myhistory.State()Esta função é utilizada para obter o estado atual da ordem.
Se a ordem foi cancelada, aceita, rejeitada ou executada, etc.
if(myhistory.State() == ORDER_STATE_REJECTED)
{
// order was rejected, not placed.
}
myhistory.TimeDone()Esta função é utilizada para obter o Horário em que a ordem foi executada, cancelada ou rejeitada.
datetime ot_done =  myhistory.TimeDone();
myhistory.Magic()Esta função é usada para obter a id do Consultor Especialista que iniciou a ordem.
long o_magic = myhistory.Magic();
myhistory.PositionId()Esta função é usada para obter a id da posição para a qual a ordem foi incluída quando executada.
long o_posid = myhistory.PositionId();
myhistory.PriceOpen()Esta função é usada para obter o preço de abertura de uma ordem.
double o_price =  myhistory.PriceOpen();
myhistory.Symbol()Esta função é usada para obter a propriedade do símbolo (par de moeda) da ordem.
string o_symbol =  myhistory.Symbol();

Não esqueça que nós utilizamos estas funções dentro de um ciclo de ordens totais no histórico.

1.4 A Classe СOrderInfo

Esta classe COrderInfo é uma que provê fácil acesso para todas as propriedades de ordem pendentes. Uma vez que um objeto desta classe foi criado, ele pode ser usado para funções de membros públicos desta classe.

O uso desta classe é de certa forma similar a classe CHistoryOrderInfo discutida acima.

Vamos criar um objeto da classe, que nós chamaremos de myorder.

// The OrderInfo Class object
COrderInfo myorder;

Para ser possível usar esta classe para obter os detalhes de uma ordem pendente, primeiro de tudo precisamos obter o total de ordens disponíveis e então selecioná-las pelo ticket de ordem.

// Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))   // get all history orders
   {    
     // get total orders
     int o_total = OrdersTotal();

Vamos então circular sobre o número total de ordens e obter suas propriedades correspondentes usando o objeto que criamos.

for (int j=0; j<o_total; j++)
{
 // we must confirm if the order is available for us to get its details using the Select function of the COrderInfo Class
Método
Descrição
Exemplo de uso
myorder.Select(ulong ticket) Esta função é usada para selecionar uma ordem pelo número do ticket para que a ordem seja facilmente manipulada.
if (myorder.Select(OrderGetTicket(j)) 
   { // order has been selected and can now be manipulated.
   }
myorder.Ticket() Esta função é utilizada para obter o ticket de ordem para a ordem selecionada.
ulong o_ticket = myorder.Ticket();
myorder.TimeSetup()Esta função é usada para obter o horário em que esta ordem foi configurada.
datetime o_setup = myorder.TimeSetup();
myorder.Type()Esta função é usada para obter o tipo de ordem como ORDER_TYPE_BUY_STOP, etc.
if (myorder.Type() == ORDER_TYPE_BUY_LIMIT)
{
// This is a Buy Limit order, etc
}
myorder.State()Esta função é utilizada para obter o estado da ordem.
Se a ordem foi cancelada, aceita, rejeitada ou executada, etc.
if (myorder.State() ==ORDER_STATE_STARTED)
{
// order has been checked 
// and may soon be treated by the broker
}
myorder.TimeDone()Esta função é usada para obter o horário em que a ordem foi executada, rejeitada ou cancelada.
datetime ot_done = myorder.TimeDone();
myorder.Magic()Esta função é usada para obter a id do Consultor Especialista que iniciou a ordem.
long o_magic =  myorder.Magic();
myorder.PositionId()Esta função é usada para obter a id da posição para a qual a ordem foi incluída quando executada.
long o_posid = myorder.PositionId();
myorder.PriceOpen()Esta função é utilizada para obter o preço de abertura para a ordem.
double o_price = myorder.PriceOpen();
myorder.StopLoss()Esta função é usada para obter o Parar Perdas da ordem.
double  s_loss = myorder.StopLoss();
myorder.TakeProfit()Esta função é utilizada para obter o Realizar Lucro da ordem.
double t_profit = myorder.TakeProfit();
myorder.PriceCurrent()Esta função é usada para obter o preço atual do símbolo no qual a ordem foi colocada.
double cur_price =  myorder.PriceCurrent();
myorder.Symbol()Esta função é usada para obter o nome do símbolo no qual a ordem foi colocada.
string o_symbol = myorder.Symbol();
myorder.StoreState()Esta função é usada para salvar ou armazenar detalhes atuais da ordem para que seja possível comparar se algo foi modificado mais tarde.
myorder.StoreState();
myorder.CheckState()Esta função é usada para checar se os detalhes da ordem que foi salva ou armazenada foram modificados.
if (myorder.CheckState() == true)
{
// Our order status or details have changed
}


1.5 A Classe CDealInfo

A classe CDealInfo provê acesso para todo o histórico de propriedades de negócio ou informação. Uma vez que criamos um objeto desta classe, iremos então usá-lo para obter toda a informação sobre negócios no histórico, em uma maneira similar a classe CHistoryOrderInfo.

Então, a primeira coisa que queremos fazer é criar um objeto desta classe e nomeá-lo mydeal.

// The DealInfo Class object
CDealInfo myinfo; 

Vamos começar obtendo o total de negócios no histórico

if (HistorySelect(0,TimeCurrent()))
   {    
    // Get total deals in history
    int tot_deals = HistoryDealsTotal(); 

Nós vamos agora percorrer pelo histórico total de ordens disponíveis e obter os detalhes de cada ordem de histórico com nosso objeto de classe.

ulong d_ticket; // deal ticket
for (int j=0; j<tot_deals; j++)
    {
     d_ticket = HistoryDealGetTicket(j);
     if (d_ticket>0)  
     {
      // First thing is to now set the deal Ticket to work with by our class object 
Método
DescriçãoExemplo de uso
mydeal.Ticket(ulong ticket)Esta função é usada para definir o ticket de negócio para uso futuro pelo objeto que criamos
mydeal.Ticket(d_ticket);
mydeal.Ticket() Esta função é usada para obter o ticket de negócio
ulong deal_ticket = mydeal.Ticket();
mydeal.Order()Esta função é usada para obter o nome do símbolo no qual a ordem foi executada
long deal_order_no =  mydeal.Order();
mydeal.Time()Esta função é usada para obter o horário em que esta ordem foi executada
datetime d_time = mydeal.Time();
mydeal.Type()Esta função é usada para obter o tipo de negócio, tenha ele sido um DEAL_TYPE_SELL, etc
if (mydeal.Type() == DEAL_TYPE_BUY)
{
// This deal was executed as a buy deal type
}
mydeal.Entry() Esta função é usada para obter a direção do negócio, seja ele DEAL_ENTRY_IN ou DEAL_ENTRY_OUT, etc.
if (mydeal.Entry() == DEAL_ENTRY_IN)
{
// This was an IN entry deal
}
mydeal.Magic() Esta função é usada para obter a id do Consultor Especialista que executou a ordem.
long d_magic = mydeal.Magic();
mydeal.PositionId() Esta função é usada para obter o identificador de posição única para a posição na qual o negócio fez parte.
long d_post_id = mydeal.PositionId();
mydeal.Price() Esta função é usada para obter o preço em que esta ordem foi executada
double d_price = mydeal.Price();
mydeal.Volume() Esta função é utilizada para obter o volume (lote) do negócio
double d_vol = mydeal.Volume();
mydeal.Symbol() Esta função é usada para obter o símbolo (par-moeda) para o qual o negócio foi executado
string d_symbol = mydeal.Symbol();


1.6 A Classe CPositionInfo

A classe CPositionInfo provê fácil acesso para as propriedades atuais de posição. Precisamos criar um objeto desta classe para ser possível usá-lo para obter as propriedades da posição.

Vamos criar um objeto desta classe e chamá-lo de myposition.

// The object of the CPositionInfo class
CPositionInfo myposition;

Nós agora vamos usar este objeto para abrir detalhes das posições. Vamos começar obtendo o total de posições abertas disponíveis:

int pos_total = PositionsTotal();

Agora é hora de passar por todas as posições abertas para obter seus detalhes.

for (int j=0; j<pos_total; j++)
    {
Método
DescriçãoExemplo de uso
myposition.Select(const string symbol)Esta função é usada para selecionar o símbolo correspondente a posição em aberto para que seja trabalhada.
if (myposition.Select(PositionGetSymbol(j)))
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
OR
// when dealing with the current symbol/chart only
if (myposition.Select(_Symbol)) 
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
myposition.Time()Esta função é usada para obter o horário em que a posição foi aberta.
datetime pos_time = myposition.Time();
myposition.Type()Esta função é usada para obter o tipo de posição aberta.
if (myposition.Type() == POSITION_TYPE_BUY)
{
// This is a buy position
}
myposition.Magic()Esta função é usada para obter a id do Consultor Especialista que abriu a posição.
long pos_magic = myposition.Magic();
myposition.Volume()Esta função é utilizada para obter o volume (lotes) da posição aberta.
double pos_vol = myposition.Volume(); // Lots
myposition.PriceOpen()Esta função é usada para obter o preço em que a posição foi aberta - o preço de abertura da posição.
double pos_op_price = myposition.PriceOpen();
myposition.StopLoss()Esta função é usada para obter o preço de Parar Perdas para a posição aberta
double pos_stoploss = myposition.StopLoss();
myposition.TakeProfit()Esta função é usada para obter o preço de Obter Lucros para a posição aberta
double pos_takeprofit = myposition.TakeProfit();
myposition.StoreState()Esta função é utilizada para armazenar o estado atual da posição.
// stores the current state of the position
myposition.StoreState();
myposition.CheckState()Esta função é usada para checar se o estado da posição aberta mudou.
if (!myposition.CheckState())
{
  // position status has not changed yet
}
myposition.Symbol()Esta função é usada para obter o nome do símbolo no qual a posição foi aberta.
string pos_symbol = myposition.Symbol();


1.7 A Classe СTrade

A classe CTrade fornece fácil acesso às operações de negócios no MQL5. Para usar esta classe, nós temos que criar um objeto da classe e então usá-lo para realizar as operações de negócio necessárias.

Vamos criar um objeto desta classe e nomeá-lo mytrade:

//An object of the CTrade class
CTrade mytrade;

O primeiro passo é definir a maioria dos parâmetros que o objeto irá usar para fazer a operação de negócio.

MétodoDescrição
Exemplo de uso
mytrade.SetExpertMagicNumber(ulong magic)Esta função é usada para definir a id especialista (número mágico) que a classe irá usar para operações de negócio.
ulong Magic_No=12345;
mytrade.SetExpertMagicNumber(Magic_No);
mytrade.SetDeviationInPoints(ulong deviation)Esta função é também usada para definir o valor do desvio (em pontos) para ser usado quando executando um negócio.
ulong Deviation=20;
mytrade.SetDeviationInPoints(Deviation); 
mytrade.OrderOpen(conststring symbol,
ENUM_ORDER_TYPE
order_type,double volume,

double
limit_price,double price,doublesl,
double
tp,ENUM_ORDER_TYPE_TIME type_time,

datetime
expiration,const stringcomment="")
Esta função é usada para executar uma ordem pendente. Para usar esta função, os parâmetros devem primeiro de tudo ser preparados e então passados para esta função.
// define the input parameters
double Lots = 0.1;
double SL = 0;
double TP = 0;
// latest Bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid()-_Point*550;
// place (BuyStop) pending order
mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELLSTOP,Lots,0.0,Oprice,
                  SL,TP,ORDER_TIME_GTC,0);
mytrade.OrderModify(ulong ticket,double price,
double
sl,double tp,
ENUM_ORDER_TYPE_TIME type_time,datetime expiration)
Esta função é usada para modificar uma ordem pendente existente.
// Select total orders in history and get total pending orders 
// (as shown within the COrderInfo class section). 
// Use the CSymbolInfo class object to get the current ASK/BID price
int Stoploss = 400;
int Takeprofit = 550;
for(int j=0; j<OrdersTotal(); j++)
{
  ulong o_ticket = OrderGetTicket(j);
  if(o_ticket != 0)
  {
   // Stoploss must have been defined
   double SL = mysymbol.Bid() + Stoploss*_Point;   
   // Takeprofit must have been defined  
   double TP = mysymbol.Bid() - Takeprofit*_Point; 
   // lastest ask price using CSymbolInfo class object
   double Oprice = mysymbol.Bid();                 
   // modify pending BuyStop order
   mytrade.OrderModify(o_ticket,Oprice,SL,TP,ORDER_TIME_GTC,0);
  }
}
mytrade.OrderDelete(ulong ticket)Esta função é usada para deletar uma ordem pendente.
// Select total orders in history and get total pending orders
// (as shown within the COrderInfo class section). 

int o_total=OrdersTotal();
for(int j=o_total-1; j>=0; j--)
{
   ulong o_ticket = OrderGetTicket(j);
   if(o_ticket != 0)
   {
    // delete the pending Sell Stop order
    mytrade.OrderDelete(o_ticket);
   }
}
mytrade.PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume,double price,double sl,double tp,const string comment="")Esta função é usada para abrir uma posição de COMPRA ou VENDA. Para usar esta função, todos os parâmetros requeridos devem primeiro de tudo ser preparados e então passados para esta função.
// define the input parameters and use the CSymbolInfo class
// object to get the current ASK/BID price
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point;   
//Takeprofit must have been defined 
double TP = mysymbol.Ask() + Takeprofit*_Point; 
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lots,
                     Oprice,SL,TP,"Test Buy");
mytrade.PositionModify(const string symbol,
double
sl,double tp)
Esta função é usada para modificar o StopLoss (parar perdas) e/ou TakeProfit (obter lucros) de uma posição aberta existente. Para usar esta função, nós precisamos primeiro de tudo selecionar a posição a ser modificada usando o objeto de Classe CPositionInfo, use o objeto de classe CSymbolInfo para obter o preço atual de COMPRA/VENDA.
if (myposition.Select(_Symbol))
{
  int newStoploss = 250;
  int newTakeprofit = 500;
  double SL = mysymbol.Ask() – newStoploss*_Point;    
  double TP = mysymbol.Ask() + newTakeprofit*_Point;  
  //modify the open position for this symbol
 mytrade.PositionModify(_Symbol,SL,TP);
}
mytrade.PositionClose(const string symbol,
ulong
deviation=ULONG_MAX)
Esta função é usada para fechar uma posição aberta existente.
if (myposition.Select(_Symbol))
{
 //close the open position for this symbol
 mytrade.PositionClose(_Symbol);  
}
mytrade.Buy(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,doubletp=0.0,const string comment="") Esta função é usada para abrir uma negociação de compra. é recomendado que você defina o volume (ou lotes) para negociar quando usando esta função. Enquanto a tp (obter lucros) e a sl (parar perdas) podem ser definidas mais tarde ao modificar a posição aberta, estas utilizam o preço de Venda para abrir a negociação.
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point; 
//Takeprofit must have been defined
double TP = mysymbol.Ask() +Takeprofit*_Point;
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.Buy(Lots,NULL,Oprice,SL,TP,“Buy Trade”);

//OR
mytrade.Buy(Lots,NULL,0.0,0.0,0.0,“Buy Trade”);
// modify position later
mytrade.Sell(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,doubletp=0.0,const string comment="") Esta função é usada para abrir uma negociação de Venda. é recomendado que você defina o volume (ou lotes) para negociar quando usando esta função. Enquanto o tp (obter lucros) e sl (parar perdas) podem ser definidos mais tarde por modificar a posição aberta, estes usam o preço de Compra atual para abrir a negociação.
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Bid() + Stoploss*_Point;
//Takeprofit must have been defined
double TP = mysymbol.Bid() - Takeprofit*_Point; 
// latest bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid();
// open a Sell trade
mytrade.Sell(Lots,NULL,Oprice,SL,TP,“Sell Trade”); 

//OR
mytrade.Sell(Lots,NULL,0.0,0.0,0.0,“Sell Trade”); 
//(modify position later)
mytrade.BuyStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0,
ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")
Esta função é usada para executar uma ordem pendente de BuyStop. O tipo de ordem padrão de horário é ORDER_TIME_GTC, e a expiração é 0. Não há necessidade em especificar estas duas variáveis se você tem o mesmo horário do tipo de ordem em mente.
 double Lot = 0.1;
//Buy price = bar 1 High + 2 pip + spread
 int sprd=mysymbol.Spread();
 double bprice =mrate[1].high + 2*_Point + sprd*_Point;
//--- Buy price
 double mprice=NormalizeDouble(bprice,_Digits); 
//--- Stop Loss
 double stloss = NormalizeDouble(bprice - STP*_Point,_Digits);
//--- Take Profit
 double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits);
//--- open BuyStop order
 mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit); 
mytrade.SellStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")Esta função é usada para executar uma ordem pendente de SellStop (parar vendas) com os parâmetros definidos. O tipo de Ordem padrão de horário é ORDER_TIME_GTC, e a expiração é 0. Não há necessidade em especificar estas duas variáveis se você tem o mesmo horário do tipo de ordem em mente.
 double Lot = 0.1;
//--- Sell price = bar 1 Low - 2 pip 
//--- MqlRates mrate already declared
 double sprice=mrate[1].low-2*_Point;
//--- SellStop price
 double slprice=NormalizeDouble(sprice,_Digits);
//--- Stop Loss
 double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);
//--- Take Profit
 double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits);
//--- Open SellStop Order
 mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit);
mytrade.BuyLimit(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") Esta função é usada para executar uma ordem BuyLimit (limite de compra) dentro dos parâmetros definidos.
Usage:
//--- Buy price = bar 1 Open  - 5 pip + spread
double Lot = 0.1;
int sprd=mysymbol.Spread();
//--- symbol spread
double bprice = mrate[1].open - 5*_Point + sprd*_Point;
//--- MqlRates mrate already declared
double mprice=NormalizeDouble(bprice,_Digits);
//--- BuyLimit price
//--- place buyLimit order, modify stoploss and takeprofit later
mytrade.BuyLimit(Lot,mprice,_Symbol); 
mytrade.SellLimit (double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")Esta função é usada para executar uma ordem de limite de venda com os parâmetros definidos.
//--- Sell Limit price = bar 1 Open  + 5 pip
double Lot = 0.1;
//--- MqlRates mrate already declared
double sprice = mrate[1].open + 5*_Point;
//--- SellLimit
double slprice=NormalizeDouble(sprice,_Digits);
//place SellLimit order, modify stoploss and takeprofit later
mytrade.SellLimit(Lot,slprice,_Symbol);

FUNçõES DE RESULTADO DE NEGóCIOS

mytrade.ResultRetcode()Esta função é utilizada para obter o código de resultado para uma operação de negócio.
// a trade operation has just been carried out
int return_code = mytrade.ResultRetcode();
mytrade.ResultRetcodeDescription()Esta função é usada para obter a descrição completa ou interpretação do código retornado de uma operação de negócio.
string ret_message =  ResultRetcodeDescription();
// display it
Alert("Error code - " , mytrade.ResultRetcode() ,
      "Error message - ", ret_message);
mytrade.ResultDeal()Esta função é usada para obter o ticket de operação para a posição aberta.
long dl_ticket = mytrade.ResultDeal();
mytrade.ResultOrder()Esta função é usada para obter o ticket de ordem para a posição aberta.
long o_ticket = mytrade.ResultOrder();
mytrade.ResultVolume()Esta função é utilizada para obter o volume (lotes) para a posição aberta.
double o_volume = mytrade.ResultVolume();
mytrade.ResultPrice()Esta função é usada para obter o ticket de operação para a posição aberta.
double r_price = mytrade.ResultPrice();
mytrade.ResultBid()Esta função é usada para obter o preço atual de mercado de COMPRA (preço re-cotado).
double rq_bid = mytrade.ResultBid;
mytrade.ResultAsk()Esta função é usada para obter o preço atual de mercado de COMPRA (preço re-cotado).
double rq_ask = mytrade.ResultAsk;
mytrade.PrintRequest() / mytrade.PrintResult() Estas duas funções podem ser usadas para imprimir, para a aba Diário, os parâmetros de pedido de negócio e para os parâmetros de resultado respectivamente.
// after a trade operation
// prints the trade request parameters
mytrade.PrintRequest(); 
//prints the trade results
mytrade.PrintResult();  

FUNçõES DE PEDIDO DE NEGóCIO

mytrade.RequestAction()Esta função é usada para obter o tipo de Operação de Negócio para o último pedido de Negócio que foi enviado.
//determine the Trade operation type for the last Trade request
if (mytrade.RequestAction() == TRADE_ACTION_DEAL)
{
  // this is a market order for an immediate execution
}
else if (mytrade.RequestAction() == TRADE_ACTION_PENDING)
{
  // this is a pending order.
}  
mytrade.RequestMagic()Esta função é usada para obter o número Mágico Especialista que foi usado no último pedido.
ulong mag_no = mytrade. RequestMagic();
mytrade.RequestOrder()
Esta função é usada para obter o ticket de ordem que foi usado no último pedido. Isso relaciona-se principalmente com a modificação de ordens pendentes.
ulong po_ticket =  mytrade.RequestOrder();
mytrade.RequestSymbol()Esta função é usada para obter o símbolo ou par de moeda que foi usado na última solicitação.
string symb = mytrade.RequestSymbol(); 
mytrade.RequestVolume()Esta função é usada para obter o número Mágico Especialista que foi usado no último pedido.
double Lot = mytrade.RequestVolume();  
mytrade.RequestPrice()Esta função é usada para obter o preço da ordem usado na última solicitação.
double oprice = mytrade.RequestPrice();   
mytrade.RequestStopLimit()Esta função é usada para obter o preço usado para Parar Perdas na última solicitação.
double limitprice = mytrade.RequestStopLimit(); 
mytrade.RequestSL()Esta função é usada para obter o preço usado para Parar Perdas na última solicitação.
double sloss = mytrade.RequestSL();  
mytrade.RequestTP()Esta função é usada para obter o preço para Obter Lucros usado na última solicitação.
double tprofit = mytrade.RequestTP();   
mytrade.RequestDeviation()Esta função é usada para o obter o Desvio usado na última solicitação.
ulong dev = mytrade.RequestDeviation();  
mytrade.RequestType()Esta função é usada para obter o tipo de ordem que foi executada na última solicitação.
if (mytrade.RequestType() == ORDER_TYPE_BUY)
 {
  // market order Buy was placed in the last request.
mytrade.RequestTypeDescription()Esta função é usada para obter o tipo de ordem executada na última solicitação.
Print("The type of order placed in the last request is :",
      mytrade.RequestTypeDescription());  
mytrade.RequestActionDescription()Esta função é usada para obter a descrição a ação de solicitação usada na última solicitação.
Print("The request action used in the last request is :", 
      mytrade.RequestTypeDescription());
mytrade.RequestTypeFillingDescription()Esta função é usada para obter o tipo de diretriz de preenchimento de ordem usada na última solicitação.
Print("The type of order filling policy used",
      " in the last request is :",
      RequestTypeFillingDescription()); 

As funções de Solicitação da Classe de Negócio são bem úteis quando identificando erros associados com a execução de ordens. Há momentos em que obtemos algumas mensagens de erro quando executando uma ordem e isto se torna um pouco confuso quando não podemos identificar imediatamente o que deu errado. Ao usar as funções de solicitação da classe de negócio, somos capazes de identificar o que fizemos errado ao imprimir alguns dos parâmetros de solicitação que foram enviados para o servidor de negociação. Um exemplo de tal uso será similar ao código abaixo:

 //--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           { //--- Request is completed or order placed           
             Alert("A Buy order at price:", mytrade.ResultPrice() , ", vol:",mytrade.ResultVolume(),
                  " has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
            mytrade.PrintResult();
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), ", sl:", mytrade.RequestSL(),
                 ", tp:",mytrade.RequestTP(), ", price:", mytrade.RequestPrice(),
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
            mytrade.PrintRequest();
            return;
           }

No código acima, nós tentamos ser capazes de identificar alguns dos parâmetros enviados em nossa solicitação, no caso de ter ocorrido algum erro. Por exemplo, se nós não tivéssemos especificado o preço de Parar Perdas correto, podemos receber erros de Parada Inválida e ao imprimir o valor de Parar Perdas usando o mytrade.RequestSL(), nós seremos capazes de saber qual é o problema com nosso preços específico de Parar Perdas.

Dedicando o tempo para mostrar como cada das classes pode ser usada, agora é hora de colocar em prática algumas das funcionalidades que descrevemos.

Perceba que todas as funcionalidades que iremos utilizar no Consultor Especialista já foram descritas acima, será uma boa ideia sempre consultar as descrições uma vez que você veja quaisquer das funções nos códigos que iremos escrever.


2. Usando as funcionalidades das Classes de Negócios

Em ordem de demonstrar como usar as funcionalidades das classes de negócio, iremos escrever um Consultor Especialista que irá realizar as seguintes tarefas.

  • Irá checar por uma condição de Compra ou Venda, e se a condição for satisfeita, irá executar uma ordem de Compra ou Venda dependendo da condição que foi satisfeita.
  • Se uma posição foi aberta e a negociação continuar a ir em nossa direção, iremos modificar o obter lucros e parar perdas da posição. Entretanto, se o negócio vai contra nós e nosso lucro alvo não foi atingido, iremos encerrar a posição.
  • Nosso CE será usado para negociar no gráfico diário de uma das seguintes moedas – GBPUSD, AUDUSD, EURUSD, etc.

2.1 Escrevendo o Consultor Especialista

Para começar, inicie um novo documento MQL5 e selecione Consultor Especialista (modelo) e clique no botão Prosseguir:

Iniciando um novo Documento MQL5.


Figura 1. Iniciando um novo documento do MQL5

Digite o nome para o Consultor Especialista e clique no botão Finalizar. Iremos definir os parâmetros de entrada manualmente mais tarde.

Dê um nome ao novo documento

Figura 2. Nomeando o Consultor Especialista

O documento criado deve parecer similar como abaixo.

O esqueleto do código especialista

Imediatamente após a linha de versão #property, iremos incluir todas as classes de negócio que iremos usar.

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The AccountInfo Class
#include <Trade\AccountInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>

Depois iremos definir nossos parâmetros de entrada:

//+------------------------------------------------------------------+
//|  INPUT PARAMETERS                                              |
//+------------------------------------------------------------------+
input int      StopLoss=100;     // Stop Loss
input int      TakeProfit=240;   // Take Profit
input int      ADX_Period=15;    // ADX Period
input int      MA_Period=15;     // Moving Average Period
input ulong    EA_Magic=99977;   // EA Magic Number
input double   Adx_Min=24.0;     // Minimum ADX Value
input double   Lot=0.1;          // Lots to Trade
input ulong    dev=100;          // Deviation 
input long     Trail_point=32;   // Points to increase TP/SL
input int      Min_Bars = 20;    // Minimum bars required for Expert Advisor to trade
input double   TradePct = 25;    // Percentage of Account Free Margin to trade

Iremos também especificar outros parâmetros que serão usados neste código de Consultor Especialista:

//+------------------------------------------------------------------+
//|  OTHER USEFUL PARAMETERS                                         |
//+------------------------------------------------------------------+
int adxHandle;                     // handle for our ADX indicator
int maHandle;                    // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[];                  // Dynamic array to hold the values of Moving Average for each bars
double p_close;                    // Variable to store the close value of a bar
int STP, TKP;                   // To be used for Stop Loss, Take Profit 
double TPC;                        // To be used for Trade percent

Vamos agora criar um objeto de cada das classes que incluímos:

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The Trade Class Object
CTrade mytrade;
//--- The PositionInfo Class Object
CPositionInfo myposition;
//--- The AccountInfo Class Object
CAccountInfo myaccount;
//--- The SymbolInfo Class Object
CSymbolInfo mysymbol;

A próxima coisa que queremos fazer agora, é definir algumas funções que iremos usar para fazer nosso trabalho muito fácil.

Uma vez que definimos estas funções, iremos apenas chamá-las dentro das seções necessárias nas funções OnInit() e OnTick().

2.1.1 A função checkTrading

Esta função será usada para realizar todas as checagens iniciais para ver se nosso Consultor Especialista pode negociar ou não. Se esta função retornar verdadeiro, nosso CE irá continuar, em outro resultado o CE não irá realizar qualquer negociação.

//+------------------------------------------------------------------+
//|  Checks if our Expert Advisor can go ahead and perform trading   |
//+------------------------------------------------------------------+
bool checkTrading()
{
  bool can_trade = false;
  // check if terminal is syncronized with server, etc
  if (myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized())
  {
    // do we have enough bars?
    int mbars = Bars(_Symbol,_Period);
    if(mbars >Min_Bars)
    {
      can_trade = true;
    }
  }
  return(can_trade);
}

Nos declaramos um tipo de dados bool can_trade e o fazemos falso. Nós usamos o objeto da classe CAccountInfo para checar se o negócio é permitido e também se Consultores Especializados são permitidos de negociar nesta conta. Nós também usamos um objeto da classe CSymbolInfo para checar se o terminal está sincronizado com o servidor de negociação.

Uma vez que estas três condições são satisfeitas, nós então checamos se o número total de limites correntes é maior do que o mínimo requerido para nosso CE negociar. Se esta função retornar verdadeira, então nosso CE irá realizar as atividades de negociação, em outro caso, nosso CE não irá iniciar nenhuma atividade de negociação até que as condições nesta função sejam satisfeitas.

Como você viu, nós decidimos incluir todas as atividades de checagem de negócios necessárias nesta função, usando os objetos necessários das bibliotecas padrões de classe de negócios.

2.1.2 A função ConfirmMargin

//+------------------------------------------------------------------+
//|  Confirms if margin is enough to open an order
//+------------------------------------------------------------------+
bool ConfirmMargin(ENUM_ORDER_TYPE otype,double price)
  {
   bool confirm = false;
   double lot_price = myaccount.MarginCheck(_Symbol,otype,Lot,price); // Lot price/ Margin    
   double act_f_mag = myaccount.FreeMargin();                        // Account free margin 
   // Check if margin required is okay based on setting
   if(MathFloor(act_f_mag*TPC)>MathFloor(lot_price))
     {
      confirm =true;
     }
    return(confirm);
  }

Nós usamos o objeto da classe CAccountInfo para confirmar se há margem suficiente para executar um negócio baseado no cenário em que iremos usar apenas uma certa porcentagem de nossa margem livre da conta para executar uma ordem.

Se a porcentagem requerida pela margem livre da conta é maior que a margem requerida para a ordem, então esta função retorna verdadeira, em outros casos, retorna falso. Com isso, nós queremos apenas executar uma ordem se a função retornar verdadeiro. Esta função toma o tipo de ordem como um parâmetro de entrada.

2.1.3 A função checkBuy

//+------------------------------------------------------------------+
//|  Checks for a Buy trade Condition                                |
//+------------------------------------------------------------------+
bool checkBuy()
{
  bool dobuy = false;
  if ((maVal[0]>maVal[1]) && (maVal[1]>maVal[2]) &&(p_close > maVal[1]))
  {
    // MA increases upwards and previous price closed above MA
    if ((adxVal[1]>Adx_Min)&& (plsDI[1]>minDI[1]))
    {
      // ADX is greater than minimum and +DI is greater tha -DI for ADX
      dobuy = true;
    }
  }
  return(dobuy);
}

Nós decidimos completar as condições para abrir um transação de compra nesta função. Nós não usamos nenhuma das funcionalidades de objeto de Classe aqui. Estamos checando por uma condição onde os valores sobre o indicador da Média Móvel está crescendo e o preço de fechamento do limite anterior é maior do que o valor da média Móvel naquele ponto.

Nós também queremos uma situação onde o valor do indicador ADX é maior do que o mínimo requerido definido nos parâmetros de entrada e o valor do DI positivo do indicador ADX é maior do que o valor negativo do DI. Uma vez que estas condições estejam satisfeitas, então queremos que nosso CE abra uma ordem de COMPRA.

2.1.4 A função checkSell

//+------------------------------------------------------------------+
//|  Checks for a Sell trade Condition                               |
//+------------------------------------------------------------------+
bool checkSell()
{
  bool dosell = false;
  if ((maVal[0]<maVal[1]) && (maVal[1]<maVal[2]) &&(p_close < maVal[1]))
  {
    // MA decreases downwards and previuos price closed below MA
    if ((adxVal[1]>Adx_Min)&& (minDI[1]>plsDI[1]))
    {
      // ADX is greater than minimum and -DI is greater tha +DI for ADX
      dosell = true;
    }
  }
  return(dosell);
} 

Esta função verifica exatamente o oposto da função CheckBuy. Nós também não usamos nenhum dos objetos de classe nesta função. Esta função checa por uma condição onde os valores do indicador da Média Móvel está decrescendo e o preço de fechamento limite anterior é menor do que o valor da média Móvel naquele ponto.

Nós também queremos uma situação onde o valor do indicador ADX é maior do que o mínimo requerido definido nos parâmetros de entrada e o valor do DI negativo do indicador ADX é maior do que o valor positivo do DI. Uma vez que estas condições estejam satisfeitas, então queremos que nosso CE abra uma ordem de VENDA.

2.1.5 A função checkClosePos
//+------------------------------------------------------------------+
//|  Checks if an Open position can be closed                        |
//+------------------------------------------------------------------+
bool checkClosePos(string ptype, double Closeprice)
{
   bool mark = false;
   if (ptype=="BUY")
   {
      // Can we close this position
     if (Closeprice < maVal[1]) // Previous price close below MA
      {
         mark = true;
      }
   }
   if (ptype=="SELL")
   {
      // Can we close this position
      if (Closeprice > maVal[1]) // Previous price close above MA
      {
         mark = true;
      }
   }
   return(mark);
}

Esta função é usada para verificar se a posição aberta atualmente pode ser fechada. Esta função é usada para monitorar se o preço de fechamento limite anterior é maior ou menor do que o valor do indicador da Média Móvel naquele ponto (dependendo da direção da transação).

Se qualquer das condições é satisfeita, esta função retorna verdadeira e então esperaremos nosso CE encerrar a posição. Esta função tem dois parâmetros de entrada, o tipo de ordem (os nomes - COMPRA ou VENDA) e o preço de fechamento limite anterior.

2.1.6 A função ClosePosition

//+------------------------------------------------------------------+
//| Checks and closes an open position                                                                |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool marker=false;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Magic()==EA_Magic && myposition.Symbol()==_Symbol)
           {
            //--- Check if we can close this position
            if(checkClosePos(ptype,clp)==true)
              {
               //--- close this position and check if we close position successfully?
               if(mytrade.PositionClose(_Symbol)) //--- Request successfully completed 
                 {
                  Alert("An opened position has been successfully closed!!");
                  marker=true;
                 }
               else
                 {
                  Alert("The position close request could not be completed - error: ",
                       mytrade.ResultRetcodeDescription());
                 }
              }
           }
        }
      return(marker);
     }

Esta é a função que na realidade usa a função acima (checkclosepos). Ela faz uso dos objetos das classes CPositionInfo e CTrade. Esta função usa o objeto da classe CPositionInfo para verificar as posições abertas disponíveis para a posição que foi aberta por nosso CE e para o símbolo atual. Se alguma posição é encontrada, ela checa se pode ser fechada usando a função checkclosepos.

Se a função checkclosepos retorna verdadeiro, esta função usa o objeto da classe CTrade para encerrar a posição e exibir os resultados da operação de encerramento de posição. Se a posição foi encerrada com sucesso, esta função retorna verdadeiro, em outro caso, ela retorna falso.

Esta função toma dois parâmetros de entrada (o nome da posição , COMPRA ou VENDA e o preço de encerramento limite anterior). Estes parâmetros foram na realidade passados para função checkclosepos que os utiliza.

2.1.7 A função CheckModify

//+------------------------------------------------------------------+
//|  Checks if we can modify an open position                        |
//+------------------------------------------------------------------+
bool CheckModify(string otype,double cprc)
{
   bool check=false;
   if (otype=="BUY")
   {
      if ((maVal[2]<maVal[1]) && (maVal[1]<maVal[0]) && (cprc>maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   else if (otype=="SELL")
   {
      if ((maVal[2]>maVal[1]) && (maVal[1]>maVal[0]) && (cprc<maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   return(check);
} 

Esta função é usada para verificar por uma condição que confirma se uma posição aberta pode ser modificada ou não. Ela utiliza o mesmo nome do tipo de ordem e o preço de encerramento limite anterior como parâmetros de entrada.

O que esta função faz é checar se a média Móvel está ainda aumentando e o preço de fechamento limite anterior é ainda maior que o valor da média Móvel naquele ponto e o valor de ADX é também maior que o mínimo requerido (para uma posição de COMPRA) enquanto verifica se a média Móvel ainda está caindo e o preço de encerramento limite anterior é menor do que o valor da média móvel naquele ponto (para uma posição de VENDA). Dependendo do tipo de posição que temos, se alguma condição é satisfeita, o CE irá considerar modificar a posição.

Esta função toma dois parâmetros de entrada (o nome da posição , COMPRA ou VENDA e o preço de encerramento limite anterior).

2.1.8 A função Modify

//+------------------------------------------------------------------+
//| Modifies an open position                                        |
//+------------------------------------------------------------------+
   void Modify(string ptype,double stpl,double tkpf)
     {
       //--- New Stop Loss, new Take profit, Bid price, Ask Price
      double ntp,nsl,pbid,pask;                  
      long tsp=Trail_point;
       //--- adjust for 5 & 3 digit prices
      if(_Digits==5 || _Digits==3) tsp=tsp*10;   
       //--- Stops Level
      long stplevel= mysymbol.StopsLevel();      
       //--- Trail point must not be less than stops level
      if(tsp<stplevel) tsp=stplevel;
      if(ptype=="BUY")
        {
          //--- current bid price
         pbid=mysymbol.Bid();           
         if(tkpf-pbid<=stplevel*_Point)
           {
            //--- distance to takeprofit less or equal to Stops level? increase takeprofit
            ntp = pbid + tsp*_Point;
            nsl = pbid - tsp*_Point;
           }
         else
           {
            //--- distance to takeprofit higher than Stops level? dont touch takeprofit
            ntp = tkpf;
            nsl = pbid - tsp*_Point;
           }
        }
      else //--- this is SELL
        {
          //--- current ask price
         pask=mysymbol.Ask();            
         if(pask-tkpf<=stplevel*_Point)
           {
            ntp = pask - tsp*_Point;
            nsl = pask + tsp*_Point;
           }
         else
           {
            ntp = tkpf;
            nsl = pask + tsp*_Point;
           }
        }
      //--- modify and check result
      if(mytrade.PositionModify(_Symbol,nsl,ntp))  
        {
          //--- Request successfully completed    
         Alert("An opened position has been successfully modified!!");
         return;
        }
      else
        {
         Alert("The position modify request could not be completed - error: ",
               mytrade.ResultRetcodeDescription());
         return;
        }

     }

Esta função faz uso da função acima (checkmodify) para fazer o trabalho. Ela utiliza objetos das classes CSymbolInfo e CTrade. Primeiro de tudo, nós declaramos 4 tipos de dados duplicados para manter o novo obter lucros, parar perdas, preço de compra e preço de venda. Então, nós declaramos um novo tipo de dado longo tsp para manter o valor definido de Trail_point na seção de parâmetros de entrada.

O valor do ponto de fuga (tsp) foi então ajustado para preços de 5 e 3 dígitos. Nós então usamos o objeto CSymbolInfo para obter o nível de paradas e ter certeza de que o ponto de fuga que queremos acrescentar não é menor do que o requerido nível de parada. Se é menor que o nível de paradas, então usaremos o valor do nível de paradas.

Dependendo do tipo de posição, nós usamos o objeto de classe CSymbolInfo para obter o preço de COMPRA ou VENDA de acordo com o caso. Se a diferença entra o preço de COMPRA ou VENDA e o preço de obter lucros inicial é menor ou igual ao nível de paradas, nós decidimos para ajustar preço de parar perdas e de obter lucros em outro caso, nós apenas ajustamos o valor de parar perdas.

Nós então usamos o objeto de classe CTrade para modificar o Parar perdas e o obter lucros para a posição. Baseado no código de retorno do resultado da negociação, uma mensagem de sucesso ou falha é também exibida.

Nós terminamos de definir algumas das funções definidas pelo usuário que farão nosso trabalho mais fácil. Agora vamos em frente para a seção de códigos CE.

2.1.9 A seção OnInit

//--- set the symbol name for our SymbolInfo Object
   mysymbol.Name(_Symbol);
// Set Expert Advisor Magic No using our Trade Class Object
   mytrade.SetExpertMagicNumber(EA_Magic);
// Set Maximum Deviation using our Trade class object
   mytrade.SetDeviationInPoints(dev);
//--- Get handle for ADX indicator
   adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
   maHandle=iMA(_Symbol,Period(),MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
   if(adxHandle<0 || maHandle<0)
     {
      Alert("Error Creating Handles for MA, ADX indicators - error: ",GetLastError(),"!!");
      return(1);
     }
   STP = StopLoss;
   TKP = TakeProfit;
//--- Let us handle brokers that offers 5 or 3 digit prices instead of 4
   if(_Digits==5 || _Digits==3)
     {
      STP = STP*10;
      TKP = TKP*10;
     }
   
//--- Set trade percent
    TPC = TradePct;
    TPC = TPC/100;
//---

Nós decidimos definir o símbolo atual para o objeto de classe CSymbolInfo. Também definimos o número mágico do Consultor Especialista e o desvio (em pontos) usando o objeto de classe CTrade. Depois disto, decidimos obter os tratadores para nossos indicadores e exibir um erro se a obtenção de tratadores falhar.

Depois, nós decidimos ajustar o parar perdas e obter lucros para preços de 3 e 5 dígitos e nós também convertemos a porcentagem livre da margem de conta para ser usada em negociações para porcentagem.

2.1.10 A seção OnDeinit

//--- Release our indicator handles
   IndicatorRelease(adxHandle);
   IndicatorRelease(maHandle);

Aqui nós decidimos liberar todos os tratadores de indicadores.

2.1.11. A seção OnTick

//--- check if EA can trade
    if (checkTrading() == false) 
   {
      Alert("EA cannot trade because certain trade requirements are not meant");
      return;
   }
//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
/*
     Let's make sure our arrays values for the Rates, ADX Values and MA values 
     is store serially similar to the timeseries array
*/
// the rates arrays
   ArraySetAsSeries(mrate,true);
// the ADX values arrays
   ArraySetAsSeries(adxVal,true);
// the MA values arrays
   ArraySetAsSeries(maVal,true);
// the minDI values array
   ArraySetAsSeries(minDI,true);
// the plsDI values array
   ArraySetAsSeries(plsDI,true);

A primeira coisa a fazer aqui é checar e ter certeza se nosso CE deve negociar ou não. Se a função checktrade retorna falso, nosso CE irá aguardar pelo próximo instante e fazer a checagem novamente.

Após isso nós declaramos uma Estrutura MqlRates MQL5 para obter os preços de cada barra e então nós usamos a função ArraySetAsSeries para definir todos os arranjos (arrays) requeridos.

//--- Get the last price quote using the SymbolInfo class object function
   if (!mysymbol.RefreshRates())
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

//--- Get the details of the latest 3 bars
   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }

//--- EA should only check for new trade if we have a new bar
// lets declare a static datetime variable
   static datetime Prev_time;
// lest get the start time for the current bar (Bar 0)
   datetime Bar_time[1];
   //copy the current bar time
   Bar_time[0] = mrate[0].time;
// We don't have a new bar when both times are the same
   if(Prev_time==Bar_time[0])
     {
      return;
     }
//Save time into static varaiable, 
   Prev_time = Bar_time[0]; 

Nós usamos o objeto de classe CSymbolInfo para obter a cotação de preço atual e então copiar os preços atuais de barras para o arranjo mrates. Imediatamente após isto nós decidimos checar pela presença de uma nova barra.

Se nós temos uma nova barra, então nosso CE irá proceder para checar se uma condição de COMPRA ou VENDA foi satisfeita, em outro caso irá aguardar até termos uma nova barra.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(adxHandle,0,0,3,adxVal)<3 || CopyBuffer(adxHandle,1,0,3,plsDI)<3
      || CopyBuffer(adxHandle,2,0,3,minDI)<3)
     {
      Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(maHandle,0,0,3,maVal)<3)
     {
      Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
      return;
     }
//--- we have no errors, so continue
// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1

   p_close=mrate[1].close;  // bar 1 close price

Aqui, nós usamos as funções do CopyBuffer para obter os buffers de nossos indicadores em arranjos e se um erro ocorrer no processo, ele será exibido. O preço de encerramento limite anterior foi copiado.

//--- Do we have positions opened already?
  bool Buy_opened = false, Sell_opened=false; 
   if (myposition.Select(_Symbol) ==true)  // we have an opened position
    {
      if (myposition.Type()== POSITION_TYPE_BUY)
       {
            Buy_opened = true;  //It is a Buy
          // Get Position StopLoss and Take Profit
           double buysl = myposition.StopLoss();      // Buy position Stop Loss
           double buytp = myposition.TakeProfit();    // Buy position Take Profit
           // Check if we can close/modify position
           if (ClosePosition("BUY",p_close)==true)
             {
                Buy_opened = false;   // position has been closed
                return; // wait for new bar
             }
           else
           {
              if (CheckModify("BUY",p_close)==true) // We can modify position
              {
                  Modify("BUY",buysl,buytp);
                  return; // wait for new bar
              }
           } 
       }
      else if(myposition.Type() == POSITION_TYPE_SELL)
       {
            Sell_opened = true; // It is a Sell
            // Get Position StopLoss and Take Profit
            double sellsl = myposition.StopLoss();    // Sell position Stop Loss
            double selltp = myposition.TakeProfit();  // Sell position Take Profit
             if (ClosePosition("SELL",p_close)==true)
             {
               Sell_opened = false;  // position has been closed
               return;   // wait for new bar
             }
             else
             {
                 if (CheckModify("SELL",p_close)==true) // We can modify position
                 {
                     Modify("SELL",sellsl,selltp);
                     return;  //wait for new bar
                 }
             } 
       }
    } 

Nós usamos o objeto de classe CPositionInfo para selecionar e checar se nós temos uma posição aberta para o símbolo atual. Se uma posição existe, e é uma de COMPRA, nós definimos Buy_opened para ser verdadeira e então usamos o objeto de classe CPositionInfo para obter o parar perdas e obter lucros da posição. Usando a função que definimos mais cedo, ClosePosition, nós checamos se a posição pode ser encerrada. Se a função retornar verdadeira, então a posição foi encerrada, então nós definimos Buy_opened para falso nós na posição inicial de COMPRA que foi encerrada. O CE irá agora esperar por um novo instante.

Entretanto, se a função retornar falso, então a posição não foi encerrada. é o momento de checar se podemos modificar a posição. Isto conseguimos ao usar a função CheckModify qual definimos anteriormente. Se a função retorna verdadeiro, então significa que a posição pode ser modificada, então nós usamos a função Modify para modificar a posição.

Se, por outro lado, a posição existe e é uma de VENDA, nós definimos Sell_opened para ser verdadeira e usamos a classe de objeto CPositionInfo para obter o parar perdas e obter lucros da posição. Nós repetimos o mesmo passo como fizemos para a posição de COMPRA em ordem de ver se a posição pode ser fechada ou modificada.

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);                //--- latest ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           {
               //--- Request is completed or order placed
             Alert("A Buy order has been successfully placed with deal Ticket#:",
                  mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                  ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                  ", price:", mytrade.RequestPrice(), 
                     " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

Ou podemos usar a função PositionOpen.

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- latest Ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         //if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
           {
              //--- Request is completed or order placed            
              Alert("A Buy order has been successfully placed with deal Ticket#:",
            mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

Aqui, nós usamos a função checkbuy para verificar por uma configuração de compra e se retornar verdadeira, então nossas condições de negociação de COMPRA foram satisfeitas. Se nós já tivermos uma posição de COMPRA, nós não queremos executar uma nova ordem. Nós então usamos a classe de objeto CSymbolInfo para obter o preço atual de VENDA e calcular o Parar perdas e Obter lucros como necessário.

Nós também usamos a função ConfirmMargin para verificar se a porcentagem de uma conta permitida para executar uma ordem é maior do que a margem necessária para executar esta ordem. Se a função retornar verdadeira, então nós seguimos em frente e executamos a negociação em outro caso, nós não executamos a negociação.

Usando o objeto de classe CTrade, nós executamos nossa ordem e usamos as mesmas chamadas objeto para obter o código de retorno da operação de negócio. Baseado no resultado do negócio, uma mensagem é exibida.

      if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
               //---Request is completed or order placed            
               Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }

        }

Ou nós podemos também usar a função PositionOpen:

      if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         //if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
             //---Request is completed or order placed            
             Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(),
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                 ", price:", mytrade.RequestPrice(), 
                   " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

Assim como nós fizemos para a COMPRA, nós usamos a função Checksell para verificar por uma configuração de venda. Se ela retornar verdadeira e nós não tivermos ainda uma posição de venda aberta, nós usamos a função ConfirmMargin para verificar se nós temos dinheiro suficiente para abrir a ordem. Se ConfirmMargin retorna verdadeira, o objeto de classe CTrade é usado para executar uma ordem e baseado na resposta do servidor de negócio, o resultado é exibido usando as funções da classe de objeto CTrade.

Até agora nós observamos como nós podemos usar as bibliotecas de classe de negócio para escrever um Consultor Especialista. A próxima coisa é testar nosso Consultor Especialista com um testador de estratégia e observar sua performance.

Compilar o código CE e então carregar no Testador de Estratégia.

Compilar relatório para o CE.

Figura 3. Consultor Especialista compila relatório

No gráfico Diário GBPUSD usando as configurações padrão: Obter Lucros - 270, Parar Perdas - 100 e Ponto de Fuga (TP/SL) - 32, nós temos os seguintes resultados:

Figura 4. Relatório de testes do Consultor Especialista - gráfico diário GBPUSD

Figura 5. Relatório gráfico de testes do Consultor Especialista - gráfico diário GBPUSD


Figura 6. Relatório de teste do Consultor Especialista mostra modificação de posições abertas - gráfico diário GBPUSD


Figura 7. Relatório de testes do Consultor Especialista para o gráfico diário GBPUSD

Você está livre para testar o CE em qualquer outro gráfico diário de símbolos com diferentes configurações de Obter lucros, Parar perdas e ponto de Fuga e verificar o que você obtém.

Entretanto, você deve entender que este Consultor Especialista foi escrito somente para o propósito de testes...

Vamos agora ver como nós podemos usar outras classes (COrderInfo, CHistoryOrderInfo, e CDealInfo) para obter detalhes de ordem/transação.

2.2 Abrindo/Excluindo uma Ordem Pendente

Neste exemplo, iremos escrever um simples Consultor Especialista que irá executar uma ordem pendente (BuyStop ou SellStop) quando nós temos condições configuradas de compra ou Venda respectivamente satisfeitas.

2.2.1 Incluir as Classes Necessárias

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>
//--- The OrderInfo Class
#include <Trade\OrderInfo.mqh>

Nós incluímos as quatro classes que iremos usar neste simples Consultor Especialista. Elas foram explicadas nos exemplos acima.

Eu não irei explicar toda seção deste Consultor Especialista já que é similar ao descrito acima, entretanto, eu irei passar pela parte essencial do Consultor Especialista que explica o que queremos para discutir neste seção.

A única coisa que é diferente é que decidimos declarar MqlRates mrate[] em um escopo global.

//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];     // To be used to store the prices, volumes and spread of each bar

Uma vez que incluímos as classes, precisamos também lembrar de criar objetos de cada classe:

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The CTrade Class Object
CTrade mytrade;
//--- The CPositionInfo Class Object
CPositionInfo myposition;
//--- The CSymbolInfo Class Object
CSymbolInfo mysymbol;
//--- The COrderInfo Class Object
COrderInfo myorder;

As funções CheckBuy() e CheckSell() são as mesmas que no Consultor Especialista explicado anteriormente.

O que nós queremos aqui é executar uma ordem de BUYSTOP quando nós tivermos uma configuração de compra e uma SELLSTOP quando tivermos uma configuração de venda.

Vamos agora passar sobre algumas das funções que criamos para fazer as coisas mais fáceis para nós.

2.2.2 A função CountOrders

//+------------------------------------------------------------------+
//|  Count Total Orders for this expert/symbol                             |
//+------------------------------------------------------------------+
int CountOrders()
  {
   int mark=0;

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol) mark++;
        }
     }
   return(mark);
  }

Esta função é usada para obter o total de ordens pendentes disponíveis em um ponto no tempo.

Nós usamos o objeto de nossa classe COrderInfo para checar os detalhes da ordem se foi selecionada com sucesso com a função myorder.Select().

Se o Mágico retorna pelo nosso objeto de classe e o símbolo retornado é o que nós estamos procurando, então a ordem foi executada pelo nosso Consultor Especialista, então ela é contada e armazenada na variável mark.

2.2.3 A função DeletePending

//+------------------------------------------------------------------+
//| Checks and Deletes a pending order                                |
//+------------------------------------------------------------------+
bool DeletePending()
  {
   bool marker=false;
//--- check all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol)
           {
            //--- check if order has stayed more than two bars time
            if(myorder.TimeSetup()<mrate[2].time)
              {
               //--- delete this pending order and check if we deleted this order successfully?
                if(mytrade.OrderDelete(myorder.Ticket())) //Request successfully completed 
                  {
                    Alert("A pending order with ticket #", myorder.Ticket(), " has been successfully deleted!!");
                    marker=true;
                  }
                 else
                  {
                    Alert("The pending order # ",myorder.Ticket(),
                             " delete request could not be completed - error: ",mytrade.ResultRetcodeDescription());
                  }

              }
           }
        }
     }
   return(marker);
  }

Assim como a função countorder, esta função também faz uso das funções de classe COrderInfo para obter as propriedades da ordem. A função checa por qualquer ordem pendente que foi configurada três limites antes (o horário de configuração da ordem pendente é menor do que mrate[2].time) e ainda não foi acionada.

Se quaisquer das ordens cai naquela categoria, a função de classe CTrade OrderDelete é usada para deletar a ordem. Ela retorna verdadeiro nos sucessos e falso em outros casos.

As duas funções acima são usadas imediatamente após um novo limite ser formado, antes de checar por uma nova configuração de negociação. Nós queremos ter certeza que não temos mais do que três ordens pendentes executadas em todos os pontos no tempo. Para fazer isso, usamos o seguinte código:

// do we have more than 3 already placed pending orders
if (CountOrders()>3) 
  {
     DeletePending(); 
     return;  
  }

2.2.4 Executando uma Ordem Pendente

   if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
               ", price:", mytrade.RequestPrice(), 
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Ou nós podemos também usar a função OrderOpen para executar a ordem BUYSTOP

   if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      //if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
              ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Ao executar nossa ordem BUYSTOP, o preço de abertura é Bar 1 High + 2pip + spread.

Lembre que o preço exibido no gráfico é o preço de COMPRA e ao executar ordens longas/compra você precisa do preço de VENDA, e é por isso que decidimos adicionar o spread (diferença) para o Bar 1 High de forma que o que temos agora é o prelo de Venda correspondente + 2pip. O parar perdas e Obter lucros já foi definido nos parâmetros de entrada.

Uma vez que preparamos todos os parâmetros necessários, usamos a função de classe BuyStop de CTrade ou OrderOpen para executar nossa ordem. O Tipo de Ordem aqui é ORDER_TYPE_BUY_STOP (ordem de Parar Perdas). Nós usamos o mesmo preço para o preço limite mas esta não é uma ordem de BuyLimit. Nós também definimos o horário de validade da ordem para ORDER_TIME_GTC o que significa que a ordem continua válida até ser cancelada.

Se você usar ORDER_TIME_GTC ou ORDER_TIME_DAY, não há necessidade de especificar um horário de expiração, é o por quê de definirmos o horário de expiração para 0.

   if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Ou nós podemos também usar a função OrderOpen para executar a ordem:

   if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      //if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
              " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Assim como a ordem de BuyStop, o preço de abertura é Bar 1 low + 2pip. Aqui nós não precisamos adicionar o spread, desde que, normalmente, nós precisamos do preço de COMPRA para executar ordens de curto/venda.

Nós também usamos a mesma função OrderOpen ou a função SellStop para executar a Ordem de SellStop. O tipo de ordem aqui é ORDER_TYPE_SELL_STOP (Ordem de Parar Vendas).

Abaixo estão os resultados de nosso Consultor Especialista simples.


Figura 8. O relatório de teste para a ordem pendente do CE

Figura 9 - O relatório gráfico para o CE

Figura 10. O relatório gráfico para o CE.

2.3 Obtendo detalhes de Ordem/Transação

Neste exemplo, iremos mostrar como nós podemos obter detalhes de uma ordem uma vez que foram acionados.

Neste estágio, não é mais uma ordem pendente porque foi acionada e transformada em uma transação.

Para entender completamente este procedimento, vamos olhar aos detalhes do registro diário de uma de nossas negociações:

Procedimento de processamento de ordem

Figura 11. Procedimento de processamento de ordem

  • Passo 1: Uma ordem pendente é executada aguardando condições serem satisfeitas (ordem Pendente)
  • Passo 2: Condição é satisfeita, ordem pendente é acionada, torna-se uma transação (ordem Pendente agora no histórico)
  • Passo 3: A transação é executada e temos uma posição aberta. (Transação está agora no histórico)

2.3.1 Obtendo Propriedades de Ordem (Histórico)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\HistoryOrderInfo.mqh>
//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECT                                             |
//+------------------------------------------------------------------+
//--- The HistoryOrderInfo Class Object
CHistoryOrderInfo myhistory;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all orders in History and get their details
   int buystop=0;
   int sellstop=0;
   int buylimit=0;
   int selllimit=0;
   int buystoplimit=0;
   int sellstoplimit=0;
   int buy=0;
   int sell=0;

   int s_started=0;
   int s_placed=0;
   int s_cancelled=0;
   int s_partial=0;
   int s_filled=0;
   int s_rejected=0;
   int s_expired=0;

   ulong o_ticket;
// Get all history records
   if(HistorySelect(0,TimeCurrent())) // get all history orders
     {
      // Get total orders in history
      for(int j=HistoryOrdersTotal(); j>0; j--)
        {
         // select order by ticket
         o_ticket=HistoryOrderGetTicket(j);
         if(o_ticket>0)
           {
            // Set order Ticket to work with
            myhistory.Ticket(o_ticket);
            Print("Order index ",j," Order Ticket is: ",myhistory.Ticket()," !");
            Print("Order index ",j," Order Setup Time is: ",TimeToString(myhistory.TimeSetup())," !");
            Print("Order index ",j," Order Open Price is: ",myhistory.PriceOpen()," !");
            Print("Order index ",j," Order Symbol is: ",myhistory.Symbol() ," !");
            Print("Order index ",j," Order Type is: ", myhistory.Type() ," !");
            Print("Order index ",j," Order Type Description is: ",myhistory.TypeDescription()," !");
            Print("Order index ",j," Order Magic is: ",myhistory.Magic()," !");
            Print("Order index ",j," Order Time Done is: ",myhistory.TimeDone()," !");
            Print("Order index ",j," Order Initial Volume is: ",myhistory.VolumeInitial()," !");
            //
            //
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP) buystop++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP) sellstop++;
            if(myhistory.Type() == ORDER_TYPE_BUY) buy++;
            if(myhistory.Type() == ORDER_TYPE_SELL) sell++;
            if(myhistory.Type() == ORDER_TYPE_BUY_LIMIT) buylimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_LIMIT) selllimit++;
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP_LIMIT) buystoplimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP_LIMIT) sellstoplimit++;

            if(myhistory.State() == ORDER_STATE_STARTED) s_started++;
            if(myhistory.State() == ORDER_STATE_PLACED) s_placed++;
            if(myhistory.State() == ORDER_STATE_CANCELED) s_cancelled++;
            if(myhistory.State() == ORDER_STATE_PARTIAL) s_partial++;
            if(myhistory.State() == ORDER_STATE_FILLED) s_filled++;
            if(myhistory.State() == ORDER_STATE_REJECTED) s_rejected++;
            if(myhistory.State() == ORDER_STATE_EXPIRED) s_expired++;
           }
        }
     }
// Print summary
   Print("Buy Stop Pending Orders : ",buystop);
   Print("Sell Stop Pending Orders: ",sellstop);
   Print("Buy Orders : ",buy);
   Print("Sell Orders: ",sell);
   Print("Total Orders in History is :",HistoryOrdersTotal()," !");
   
   Print("Orders type summary");
   Print("Market Buy Orders: ",buy);
   Print("Market Sell Orders: ",sell);
   Print("Pending Buy Stop: ",buystop);
   Print("Pending Sell Stop: ",sellstop);
   Print("Pending Buy Limit: ",buylimit);
   Print("Pending Sell Limit: ",selllimit);
   Print("Pending Buy Stop Limit: ",buystoplimit);
   Print("Pending Sell Stop Limit: ",sellstoplimit);
   Print("Total orders:",HistoryOrdersTotal()," !");

   Print("Orders state summary");
   Print("Checked, but not yet accepted by broker: ",s_started);
   Print("Accepted: ",s_placed);
   Print("Canceled by client: ",s_cancelled);
   Print("Partially executed: ",s_partial);
   Print("Fully executed: ",s_filled);
   Print("Rejected: ",s_rejected);
   Print("Expired: ",s_expired);
  }

Este é apenas um simples script que mostra como obter detalhes de ordens em nosso registro de Histórico. Nós incluímos a classe CHistoryOrderInfo e criamos um objeto da classe.

Nós agora usamos o objeto para obter os detalhes das ordens.

O resultado para o script de histórico-ordem

Figura 12. Resultado do script de histórico de ordens

2.3.2 Obtendo Propriedades de Transação (Histórico)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The CDealInfo Class
#include <Trade\DealInfo.mqh>
//+------------------------------------------------------------------+
//|  Create class object                                             |
//+------------------------------------------------------------------+
//--- The CDealInfo Class Object
CDealInfo mydeal;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all deals in History and get their details
    int buy=0;
    int sell=0;
    int deal_in=0;
    int deal_out=0;
    ulong d_ticket;
    // Get all history records
    if (HistorySelect(0,TimeCurrent())) 
    {
      // Get total deals in history
      for (int j=HistoryDealsTotal(); j>0; j--)
      {
         // select deals by ticket
         if (d_ticket = HistoryDealGetTicket(j))
         {
          // Set Deal Ticket to work with
          mydeal.Ticket(d_ticket);
          Print("Deal index ", j ," Deal Ticket is: ", mydeal.Ticket() ," !");
          Print("Deal index ", j ," Deal Execution Time is: ", TimeToString(mydeal.Time()) ," !");
          Print("Deal index ", j ," Deal Price is: ", mydeal.Price() ," !");
          Print("Deal index ", j ," Deal Symbol is: ", mydeal.Symbol() ," !");
          Print("Deal index ", j ," Deal Type Description is: ", mydeal.TypeDescription() ," !");
          Print("Deal index ", j ," Deal Magic is: ", mydeal.Magic() ," !");
          Print("Deal index ", j ," Deal Time is: ", mydeal.Time() ," !");
          Print("Deal index ", j ," Deal Initial Volume is: ", mydeal.Volume() ," !");
          Print("Deal index ", j ," Deal Entry Type Description is: ", mydeal.EntryDescription() ," !");
          Print("Deal index ", j ," Deal Profit is: ", mydeal.Profit() ," !");
          //
          if (mydeal.Entry() == DEAL_ENTRY_IN) deal_in++;
          if (mydeal.Entry() == DEAL_ENTRY_OUT) deal_out++;
          if (mydeal.Type() == DEAL_TYPE_BUY) buy++;
          if (mydeal.Type() == DEAL_TYPE_SELL) sell++;
         }
      }
    }
    // Print Summary
    Print("Total Deals in History is :", HistoryDealsTotal(), " !");
    Print("Total Deal Entry IN is : ", deal_in);
    Print("Total Deal Entry OUT is: ", deal_out);
    Print("Total Buy Deal is : ", buy);
    Print("Total Sell Deal is: ", sell);
  }

Este é apenas um simples script que mostra como obter detalhes de nossos registros de transações.

O resultado para o script de transação

Figura 13. O resultado do script de transação


Conclusão

Neste artigo, foi possível olhar nas principais funções das bibliotecas de Classe de Negócio padrões e demonstrar como algumas destas funcionalidades podem ser usadas ao escrever Consultores Especializados que implementam modificações de posições, execução de ordens pendentes e eliminação e verificação de margem antes de executar um negócio.

Nós também demonstramos como podem ser usadas para obter detalhes de ordens e transações. Há algumas destas funções que não usamos ao escrever nosso Consultor Especialista, dependendo do tipo de estratégia de negócios que você utiliza, você pode usar mais ou menos do que usamos neste exemplo.

Será uma boa ideia revisar a seção de descrição para várias funções e verificar como você pode usá-las ao escrever seu próprio Consultor Especialista.

As bibliotecas de classe padrão são feitas para facilitar a vida tanto de negociadores quanto de desenvolvedores, portanto certifique-se de usá-las.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/138

Encontrando erros e registrando Encontrando erros e registrando
O MetaEditor 5 possui o recurso de depuração Mas, quando você escreve seus programas MQL5, geralmente você deseja exibir não apenas valores individuais, mas todas as mensagens que aparecem durante o trabalho online e teste. Quando o conteúdo do arquivo de registro tem um tamanho grande, é óbvio automatizar a recuperação rápida e fácil da mensagem requerida. Neste artigo consideraremos várias maneiras de encontrar erros em programas do MQL5 e métodos de registro. Além disso, simplificaremos o logging em arquivos e conheceremos um programa simples LogMon para visualizações confortáveis dos registros.
Usando a função TesterWithdrawal() para Modelar as Retiradas de Lucro Usando a função TesterWithdrawal() para Modelar as Retiradas de Lucro
Este artigo descreve a utilização da função TesterWithDrawal() para estimar riscos nos sistemas de negócio que implicam na remoção de uma determinada parte dos ativos durante sua operação. Além disso, ele descreve o efeito desta função no algoritmo de cálculo do rebaixamento de igualdade no Strategy tester. Esta função é útil quando otimizar parâmetros de seus Expert Advisors.
Simulink: um guia para os desenvolvedores de Expert Advisors Simulink: um guia para os desenvolvedores de Expert Advisors
Não sou um programador profissional. E assim, o princípio de "ir do simples para o complexo" é de suma importância para mim quando trabalho com o desenvolvimento de um sistema de negócio. O que exatamente é simples para mim? Primeiramente, esta é a visualização do processo de criação do sistema e a lógica de seu funcionamento. Também, é um mínimo de código escrito à mão. Neste artigo, tentarei criar e testar o sistema de negócio, com base no pacote Matlab e, depois, escrever um Expert Advisor para o MetaTrader 5. Os dados do histórico do MetaTrader 5 serão usados para o processo de teste.
Como criar rapidamente um Consultor Especialista para o Campeonato de Negociações Automáticas 2010 Como criar rapidamente um Consultor Especialista para o Campeonato de Negociações Automáticas 2010
A fim de desenvolver um especialista para participar no Automated Trading Championship 2010 (Campeonato de Negociações Automáticas 2010), vamos usar um modelo de um conselheiro especialista pronto. Até mesmo um programador MQL5 iniciante será capaz desta tarefa, porque para suas estratégias as classes básicas, funções e modelos já estão desenvolvidos. é suficiente escrever uma quantidade mínima de código para implementar sua ideia de negociação.