English Русский 中文 Español Deutsch 日本語
Por onde começar ao criar um robô de negociação para operar na Bolsa de Valores de Moscou MOEX

Por onde começar ao criar um robô de negociação para operar na Bolsa de Valores de Moscou MOEX

MetaTrader 5Exemplos | 23 agosto 2016, 11:04
3 991 0
MetaQuotes
MetaQuotes

Na Bolsa de Valores de Moscou, muitos traders gostariam de automatizar seus algoritmos de negociação, mas não sabem por onde começar. A linguagem MQL5 não só oferece uma enorme gama de funções de negociação, mas também classes prontas que facilitam os primeiros passos no mundo do trading algorítmico. Neste artigo, mostraremos quais recursos prontos oferece a linguagem de estratégias de negociação MQL5 aos algo-traders na Bolsa de Valores de Moscou.

Existem dois tipos ordens de negociação na Bolsa de Valores de Moscou MOEX

  A Bolsa de Valores de Moscou suporta dois tipos de ordens de negociação, isto é, ordens de mercado e limite.
  • As ordens de mercado são entregues imediatamente à bolsa de valores e executadas ao melhor preço disponível. Para envias estas ordens para a MQL5, usam-se ordens de mercado do tipo ORDER_TYPE_BUY e ORDER_TYPE_SELL.
  • As ordens limite são armazenadas no servidor da bolsa, elas são executadas assim que aparece uma ordem oposta apropriada. Na linguagem MQL5, estas ordens são representadas por dois tipos de ordens, isto é,ORDER_TYPE_BUY_LIMIT e ORDER_TYPE_SELL_LIMIT.

A ordem de mercado garante a transação (mas nem sempre), porém não garante o preço. Isto significa que o preço da transação pode diferir significativamente da oferta atual. Uma ordem limite garante o preço, mas não garante a execução da operação segundo esse preço. Como resultado, sua ordem pode não ser executada.

Todos os outros tipos de ordens - que são oferecidos aos traders da Bolsa de Valores de Moscou - são parte do software através do qual esses traders podem interagir com a bolsa. Em outras palavras, as restantes ordens são algorítmicas. Elas são armazenadas e processadas fora da Bolsa de Valores de Moscou, bem como enviadas para essa bolsa na forma de ordens de mercado ou limite como resultado de um processamento interno.

A plataforma MetaTrader 5 oferece aos traders os seguintes tipos de ordens de negociação, eles podem ser utilizados para negociação na Bolsa de Valores de Moscou:

Identificador Descrição Armazenamento e execução

ORDER_TYPE_BUY

Ordem de mercado para compra

A ordem se envia à bolsa de valores como uma ordem de mercado para comprar ao melhor preço de venda disponível

ORDER_TYPE_SELL

Ordem de mercado para venda

A ordem se envia à bolsa de valores como uma ordem de mercado para vender ao melhor preço de compra disponível

ORDER_TYPE_BUY_LIMIT

Ordem pendente Buy Limit

A ordem se envia à bolsa de valores como uma ordem limite para comprar e se executa assim que aparecer uma oferta de venda quer ao melhor preço de venda disponível quer ao preço estabelecido

ORDER_TYPE_SELL_LIMIT

Ordem pendente Sell Limit

A ordem se envia à bolsa de valores como uma ordem limite para vender e se executa assim que aparecer uma oferta de compra quer ao melhor preço de compra disponível quer ao preço estabelecido

ORDER_TYPE_BUY_STOP

Ordem pendente Buy Stop

A ordem se armazena no servidor da MetaTrader 5, e assim que se executa, envia-se à bolsa:
  • para mercados de moedas e de valores mobiliários, a ordem se envia como ordem de mercado para compra
  • para FORTS, a ordem se envia como ordem limite para compra ao pior preço de fronteira do canal

ORDER_TYPE_SELL_STOP

Отложенный ордер Sell Stop

A ordem se armazena no servidor da MetaTrader 5, e assim que se executa, envia-se à bolsa:
  • para mercados de moedas e de valores mobiliários, a ordem se envia como ordem de mercado para venda
  • para FORTS, a ordem se envia como ordem limite para venda ao pior preço de fronteira do canal

ORDER_TYPE_BUY_STOP_LIMIT

Ordem pendente BUY STOP LIMIT

A ordem se armazena no servidor da MetaTrader 5, e assim que se executa, envia-se como uma ordem limite para compra

ORDER_TYPE_SELL_STOP_LIMIT

Ordem pendente SELL STOP LIMIT

A ordem se armazena no servidor da MetaTrader 5, e assim que se executa, envia-se como uma ordem limite para venda

A plataforma MetaTrader 5 permite definir os níveis TakeProfit e StopLoss para posições abertas. Os níveis são armazenados no servidor de negociação da MetaTrader 5 e são executados automaticamente, mesmo sem conexão à conta de negociação:

  • o nível TakeProfit define o preço para fechar a posição em uma direção favorável, assim que ele se executa, a ordem limite se envia para a bolsa ao preço TakeProfit;
  • o nível StopLoss serve para implementar um stop de proteção em uma direção desfavorável, assim que ele se executa, a ordem limite se envia para a bolsa ao preço StopLoss para mercados de moedas e de valores mobiliários, enquanto para FORTS, se envia uma ordem limite ao pior preço de fronteira do canal.

