Leitura da posição atual para impedir novas entradas

 

Caros, boa noite.

 

Tenho o código em anexo e uma das partes do código é a leitura da posição atual para impedir novas entradas quando já existir uma posição em andamento.

Oque acontece é que o código que estou usando para ler a posição atual "aparentemente" não está funcionando/retornando o resultado esperado (figura 2), inclusive no alert colocado após o envio da segunda ordem (que gerou sobreposição)  retorna um false.

Natural que retorne um false, caso contrário não entraria no código de envio da ordem, a questão que não consigo entender é porque não vejo a posição que foi iniciada as 2009.09.21 09:19:59 (figura 1) 

Eu preciso que caso já exista uma posição (não ordem) em aberto não seja gerado uma nova entrada.

 

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>


////////INICIO INSPECAO PARA NÃO ABRIR SOBREPOSIÇÕES
   bool Buy_opened=false;
   bool Sell_opened=false;
   if(PositionGetInteger(POSITION_MAGIC)==EA_Magic)
   if(PositionSelect(Symbol())==true)
     {
      long type=PositionGetInteger(POSITION_TYPE);
      if(type==(long)POSITION_TYPE_BUY)
        {
         Buy_opened=true;
        }
      if(type==(long)POSITION_TYPE_SELL)
        {
         Sell_opened=true;
        }
     }
////////FIM INSPECAO PARA ABRIR SOBREPOSIÇÕES


//CANCELA AS ORDENS PENDENTES DO MAGIC NUMBER JÁ EXISTENTES PARA ESTE ATIVO
   int ord_total=OrdersTotal();
   if(ord_total > 0)
     {
      for(int i=ord_total-1;i>=0;i--)
        {
         ulong ticket=OrderGetTicket(i);
         if(OrderSelect(ticket) && OrderGetInteger(ORDER_MAGIC)==EA_Magic)
           {
            CTrade *trade=new CTrade();
            trade.OrderDelete(ticket);
            Alert("ORDEM CANCELADA COM SUCESSO POR SURGIMENTO DE NOVA ENTRADA");
            delete trade;
           }
        }
     }

if(Sell_opened==false)
{
//ENVIA A ORDEM
         ZeroMemory(mrequest);
         mrequest.action = TRADE_ACTION_PENDING;
         mrequest.price = preco_entrada;
         mrequest.sl = loss;
         mrequest.tp = gain_principal;
         mrequest.symbol = Symbol();
         mrequest.volume = QTDE_CONTRATOS;
         mrequest.magic = EA_Magic;
         mrequest.type = ORDER_TYPE_SELL_STOP;
         mrequest.type_filling = ORDER_FILLING_RETURN;
         mrequest.expiration = SYMBOL_EXPIRATION_DAY;
         mrequest.type_time = ORDER_TIME_DAY;
         mrequest.deviation=100;
         OrderSend(mrequest,mresult);
         if(mresult.retcode==10009 || mresult.retcode==10008)
        {
        Alert("Ordem de venda inputada com sucesso. DISPARO:",mrequest.price, "| LOSS:", mrequest.sl, "| GAIN PRINCIPAL:", mrequest.tp, "| GAIN SEGURANCA:", gain_seguranca);
        Alert(Sell_opened); 
        }
}

 

 

Alguém pode por favor me ajudar. 

Arquivos anexados:
entrada_1.JPG  221 kb
entrada_2.JPG  202 kb
 
rflsjppr:

Caros, boa noite.

Tenho o código em anexo e uma das partes do código é a leitura da posição atual para impedir novas entradas quando já existir uma posição em andamento.

Oque acontece é que o código que estou usando para ler a posição atual "aparentemente" não está funcionando/retornando o resultado esperado (figura 2), inclusive no alert colocado após o envio da segunda ordem (que gerou sobreposição)  retorna um false.

Natural que retorne um false, caso contrário não entraria no código de envio da ordem, a questão que não consigo entender é porque não vejo a posição que foi iniciada as 2009.09.21 09:19:59 (figura 1) 

Eu preciso que caso já exista uma posição (não ordem) em aberto não seja gerado uma nova entrada.

