Precisa de ajuda com o erro #130 de perda de dados inválido - página 4

 
Obrigado por ter notado o Raptor.
Chamei minha função DoubleRound com MODE_TICKVALUE (que é 12,50) ao invés de MODE_TICKSIZE (0,25).

Eu a consertei, mas não fez com que a #130 desaparecesse

   if(long)
      SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * MarketInfo(Symbol(), MODE_POINT));
   else
      SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * MarketInfo(Symbol(), MODE_POINT));
   Log("SL: " + SL);   
   //round to nearest Tickvalue   
   SL = DoubleRound(SL, MarketInfo(Symbol(), MODE_TICKSIZE));
   Log("SL rounded: " + SL);

Aqui está um registro do erro com a linha DoubleRound atualizada:

#ESZ1,M5: loaded successfully 
#ESZ1,M5: Date: 2011/11/16 21:54
#ESZ1,M5: Symbol: #ESZ1
#ESZ1,M5: Depot: 56127.45000000
#ESZ1,M5: Stop Level [Points]: 75.00000000
#ESZ1,M5: Freeze Level [Points]: 0.00000000
#ESZ1,M5: Spread [Points]: 25.00000000
#ESZ1,M5: Min/Max Lot: 0.01000000/1000.00000000
#ESZ1,M5: Point: 0.01000000
#ESZ1,M5: Tick Size: 0.25000000
#ESZ1,M5: Tick Value: 12.50000000
#ESZ1,M5: Digits: 2.00000000
#ESZ1,M5: Contract: 2011.09.14 00:00-2011.12.16 23:59
#ESZ1,M5: Expert ID: 35698390 
#ESZ1,M5: Init successfully completed.
#ESZ1,M5: initialized

#ESZ1,M5: Opening Position: Short
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1251.00000000/1250.75000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719226 sell 1.00 #ESZ1 at 1250.75 ok
#ESZ1,M5: Order 13719226 Successfully Opened
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1252.00000000
#ESZ1,M5: SL rounded: 1252.00000000
#ESZ1,M5: error=130

para comparação, aqui está um registro, onde funcionou:

#ESZ1,M5: Opening Position: Long
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1249.25000000/1249.00000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719321 buy 1.00 #ESZ1 at 1249.25 ok 
#ESZ1,M5: Order 13719321 Successfully Opened 
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1248.00000000
#ESZ1,M5: SL rounded: 1248.00000000
#ESZ1,M5: modify #13719321 buy 1.00 #ESZ1 at 1249.25 sl: 1248.00 tp: 0.00 ok 
#ESZ1,M5: Stoploss successfully set

de qualquer forma, parece funcionar com mais freqüência agora, estamos definitivamente nos aproximando :)
 
shinobi:

em qualquer caso, parece funcionar com mais freqüência agora, estamos definitivamente chegando mais perto :)

Não consigo entender por que a Modify falhou... você está recebendo um novo Bid/Ask entre a OrderSend e a OrderModify ?

Tudo que posso sugerir agora é que quando você receber um erro 130. . imprima tudo de novo, Bid, Ask (usando MarketInfo), OOP, StopLevel, SL que você está tentando definir, etc, etc, etc.

 
shinobi:
Chamei minha função DoubleRound com MODE_TICKVALUE (que é 12,50) ao invés de MODE_TICKSIZE (0,25).
O valor do Tick está definitivamente errado. Tente com o tamanho do tiquetaque:
double DoubleRound(double number, double step){
   return( MathRound(number/step)*step );
}
 
Caro Raptor, WHRoeder e SDC,

O erro de parada nº 130 não aparece mais. Os últimos passos pareciam ter finalmente resolvido o problema.
Afixarei outro post depois disto, resumindo todos os passos dados. Assim, outros no fórum de combate ao erro nº 130 podem usar este tópico como referência.


Obrigado por sua ajuda contínua :).

shinobi
 
shinobi:

Obrigado por sua ajuda contínua :).

shinobi
Muito bem feito por ficar com ele... há sempre uma explicação, apenas que às vezes pode ser complicado encontrá-lo.
 
