Operações de negócios no MQL5 - São fáceis

MetaQuotes | 13 janeiro, 2014

Quase todos os negociadores chegam ao mercado para fazer dinheiro, mas alguns também apreciam o processo em si. No entanto, não é apenas a negociação manual que pode lhe proporcionar uma experiência emocionante. O desenvolvimento de sistemas automatizados de negociação também pode ser bastante impressionante. Criar uma negociação automática pode ser tão interessante quanto ler um bom romance de mistério.

Ao desenvolver um algoritmo de negociação, temos que lidar com muitas questões técnicas, incluindo as mais importantes:

  1. O que negociar?
  2. Quando negociar?
  3. Como negociar?

Precisamos responder a primeira questão para escolher o símbolo mais adequado. A escolha pode ser afetada por vários fatores, incluindo a capacidade de automatizar nosso sistema de negociação para o mercado. A segunda questão envolve a elaboração das regras de negociação, indicando claramente a direção dos negócios, bem como a entrada e saída de pontos. A terceira questão parece ser relativamente simples: como comprar e vender usando alguma linguagem de programação definida?

Neste artigo, vamos considerar como implementar operações de comércio em negociação algorítmica utilizando a linguagem MQL5.


Recursos de MQL5 para negociação algorítmica

MQL5 é uma linguagem de programação de estratégias de negociação com muitas funções comerciais para trabalhar com encomendas, posições e solicitações comerciais. Assim, fazer algorítimos de negociação automática em MQL5 é a tarefa que menos consome trabalho para um desenvolvedor.

Os recursos da MQL5 permitem que você faça um pedido de negociação e o envie para um servidor usando as funções OrderSend() ou OrderSendAsync(), receba seu resultado de processamento, visualize o histórico de negociação, examine a especificação do contrato para um símbolo, lide com um evento de negociação bem como receba outros dados necessários.

Além disso, MQL5 pode ser usada para escrever indicadores técnicos personalizados e aplicar os já implementados, desenhando quaisquer marcas e objetos em um gráfico, desenvolvendo a interface de usuário personalizada, etc. Exemplos de implementação podem ser vistos em vários artigos.


Operações de negócio: Fácil como o ABC!

Existem vários tipos básicos de operações de negócio que podem ser necessárias para a sua negociação automática:

  1. comprar/vender a preços correntes,
  2. colocar uma ordem pendente de compra/venda de acordo com uma determinada condição,
  3. modificar/excluir uma ordem pendente,
  4. fechar/adicionar para reduzir/reverter uma posição.

Todas essas operações são realizadas utilizando a função OrderSend(). Há também uma versão assíncrona chamada OrderSendAsync(). Toda a variedade de operações de negócio é representada pela estrutura MqlTradeRequest contendo a descrição de pedido do negócio. Por tanto, corrigir o preenchimento da estrutura MqlTradeRequest e lidar com resultados da execução de solicitação pode ser um desafio quando se trata de operações de comércio.

De acordo com o seu sistema de negociação, você pode comprar ou vender a preço de mercado (COMPRA ou VENDA), bem como fazer um pedido de compra/venda pendente a uma certa distância em relação ao preço de mercado atual:

Estes tipos de pedidos padrão correspondem a enumeração ENUM_ORDER_TYPE.



Você pode precisar modificar ou excluir um pedido pendente. Isso também pode ser feito usando as funções OrderSend()/OrderSendAsync(). Modificar uma posição aberta também é um processo bastante simples, uma vez que é realizado utilizando as mesmas operações comerciais.

Se você acha que as operações de negócio são complexas e confusas, é questão de tempo até você mudar de ideia. Vamos mostrar não só como codificar compras e vendas em MQL5, de forma rápida e fácil, mas também como trabalhar com uma conta comercial e propriedades de símbolos. As classes de negociação nos ajudarão nessa tarefa.


Verifique sua conta de negociação com CAccountInfo

A primeira coisa que você precisa saber ao lançar sua negociação automática é qual a conta de negociação que será usada para a sua operação. Visto que estamos escrevendo um código de formação, vamos implementar uma verificação para o caso no qual o Expert Advisor foi lançado em uma conta real.

A classe CAccountInfo é usada para trabalhar com uma conta. Nós vamos adicionar a inclusão de arquivos AccountInfo.mqh e declarar a variável da classe - conta:

#include 
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- object for working with the account
   CAccountInfo account;
//--- receiving the account number, the Expert Advisor is launched at
   long login=account.Login();
   Print("Login=",login);
//--- clarifying account type
   ENUM_ACCOUNT_TRADE_MODE account_type=account.TradeMode();
//--- if the account is real, the Expert Advisor is stopped immediately!
   if(account_type==ACCOUNT_TRADE_MODE_REAL)
     {
      MessageBox("Trading on a real account is forbidden, disabling","The Expert Advisor has been launched on a real account!");
      return(-1);
     }
//--- displaying the account type    
   Print("Account type: ",EnumToString(account_type));
//--- clarifying if we can trade on this account
   if(account.TradeAllowed())
      Print("Trading on this account is allowed");
   else
      Print("Trading on this account is forbidden: you may have entered using the Investor password");
//--- clarifying if we can use an Expert Advisor on this account
   if(account.TradeExpert())
      Print("Automated trading on this account is allowed");
   else
      Print("Automated trading using Expert Advisors and scripts on this account is forbidden");
//--- clarifying if the permissible number of orders has been set
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Maximum permissible amount of active pending orders: ",orders_limit);
//--- displaying company and server names
   Print(account.Company(),": server ",account.Server());
//--- displaying balance and current profit on the account in the end
   Print("Balance=",account.Balance(),"  Profit=",account.Profit(),"   Equity=",account.Equity());
   Print(__FUNCTION__,"  completed"); //---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

Como podemos ver no código acima, a abundância de dados úteis podem ser recebidos usando a variável de conta na função OnInit(). Você pode adicionar este código ao seu Expert Advisor para examinar os logs facilmente ao analisar o seu funcionamento.

Os resultados de um Expert Advisor iniciado na conta do Automated Trading Championship 2012, são mostrados abaixo.



Receber definições de símbolo com CSymbolInfo

Agora temos os dados sobre a conta, mas também precisamos conhecer as propriedades do símbolo que vamos negociar, antes de realizar as operações necessárias. A classe CSymbolInfo, com um grande número de métodos é projetada para esses fins. Vamos mostrar apenas uma pequena parte dos métodos no exemplo abaixo.

#include
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- object for receiving symbol settings
   CSymbolInfo symbol_info;
//--- set the name for the appropriate symbol
   symbol_info.Name(_Symbol);
//--- receive current rates and display
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- receive minimum freeze levels for trade operations
   Print("StopsLevel=",symbol_info.StopsLevel()," pips, FreezeLevel=",
         symbol_info.FreezeLevel()," pips");
//--- receive the number of decimal places and point size
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- spread info
   Print("SpreadFloat=",symbol_info.SpreadFloat(),", Spread(current)=",
         symbol_info.Spread()," pips");
//--- request order execution type for limitations
   Print("Limitations for trade operations: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- clarifying trades execution mode
   Print("Trades execution mode: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//--- clarifying contracts price calculation method
   Print("Contract price calculation: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- sizes of contracts
   Print("Standard contract size: ",symbol_info.ContractSize(),
         " (",symbol_info.CurrencyBase(),")");
//--- minimum and maximum volumes in trade operations
   Print("Volume info: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

As propriedades EURUSD no Automated Trading Championship são mostradas abaixo. Agora estamos prontos para realizar as operações de comércio.



CTrade - Classe conveniente para operações de negócio

A negociação de MQL5 é realizada apenas por duas funções - OrderSend() e OrderSendAsync(). Na verdade, estas são duas implementações de uma função. OrderSend() envia um pedido de negociação e aguarda o seu resultado de execução, enquanto o OrderSendAsync() assíncrono apenas envia uma solicitação permitindo a aplicação de continuar sua operação, sem esperar por uma resposta do servidor de negociação. Assim, é muito fácil de negociar em MQL5, já que você usa apenas uma função para todas as operações de comércio.

Então, qual é o desafio? Ambas as funções recebem a estrutura MqlTradeRequest contendo mais de uma dezena de campos como primeiro parâmetro. Nem todos os campos devem ser obrigatoriamente preenchidos. O conjunto dos necessários dependem do tipo de operação de negócio. Um valor incorreto ou um campo em branco, que é necessário para ser preenchido, resultará num erro e o pedido não será enviado para um servidor. 5 desses campos exigem valores corretos de enumerações predefinidas.

Tal grande número de campos é necessário para a descrição de muitas propriedades de pedidos em uma solicitação de negócio. As ordens podem mudar dependendo da política de execução, tempo de validade e alguns outros parâmetros. Mas você não tem que aprender todas essas sutilezas. Basta usar a classe CTrade já pronta. É assim que a classe pode ser usada em sua negociação automática:

#include
//--- object for performing trade operations
CTrade  trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- set MagicNumber for your orders identification
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- set available slippage in points when buying/selling
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- order filling mode, the mode allowed by the server should be used
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- logging mode: it would be better not to declare this method at all, the class will set the best mode on its own
   trade.LogLevel(1); 
//--- what function is to be used for trading: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

Agora vamos ver como CTrade ajuda em operações comerciais.

Compra/venda a preços correntes

As estratégias de negociação muitas vezes oferecem a possibilidade de comprar ou vender a preço corrente no momento. Neste caso, CTrade só pede para especificar um volume de operação comercial necessário. Todos os outros parâmetros (preço de abertura e nome do símbolo, níveis Stop Loss e Take Profit, comentários de pedidos) são opcionais.

//--- 1. example of buying at the current symbol
   if(!trade.Buy(0.1))
     {
      //--- failure message
      Print("Buy() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Por padrão, CTrade usará o nome do símbolo do gráfico que foi lançado se o nome do símbolo não é especificado. É conveniente para as estratégias simples. Para estratégias múltiplas você sempre deve especificar explicitamente o símbolo para que a operação comercial seja realizada.

//--- 2. example of buying at the specified symbol
   if(!trade.Buy(0.1,"GBPUSD"))
     {
      //--- failure message
      Print("Buy() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Todos os parâmetros de pedido podem ser especificados: Níveis Stop Loss/Take Profit, preço aberto e comentários.

//--- 3. example of buying at the specified symbol with specified SL and TP
   double volume=0.1;         // specify a trade operation volume
   string symbol="GBPUSD";    //specify the symbol, for which the operation is performed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double bid=SymbolInfoDouble(symbol,SYMBOL_BID);             // current price for closing LONG
   double SL=bid-1000*point;                                   // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                              // normalizing Stop Loss
   double TP=bid+1000*point;                                   // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                              // normalizing Take Profit
//--- receive the current open price for LONG positions
   double open_price=SymbolInfoDouble(symbol,SYMBOL_ASK);
   string comment=StringFormat("Buy %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(open_price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
   if(!trade.Buy(volume,symbol,open_price,SL,TP,comment))
     {
      //--- failure message
      Print("Buy() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Como já dissemos, o Magic Number e a deslizagem permitida foram definidos ao inicializar uma cópia com Ctrade. Portanto, eles não são necessários. No entanto, eles também podem ser definidos antes de cada operação de comercial, se necessário.

Colocando um pedido limite

O método da classe BuyLimit() ou SellLimit() apropriado é usado para o envio de um pedido limite. A versão abreviada (quando apenas um preço de abertura e um volume são especificados) será adequada na maioria dos casos. O preço aberto para Buy Limit deve ser menor do que o preço atual, ao mesmo tempo que deve ser maior para o Sell Limit. Esses pedidos são usados para entrar no mercado com o melhor preço e geralmente são mais adequados para as estratégias esperando o salto de preços a partir da linha de suporte. O símbolo, em que um Expert Advisor tiver sido iniciado, é utilizado nesse caso:

//--- 1. example of placing a Buy Limit pending order
   string symbol="GBPUSD";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                   // unnormalized open price
   price=NormalizeDouble(price,digits);                       // normalizing open price
//--- everything is ready, sending a Buy Limit pending order to the server
   if(!trade.BuyLimit(0.1,price))
     {
      //--- failure message
      Print("BuyLimit() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyLimit() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Versão mais detalhada com especificação de todos os parâmetros também podem ser utilizada: Níveis de SL/TP, tempo de validade, nome do símbolo e comentários para o pedido.

//--- 2. example of placing a Buy Limit pending order with all parameters
   double volume=0.1;
   string symbol="GBPUSD";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                 // unnormalized open price
   price=NormalizeDouble(price,digits);                      // normalizing open price
   int SL_pips=300;                                         // Stop Loss in points
   int TP_pips=500;                                         // Take Profit in points
   double SL=price-SL_pips*point;                           // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                            // normalizing Stop Loss
   double TP=price+TP_pips*point;                           // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                            // normalizing Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- everything is ready, sending a Buy Limit pending order to the server
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- failure message
      Print("BuyLimit() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyLimit() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Sua tarefa na segunda versão é indicar os níveis de TP e SL corretamente. Deve-se notar que o nível de Take Profit deve ser superior ao preço de abertura no momento da compra, enquanto o nível de Stop Loss deve ser inferior ao preço de abertura. A situação inversa é para encomendas de Sell Limit. Você pode facilmente conhecer o seu erro ao testar um Expert Advisor em dados históricos. Nestes casos a classe CTrade exibe automaticamente mensagens (a menos que tenha chamado a função LogLevel).

Colocando um ordem de parada

Os métodos similares BuyStop() e SellStop() são usados para enviar uma ordem de parada. O preço aberto para Buy Stop deve ser mais elevado do que o preço corrente, ao mesmo tempo que deve ser menor para Sell Stop. As ordens de parada são usadas em estratégias que entram no mercado durante uma quebra de nível de resistência, assim como para conter perdas. Versão simples:

//--- 1. example of placing a Buy Stop pending order
   string symbol="USDJPY";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                    // unnormalized open price
   price=NormalizeDouble(price,digits);                        // normalizing open price
//--- everything is ready, sending a Buy Stop pending order to the server 
   if(!trade.BuyStop(0.1,price))
     {
      //--- failure message
      Print("BuyStop() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyStop() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

A versão mais detalhada quando a quantidade máxima de parâmetros para Buy Stop pendente deve ser especificada:

//--- 2. example of placing a Buy Stop pending order with all parameters
   double volume=0.1;
   string symbol="USDJPY";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                   // unnormalized open price
   price=NormalizeDouble(price,digits);                       // normalizing open price
   int SL_pips=300;                                          // Stop Loss in points
   int TP_pips=500;                                          // Take Profit in points
   double SL=price-SL_pips*point;                            // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                             // normalizing Stop Loss
   double TP=price+TP_pips*point;                            // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                             // normalizing Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Stop %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- everything is ready, sending a Buy Stop pending order to the server 
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- failure message
      Print("BuyStop() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyStop() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

O método da classe CTrade apropriado é usado para enviar um pedido de Sell Stop. Especificar os preços corretamente é de suma importância aqui.

Trabalhando com posições

Você pode usar os métodos de abertura de posição em vez dos Buy() e Sell(), mas você terá que especificar mais detalhes deste caso:

//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- receiving a buy price
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- calculate and normalize SL and TP levels
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- filling comments
   string comment="Buy "+_Symbol+" 0.1 at "+DoubleToString(price,digits);
//--- everything is ready, trying to open a buy position
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,price,SL,TP,comment))
     {
      //--- failure message
      Print("PositionOpen() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionOpen() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Você precisa especificar apenas o nome do símbolo, o resto será feito pela classe CTrade.

//--- closing a position at the current symbol
   if(!trade.PositionClose(_Symbol))
     {
      //--- failure message
      Print("PositionClose() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionClose() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Apenas os níveis Stop Loss e Take Profit estão disponíveis para modificar uma posição aberta. Isto é feito usando o método PositionModify()

//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- receiving the current Bid price
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- calculate and normalize SL and TP levels
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- everything is ready, trying to modify the buy position
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- failure message
      Print("Метод PositionModify() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionModify() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Modificando e excluindo um pedido

O método OrderModify() foi implementado na classe CTrade para mudar os parâmetros de ordens pendentes. Todos os parâmetros necessários devem ser submetidos a este método.

//--- this is a sample order ticket, it should be received
   ulong ticket=1234556;
//--- this is a sample symbol, it should be received
   string symbol="EURUSD";
//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- receiving a buy price
   double price=SymbolInfoDouble(symbol,SYMBOL_ASK);
//--- calculate and normalize SL and TP levels
//--- they should be calculated based on the order type
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
   //--- setting one day as a lifetime
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);   
//--- everything is ready, trying to modify the order 
   if(!trade.OrderModify(ticket,price,SL,TP,ORDER_TIME_GTC,expiration))
     {
      //--- failure message
      Print("OrderModify() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("OrderModify() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Você deve receber o bilhete do pedido que deve ser mudado. Níveis corretos de Stop Loss e Take Profit devem ser especificados de acordo com os seus tipos. Além disso, o novo preço de abertura também deveria estar correto em relação ao preço atual.

Você deve conhecer o bilhete de uma ordem para excluí-lo:

//--- this is a sample order ticket, it should be received
   ulong ticket=1234556;
//--- everyrging is ready, trying to modify a buy position
   if(!trade.OrderDelete(ticket))
     {
      //--- failure message
      Print("OrderDelete() method failed. Return code=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("OrderDelete() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

A classe também contém o método OrderOpen() multiuso que pode definir os pedidos pendentes de qualquer tipo. Ao contrário dos métodos BuyLimit, BuyStop, SellLimit e SellStop especializados, ela requer a especificação dos parâmetros mais essenciais. Talvez, você achará mais conveniente.


O que mais deve ser resolvido?

Então, temos respondido duas das três perguntas. Você escolheu o símbolo para a sua estratégia e nós mostramos-lhe como codificar operações de compra e venda facilmente, bem como ordens pendentes em uma negociação automática. Mas a seção da classe de negociação tem algumas ferramentas mais úteis para os desenvolvedores da MQL5:

Com essas classes, você pode concentrar sua atenção sobre o lado comercial de sua estratégia minimizando todas as questões técnicas. Além disso, a classe CTrade pode ser usada para analisar os pedidos comerciais. Depois de alguma prática, você será capaz de usá-lo para criar suas classes personalizadas com lógicas necessárias de manuseio dos resultados de execução de pedidos de negócio.

A última questão é a como receber sinais de negociação e como codificar isso na MQL5. A maioria dos recém chegados na negociação de algoritmo começam a partir dos sistemas de negociação padrão simples, por exemplo, aqueles baseados no cruzamento da média em movimento. Para fazer isso, você deve primeiro aprender a trabalhar com a criação de indicadores técnicos e usá-los em sua negociação automática.

Recomendamos que você leia os artigos a partir das seçõesIndicators e Examples->Indicators começando desde os primeiros. Isso permitirá que você se mova desde as mais simples para as questões mais complexas. Se você quer receber rapidamente uma ideia sobre como usar indicadores, veja MQL5 para iniciantes: Guia para o uso de indicadores técnicos em Expert Advisors.


Tornar coisas complicadas simples

Em qualquer empreendimento, as primeiras dificuldades gradualmente se tornam problemas mais simples que você tem que lidar. Os métodos para desenvolver robôs de negócio oferecidos aqui são destinados principalmente para iniciantes, embora muitos desenvolvedores experientes possam encontrar algo novo e útil.

A linguagem MQL5 fornece não só oportunidades ilimitadas para algoritmos de negociação, mas também permite que todos possam implementá-la da maneira mais simples e rápida. Use as classes comerciais da biblioteca padrão para economizar tempo para coisas mais importantes, como por exemplo, para procurar a resposta para a eterna questão de todos os comerciantes - o que é uma tendência e como ela pode ser encontrada em tempo real.

Logo você verá que o desenvolvimento de uma negociação automática em MQL5 é muito mais fácil do que aprender uma língua estrangeira ou seguir uma tendência!