Alguém pode por favor me ajudar. 

Olá rflsjppr,

Quando você envia uma ordem do tipo Buy Stop ou Sell Stop, esse tipo de ordem não abre IMEDIATAMENTE uma posição. É preciso esperar o preço tocar no seu gatilho e, apenas aí, uma posição será aberta.

O que você está verificando é se existe uma POSIÇÃO aberta, quando na verdade você deveria verificar se existe alguma ORDEM pendente.

Vale a pena verificar a diferença entre ORDEM e POSIÇÃO antes de desenvolver seu EA. Pra isso, sugiro a leitura do seguinte artigo: https://www.mql5.com/pt/articles/211

Abraços,
Malacarne

Ordens, posições e negócios no MetaTrader 5
Ordens, posições e negócios no MetaTrader 5
  • 2014.01.10
  • MetaQuotes Software Corp.
  • www.mql5.com
A criação robusta de um robô de negócio não pode ser feita sem um entendimento dos mecanismos do sistema de negócio do MetaTrader 5. O terminal do cliente recebe as informações sobre as posições, ordens e negócios a partir do servidor de negócio. Para manipular estes dados adequadamente utilizando o MQL5, é necessário ter um bom entendimento da interação entre o programa MQL5 e o terminal do cliente.
 

Malacarne.

Excelente, obrigado pela ajuda.

Foi justamente oque pensei, mas segundo a figura entrada_1 a ordem tinha como gatilho o 310 e o preço foi até 300, assim a ordem foi acionada e efetivada as  2009.09.21 09:19:59, correto?

 

Srs.

 

Acho que meu código estava errado, alterei agora para primeiro chamar a posição pelo Symbol() e pois pelo magic number e funcionou, ou seja, não abriu nova posição na barra de 2009.09.21 09:20:00 (figura ok).

 

////////INICIO INSPECAO PARA NÃO ABRIR SOBREPOSIÇÕES
   Buy_opened=false;
   Sell_opened=false;
   if(PositionSelect(Symbol()))
   if(PositionGetInteger(POSITION_MAGIC)==EA_Magic)
     {
      long type=PositionGetInteger(POSITION_TYPE);
      if(type==(long)POSITION_TYPE_BUY)
         Buy_opened=true;
      if(type==(long)POSITION_TYPE_SELL)
         Sell_opened=true;
     }
////////FIM INSPECAO PARA ABRIR SOBREPOSIÇÕES

 

 

Obrigado a todos.

Arquivos anexados:
ok.JPG  163 kb
 
rflsjppr:

Srs.

 

Acho que meu código estava errado, alterei agora para primeiro chamar a posição pelo Symbol() e pois pelo magic number e funcionou, ou seja, não abriu nova posição na barra de 2009.09.21 09:20:00 (figura ok).

 

 

 

Obrigado a todos.

Olá rflsjppr, exatamente, você deve chamar antes o PositionSelect(), como corrigido.

Pelo código original, a leitura de PositionGetInteger() estava sempre falhando e retornando 0, mascarando a existência de posições abertas.

Aliás, esse seria um bom teste para uma prova sobre MQL5! 

 
rflsjppr:

Srs.

 

Acho que meu código estava errado, alterei agora para primeiro chamar a posição pelo Symbol() e pois pelo magic number e funcionou, ou seja, não abriu nova posição na barra de 2009.09.21 09:20:00 (figura ok).

 

 

 

Obrigado a todos.

rflsjppr,

 

analisando o EA fonte do seu projeto, eu percebi algo que não sei se está correto.

este comando "força" a leitura do sinal, pelo que eu li num outro tutorial.

ENUM_ORDER_TYPE signal=WRONG_VALUE

porém abaixo deste comando teria que ter este outro que "força a leitura" e eu não

então acho que teria que ter esse comando logo abaixo, pois ele é quem "força a leitura" quando o primeiro comando acima é "setado"

GetSymbolProperties(symbol_number,S_ALL);

 ou seja.
ENUM_ORDER_TYPE signal=WRONG_VALUE;
GetSymbolProperties(symbol_number,S_ALL);