Referência para possíveis causas do erro #130: stoploss inválido.
  1. Dicas gerais
  2. Corretor ECN
  3. Corretor de 4/5 dígitos
  4. Mudança das taxas de mercado
  5. Espalhe
  6. Nível de parada
  7. Nível de Congelamento
  8. Tamanho do bilhete
  9. Exemplo completo
  10. Agradecimentos
  1. Dicas gerais
    A técnica mais importante para combater os erros é o corte excessivo de madeira. Fazer saída para tudo que poderia ser conectado remotamente ao erro. Se você definir uma função de registro que você pode ligar e desligar, você pode manter o código após ter resolvido o problema.
    Ao inicializar seu consultor especializado, você deve registrar todas as informações que a MarketInfo pode lhe dizer: https://docs.mql4.com/constants/marketinfo
    Certifique-se também sempre de verificar os valores de retorno das funções, por exemplo, para OrderModify:
    if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
    }  


  2. Corretor ECN
    A Corretora ECN exige que você faça pedidos separados para compra/venda e stoplos/takeprofit. Portanto, você precisa dividir seu código em duas ordens como esta:
    int ticket = OrderSend(Symbol(), OP_BUY, 1, MarketInfo(Symbol(), MODE_ASK), 2, 0, 0, "", 12345);
    OrderSelect(ticket, SELECT_BY_TICKET);
    entry_price = OrderOpenPrice();
    OrderModify(ticket, entry_price, stoploss, takeprofit, 0);
    
    Para pedidos de venda, você precisa substituir OP_BUY por OP_SELL. Você também deve verificar os valores de retorno de OrderSelect e OrderModify (ver Dicas gerais acima).

  3. Corretor de 4/5 dígitos
    Alguns corretores exigem que o stoploss, o takeprofit e o slippage sejam ajustados para 4/5 dígitos. Você pode fazer isso colocando o seguinte código em sua função init() (thx WHRoeder):
    int     pips2points;    // slippage  3 pips    3=points    30=points
    double  pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
    int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
    //init digit adjustment
    if (Digits % 2 == 1) {      // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
        pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
    } else {
        pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; 
    }
    Então você precisa multiplicar o stoploss, takeprofit e slippage com pips2db1 antes de enviá-lo para o Broker
    OrderModify(ticket, entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. Mudança das taxas de mercado
    Outra causa possível é que as taxas de mercado mudaram entre o tick ativado o Expert Advisor (EA), e o OrderSend() ou OrderModify() da EA foi executado. Para evitar este problema, há duas soluções possíveis:
    A primeira é a de usar: RefreshRates() antes de usar variáveis de mercado pré-definidas, como por exemplo: Ask e Bid. (estas variáveis recebem seus valores quando o tick ativa o EA)
    A segunda é não utilizar variáveis de mercado pré-definidas. Em vez disso, você pode usar os valores atuais do mercado com MarketInfo(). Em vez de Ask, Bid e Point use
    MarketInfo(Symbol(), MODE_ASK)
    MarketInfo(Symbol(), MODE_BID)
    MarketInfo(Symbol(), MODE_POINT)
    

  5. Espalhe
    Se o stoploss ou o takeprofit estiverem muito próximos do preço de entrada, o pedido será rejeitado. A fim de evitar este problema, deve-se levar em conta o atual diferencial entre a Ask e a Bid. Mais uma vez, há duas soluções:
    A primeira é calcular o spread e adicioná-lo/subtraí-lo ao seu stoploss/takeprofit.
    double spread = MarketInfo(Symbol(), MODE_ASK) - MarketInfo(Symbol(), MODE_BID);
    //buy
    stoploss = stoploss - spread;
    takeprofit = takeprofit + spread;
    //sell
    stoploss = stoploss + spread;
    takeprofit = takeprofit - spread;
    A segunda solução para levar implicitamente em conta o spread usando Ask e Bid, ao computar o stoploss ou o takeprofit:
    stoploss = 50
    takeprofit = 50
    //buy
    SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo(Symbol(), MODE_ASK) + (takeprofit * MarketInfo(Symbol(), MODE_POINT))
    //sell
    SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo(Symbol(), MODE_BID) -  (takeprofit * MarketInfo(Symbol(), MODE_POINT))

  6. Nível de parada
    Os corretores têm um certo nível de parada. Se o seu nível de parada estiver abaixo desse nível, seu pedido será rejeitado. Você pode verificar o nível de parada com MarketInfo(Symbol(), MODE_STOPLEVEL).
    Para evitar isto, verifique o nível de parada do corretor e ajuste-o se necessário:
    double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if(stoploss < stoplevel)
       stoploss = stoplevel + 1;

  7. Nível de Congelamento
    Nível de Congelamento é um conceito semelhante. Seu nível de congelamento também precisa ser maior do que o nível de congelamento do corretor. Você pode verificar o nível de congelamento por MarketInfo(Symbol(), MODE_FREEZELEVEL).
    Para evitar isto, verifique novamente seu nível de congelamento contra o nível de congelamento do corretor:
    double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
    if(stoploss < freezelevel)
       stoploss = freezelevel + 1;

  8. Tamanho do bilhete
    Finalmente, seu stoploss ou takeprofit pode ser rejeitado, porque o Symbol só suporta stoploss/takeprofit que corresponda ao seu tamanho de carrapato. O tamanho do ticksize é a distância mínima que o prêmio do símbolo pode percorrer para cima e para baixo. Por exemplo, se o preço for 1000 e o tamanho do ticksize 0,25, então o preço só pode subir ou descer por um múltiplo de 0,25 (0,25 * n, onde n é um número natural). Portanto, o preço pode subir de 0,25 a 1000,25 ou descer de 1,75 a 998,25.
    Para contabilizar o tamanho do ticksize, é necessário uma função para arredondar valores duplos para um determinado valor de etapa (por exemplo, o mais próximo de 0,25). Aqui está uma função desse tipo:
    double DoubleRound(double number, double step)
    {
        double mod = MathMod(number, step);
        if(mod < step/2.0)
          step = 0;
        double rounded = number - mod + step;
        return (rounded);
    }
    Por exemplo, ligar para DoubleRound com número = 1023.81234 e passo = 0.25 retornaria 1023.75. Chamando-a com 1023.967834 retornaria 1024,00
    Agora, antes de enviar o stoploss ou o takeprofit, arredonde-o para o tamanho de ticksize da Symbol:
    stoploss = (stoploss, MarketInfo(Symbol(), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo(Symbol(), MODE_TICKSIZE));

  9. Exemplo completo
    Aqui está um pequeno exemplo completo, levando em conta todas as medidas contrárias acima:
    int init()
    {
        //for 4/5 Digits-Broker adjustment
        int     pips2points;    // slippage  3 pips    3=points    30=points
        double  pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
        int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
       //init digit adjustment
       if (Digits % 2 == 1) {      // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
                   pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
       } else {
                   pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; 
       }
    
       Print("Date: " + Year() + "/" + Month() + "/" + Day() + " " + Hour() + ":" + Minute());
       Print("Symbol: " + Symbol());
       Print("Depot: " + AccountBalance());
       Print("Stop Level [Points]: " + MarketInfo(Symbol(), MODE_STOPLEVEL));
       Print("Freeze Level [Points]: " + MarketInfo(Symbol(), MODE_FREEZELEVEL));
       Print("Spread [Points]: " + MarketInfo(Symbol(), MODE_SPREAD));
       Print("Min/Max Lot: " + MarketInfo(Symbol(), MODE_MINLOT) + "/" + MarketInfo(Symbol(), MODE_MAXLOT));
       Print("Point: " + MarketInfo(Symbol(), MODE_POINT));
       Print("Tick Size: " + MarketInfo(Symbol(), MODE_TICKSIZE));
       Print("Tick Value: " + MarketInfo(Symbol(), MODE_TICKVALUE));
       Print("Digits: " + MarketInfo(Symbol(), MODE_DIGITS));
       Print("Contract: " + TimeToStr(MarketInfo(Symbol(), MODE_STARTING)) + "-" + TimeToStr(MarketInfo(Symbol(), MODE_EXPIRATION)));
    }
    
    //long = true: buy; long = false: sell
    int take_position(bool long)
    {
       int stoploss = 50;
       double SL = 0.0;
       int ticket = -1;
       
       //send order
       if(long)  //buy
          ticket = OrderSend(Symbol(), OP_BUY, 1, MarketInfo(Symbol(), MODE_ASK), 2, 0, 0, "", 1234);  
       else      //sell
          ticket = OrderSend(Symbol(), OP_SELL, 1, MarketInfo(Symbol(), MODE_BID), 2, 0, 0, "", 1234); 
    
       //check for errors
       if(result_ticket == -1) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }
       Print("order "+ticket+" successfully opened");
    
       //select order
       if (!OrderSelect(result_ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }    
       double entry_price = OrderOpenPrice();
       
       //check stoplevel
       double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
       Print("Stoplevel: " + stoplevel);
       if(stoploss < stoplevel)
          stoploss = stoplevel + 1;
    
       //check freezelevel
       double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
       Print("Freezelevel: " + freezelevel);
       if(stoploss < freezelevel)
          stoploss = freezelevel + 1;
    
       Print("adjusted stoploss: " + stoploss);
       
       //account for spread AND account for 4/5-Digit Brokers
       if(long)
          SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * pips2dbl);
       else
          SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * pips2dbl);
       Print("SL: " + SL);
       
       //round to nearest Tickvalue   
       SL = DoubleRound(SL, MarketInfo(Symbol(), MODE_TICKSIZE));
       Print("SL rounded: " + SL);
       
       //set stoploss
       if(!OrderModify(result_ticket, entry_price, SL, 0, Red)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }
    
       Print("Stoploss successfully set");
       return(0);
    }
    Espero que isso ajude a se livrar da #130. Se a modificação de seu código não funcionar, use um exemplo mínimo, como o acima, primeiro. E depois, quando o erro desaparecer, tome conta da alteração em seu código.

    Boa sorte,
    shinobi

  10. Agradecimentos
    Meus agradecimentos ao Raptor, WHRoeder, SDC, BigAl, gjol e 35806 por me ajudarem a me livrar do erro e a montar esta referência.
Razão: