需要帮助解决错误#130无效止损的问题 - 页 4 1234 新评论 [删除] 2011.11.16 20:02 #31 谢谢你注意到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 无论如何,现在似乎更频繁地工作了,我们肯定是越来越接近了。) Simon Gniadkowski 2011.11.17 09:52 #32 shinobi: 在任何情况下,它现在似乎更经常工作,我们肯定会越来越接近。) 我看不出为什么修改会失败 ......你在OrderSend和OrderModify之间得到了一个新的Bid/Ask吗? 我现在能建议的是,当你得到一个错误的130... ...重新打印所有的东西,Bid,Ask(使用MarketInfo),OOP,StopLevel,你试图设置的SL,等等,等等。 William Roeder 2011.11.17 12:34 #33 shinobi: 我用MODE_TICKVALUE(即12.50)而不是MODE_TICKSIZE(0.25)调用我的DoubleRound函数。 滴答值肯定是错误的。试着用ticksize来代替这个。 double DoubleRound(double number, double step){ return( MathRound(number/step)*step ); } [删除] 2011.11.19 18:28 #34 亲爱的猛禽,WHRoeder和SDC。 130号的止损错误不再出现了。最后的步骤似乎终于找到了问题所在。 我将在这之后再发一个帖子,总结所有采取的步骤。这样论坛里其他与错误#130作斗争的人就可以把这个主题作为参考。 谢谢你一直以来的帮助:)。 shinobi Simon Gniadkowski 2011.11.19 19:38 #35 shinobi: 谢谢你一直以来的帮助:)。 忍者 做得好,坚持下去......总是有解释的,只是有时会很难找到。 [删除] 2011.11.19 19:58 #36 错误#130的可能原因参考:无效的止损。 一般提示 ECN经纪商 4/5位数的经纪人 变化的市场利率 价差 停止水平 冻结水平 票价大小 完整的例子 鸣谢 一般提示 对抗错误的最重要的技术是过度记录。对所有可能与错误有联系的东西进行输出。如果你定义了一个可以打开和关闭的日志函数,你可以在解决了问题后保留这些代码。 当初始化您的专家顾问时,您应该记录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); } 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的返回值(见上面的一般提示)。 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); 变化的市场利率 另一个可能的原因是,市场汇率在激活专家顾问(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) 价差 如果止损或止盈离进场价格太近,订单将被拒绝。为了避免这个问题,你应该考虑到当前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)) 止损水平 券商有一定的止损水平。如果你的止损低于该水平,你的订单将被拒绝。你可以用MarketInfo(Symbol(), MODE_STOPLEVEL)检查止损水平。 为了避免这种情况,请对照经纪人的止损水平检查您的止损,如果有必要,请调整它。 double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL); if(stoploss < stoplevel) stoploss = stoplevel + 1; 冻结水平 冻结水平是一个类似的概念。你的止损也需要大于经纪人的冻结水平。你可以通过MarketInfo(Symbol(), MODE_FREEZELEVEL)检查冻结水平。 为了避免这种情况,再次根据经纪人的冻结水平检查你的止损。 double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL); if(stoploss < freezelevel) stoploss = freezelevel + 1; 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)); 完整的例子 下面是一个完整的小例子,其中考虑到了上述所有的反击措施。 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 鸣谢 感谢Raptor, WHRoeder, SDC, BigAl, gjol和35806帮助我摆脱了这个错误,并把这个参考资料放在一起。 1234 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
我用MODE_TICKVALUE(即12.50)而不是MODE_TICKSIZE(0.25)调用我的DoubleRound函数。
我修复了它,但它并没有使#130消失
。
这是一个带有更新的DoubleRound行的错误日志:
作为比较,这里是一个日志,它在那里工作:
无论如何,现在似乎更频繁地工作了,我们肯定是越来越接近了。)
在任何情况下,它现在似乎更经常工作,我们肯定会越来越接近。)
我看不出为什么修改会失败 ......你在OrderSend和OrderModify之间得到了一个新的Bid/Ask吗?
我现在能建议的是,当你得到一个错误的130... ...重新打印所有的东西,Bid,Ask(使用MarketInfo),OOP,StopLevel,你试图设置的SL,等等,等等。
我用MODE_TICKVALUE(即12.50)而不是MODE_TICKSIZE(0.25)调用我的DoubleRound函数。
130号的止损错误不再出现了。最后的步骤似乎终于找到了问题所在。
我将在这之后再发一个帖子,总结所有采取的步骤。这样论坛里其他与错误#130作斗争的人就可以把这个主题作为参考。
谢谢你一直以来的帮助:)。
shinobi
谢谢你一直以来的帮助:)。
忍者
对抗错误的最重要的技术是过度记录。对所有可能与错误有联系的东西进行输出。如果你定义了一个可以打开和关闭的日志函数,你可以在解决了问题后保留这些代码。
当初始化您的专家顾问时,您应该记录MarketInfo可以告诉您的所有信息:https://docs.mql4.com/constants/marketinfo
另外,一定要注意检查函数的返回值,例如OrderModify。
ECN经纪商要求您为买入/卖出和止损/获利做出单独的订单。所以你需要把你的代码分成两个订单,像这样。
对于卖出订单,你需要用OP_SELL代替OP_BUY。你还应该检查OrderSelect和OrderModify的返回值(见上面的一般提示)。
一些经纪商要求将止损、止盈和滑点调整为4/5位数。你可以在你的init()函数中加入以下代码(thx WHRoeder)来做到这一点。
然后你需要将止损、止盈和滑点与pips2db1相乘,再发送给经纪商。
另一个可能的原因是,市场汇率在激活专家顾问(EA)和执行EA OrderSend()或OrderModify()之间发生变化。为了避免这个问题,有两个可能的解决方案。
第一种是使用。RefreshRates(),然后再使用预定义的市场变量,例如。Ask和Bid。(这些变量在嘀嗒声激活EA时获得其值)
第二种是根本不使用预定义的市场变量。相反,你可以使用MarketInfo()的当前市场价值。用MarketInfo()代替Ask, Bid和Point。
如果止损或止盈离进场价格太近,订单将被拒绝。为了避免这个问题,你应该考虑到当前Ask和Bid之间的价差。同样有两个解决方案。
第一种是计算价差并将其加入/减去你的止损/止盈。
第二种解决方案是在计算止损或止盈时,使用卖出价和买入价隐含地将价差考虑在内。
券商有一定的止损水平。如果你的止损低于该水平,你的订单将被拒绝。你可以用MarketInfo(Symbol(), MODE_STOPLEVEL)检查止损水平。
为了避免这种情况,请对照经纪人的止损水平检查您的止损,如果有必要,请调整它。
冻结水平是一个类似的概念。你的止损也需要大于经纪人的冻结水平。你可以通过MarketInfo(Symbol(), MODE_FREEZELEVEL)检查冻结水平。
为了避免这种情况,再次根据经纪人的冻结水平检查你的止损。
最后,你的止损或止盈可能被拒绝,因为符号只支持与它的ticksize相匹配的止损/止盈。Ticksize是符号的奖赏可以上升和下降的最小距离。例如,如果价格是1000,ticksize是0.25,那么价格只能上升或下降0.25的倍数(0.25*n,其中n是一个自然数)。所以价格可能上升0.25到1000.25或下降1.75到998.25。
为了考虑ticksize,你需要一个函数将双倍值四舍五入到某个阶梯值(例如,最接近的0.25)。下面就是这样一个函数。
例如,用 number = 1023.81234 和 step = 0.25 调用 DoubleRound 会返回 1023.75。用1023.967834调用它将返回1024.00。
现在,在发送止损或止盈之前,用以下方法将其四舍五入到符号的ticksize。
下面是一个完整的小例子,其中考虑到了上述所有的反击措施。
我希望这有助于摆脱#130。如果修改你的代码不起作用,先用一个最小的例子,就像上面的例子。然后,当错误消失的时候,再把修改后的代码接过来,变成你的代码。
祝您好运。
shinobi
感谢Raptor, WHRoeder, SDC, BigAl, gjol和35806帮助我摆脱了这个错误,并把这个参考资料放在一起。