//fonte original do robô que vc postou

 //--- verifica os sinais

   ENUM_ORDER_TYPE signal=WRONG_VALUE;
   GetSymbolProperties(symbol_number,S_ALL);  //<<eu acho que precisaria desta linha adicional, não?  teste e veja se dá diferença.
   if(rt[0].open>ma[0] && rt[0].close<ma[0])
      signal=ORDER_TYPE_SELL;    // condição de venda
   else
     {
      if(rt[0].open<ma[0] && rt[0].close>ma[0])
         signal=ORDER_TYPE_BUY;  // condição de compra
     }
//--- verificações adicionais
 

Estou com o mesmo problema do amigo acima..

Coloquei o código para verificar se existe uma posição aberta e impedir que seja aberta uma nova ordem quando existir uma posição já aberta... mas acontece que a cada tick abre uma nova ordem mesmo tendo posição aberta(em 1 minuto chega a ficar com 300 ordens abertas :( )...

Não consigo achar onde esta o erro...


//+------------------------------------------------------------------+

//|                                                 ADXGradiente.mq5 |

//|                                                    APTO          |

//|                                             https://www.mql5.com |

//+------------------------------------------------------------------+

#property copyright "APTO"

#property link      "https://www.mql5.com"

#property version   "1.00"

//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

#include <Trade\Trade.mqh>

CTrade trade;



input int periodADX = 14;//Periodo ADX

input double lote = 1.0;//Volume

input double stopLoss = 2.0;//Stop Loss

input double takeprofit = 10.0;//Take Profit

input ulong magicNum = 123;//Mágic Number

input ulong desvPts = 50;//Spread(Pontos)


input ENUM_ORDER_TYPE_FILLING preenchimento = ORDER_FILLING_RETURN;//Preenchimento da Ordem



double PRC;

double STL;

double TKP;


bool posAberta;//variavel verificar se há posição aberta para o ativo em questão


int handleADX;


MqlTick ultimoTick; //saber preço do ativo(Último Preço, Preço de Compra, Preço de Venda e Volume)


int OnInit()

  {

//---

  //Criar manipulador indicador

  handleADX = iADX(_Symbol,_Period,periodADX);

  

  //Adicionar indicador no gráfico

  ChartIndicatorAdd(0, 0, handleADX);

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

   trade.SetTypeFilling(ORDER_FILLING_RETURN);//Tipo de preenchimento das Ordens

   trade.SetDeviationInPoints(desvPts); // Desvio em pontos Spread;  

   trade.SetExpertMagicNumber(magicNum);//Útil quando utiliza mais de 1 robo na mesma conta;

//---

   

  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

//---


SymbolInfoTick(_Symbol, ultimoTick);//Verificar o ultimo preço negociado no ativo


 //Declaração dos Arrays:

   double sinal[];

   double ADXC[];

   double ADXV[];

   

 //Usar ArraySetAsSeries para mudar a ordem do array(a partir do mais recente para o mais antigo)

   ArraySetAsSeries(sinal, true);

   ArraySetAsSeries(ADXC, true);

   ArraySetAsSeries(ADXV, true);

   

 //Copiando os valores do manipulador para o array

  CopyBuffer(handleADX,0,0,2,sinal);

  CopyBuffer(handleADX,1,0,2,ADXC);

  CopyBuffer(handleADX,2,0,2,ADXV);

  

   posAberta = false;//ver se tem posição em aberto no ativo e robo em questão(numero magico)

   for (int i = PositionsTotal()-1; i>=0; i--)//enquanto Posições abertas for >=0 fazer decremento;

   {

      string symbol = PositionGetSymbol(i);//declara variavel para armazenar o ativo da posição selecionada;

        ulong magic = PositionGetInteger(POSITION_MAGIC);//declara a variavel para armazenar o numero magico da posição selecionada;

           if(symbol == _Symbol && magic == magicNum )//se a variavel que armazena o ativo da posição for = ao ativo atual e numero magico atual,então é verdadeira;

          {

              posAberta = true;

               break;

           }

     }

      

   //Criar metricas para compra e venda com if e if else:

      if(ADXC[1]>ADXV[1] && sinal[1]>=30 && !posAberta)

       { 

           PRC = NormalizeDouble(ultimoTick.ask, _Digits);

           STL = NormalizeDouble(PRC - stopLoss, _Digits);

           TKP = NormalizeDouble(PRC + takeprofit, _Digits);

  

       if(trade.Buy(lote, _Symbol, PRC, STL, TKP,"Compra"))//Executar uma Ordem de Compra a mercado:

         {

            Print("Ordem de Compra - sem falha. ResulRetcode: ", trade.ResultRetcode()," ", "RetcodeDescription: ", trade.ResultRetcodeDescription());

         }

           else

         {

            Print("Ordem de Compra - com falha. ResulRetcode: ", trade.ResultRetcode()," ", "RetcodeDescription: ", trade.ResultRetcodeDescription());

         }

      }

    

     else if (ADXC[1]<ADXV[1] && sinal[1]>=30 && !posAberta)

       {

           PRC = NormalizeDouble(ultimoTick.bid, _Digits);

           STL = NormalizeDouble(PRC + stopLoss, _Digits);

           TKP = NormalizeDouble(PRC - takeprofit, _Digits);

              

       if(trade.Sell(lote, _Symbol, PRC , STL , TKP, "Venda"))//Executar uma Ordem de Venda a mercado:

         {

            Print("Ordem de Venda - sem falha. ResulRetcode: ", trade.ResultRetcode()," ", "RetcodeDescription: ", trade.ResultRetcodeDescription());

         }

          else

         {

            Print("Ordem de Venda - com falha. ResulRetcode: ", trade.ResultRetcode()," ", "RetcodeDescription: ", trade.ResultRetcodeDescription());

         }

      }

  }

      

 

         

   

 

//+------------------------------------------------------------------+


Arquivos anexados:
 
AnaPaulaSantana1:

Estou com o mesmo problema do amigo acima..

Coloquei o código para verificar se existe uma posição aberta e impedir que seja aberta uma nova ordem quando existir uma posição já aberta... mas acontece que a cada tick abre uma nova ordem mesmo tendo posição aberta(em 1 minuto chega a ficar com 300 ordens abertas :( )...

Não consigo achar onde esta o erro...


int OnInit()

  {

//---

  //Criar manipulador indicador

  handleADX = iADX(_Symbol,_Period,periodADX);

  

  //Adicionar indicador no gráfico

  ChartIndicatorAdd(0, 0, handleADX);

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

   trade.SetTypeFilling(ORDER_FILLING_RETURN);//Tipo de preenchimento das Ordens

   trade.SetDeviationInPoints(desvPts); // Desvio em pontos Spread;  

   trade.SetExpertMagicNumber(magicNum);//Útil quando utiliza mais de 1 robo na mesma conta;

//---

   

  }

É que você inseriu o comando  trade.SetExpertMagicNumber(magicNum) no OnDeinit().

Com isso as suas posições não estão com o Magic Number que vc usa pra comparar.

A solução é inserir   trade.SetExpertMagicNumber(magicNum) no OnInit() e não no OnDeinit().

Aliás, também há outros comandos no OnDeinit(), como o SetTypeFilling e o SetDeviationPoints, que também deveriam estar no OnInit().

 
Trader_Patinhas:

É que você inseriu o comando  trade.SetExpertMagicNumber(magicNum) no OnDeinit().

Com isso as suas posições não estão com o Magic Number que vc usa pra comparar.

A solução é inserir   trade.SetExpertMagicNumber(magicNum) no OnInit() e não no OnDeinit().

Aliás, também há outros comandos no OnDeinit(), como o SetTypeFilling e o SetDeviationPoints, que também deveriam estar no OnInit().

Olá!

Você tem toda razão rsrs...

Desculpe minha falta de atenção e muito obrigada pela ajuda hehe

 
AnaPaulaSantana1:

Olá!

Você tem toda razão rsrs...

Desculpe minha falta de atenção e muito obrigada pela ajuda hehe

Toma cuidado com essa estratégia Martingale. Ela pode te machucar!
Razão: