需要帮助解决错误#130无效止损的问题 - 页 4

 
谢谢你注意到Raptor。
我用MODE_TICKVALUE(即12.50)而不是MODE_TICKSIZE(0.25)调用我的DoubleRound函数

我修复了它,但它并没有使#130消失

   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);

这是一个带有更新的DoubleRound行的错误日志:

#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

作为比较,这里是一个日志,它在那里工作:

#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

无论如何,现在似乎更频繁地工作了,我们肯定是越来越接近了。)
 
shinobi:

在任何情况下,它现在似乎更经常工作,我们肯定会越来越接近。)

我看不出为什么修改会失败 ......你在OrderSend和OrderModify之间得到了一个新的Bid/Ask吗?

我现在能建议的是,当你得到一个错误的130... ...重新打印所有的东西,Bid,Ask(使用MarketInfo),OOP,StopLevel,你试图设置的SL,等等,等等。

 
shinobi:
我用MODE_TICKVALUE(即12.50)而不是MODE_TICKSIZE(0.25)调用我的DoubleRound函数。
滴答值肯定是错误的。试着用ticksize来代替这个。
double DoubleRound(double number, double step){
   return( MathRound(number/step)*step );
}
 
亲爱的猛禽,WHRoeder和SDC。

130号的止损错误不再出现了。最后的步骤似乎终于找到了问题所在。
我将在这之后再发一个帖子,总结所有采取的步骤。这样论坛里其他与错误#130作斗争的人就可以把这个主题作为参考。


谢谢你一直以来的帮助:)。

shinobi
 
shinobi:

谢谢你一直以来的帮助:)。

忍者
做得好,坚持下去......总是有解释的,只是有时会很难找到。
 
错误#130的可能原因参考:无效的止损。
  1. 一般提示
  2. ECN经纪商
  3. 4/5位数的经纪人
  4. 变化的市场利率
  5. 价差
  6. 停止水平
  7. 冻结水平
  8. 票价大小
  9. 完整的例子
  10. 鸣谢
  1. 一般提示
    对抗错误的最重要的技术是过度记录。对所有可能与错误有联系的东西进行输出。如果你定义了一个可以打开和关闭的日志函数,你可以在解决了问题后保留这些代码。
    当初始化您的专家顾问时,您应该记录MarketInfo可以告诉您的所有信息:https://docs.mql4.com/constants/marketinfo
    另外,一定要注意检查函数的返回值,例如OrderModify。
    if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
    }  


  2. ECN经纪商
    ECN经纪商要求您为买入/卖出和止损/获利做出单独的订单。所以你需要把你的代码分成两个订单,像这样。
    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);
    
    对于卖出订单,你需要用OP_SELL代替OP_BUY。你还应该检查OrderSelect和OrderModify的返回值(见上面的一般提示)。

  3. 4/5位数的经纪人
    一些经纪商要求将止损、止盈和滑点调整为4/5位数。你可以在你的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; 
    }
    然后你需要将止损、止盈和滑点与pips2db1相乘,再发送给经纪商。
    OrderModify(ticket, entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. 变化的市场利率
    另一个可能的原因是,市场汇率在激活专家顾问(EA)和执行EA OrderSend()或OrderModify()之间发生变化。为了避免这个问题,有两个可能的解决方案。
    第一种是使用。RefreshRates(),然后再使用预定义的市场变量,例如。Ask和Bid。(这些变量在嘀嗒声激活EA时获得其值)
    第二种是根本不使用预定义的市场变量。相反,你可以使用MarketInfo()的当前市场价值。用MarketInfo()代替Ask, Bid和Point。
    MarketInfo(Symbol(), MODE_ASK)
    MarketInfo(Symbol(), MODE_BID)
    MarketInfo(Symbol(), MODE_POINT)
    

  5. 价差
    如果止损或止盈离进场价格太近,订单将被拒绝。为了避免这个问题,你应该考虑到当前Ask和Bid之间的价差。同样有两个解决方案。
    第一种是计算价差并将其加入/减去你的止损/止盈。
    double spread = MarketInfo(Symbol(), MODE_ASK) - MarketInfo(Symbol(), MODE_BID);
    //buy
    stoploss = stoploss - spread;
    takeprofit = takeprofit + spread;
    //sell
    stoploss = stoploss + spread;
    takeprofit = takeprofit - spread;
    第二种解决方案是在计算止损或止盈时,使用卖出价和买入价隐含地将价差考虑在内。
    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. 止损水平
    券商有一定的止损水平。如果你的止损低于该水平,你的订单将被拒绝。你可以用MarketInfo(Symbol(), MODE_STOPLEVEL)检查止损水平。
    为了避免这种情况,请对照经纪人的止损水平检查您的止损,如果有必要,请调整它。
    double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if(stoploss < stoplevel)
       stoploss = stoplevel + 1;

  7. 冻结水平
    冻结水平是一个类似的概念。你的止损也需要大于经纪人的冻结水平。你可以通过MarketInfo(Symbol(), MODE_FREEZELEVEL)检查冻结水平。
    为了避免这种情况,再次根据经纪人的冻结水平检查你的止损。
    double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
    if(stoploss < freezelevel)
       stoploss = freezelevel + 1;

  8. Ticksize
    最后,你的止损或止盈可能被拒绝,因为符号只支持与它的ticksize相匹配的止损/止盈。Ticksize是符号的奖赏可以上升和下降的最小距离。例如,如果价格是1000,ticksize是0.25,那么价格只能上升或下降0.25的倍数(0.25*n,其中n是一个自然数)。所以价格可能上升0.25到1000.25或下降1.75到998.25。
    为了考虑ticksize,你需要一个函数将双倍值四舍五入到某个阶梯值(例如,最接近的0.25)。下面就是这样一个函数。
    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);
    }
    例如,用 number = 1023.81234 和 step = 0.25 调用 DoubleRound 会返回 1023.75。用1023.967834调用它将返回1024.00。
    现在,在发送止损或止盈之前,用以下方法将其四舍五入到符号的ticksize。
    stoploss = (stoploss, MarketInfo(Symbol(), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo(Symbol(), MODE_TICKSIZE));

  9. 完整的例子
    下面是一个完整的小例子,其中考虑到了上述所有的反击措施。
    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);
    }
    我希望这有助于摆脱#130。如果修改你的代码不起作用,先用一个最小的例子,就像上面的例子。然后,当错误消失的时候,再把修改后的代码接过来,变成你的代码。

    祝您好运。
    shinobi

  10. 鸣谢
    感谢Raptor, WHRoeder, SDC, BigAl, gjol和35806帮助我摆脱了这个错误,并把这个参考资料放在一起。