Além disso, a plataforma MetaTrader 5 permite definir e modificar os níveis StopLoss/TakeProfit para posições pendentes, bem como modificar os níveis de execução de todas as ordens pendentes.


Operações de negociação na MetaTrader 5

A MetaTrader 5 proporciona alguns tipos básicos de operações de negociação que podem ser necessários em seu robô de negociação:

  1. compra/venda ao preço atual;
  2. colocação de uma ordem pendente para compra/venda sob certa condição;
  3. modificação/exclusão de uma ordem pendente;
  4. fechamento/aumento/redução/inversão da posição.

Na MQL5, todas as operações de negociação são implementadas com ajuda da função OrderSend(), ela retorna o controle do programa, após enviar com sucesso a ordem de negociação para a Bolsa de Valores de Moscou. Nesse momento, o estado da ordem muda para o valor ORDER_STATE_PLACED, porém isso não significa que sua ordem será executada com sucesso (o estado dessa ordem mudará para ORDER_STATE_FILLED ou ORDER_STATE_PARTIAL). O resultado final da execução de seu pedido de negociação depende do mercado atual, e a ordem pode ser rejeitada pela bolsa (estado ORDER_STATE_REJECTED) por razões diferentes.

Aliás, a OrderSendAsync(), que é uma versão assíncrona desta função, trabalha mais rápido do que a OrderSend(), uma vez que não espera o envio da ordem para o sistema de a bolsa. A resposta a esta função se envia assim que o pedido é enviado pelo terminal MetaTrader 5 para o lado de fora. Isso significa que seu pedido de negociação passou a verificação básica no terminal, e agora foi enviado para processamento no servidor de negociação da MetaTrader 5. O tempo necessário para adicionar seu pedido à fila de espera da bolsa e o momento em que a ordem será executada ou rejeitada dependem da carga de trabalho da bosa de valores e de quão rápida é sua conexão de Internet.

A grande variedade de operações de negociação é descrita pela estrutura MqlTradeRequest, ela contém a descrição do pedido de negociação. Por isso, a única dificuldade aqui é preencher corretamente a estrutura MqlTradeRequest e processar o resultado da execução do pedido.

De acordo com as regras de seu sistema de negociação, você pode fazer uma compra ou uma venda ao preço de mercado (BUY ou SELL), ou pode colocar uma ordem pendente para executar a compra/venda a uma certa distância do preço atual de mercado:

  • BUY STOP, SELL STOP — compra o venda uma vez o preço rompe o nível especificado (pior do que o preço atual). As ordens deste tipo são armazenadas no servidor da MetaTrader 5 e são enviadas para a Bolsa de Valores de Moscou assim que a ordem é executada, ela é enviada como ordem de mercado (mercados de moedas e valores mobiliários) ou ordem limite (FORTS).
  • BUY LIMIT, SELL LIMIT — compra ou venda uma vez o nível especificado é atingido (melhor preço atual). As ordens deste tipo são enviadas para a Bolsa de Valores de Moscou na forma de ordem limite. Deve-se notar que, na Bolsa de Valores de Moscou, você pode especificar, na ordem limite, o nível dentro do spread, ou mesmo no verso do spread. Isso ajuda a limitar a derrapagem (slippage) durante a execução da transação.
  • BUY STOP LIMIT, SELL STOP LIMIT — colocação da ordem BUY LIMIT ou SELL LIMIT uma vez o preço especificado é atingido. As ordens deste tipo são armazenadas no servidor da MetaTrader 5, e, uma vez a ordem é executada, para a Bolsa de Valores de Moscou é enviada uma ordem limite habitual. O nível de abertura dessa ordem limite pode ser tanto superior quanto inferior ao preço de execução da ordem.

A seguinte figura apresenta o princípio de uso das ordens BUY STOP, SELL STOP e BUY LIMIT, SELL LIMIT, bem como as maneiras de colocá-las a partir do livro de ofertas.


Além disso, você pode precisar modificar ou mesmo eliminar uma ordem pendente. Isto também é feito com a ajuda das funções OrderSend()/OrderSendAsync(). Trabalhar com a posição aberta também não é difícil, pois ocorre como resultado das mesmas operações de negociação.

Neste artigo, mostraremos quão simples e fácil é programar a compra e venda na MQL5, demonstraremos como trabalhar com uma conta de negociação e propriedades dos símbolos. Para fazer isso, serão úteis as classes de negociação da Biblioteca Padrão.

Negociar na bolsa de valores com a ajuda de robôs é fácil

A linguagem MQL5 suporta nativamente todas os recursos de negociação da plataforma MetaTrader 5, nela há muitas funções de negociação para trabalhar com ordens, posições e pedidos de negociação. Além disso, as operações são sempre as mesmas, não importa o que você esteja negociando: títulos, futuros, títulos, opções, etc.

Com ajuda dos recursos da MQL5, você pode criar uma ordem de negociação e enviá-la para o servidor usando a função OrderSend() ou OrderSendAsync(), obter o resultado de sua execução, observar o histórico de negociação, conferir as especificações do contrato para o instrumento, manipular um evento de negociação e obter outras informações úteis.

Para os desenvolvedores de robôs de negociação, é importante compreender: cada transação de negociação quer a abertura de uma posição quer a colocação de StopLoss ou TakeProfit quer o fechamento de uma posição pela transação oposta sempre abarca um conjunto de transações realizadas no servidor da MetaTrader 5 e na Bolsa de Valores de Moscou. Para ver como isso acontece, você pode executar, em sua conta, o conselheiro (EA)TradeTransactionListener.mql5, ele apenas escuta os eventos TradeTransaction e exibe um breve resumo sobre eles:

//+------------------------------------------------------------------+
//|                                     TradeTransactionListener.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   PrintFormat("LAST PING=%.f ms",
               TerminalInfoInteger(TERMINAL_PING_LAST)/1000.);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
   static int counter=0;   // contador de chamadas OnTradeTransaction()
   static uint lasttime=0; // hora da última chamada da OnTradeTransaction()
//---
   uint time=GetTickCount();
//--- se a última operação tiver sido realizada há mais de 1 segundo,
   if(time-lasttime>1000)
     {
      counter=0; // irá significar que isto é uma nova operação de negociação e é possível redefinir o contador
      if(IS_DEBUG_MODE)
         Print(" Nova operação de negociação");
     }
   lasttime=time;
   counter++;
   Print(counter,". ",__FUNCTION__);
//--- resultado da execução do pedido de negociação
   ulong            lastOrderID   =trans.order;
   ENUM_ORDER_TYPE  lastOrderType =trans.order_type;
   ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- nome do símbolo segundo o qual foi realizada a transação
   string trans_symbol=trans.symbol;
//--- tipo de transação
   ENUM_TRADE_TRANSACTION_TYPE  trans_type=trans.type;
   switch(trans.type)
     {
      case  TRADE_TRANSACTION_POSITION:   // alteração da posição
        {
         ulong pos_ID=trans.position;
         PrintFormat("MqlTradeTransaction: Position #%I64u %s modified: SL=%.5f TP=%.5f",
                     pos_ID,trans_symbol,trans.price_sl,trans.price_tp);
        }
      break;
      case TRADE_TRANSACTION_REQUEST:     // envia do pedido de negociação
         PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
         break;
      case TRADE_TRANSACTION_DEAL_ADD:    // adição de transação
        {
         ulong          lastDealID   =trans.deal;
         ENUM_DEAL_TYPE lastDealType =trans.deal_type;
         double        lastDealVolume=trans.volume;
         //--- identificador da transação no sistema externo: bilhete atribuído pela Bolsa de Valores de Moscou
         string Exchange_ticket="";
         if(HistoryDealSelect(lastDealID))
            Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
         if(Exchange_ticket!="")
            Exchange_ticket=StringFormat("(MOEX deal=%s)",Exchange_ticket);

         PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot   %s",EnumToString(trans_type),
                     lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD: // adição da ordem no histórico
        {
         //--- identificador da ordem no sistema externo: bilhete atribuído pela Bolsa de Valores de Moscou
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_FILLED)
           {
            if(HistoryOrderSelect(lastOrderID))
               Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("(MOEX ticket=%s)",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
      default: // outras transações
        {
         //--- identificador da ordem no sistema externo: bilhete atribuído pela Bolsa de Valores de Moscou
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_PLACED)
           {
            if(OrderSelect(lastOrderID))
               Exchange_ticket=OrderGetString(ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("MOEX ticket=%s",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
     }
//--- bilhete da ordem    
   ulong orderID_result=result.order;
   string retcode_result=GetRetcodeID(result.retcode);
   if(orderID_result!=0)
      PrintFormat("MqlTradeResult: order #%d retcode=%s ",orderID_result,retcode_result);
//---   
  }
//+------------------------------------------------------------------+
//| converte códigos numéricos de respostas para uma cadeia de caracteres Mnemonic            |
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
  {
   switch(retcode)
     {
      case 10004: return("TRADE_RETCODE_REQUOTE");             break;
      case 10006: return("TRADE_RETCODE_REJECT");              break;
      case 10007: return("TRADE_RETCODE_CANCEL");              break;
      case 10008: return("TRADE_RETCODE_PLACED");              break;
      case 10009: return("TRADE_RETCODE_DONE");                break;
      case 10010: return("TRADE_RETCODE_DONE_PARTIAL");        break;
      case 10011: return("TRADE_RETCODE_ERROR");               break;
      case 10012: return("TRADE_RETCODE_TIMEOUT");             break;
      case 10013: return("TRADE_RETCODE_INVALID");             break;
      case 10014: return("TRADE_RETCODE_INVALID_VOLUME");      break;
      case 10015: return("TRADE_RETCODE_INVALID_PRICE");       break;
      case 10016: return("TRADE_RETCODE_INVALID_STOPS");       break;
      case 10017: return("TRADE_RETCODE_TRADE_DISABLED");      break;
      case 10018: return("TRADE_RETCODE_MARKET_CLOSED");       break;
      case 10019: return("TRADE_RETCODE_NO_MONEY");            break;
      case 10020: return("TRADE_RETCODE_PRICE_CHANGED");       break;
      case 10021: return("TRADE_RETCODE_PRICE_OFF");           break;
      case 10022: return("TRADE_RETCODE_INVALID_EXPIRATION");  break;
      case 10023: return("TRADE_RETCODE_ORDER_CHANGED");       break;
      case 10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS");   break;
      case 10025: return("TRADE_RETCODE_NO_CHANGES");          break;
      case 10026: return("TRADE_RETCODE_SERVER_DISABLES_AT");  break;
      case 10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT");  break;
      case 10028: return("TRADE_RETCODE_LOCKED");              break;
      case 10029: return("TRADE_RETCODE_FROZEN");              break;
      case 10030: return("TRADE_RETCODE_INVALID_FILL");        break;
      case 10031: return("TRADE_RETCODE_CONNECTION");          break;
      case 10032: return("TRADE_RETCODE_ONLY_REAL");           break;
      case 10033: return("TRADE_RETCODE_LIMIT_ORDERS");        break;
      case 10034: return("TRADE_RETCODE_LIMIT_VOLUME");        break;
      case 10035: return("TRADE_RETCODE_INVALID_ORDER");       break;
      case 10036: return("TRADE_RETCODE_POSITION_CLOSED");     break;
      default:
         return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode));
         break;
     }
//---
  }
//+------------------------------------------------------------------+


Exemplo para a operação "ouvinte":

2016.06.09 14:51:19.763 TradeTransactionListener (Si-6.16,M15)  LAST PING=14 ms
Compra
2016.06.09 14:51:24.856 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:51:24.856 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_ADD order #49118594 ORDER_TYPE_BUY ORDER_STATE_STARTED   
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeResult: order #49118594 retcode=TRADE_RETCODE_PLACED 
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  3. OnTradeTransaction
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118594 ORDER_TYPE_BUY ORDER_STATE_REQUEST_ADD   
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  4. OnTradeTransaction
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118594 ORDER_TYPE_BUY ORDER_STATE_PLACED   
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  5. OnTradeTransaction
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_DELETE order #49118594 ORDER_TYPE_BUY ORDER_STATE_PLACED   
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  6. OnTradeTransaction
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_HISTORY_ADD order #49118594 ORDER_TYPE_BUY Si-6.16 ORDER_STATE_FILLED   (MOEX ticket=3377179723)
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  7. OnTradeTransaction
2016.06.09 14:51:24.885 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_DEAL_ADD deal #6945344 DEAL_TYPE_BUY Si-6.16 1.00 lot   (MOEX deal=185290434)
Colocação de SL/TP
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: Position  #0 Si-6.16 modified: SL=62000.00000 TP=67000.00000
Fechamento da posição (venda)
2016.06.09 14:52:24.063 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:52:24.063 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_ADD order #49118750 ORDER_TYPE_SELL ORDER_STATE_STARTED   
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeResult: order #49118750 retcode=TRADE_RETCODE_PLACED 
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  3. OnTradeTransaction
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118750 ORDER_TYPE_SELL ORDER_STATE_REQUEST_ADD   
2016.06.09 14:52:24.071 TradeTransactionListener (Si-6.16,M15)  4. OnTradeTransaction
2016.06.09 14:52:24.071 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118750 ORDER_TYPE_SELL ORDER_STATE_PLACED   
2016.06.09 14:52:24.073 TradeTransactionListener (Si-6.16,M15)  5. OnTradeTransaction
2016.06.09 14:52:24.073 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_DEAL_ADD deal #6945378 DEAL_TYPE_SELL Si-6.16 1.00 lot   (MOEX deal=185290646)
2016.06.09 14:52:24.075 TradeTransactionListener (Si-6.16,M15)  6. OnTradeTransaction
2016.06.09 14:52:24.075 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_DELETE order #49118750 ORDER_TYPE_SELL ORDER_STATE_PLACED   
2016.06.09 14:52:24.077 TradeTransactionListener (Si-6.16,M15)  7. OnTradeTransaction
2016.06.09 14:52:24.077 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_HISTORY_ADD order #49118750 ORDER_TYPE_SELL Si-6.16 ORDER_STATE_FILLED   (MOEX ticket=3377182821)

Agora é hora de revisar os exemplos do código-fonte.


Trabalhando com sua conta de negociação

Para começar, ao executar o robô de negociação, é necessário obter informações sobre a conta de negociação na qual ele vai operar.

Para trabalhar com a conta, existe a classe CAccountInfo, ela foi especialmente concebida para isto. Adicionamos ao nosso código de conexão o arquivo AccountInfo.mqh e e declaramos a variável dessa classe account:

#include <Trade\AccountInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- objeto para trabalhar com a com a conta
CAccountInfo account;
//--- obtemos o número da conta em que o conselheiro (EA) está em execução
   long login=account.Login();
   Print("Login=",login);
//--- exibimos a moeda da conta    
   Print("Валюта счета: ",account.Currency());   
//--- exibimos o saldo e o lucro atual na conta
   Print("Balance=",account.Balance(),"  Profit=",account.Profit(),"   Equity=",account.Equity());
//--- exibimos o tipo de conta    
   Print("Tipo de conta: ",account.TradeModeDescription());
//--- aclaramos se é possível negociar nessa conta
   if(account.TradeAllowed())
      Print("Negociação permitida nesta conta");
   else
      Print("Negociação restringida na conta: possivelmente o login foi feito usando a senha de investidor");
//--- mod de cálculo de margem
   Print("modo de cálculo de margem: ",account.MarginModeDescription());
//--- aclaramos se é permitido negociar na conta usando o conselheiro (EA)
   if(account.TradeExpert())
      Print("Negociação automática permitida na conta de negociação");
   else
      Print("Negociação automática restrita usando conselheiros e scripts");
//--- número máximo permitido de ordens especificadas ou não
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Número máximo permitido de ordens pendentes atuais: ",orders_limit);
//--- exibimos o nome da empresa e o servidor
   Print(account.Company(),": server ",account.Server());
   Print(__FUNCTION__,"  completed"); //---   
  }

Como pode ser visto a partir do código acima, usando a variável account na função OnInit(), é possível obter muita informação útil. Você pode adicionar esse código ao seu conselheiro (Expert Advisor), desse modo será muito mais fácil analisar os logs, ao analisar as operações do EA.

A figura abaixo mostra o resultado da execução do script.



Obtenção das propriedades de um instrumento financeiro

Obtivemos informações sobre a conta, no entanto, a fim de poder executar operações de negociação, também precisamos saber as propriedades do ativo financeiro que vamos a operar. Para fazer isso, vamos usar mais uma classe CSymbolInfo com um número grande de métodos. Apresentamos abaixo apenas uma pequena parte deles.

#include<Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- objeto para obter as propriedades do símbolo
CSymbolInfo symbol_info;
//--- definimos o nome do símbolo para o qual vamos receber informações
   symbol_info.Name(_Symbol);
//--- obtermos as cotações atuais e exibimos
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- obtemos o número de símbolos após o ponto e o tamanho do ponto
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- solicitamos o tipo de execução de ordem, verificamos as restrições
   Print("Restrições para as operações de negociação: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- aclaramos o modo de realização das negociações
   Print("Modo de execução das transações: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//--- aclaramos o modo de cálculo do custo do contrato
   Print("Cálculo do custo do contrato: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- tamanho do contrato
   Print("Tamanho do contrato padrão: ",symbol_info.ContractSize());
//--- tamanho da margem inicial para 1 contrato
   Print("Margem inicial para o contrato padrão: ",symbol_info.MarginInitial()," ",symbol_info.CurrencyBase());
//--- tamanhos mínimo e máximo de volume nãs operações de negociação
   Print("Volume info: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");   
  }

A figura abaixo mostra as propriedades do símbolo Si-6.16 a partir das seções do mercado FORTS da Bolsa de Valores de Moscou. Agora estamos prontos para ir diretamente para a negociação.



Programação de operações de negociação

Para enviar ordens de negociação, na linguagem MQL5 existem duas funções, isto é, OrderSend() e OrderSendAsync(). Na verdade, estas são duas implementações da mesma função. A função OrderSend() envia o pedido de negociação e espera o resultado de sua execução, enquanto a função assíncrona OrderSendAsync() simplesmente envia o pedido e permite continuar trabalhando com o programa, sem esperar pela resposta do servidor de negociação. Assim, o trabalho na MQL5 se torna realmente simples, pois basta uma função para todas as operações de negociação

Ambas as funções obtém, como primeiro parâmetro, a estrutura MqlTradeRequest, ela contém mais de uma dúzia de campos. O conjunto de campos necessários depende do tipo de operação de negociação, por isso nem todos os campos precisam ser preenchidos Se um valor estiver incorreto ou faltar um campo obrigatório, o pedido falhará ao passar a verificação no terminal, e simplesmente não será enviado para o servidor. 5 campos requerem que você especifique o valor correto a partir das enumerações predefinidas.

O pedido de negociação tem um número tão grande de campos, devido à necessidade de descrever o conjunto de propriedades da ordem, elas podem variar dependendo da política de execução, o tempo de expiração e outros parâmetros. Você não precisa memorizar todos esses detalhes, basta usar a classe pronta CTrade. O uso desta classe em seu robô de negociação pode ter a seguinte aparência:

#include<Trade\Trade.mqh>
//--- objeto para negociação
CTrade  trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- especificamos o MagicNumber para identificação de nossas ordens
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- definimos a derrapagem (slippage) permitida em pontos ao efetuar uma compra/venda
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- modo de execução da ordem, é preciso usar esse modo, porque ele é permitido pelo servidor
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- modo log: é melhor não chamar esse método, a classe e si definirá o melhor modo
   trade.LogLevel(1); 
//--- que função usar para negociar: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

Para negociar na bolsa de valores, habitualmente usa-se o modo de execução ORDER_FILLING_RETURN. Descrição:

Esse modo se usa apenas nos modos "Execução no mercado" e "Execução na bolsa": para mercados (ORDER_TYPE_BUY e ORDER_TYPE_SELL), ordens limite e stop limite(ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT e ORDER_TYPE_SELL_STOP_LIMIT). No caso de uma execução parcial, a ordem de mercado ou limite com um volume residual não é removida e permanece em vigor.

Durante a ativação das ordens ORDER_TYPE_BUY_STOP_LIMIT e ORDER_TYPE_SELL_STOP_LIMIT, será criado a ordem limite correspondente ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT com execução ORDER_FILLING_RETURN.

É hora de ver como CTrade ajuda nas operações de negociação.

Compra/venda aos preços disponíveis

Muitas vezes, em estratégias de negociação, é necessária comprar ou vender aos preços que estejam disponíveis nesse momento. O CTrade conhece esta situação e pede apenas o volume necessário de negociação. Todos os outros parâmetros, isto é, o preço de abertura, o nome do símbolo, os níveis Stop Loss e Take Profit e os comentários da ordem podem ser omitidos.

//--- 1. exemplo de compra no símbolo atual
   if(!trade.Buy(1))
     {
      //--- notificamos sobre o erro
      Print("O método Buy() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método Buy() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Por padrão, se o nome do instrumento não for especificado, o CTrade usará o nome do símbolo, no gráfico em que ele está em execução. Isso facilita o trabalho para estratégias simples. Para o robô, que negocia em vários instrumentos, você precisa a cada vez especificar explicitamente o símbolo no qual a negociação será realizada.

//--- 2. exemplo de compra em um símbolo especificado
   if(!trade.Buy(1,"Si-6.16"))
     {
      //--- notificamos sobre o erro
      Print("O método Buy() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método Buy() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Você pode especificar todos os parâmetros da ordem: os níveis Stop Loss/Take Profit, o preço de abertura e o comentário.

//--- 3. exemplo de compra no símbolo especificado com SL e TP especificados
   double volume=1;           // indicamos o volume da operação de negociação
   string symbol="Si-6.16";   // indicamos o símbolo no qual é realizada a operação
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de caráteres após a vírgula
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // ponto
   double bid=SymbolInfoDouble(symbol,SYMBOL_BID);             // preço atual para fechamento LONG
   double SL=bid-100*point;                                    // valor não-normalizado SL
   SL=NormalizeDouble(SL,digits);                              // normalizamos o Stop Loss
   double TP=bid+100*point;                                    // valor não-normalizado TP
   TP=NormalizeDouble(TP,digits);                              // normalizamos o Take Profit
//--- obtemos o preço atual de abertura para posições LONG
   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))
     {
      //--- notificamos sobre o erro
      Print("O método Buy() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método Buy() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Lembramos que o MagicNumber e a derrapagem permissível são definidas ao inicializar a instância CTrade, por isso não precisamos defini-los agora. Embora eles também podem ser definidos diretamente antes de cada transação, se necessário.

Colocação de uma ordem limite

Para enviar uma ordem limite, é usado o método apropriado da classe BuyLimit() ou SellLimit(). Uma versão breve, onde você especifica somente o preço e o volume, será suficiente na maioria dos casos. O preço de abertura para BuyLimit deve ser inferior ao preço atual, enquanto para SellLimit, deve ser superior. Ou seja, essas ordens são usados ​​para entrar no mercado ao melhor preço, por exemplo, nas estratégias à expectativa de uma recuperação do nível de suporte. Neste caso, usa-se o símbolo em que o conselheiro (EA) está em execução:

//--- 1. exemplo de colocação de uma ordem pendente BuyLimit
   string symbol="Si-6.16";                                    // definimos o símbolo no qual é colocada a ordem
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de caráteres após a vírgula
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // ponto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // preço atual de compra
   double price=ask-100*point;                                 // preço de abertura não-normalizado
   price=NormalizeDouble(price,digits);                        // normalizamos o preço de abertura
//--- tudo está pronto, enviamos para o servidor a ordem pendente Buy Limit
   if(!trade.BuyLimit(1,price))
     {
      //--- notificamos sobre o erro
      Print("O método BuyLimit() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método BuyLimit() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Você também pode usar uma versão mais detalhada mostrando todos os parâmetros: níveis SL/TP, tempo de expiração, nome do instrumento e um comentário para a ordem.

//--- 2. exemplo de como colocar uma ordem pendente BuyLimit com todos os parâmetros
   double volume=1;
   string symbol="Si-6.16";                                    // definimos o símbolo no qual é colocada a ordem
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de caráteres após a vírgula
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // ponto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // preço atual de compra
   double price=ask-100*point;                                 // preço de abertura não-normalizado
   price=NormalizeDouble(price,digits);                        // normalizamos o preço de abertura
   int SL_pips=100;                                            // Stop Loss em pontos
   int TP_pips=100;                                            // Take Profit em pontos
   double SL=price-SL_pips*point;                              // valor não-normalizado SL
   SL=NormalizeDouble(SL,digits);                              // normalizamos o Stop Loss
   double TP=price+TP_pips*point;                              // valor não-normalizado TP
   TP=NormalizeDouble(TP,digits);                              // normalizamos o 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));
//--- tudo está pronto, enviamos para o servidor a ordem pendente Buy Limit
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- notificamos sobre o erro
      Print("O método BuyLimit() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método BuyLimit() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Na segunda versão, é necessário especificar corretamente os níveis SL e TP. Não se esqueça que, para a compra, o nível Take Profit deve ser superior ao preço de abertura, enquanto o nível Stop Loss, inferior ao preço de abertura. Para ordens SellLimit é tudo ao contrário. Você pode facilmente descobrir seu erro ao testar o conselheiro (EA) de acordo como os dados históricos, a classe CTrade exibe automaticamente mensagens em tais casos (se você não chamar funções LogLevel).

Colocação de uma ordem stop

Para colocar ordens stop, usam-se os métodos BuyStop() e SellStop(). O preço de abertura para Buy Stop deve ser superior ao preço atual, enquanto para SellStop, inferior. As ordens stop se usam nas estratégias que entram no mercado quando existe uma fuga de um nível de resistência, bem como para limitar as perdas. Versão simples:

//--- 1. exemplo de colocação de uma ordem pendente Buy Stop
   string symbol="RTS-6.16";    // definimos o símbolo no qual é colocada a ordem
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de caráteres após a vírgula
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // ponto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // preço atual de compra
   double price=ask+100*point;                                 // preço de abertura não-normalizado
   price=NormalizeDouble(price,digits);                        // normalizamos o preço de abertura
//--- tudo está pronto, enviamos para o servidor a ordem pendente Buy Stop 
   if(!trade.BuyStop(1,price))
     {
      //--- notificamos sobre o erro
      Print("O método BuyStop() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método BuyStop() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Esta é uma versão mais detalhada de como especificar os parâmetros máximos para a ordem pendente BuyStop:

//--- 2. exemplo de colocação de uma ordem pendente Buy Stop com todos os parâmetros
   double volume=1;
   string symbol="RTS-6.16";    // definimos o símbolo no qual é colocada a ordem
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de caráteres após a vírgula
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // ponto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // preço atual de compra
   double price=ask+100*point;                                 // preço de abertura não-normalizado
   price=NormalizeDouble(price,digits);                        // normalizamos o preço de abertura
   int SL_pips=100;                                            // Stop Loss em pontos
   int TP_pips=100;                                            // Take Profit em pontos
   double SL=price-SL_pips*point;                              // valor não-normalizado SL
   SL=NormalizeDouble(SL,digits);                              // normalizamos o Stop Loss
   double TP=price+TP_pips*point;                              // valor não-normalizado TP
   TP=NormalizeDouble(TP,digits);                              // normalizamos o 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));
//--- tudo está pronto, enviamos para o servidor a ordem pendente Buy Stop 
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- notificamos sobre o erro
      Print("O método BuyStop() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método BuyStop() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Para enviar uma ordem SellStop, é implementado o método apropriado da classe CTrade, o mais importante aqui é especificar o preço correto.

Trabalhando com a posição

Em vez do usar os métodos Buy() e Sell(), você pode implementar os métodos para abertura da posição. No entanto, neste caso, é necessário especificar mais detalhes:

//--- número de símbolos após a vírgula
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- valor do punto
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- obtemos o preço de compra
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- calculamos e normalizamos os níveis SL e TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- preenchemos os comentários
   string comment="Buy "+_Symbol+" 1 at "+DoubleToString(price,digits);
//--- tudo está pronto, tentamos abrir a posição para compra
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,price,SL,TP,comment))
     {
      //--- notificamos sobre o erro
      Print("O método PositionOpen() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método PositionOpen() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Para fechar a posição, basta indicar o nome do instrumento, o trabalho restante é feito pela a classe CTrade.

//--- fechamos a posição de acordo como o símbolo atual
   if(!trade.PositionClose(_Symbol))
     {
      //--- notificamos sobre o erro
      Print("O método PositionClose() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método PositionClose() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Na posição aberta, você pode alterar os níveis StopLoss e TakeProfit. Isto é feito usando o método ModifyPosition().

//--- número de símbolos após a vírgula
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- valor do punto
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- obtemos o preço atual Bid
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- calculamos e normalizamos os níveis SL e TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- tudo está pronto, tentamos modificar a posição para compra
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- notificamos sobre o erro
      Print("O método PositionModify() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método PositionModify() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Modificação e exclusão da ordem

Para alterar os parâmetros da ordem pendente, na classe CTrade existe o método OrderModify(), ao qual devem ser passados os parâmetros necessários.

//--- verificamos a presença da ordem  
   if(!OrderSelect(ticket))
     {
      Print("Ordem #",ticket," não encontrada");
      return;

     }
//--- símbolo 
   string symbol=OrderGetString(ORDER_SYMBOL);
//--- número de símbolos após a vírgula
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- valor do punto
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- obtemos o preço de abertura
   double price=OrderGetDouble(ORDER_PRICE_OPEN);
//--- calculamos e normalizamos os níveis SL e TP
   double SL=NormalizeDouble(price-200*point,digits);
   double TP=NormalizeDouble(price+200*point,digits);
//--- tudo está pronto, tentamos modificar a ordem 
   if(!trade.OrderModify(ticket,price,SL,TP,ORDER_TIME_DAY,0))
     {
      //--- notificamos sobre o erro
      Print("O método OrderModify() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método OrderModify() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Você precisa obter o bilhete da ordem que você deseja alterar e, dependendo do seu tipo, especificar os níveis corretos StopLoss e TakeProfit. Além disso, o novo preço de abertura também deve ser correto em relação ao preço atual.

Para excluir uma ordem pendente, basta saber o seu bilhete:

//--- verificamos a presença da ordem  
   if(!OrderSelect(ticket))
     {
      Print("Ordem #",ticket," não encontrada");
      return;
     }
//--- tudo está pronto, tentamos excluir a ordem
   if(!trade.OrderDelete(ticket))
     {
      //--- notificamos sobre o erro
      Print("O método OrderDelete() falhou. Código de retorno=",trade.ResultRetcode(),
            ". Descrição do código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("O método OrderDelete() foi bem-sucedido. Código de retorno=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Na classe també existe o método universal OrderOpen(), ele pode colocar ordens pendentes de quaisquer tipos. Em contraste como os métodos especializados BuyLimit, BuyStop, SellLimit e SellStop, ele exige definir os parâmetros mais necessários. Talvez alguns achem que ele é mais simples.


Que outra coisa ver nas classes de negociação

Neste artigo, mostramos técnicas simples para programar operações de negociação de compra e venda, bem como trabalhar com ordens pendentes. Mas, na seção Classes de negociação, existem vários assistentes amigáveis ​para desenvolvimento de robôs de negociação na MQL5:

Usando essas classes, você pode se concentrar apenas em sua estratégia, trazendo todas as questões técnicas a um mínimo. Além disso, pode usar a classe CTrade para estudar os pedidos de negociação, por exemplo, usando o depurador. Depois de algum tempo, você poderá criar suas próprias classes, nelas implementará a lógica necessária para processar resultados de execução de ordens de negociação.

Comece sua viagem à negociação algorítmica com scripts simples

Embora muitos desenvolvedores experientes também possam encontrar algo novo e útil, os métodos propostos neste artigo estão destinados principalmente para desenvolvedores de robôs de negociação iniciantes. Tente executar os scripts simples descritos neste artigo para entender que a criação de um robô de negociação é mais fácil do que pensava.

Para aqueles que decidiram ir mais longe, oferecemos mais dois artigos sobre este tópico:

  1. Princípios da precificação da bolsa tomando como exemplo o mercado de derivativos da bolsa de moscou (moex)
  2. Como proteger seu expert advisor investindo na bolsa de moscou

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

Arquivos anexados |
accountinfo.mq5 (4.6 KB)
symbolinfo.mq5 (4.91 KB)
expert_sample.mq5 (37.09 KB)
limit_sample.mq5 (12.86 KB)
Interfaces Gráficas III: Botões Simples e Multifuncionais (Capítulo 1) Interfaces Gráficas III: Botões Simples e Multifuncionais (Capítulo 1)
Vamos começar a estudos sobre o controle chamado botão. Nós vamos mostrar exemplos de várias classes para a criação de um botão simples, botões com funcionalidades estendidas (botão com ícones/imagens e botão de divisão - "split button") e aqueles que são interconectados (grupos de botões e botão de radio). Além disso, nós vamos apresentar alguns incrementos para as classes existentes afim de ampliar a capacidade dos controles.
Interfaces Gráficas II: O Elemento Menu Principal (Capítulo 4) Interfaces Gráficas II: O Elemento Menu Principal (Capítulo 4)
Este é o capítulo final da segunda parte da série sobre interfaces gráficas. Aqui, nós vamos estudar a criação do menu principal. Demonstraremos neste artigo o desenvolvimento deste controle e a configuração dos manipuladores das classes da biblioteca para que ele tenha uma reação correta para as ações do usuário. Nós também vamos discutir como anexar os menus de contexto para os elementos do menu principal. Além disso, nós vamos mencionar a questão do bloqueio dos elementos inativos atualmente.
Interfaces Gráficas III: Grupos de Botões Simples e Multifuncionais (Capítulo 2) Interfaces Gráficas III: Grupos de Botões Simples e Multifuncionais (Capítulo 2)
O primeiro capítulo desta série foi sobre os botões simples e multifuncionais. O segundo artigo se dedicará aos grupos de botões interconectados entre si, que permitirão a criação dos controles, quando um usuário puder selecionar uma das opções a partir de um determinado conjunto (grupo).
Interfaces Gráficas II: Configuração dos manipuladores de eventos da Biblioteca (Capítulo 3) Interfaces Gráficas II: Configuração dos manipuladores de eventos da Biblioteca (Capítulo 3)
Os artigos anteriores contêm a implementação das classes para criar os componentes do menu principal. Agora, está na hora de olharmos com mais atenção os manipuladores de eventos nas classes base principais e dos controles criados. Nós também prestaremos uma atenção especial na gestão do estado do gráfico, dependendo da localização do cursor do mouse.