Stoploss não funciona

 

Estou fazendo backtest com dados históricos, e o stop loss não está funcionando. Tem dois casos:

1 – quando estou comprado, conforme o preço vai subindo, também vou subindo o stoploss,  quando chega no valor de compra eu zero o stoploss, porém quando chega próximo do valor de compra, o trigger é acionado. Veja exemplo:

Comprei PETR4 à 25,63, no percurso cheguei com o stoploss em 25,62, o trigger foi acionado e vendeu à 25,89. É claro que tive lucro, porém poderia ter sido maior.

2 – O preço chega no stoploss mas o trigger não é acionado. Veja exemplo:

Comprei PETR4 à 26,85 (ticket 8), com stoploss em 26,58 às 13:37h. às 15:34h o preço fechou em 26,50, mas não fez a venda.


Código: estou usando o CTrade.

 

Lote = 100 (é parâmetro)

Stop = 1 (é parâmetro e tratado como percentual)

Take = 2 (é parâmetro e tratado como percentual)

double precocompra = simbolo.Ask();

double stopcompra = simbolo.NormalizePrice((precocompra * (100-stop) / 100));

double takecompra = simbolo.NormalizePrice((precocompra * (100+take) / 100));

negocio.Buy(lote, NULL, precocompra, stopcompra, takecompra,"compra com preco, sl e tp");

 
Fabiano Possato:


Fabiano,

o erro está na lógica do trailing,  então se você postar o código completo eu poderia lhe ajudar. 

PS: Por favor insira o código usando o Alt-S.

 
Obrigado pela ajuda Rogerio. O TP tamabém não está funcionando.
essa á a função de compra:

void Compra()
{
   double precocompra = simbolo.Ask();
   double stopcompra = simbolo.NormalizePrice((precocompra * (100-stop) / 100));
   double takecompra = simbolo.NormalizePrice((precocompra * (100+take) / 100));

   Print("Preço de compra: ", precocompra,"    Stop Loss: ", stopcompra,"    Take Profit: ", takecompra);

//se houver ordem pendente, cancela antes de enviar nova ordem
   int ordemcancelada = CancelaOrdem(); 
   Print ("quantidade de ordens canceladas: ", ordemcancelada);

// verifica se existe posição, se existe posição de compra, não executa nova compra
   double posicaoatual = Posicao();
   if (posicaoatual > 0) 
   {
      Print("Posição de compra: ", posicaoatual,". Nova compra não enviada");
      return;
   }
   
// se existe posicao de venda, dobra o lote para compra, assim inverte a posição  
// se não existe posição nenhuma, envia compra com o lote parametrizado
   double lotenegociacao = 0;
/*   if(posicaoatual < 0)
   {
      lotenegociacao = -posicaoatual + lote;
   }
   else
   {
      lotenegociacao = lote;
   }

   negocio.Buy(lote, NULL, precocompra, stopcompra, takecompra,"compra com preco, sl e tp");
//   negocio.Buy(lotenegociacao,NULL,0,0,0,"compra a mercado sem sl e tp");
*/ 

//--- se a posição for fechada, aguardo 10 minutos para fazer nova operação
   if (posicaoatual < 0)
   {
      negocio.Buy(lote, NULL, 0, 0, 0,"compra para fechar posição");
   }
   else
   {
      negocio.Buy(lote, NULL, precocompra, stopcompra, takecompra,"compra com preco, sl e tp");
//      negocio.BuyStop(lote, precocompra, NULL, stopcompra, takecompra,0,0,"compra stop");
   }
   hrultimaoper = TimeCurrent(); 
}
 
Fabiano Possato:

--conforme o preço vai subindo, também vou subindo o stoploss,

Anexe o código do trailing.

 
//+------------------------------------------------------------------+
//| Verifica os níveis de stop loss e take profit e ajusta se necessário
//+------------------------------------------------------------------+
void BreakEven()
{

   double qtdeacoes = 0;
   long tipoposicao = 0;
   double percentualvaricao = 0;
   
   if (!PositionSelect(_Symbol))
   {
      return;
   }
   
   qtdeacoes = PositionGetDouble(POSITION_VOLUME);
   tipoposicao = PositionGetInteger(POSITION_TYPE);

   double slatual = PositionGetDouble(POSITION_SL);
   double tpatual = PositionGetDouble(POSITION_TP);
   double precoabertura = PositionGetDouble(POSITION_PRICE_OPEN);
   long ticket = PositionGetInteger(POSITION_TICKET);
   double variacao = simbolo.Last() - precoabertura;

   if (tipoposicao == POSITION_TYPE_SELL && variacao < 0)
   {
      percentualvaricao = (-variacao * 100 / precoabertura);
      Print ("percentualvaricao: ", percentualvaricao, " breakeven: ", breakeven);
      if (percentualvaricao >= breakeven)
      {
         double stopvenda = simbolo.NormalizePrice((precoatual * (100+stop) / 100));
//         double takevenda = simbolo.NormalizePrice((precoatual * (100-take) / 100));  
         takevenda = tpatual;
             Print ("calculo sl e tp: Ticket: ", ticket, " sl atual: ", slatual, "sl calc: ", stopvenda, " tp atual: ", tpatual,
               "tp calc: ", takevenda);
         if (slatual == 0 || stopvenda < slatual || takevenda < tpatual)
         {
            if (stopvenda <= precoabertura)
            {
               stopvenda = 0; // zera o stop loss quando ultrapassar o valor da venda, senão o gatilho é acionado
            }
            negocio.PositionModify(ticket,stopvenda,takevenda);
            Print ("Venda modificada: Ticket: ", ticket, " sl anterior: ", slatual, "sl atual: ", stopvenda, " tp anterior: ", tpatual,
               "tp atual: ", takevenda);
         }    
      }      
   }

   if (tipoposicao == POSITION_TYPE_BUY && variacao > 0)
   {
      percentualvaricao = (variacao * 100 / precoabertura);
      if (percentualvaricao >= breakeven)
      {
         double stopcompra = simbolo.NormalizePrice((precoatual * (100-stop) / 100));
//        double takecompra = simbolo.NormalizePrice((precoatual * (100+take) / 100));
         takecompra = tpatual;
         if (slatual == 0 || stopcompra > slatual || takecompra > tpatual)
         {
            if (stopcompra >= precoabertura)
            {
               stopcompra = 0; // zera o stop loss quando ultrapassar o valor da compra, senão o gatilho é acionado
            }            negocio.PositionModify(ticket,stopcompra,takecompra);
            Print ("Compra modificada: Ticket: ", ticket, " sl anterior: ", slatual, "sl atual: ", stopcompra, " tp anterior: ", tpatual,
               "tp atual: ", takecompra);
         }
      }
   }   

}

 
os valores de stoploss e takeprofit aparecem, tanto na ordem inicial quanto nas alterações, com valores corretos. Porém, a operação de compra ou venda não é feita, ou trigger não é acionado. Só é acionado no primeiro caso, quando o valor do stoploss chega no valor da abertura da operação, porém o preço da ação é totalmente diferente.
 
Fabiano Possato:

Opa,

qual o valor de precoatual ? 

Seria conveniente você olhar o log <DIARIO> se há erros de execução, já que você não trata no código.

 

precoatual é a última cotação do papel.

precoatual = simbolo.Last();

Os valores estão todos corretos, o trigger que está sendo acionado em momento errado. Já olhei todo o diário, em diferentes datas, não dá erro nenhum.

 
Fabiano Possato:

precoatual é a última cotação do papel.

precoatual = simbolo.Last();

Os valores estão todos corretos, o trigger que está sendo acionado em momento errado. Já olhei todo o diário, em diferentes datas, não dá erro nenhum.

Na configuração do testador você DIGITOU a moeda  BRL  ( Brasil Real ) ? 

 

Rogerio,

no testador não aparece a opção de BRL, veja em anexo. 

Arquivos anexados:
 
Fabiano Possato:

Rogerio,

no testador não aparece a opção de BRL, veja em anexo.

Então você digita BRL e bota para rodar!

Razão: