
Operações de negócios no MQL5 - São fáceis
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:
- O que negociar?
- Quando negociar?
- 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:
- comprar/vender a preços correntes,
- colocar uma ordem pendente de compra/venda de acordo com uma determinada condição,
- modificar/excluir uma ordem pendente,
- 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:
- BUY STOP, SELL STOP - compra ou venda, no caso de um deslocamento específico de nível (pior do que o preço atual);
- BUY LIMIT, SELL LIMIT - compra ou venda, no caso de um nível específico são atingidas (melhor do que o preço atual);
- BUY STOP LIMIT, SELL STOP LIMIT - definição de BUY LIMIT ou SEEL LIMIT no caso de um preço específico são atingidos.
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:
- COrderInfo - para trabalhar com pedidos;
- CHistoryOrderInfo - para trabalhar com pedidos executados no histórico de negociação;
- CPositionInfo - para trabalhar com posições;
- CDealInfo - para trabalhar com negócios;
- CTerminalInfo - para receber dados no terminal (este aqui é bem interessante).
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!
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/481





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Bom dia a todos!
Continuo estudando a linguagem de programação MQL5. Pesquisei quase todo o site em busca de informações úteis para mim. A maioria das informações encontradas no site é destinada a pessoas que já têm um conhecimento básico de programação.
E aqui! Encontrei outro ótimo artigo, que me ajudou a entender e refinar meu Expert Advisor! É uma pena que o autor não tenha continuado a escrever essa série de artigos e tenha se limitado apenas a 2012. Mas, mesmo assim, expresso grande respeito a esse homem e digo a ele o mesmo GRANDE OBRIGADO em nome de todos os iniciantes!
Com todo o respeito, Vladimir.
Olá, obrigado por essa postagem muito útil e, por favor, ajude-me a resolver esse problema. Sou novo no MT5 e estou aprendendo a criar EAs, então copiei o código de exemplo para executar o Ctrade.Buy, mas o backtest falhou. Aqui estão mais informações:
1) Conta: É uma conta real com a moeda base como NZD
2) Configurações do MetaEditor para o backtest:
3) Código: Copiado de https://www.mql5.com/pt/articles/481:
//+------------------------------------------------------------------+
//| demo.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#include<Trade\Trade.mqh>
//--- 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 execution mode
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);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
BuySample1();
}
//--- Buy sample
//+------------------------------------------------------------------+
//| Buying a specified volume at the current symbol |
//+------------------------------------------------------------------+
void BuySample1()
{
//--- 1. example of buying at the current symbol
if(!trade.Buy(0.1))
{
//--- failure message
Print("Buy() method failed. Return code=",trade.ResultRetcode(),
". Code description: ",trade.ResultRetcodeDescription());
}
else
{
Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
" (",trade.ResultRetcodeDescription(),")");
}
//---
}
4) Registro de erros (observe que estou testando apenas em EUR/USD):
GJ 0 19:36:44.410 127.0.0.1 login (build 1730)
HH 0 19:36:44.420 Rede 38520 bytes de informações da conta carregadas
JO 0 19:36:44.420 Rede 1482 bytes de parâmetros do testador carregados
QE 0 19:36:44.420 Rede 188 bytes de parâmetros de entrada carregados
FR 0 19:36:44.421 Rede 443 bytes de lista de símbolos carregados
IF 0 19:36:44.421 Arquivo de especialista do testador adicionado: Experts\demo.ex5. 46684 bytes carregados
QH 0 19:36:44.433 Depósito inicial do testador 10000.00 NZD, alavancagem 1:100
JN 0 19:36:44.437 Testador inicializado com sucesso
ES 0 19:36:44.437 Rede 46 Kb de dados totais de inicialização recebidos
PP 0 19:36:44.437 Testador Intel Core i7-4510U @ 2.00GHz, 8103 MB
RJ 0 19:36:44.799 Símbolos EURUSD: símbolo a ser sincronizado
HR 0 19:36:44.800 Símbolos EURUSD: símbolo sincronizado, 3624 bytes de informações de símbolo recebidas
NJ 0 19:36:44.800 Histórico EURUSD: sincronização do histórico iniciada
GO 0 19:36:44.856 Histórico EURUSD: carregar 27 bytes de dados do histórico para sincronizar em 0:00:00.000
RQ 0 19:36:44.856 Histórico EURUSD: histórico sincronizado de 2012.01.01 a 2017.11.15
EF 0 19:36:44.993 Histórico EURUSD,Daily: cache do histórico alocado para 1010 barras e contém 312 barras de 2014.01.01 00:00 a 2014.12.31 00:00
ND 0 19:36:44.993 Histórico EURUSD,Diário: histórico começa a partir de 2014.01.01 00:00
OL 0 19:36:44.996 Testador EURUSD,Daily (HalifaxPlus-Live): geração de cada tick
GN 0 19:36:44.996 Testador EURUSD,Daily: teste de Experts\demo.ex5 de 2015.01.01 00:00 a 2017.11.15 00:00 iniciado
CK 0 19:36:56.288 Symbols NZDUSD: símbolo a ser sincronizado
IS 0 19:36:56.288 Símbolos NZDUSD: símbolo sincronizado, 3624 bytes de informação de símbolo recebidos
JL 0 19:36:56.288 Histórico NZDUSD: sincronização do histórico iniciada
HJ 0 19:36:56.575 Histórico NZDUSD: carregar 14 Kb de dados do histórico para sincronizar em 0:00:00.078
LS 0 19:36:56.575 Histórico NZDUSD: histórico sincronizado de 2013.01.01 a 2017.11.15
CO 0 19:36:56.579 Símbolos EURNZD: símbolo a ser sincronizado
OJ 0 19:36:56.580 Símbolos EURNZD: símbolo sincronizado, 3624 bytes de informação de símbolo recebidos
DL 0 19:36:56.580 Histórico EURNZD: sincronização do histórico iniciada
MK 0 19:36:56.656 Histórico EURNZD: carregar 27 bytes de dados do histórico para sincronizar em 0:00:00.000
OD 0 19:36:56.656 Histórico EURNZD: histórico sincronizado de 2013.01.01 a 2017.11.15
IN 0 19:36:56.665 Trade 2015.01.02 03:00:00 market buy 0.10 EURUSD (1.20538 / 1.20549 / 1.20538)
PE 0 19:36:56.665 Trades 2015.01.02 03:00:00 deal #2 buy 0.10 EURUSD at 1.20549 done(based on order #2)
FH 0 19:36:56.666 Negociação 2015.01.02 03:00:00 negócio realizado [#2 comprar 0.10 EURUSD a 1.20549]
OG 0 19:36:56.666 Trade 2015.01.02 03:00:00 ordem executada comprar 0.10 em 1.20549 [#2 comprar 0.10 EURUSD em 1.20549]
FO 0 19:36:56.670 demo (EURUSD,D1) 2015.01.02 03:00:00 Buy() method executed successfully. Código de retorno=10009 (realizado em 1.20549)
NM 2 19:37:15.823 Histórico NZDUSD 2016.09.21 23:01:00: histórico corrompido detectado (s:-73370, o:73433, h:+48, l:-123, c:-117 -- tv:63, rv:11250111)
JF 2 19:37:15.823 Histórico NZDUSD 2016.09.21, contêiner ruim encontrado, deve ser ressincronizado
LQ 2 19:37:16.106 Erro 9 no histórico do testador em uma função indefinida
OH 2 19:37:16.106 O testador parou em 0% do intervalo de teste com o erro '20 NZDUSD'
Por favor, diga-me o que está errado e como posso resolver isso?
Olá, obrigado por essa postagem muito útil e, por favor, ajude-me a resolver esse problema. Sou novo no MT5 e estou aprendendo a criar EAs, então copiei o código de exemplo para executar o Ctrade.Buy, mas o backtest falhou. Aqui estão mais informações:
1) Conta: É uma conta real com a moeda base como NZD
2) Configurações do MetaEditor para o backtest:
3) Código: Copiado de https://www.mql5.com/pt/articles/481:
//+------------------------------------------------------------------+
//| demo.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#include<Trade\Trade.mqh>
//--- 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 execution mode
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);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
BuySample1();
}
//--- Buy sample
//+------------------------------------------------------------------+
//| Buying a specified volume at the current symbol |
//+------------------------------------------------------------------+
void BuySample1()
{
//--- 1. example of buying at the current symbol
if(!trade.Buy(0.1))
{
//--- failure message
Print("Buy() method failed. Return code=",trade.ResultRetcode(),
". Code description: ",trade.ResultRetcodeDescription());
}
else
{
Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
" (",trade.ResultRetcodeDescription(),")");
}
//---
}
4) Registro de erros (observe que estou testando apenas em EUR/USD):
GJ 0 19:36:44.410 127.0.0.1 login (build 1730)
HH 0 19:36:44.420 Rede 38520 bytes de informações da conta carregadas
JO 0 19:36:44.420 Rede 1482 bytes de parâmetros do testador carregados
QE 0 19:36:44.420 Rede 188 bytes de parâmetros de entrada carregados
FR 0 19:36:44.421 Rede 443 bytes de lista de símbolos carregados
IF 0 19:36:44.421 Arquivo de especialista do testador adicionado: Experts\demo.ex5. 46684 bytes carregados
QH 0 19:36:44.433 Depósito inicial do testador 10000.00 NZD, alavancagem 1:100
JN 0 19:36:44.437 Testador inicializado com sucesso
ES 0 19:36:44.437 Rede 46 Kb de dados totais de inicialização recebidos
PP 0 19:36:44.437 Testador Intel Core i7-4510U @ 2.00GHz, 8103 MB
RJ 0 19:36:44.799 Símbolos EURUSD: símbolo a ser sincronizado
HR 0 19:36:44.800 Símbolos EURUSD: símbolo sincronizado, 3624 bytes de informações de símbolo recebidas
NJ 0 19:36:44.800 Histórico EURUSD: sincronização do histórico iniciada
GO 0 19:36:44.856 Histórico EURUSD: carregar 27 bytes de dados do histórico para sincronizar em 0:00:00.000
RQ 0 19:36:44.856 Histórico EURUSD: histórico sincronizado de 2012.01.01 a 2017.11.15
EF 0 19:36:44.993 Histórico EURUSD,Daily: cache de histórico alocado para 1010 barras e contém 312 barras de 2014.01.01 00:00 a 2014.12.31 00:00
ND 0 19:36:44.993 Histórico EURUSD,Diário: histórico começa a partir de 2014.01.01 00:00
OL 0 19:36:44.996 Testador EURUSD,Daily (HalifaxPlus-Live): geração de cada tick
GN 0 19:36:44.996 Testador EURUSD,Daily: teste de Experts\demo.ex5 de 2015.01.01 00:00 a 2017.11.15 00:00 iniciado
CK 0 19:36:56.288 Symbols NZDUSD: símbolo a ser sincronizado
IS 0 19:36:56.288 Símbolos NZDUSD: símbolo sincronizado, 3624 bytes de informação de símbolo recebidos
JL 0 19:36:56.288 Histórico NZDUSD: sincronização do histórico iniciada
HJ 0 19:36:56.575 Histórico NZDUSD: carregar 14 Kb de dados do histórico para sincronizar em 0:00:00.078
LS 0 19:36:56.575 Histórico NZDUSD: histórico sincronizado de 2013.01.01 a 2017.11.15
CO 0 19:36:56.579 Símbolos EURNZD: símbolo a ser sincronizado
OJ 0 19:36:56.580 Símbolos EURNZD: símbolo sincronizado, 3624 bytes de informação de símbolo recebidos
DL 0 19:36:56.580 Histórico EURNZD: sincronização do histórico iniciada
MK 0 19:36:56.656 Histórico EURNZD: carregar 27 bytes de dados do histórico para sincronizar em 0:00:00.000
OD 0 19:36:56.656 Histórico EURNZD: histórico sincronizado de 2013.01.01 a 2017.11.15
IN 0 19:36:56.665 Trade 2015.01.02 03:00:00 market buy 0.10 EURUSD (1.20538 / 1.20549 / 1.20538)
PE 0 19:36:56.665 Trades 2015.01.02 03:00:00 deal #2 buy 0.10 EURUSD at 1.20549 done(based on order #2)
FH 0 19:36:56.666 Negociação 2015.01.02 03:00:00 negócio realizado [#2 comprar 0.10 EURUSD a 1.20549]
OG 0 19:36:56.666 Trade 2015.01.02 03:00:00 ordem executada comprar 0.10 em 1.20549 [#2 comprar 0.10 EURUSD em 1.20549]
FO 0 19:36:56.670 demo (EURUSD,D1) 2015.01.02 03:00:00 Buy() method executed successfully. Código de retorno=10009 (realizado em 1.20549)
NM 2 19:37:15.823 Histórico NZDUSD 2016.09.21 23:01:00: histórico corrompido detectado (s:-73370, o:73433, h:+48, l:-123, c:-117 -- tv:63, rv:11250111)
JF 2 19:37:15.823 Histórico NZDUSD 2016.09.21, contêiner ruim encontrado, deve ser ressincronizado
LQ 2 19:37:16.106 Erro 9 no histórico do testador em uma função indefinida
OH 2 19:37:16.106 O testador parou em 0% do intervalo de teste com o erro '20 NZDUSD'
Por favor, diga-me o que está errado e como posso resolver isso?
No artigo, ao abrir ordens de limite e de parada em qualquer lugar
Será que aqueles que escrevem que o artigo os ajudou a inserir o código do artigo?