Saída repetida

 

Meu EA tem gatilho de saída quando dá as 17:30, porém foram dadas 3 ordens seguidas :

O que ocasionou numa reentrada no sentido oposto e uma saída instantânea, o que me fez perder 10 pontos em segundos:


Como faço para este momento de saída ser de um modo que esta reentrada não aconteça?
Obrigado!

   if (DailyClose && TimeToString(TimeCurrent(), TIME_MINUTES)>=closeHour)
    {
      Print("try to close position on DailyClose");
      _res = trade.PositionClose(Symbol(), Slippage);
      return;
    }
 
Lucas Tavares:

Meu EA tem gatilho de saída quando dá as 17:30, porém foram dadas 3 ordens seguidas :

O que ocasionou numa reentrada no sentido oposto e uma saída instantânea, o que me fez perder 10 pontos em segundos:


Como faço para este momento de saída ser de um modo que esta reentrada não aconteça?
Obrigado!

Nunca vi isso... É conta Netting?
 
Flavio Jarabeck:
Nunca vi isso... É conta Netting?
Sim.
Parece que saí de cada entrada uma a uma, e depois "saí" de todas de vez, entrando novamente em sentido contrário, e tive que sair imediatamente.
 


Eu tinha entrado com 6, depois 3.

Na hora de sair tive 3 aparentes ordens de saída :

Saí em pedaços, com 9 (1), e por algum motivo vendi mais 9(2), como se fosse uma saída, e acabei entrando vendido. O que engatilhou o ea a me tirar comprando 9(3).


Será que uma ordem de esperar, e confirmar se saí, e repetir a tentativa de saída caso necessário resolveria meu problema?

 
Lucas Tavares:


Lucas, 

essa rotina de fechamento fica dentro do  OnTimer() ?

 
Fica no OnTick(), e tem um bool _res; antes do OnInit
 
Lucas Tavares:
Fica no OnTick(), e tem um bool _res; antes do OnInit

Sem ver o resto do código não dá pra inferir muita coisa, mas vou arriscar um palpite...

Imagino que essa variável DailyClose seja uma variável booleana que indique que a posição está aberta e que, depois da confirmação de que a posição foi realmente fechada ela se torne falsa, para evitar que o fechamento seja repetido.

O que pode estar acontecendo é que ela só se torna falsa após a confirmação e que, nesse meio tempo antes da confirmação, tenham chegado novos ticks e o evento Ontick() tenha sido disparado mais uma vez, ainda com DailyClose = true. Assim, este segundo fechamento indevido acabou deixando uma posição aberta, que tornou DailyClose true de novo e disparou a ordem de fechamento uma terceira vez, e dessa vez deu certo (a confirmação da posição zerada chegou antes de quaisquer novos ticks).

Se esse meu palpite estiver correto, uma solução seria declarar dentro do OnTick() uma segunda variável booleana estática para indicar que a ordem de fechar a posição já foi enviada neste mesmo pregão, evitando assim enviar mais de uma vez o comando de fechamento.

Segue abaixo uma sugestão de implementação dessa lógica: 

void OnTick()
{
        static bool PositionCloseSent = false;  // esta variável tem que ser estática, para que seu conteúdo seja preservado na próxima chamada do OnTick()
 
        [... restante do código do OnTick() aqui ...] 

        if (DailyClose && TimeToString(TimeCurrent(), TIME_MINUTES)>=closeHour)
        {
                 // este "if" é para executar o PositionClose somente se esse comando ainda não tiver sido executado neste mesmo pregão

                if ( ! PositionCloseSent ) 
                {
                        Print("try to close position on DailyClose");
                        _res = trade.PositionClose(Symbol(), Slippage);
                        PositionCloseSent = true; // isto aqui é para que o comando não seja executado novamente na próxima chamada do OnTick()
                }

                return;
        }
        else      // este "else" é necessário para que o robô volte a fechar a posição às 17:30 do dia seguinte (desnecessário se for reiniciado a cada pregão)
        {
                PositionCloseSent = false; 
        }

        [... restante do código do OnTick() aqui ...] 

}

ATENÇÃO: O código acima, além de não ter sido testado, baseia-se em um palpite meu a respeito da natureza do problema que vc está enfrentando. Recomendo fortemente que procure entender o funcionamento do seu robô e confirme se o que falei faz sentido ou não e, caso faça sentido, se essa solução sugerida é realmente aplicável, pois eu não tenho certeza sobre como essas variáveis aí são iniciadas e atualizadas no restante do código que vc não mostrou.

 

Você parece ter explicado o que aconteceu, @Trader_Patinhas !
Obrigado pela elaboração do código e do raciocínio,ele funcionou sim! Não testei ainda ao vivo para ver se me resolve o problema, mas estava pensando, se fizer isto não resolveria? :

  {
      Print("try to close position on DailyClose");
      _res = trade.PositionClose(Symbol(), Slippage);
      Sleep(2000);
      return;
    }
Após ele dar a ordem, ele tiraria 2 segundos para pensar e ter tudo resolvido (que normalmente é feito em 0.2s) e em seguida, ficaria falso, e não mandaria novamente esta ordem.
Faz sentido?
 
Lucas Tavares:

Você parece ter explicado o que aconteceu, @Trader_Patinhas !
Obrigado pela elaboração do código e do raciocínio,ele funcionou sim! Não testei ainda ao vivo para ver se me resolve o problema, mas estava pensando, se fizer isto não resolveria? :

Após ele dar a ordem, ele tiraria 2 segundos para pensar e ter tudo resolvido (que normalmente é feito em 0.2s) e em seguida, ficaria falso, e não mandaria novamente esta ordem.
Faz sentido?


Lucas, o método PositionClose(...) testa se existe posição aberta e coloca em result.retcode    = TRADE_RETCODE_REJECT e retorna false caso não exista posição aberta! Minha sugestão para o seu código. 

 

   if (DailyClose && TimeToString(TimeCurrent(), TIME_MINUTES )>=closeHour   && position.SelectPosition(Symbol()) )
   { 
       res = trade.PositionClose(Symbol(), Slippage);

       if(trade.ResultRetCode() !=  10009 ) //  Se não deu DONE
        Print("Failed close position on DailyClose ",trade.ResulRetCode()," ",trade.ResultRetCodeDescription());
       else 
        Print("Success close position on DailyClose");

       return;
    }


Mostra a rotina para não abrir novas posições a partir de closeHour ou a rotina que testa o horário permitido para abrir posições.

 
Bem elaborado Rogerio! Vou ver como fecha agora com o código que coloquei, qualquer coisa eu testo o seu.
Mas de toda forma fica aí o aprendizado do funcionamento do PositionClose.
Aonde você conseguiu este mecanismo em que ele puxa o ResulRetCode? Não vi isso quando li na documentação.
 
Lucas Tavares:
Não vi isso quando li na documentação.

Tá precisando de óculos!... rsrsrs 

Brincadeiras a parte, tá lá sim, no guia de referência em Biblioteca padrão, Classes de negociação ctrade .

Razão: