Dúvida sobre classe CTrade, ao utilizar o método Buy a função cria duas ordens iguais

 

Boa noite,

Senhores,


Estou tentando utilizar o método Buy para criar uma ordem no metatrader, porém ao utilizar a função a mesma cria duas ordens iguais, sendo que a função está sendo chamada apenas 1 vez para que seja criada apenas uma ordem.


Em anexo segue o trecho do código que estou utilizando e também uma imagem do testador de estratégia com o resultado da execução.

Se alguém souber como me ajudar, ficarei grato.  

Fórum MQL5
Fórum MQL5
  • www.mql5.com
MQL5: Fórum sobre sistemas de negociação automatizados e testes de estratégia
Arquivos anexados:
Cedigo.PNG  30 kb
Testador.PNG  53 kb
 
FilipeFraaga:

Boa noite,

Senhores,


Estou tentando utilizar o método Buy para criar uma ordem no metatrader, porém ao utilizar a função a mesma cria duas ordens iguais, sendo que a função está sendo chamada apenas 1 vez para que seja criada apenas uma ordem.


Em anexo segue o trecho do código que estou utilizando e também uma imagem do testador de estratégia com o resultado da execução.

Se alguém souber como me ajudar, ficarei grato.  

Sua premissa está errada.

O mundo Real nunca é o que acontece nos testes, você não pode fazer esse checking no OnTick(). Volte pra prancheta e estude sobre o que realmente faz o OnTick() e quando ele é executado.

Depois estude sobre o OnTradeTransaction().

 
Flavio Jarabeck #:

Sua premissa está errada.

O mundo Real nunca é o que acontece nos testes, você não pode fazer esse checking no OnTick(). Volte pra prancheta e estude sobre o que realmente faz o OnTick() e quando ele é executado.

Depois estude sobre o OnTradeTransaction().

Boa noite,

Flávio,


Sou um iniciante no desenvolvimento de softwares com mql 5 para Experts Trader, vindo de outra área de desenvolvimento focada no ramo industrial. Sou grato pelo comentário e pela informação, mesmo que um tanto quanto abrupta. 

Já que a minha premissa está errada, poderia ao menos me indicar um caminho/direção para executar de melhor forma ?


Obrigado pela atenção, por enquanto um abraço!

 
FilipeFraaga #:


Olá Felipe,

primeiro uma observação, a premissa é que 99,99% o erro é de código, ou seja não é do compilador ou computador... 

Então vamos ao erro, você emitiu duas ordens de compra.

1º no Trade(buy)

2º no OrderSend()

Anexa o fonte, Alt-S e cole o código,  vou arrumar as coisas para você dar mais uns passos.
 

Olá Rogerio,

Boa tarde, obrigado pelo comentário.

Em relação ao erro, estou utilizando apenas o método trade.buy da biblioteca CTrade, ao abrir o fonte da biblioteca percebi que a mesma sempre utiliza o método trade.PositionOpen para realizar a ordem do tipo a mercado mesmo que eu esteja utilizando trade.Buy, fazendo está chamada internamente na biblioteca. O que ainda não entendi é como ele realiza as duas operações através do trade.Buy e outra através do OrderSend() como mencionou.

Segue o código, 

Grato pela, resposta e pelo auxilio.

//+------------------------------------------------------------------+
//|                                                        Teste.mq5 |
//|                                                     Filipe Lopes |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Filipe Lopes"
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>

CTrade   trade;

bool realizaOp = false;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {   
      MqlTradeRequest mrequest;
      MqlTradeResult  mresult;
      
      if(!realizaOp)
       {
         trade.SetAsyncMode(false);
         trade.SetDeviationInPoints(5);
         trade.SetExpertMagicNumber(1234);
         trade.LogLevel(2);
         trade.SetTypeFilling(ORDER_FILLING_FOK);
         
         trade.Buy(5,_Symbol,PRICE_HIGH,NULL,NULL,"Order");

         trade.Request(mrequest);
         trade.Result(mresult); 
            
         if(!OrderSend(mrequest, mresult))
           {
            PrintFormat("Erro em OrderSend: %d", GetLastError());
            PrintFormat("Código de Retorno: %d", mresult.retcode);
           }
      
         if(trade.ResultRetcode() == 10009 || trade.ResultRetcode() == 10008)
           {
            Print("Operação realizada. Ticket#: " + IntegerToString(mresult.order) + " Volumes: " + DoubleToString(mresult.volume, 0) 
            + " TakeProfit: " + DoubleToString(mrequest.tp, _Digits) + " StopLoss: " + DoubleToString(mrequest.sl, _Digits));     
           }
         else
           {
            Print("Operação NÃO realizada. Erro: " + IntegerToString(GetLastError()) + " Volumes: " + DoubleToString(mresult.volume, 0) 
            + " TakeProfit: " + DoubleToString(mrequest.tp, _Digits) + " StopLoss: " + DoubleToString(mrequest.sl, _Digits));
            ResetLastError();
           }
           
         realizaOp = true;
       }
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
//---
   
  }
//+------------------------------------------------------------------+

 

Bom dia Felipe,

você precisa estudar, leia o manual e passe a usar os termos corretos para cada conceito.  

...       

A Biblioteca padrão do MQL5 é um conjunto de classes e a CTrade é uma classe para facilitar o acesso às funções de negociação. 


...

OrderSend()

A função OrderSend() é usada para a execução de operações de negociação enviando solicitações para um servidor de negociação.


...

CTrade Buy()

Buy é o método da classe CTrade para abrir posições compradas. Se você leu o fonte deve ter observado que o Buy() chama o método PositionOpen(), no método PositionOpen() é preparado a estrutura do pedido de negociação ( mrequest ) e é chamada a função de negociação OrderSend().

...

CTrade  Request()

Request é o método que obtém a cópia da última estrutura de pedido de negociação.


Eu acho que agora dá para você enxergar que no seu código você copiou a estrutura do pedido preparada no BUY(...) e emitiu um segunda ordem de compra no OrderSend(...)


 

No fonte abaixo eu só fiz por no lugar os métodos que você usou e tenho algumas observações quando for operar na B3.

Evite modo "Async".  O parâmetro DevitationPoint  é inúltil pois as ordens são a mercado.  O modo de preenchimento FOK só a XP aceita.



//+------------------------------------------------------------------+
//|                                                        Teste.mq5 |
//|                                                     Filipe Lopes |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Filipe Lopes"
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>

CTrade   trade;

MqlTradeRequest mrequest;
MqlTradeResult  mresult;
bool realizaOp = false;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   trade.SetAsyncMode(false);
   trade.SetDeviationInPoints(5);
   trade.SetExpertMagicNumber(1234);
   trade.LogLevel(2);
   trade.SetTypeFilling(ORDER_FILLING_FOK);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!realizaOp)
     {
      trade.Buy(5, _Symbol, PRICE_HIGH, NULL, NULL, "Order");
      if(trade.ResultRetcode() == 10009 || trade.ResultRetcode() == 10008)
        {
         Print("Operação realizada. Ticket#: " + IntegerToString(mresult.order) + " Volumes: " + DoubleToString(mresult.volume, 0)
               + " TakeProfit: " + DoubleToString(mrequest.tp, _Digits) + " StopLoss: " + DoubleToString(mrequest.sl, _Digits));
        }
      else
        {
         Print("Operação NÃO realizada. Erro: " + IntegerToString(GetLastError()) + " Volumes: " + DoubleToString(mresult.volume, 0)
               + " TakeProfit: " + DoubleToString(mrequest.tp, _Digits) + " StopLoss: " + DoubleToString(mrequest.sl, _Digits));
         ResetLastError();
        }
      realizaOp = true;
     }
  }
//+------------------------------------------------------------------+
 

Bom dia Rogerio,

Obrigado por todo auxilio e pela distribuição do seu conhecimento, após sua ultima resposta entendi como estava sendo realizada a segunda ordem através do OrderSend(), ao retirar o trecho do código que utilizava a função OrderSend() o mesmo já funcionou como queria realizando apenas uma operação.


Obrigado também pela reestruturação do código, desta forma consigo enxergar melhor onde devemos declarar e definir certas coisas. Grato!


Quanto a alguns parâmetros citados, o parâmetro DevitationPoint estou utilizando por que pretendo utilizar outros tipos de ordens dentro do código não apenas ordens a mercado, o parâmetro SetTypeFilling no momento estou utilizando desta forma pois ao ler o manual vi que se enquadraria mais na forma que quero trabalhar e também atualmente estou utilizando a corretora XP. Qual seria outro parâmetro útil para abranger um número maior de corretoras ?


Por enquanto obrigado por todo auxilio e atenção, sou grato!


Deixo aqui também como resolvido este tópico no escopo inicial, não sei se tem como marcar como resolvido aqui no fórum.


Obrigado! :)

 
FilipeFraaga #:

Olá Rogerio,

Boa tarde, obrigado pelo comentário.

Em relação ao erro, estou utilizando apenas o método trade.buy da biblioteca CTrade, ao abrir o fonte da biblioteca percebi que a mesma sempre utiliza o método trade.PositionOpen para realizar a ordem do tipo a mercado mesmo que eu esteja utilizando trade.Buy, fazendo está chamada internamente na biblioteca. O que ainda não entendi é como ele realiza as duas operações através do trade.Buy e outra através do OrderSend() como mencionou.

Segue o código, 

Grato pela, resposta e pelo auxilio.

 
José Geraldo Soares Filho #:
Razão: