为什么 MQL4 OrderModify() 在回测时不会修改订单?

Why MQL4 OrderModify() will not modify the order when backtesting?

我正在尝试 ADDMetaTrader 4 我的公开市场订单中止损,当头寸达到 100 点时“到good" 等于订单开仓价;

OrderStopLoss() == OrderOpenPrice()

但这并没有发生。

我已经添加了 Print()GetLastError() 函数,但日志中没有出现任何内容,所以它一定是我编码中的东西 - 但看不出有什么问题。

好的,这就是我目前所拥有的,一个用于买入的 for 循环,一个用于卖出。我还按照建议对“双打”进行了规范化,并且还在最顶部将 BuyMod 和 SellMod 声明为“true”。这应该确保默认值不会求助于 false。我还认为如果我告诉您我有 MetaEditor 版本 5 build 1241 可能会有帮助:)

我的代码如下;

/*Breakeven Order Modification*/
bool BuyMod               =  true;
bool SellMod              =  true;
                for(int b = OrdersTotal()-1;b>=0;b--)
                {
                if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
                   {
                   double   aBidPrice   =  MarketInfo(Symbol(),MODE_BID);
                   double   anOpenPrice =  OrderOpenPrice();
                   double   aNewTpPrice =  OrderTakeProfit();
                   double   aCurrentSL  =  OrderStopLoss();
                   double   aNewSLPrice =  anOpenPrice;
                   double   pnlPoints   =  (aBidPrice - anOpenPrice)/_Point;
                   double   stopPoints  =  (aBidPrice - aNewSLPrice)/_Point;
                   int      stopLevel   =  int(MarketInfo(Symbol(),MODE_STOPLEVEL));
                   int      aTicket     =  OrderTicket();
                   if(OrderType() == OP_BUY)
                   if(stopPoints >= stopLevel)
                   if(aTicket > 0)
                   if(pnlPoints >= breakeven)
                   if(aNewSLPrice != aCurrentSL)
                      {
                      BuyMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,buycolor);
                      SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
                      }
                   }
                }
                for(int s = OrdersTotal()-1; s>=0; s--)
                {
                if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))
                   {
                   double   anAskPrice  =  MarketInfo(Symbol(),MODE_ASK);
                   double   anOpenPrice =  OrderOpenPrice();
                   double   aNewTpPrice =  OrderTakeProfit();
                   double   aCurrentSL  =  OrderStopLoss();
                   double   aNewSLPrice =  anOpenPrice;
                   double   pnlPoints   =  (anOpenPrice - anAskPrice)/_Point;
                   double   stopPoints  =  (aNewSLPrice - anAskPrice)/_Point;
                   int      stopLevel   =  int(MarketInfo(Symbol(),MODE_STOPLEVEL));
                   int      aTicket     =  OrderTicket();
                   if(OrderType()== OP_SELL)
                   if(stopPoints >= stopLevel)
                   if(pnlPoints >= breakeven)
                   if(aNewSLPrice != aCurrentSL)
                   if(aTicket > 0)
                      {
                      SellMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,sellcolor);
                      SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
                      }
                   }
                }

交易算法-交易 mql4 metatrader4

shareeditdeleteflag

刚刚编辑

2 天前问过

托德·吉尔贝 264

您可能想知道,Whosebug 不提倡重复问题。 (见

问题出在您对内置 OrderModify() 函数的调用中。

OrderStopLoss() == OrderModify() 将评估为 false 反过来将评估为 0 因为 ==是比较运算符。

一个OrderStopLoss()是对另一个内置函数(不是变量)的调用,你不能向它保存任何东西所以 OrderStopLoss() = 4也不行。

From the MQL4 documentation:

bool  OrderModify( int        ticket,      // ticket 
                   double     price,       // price 
                   double     stoploss,    // stop loss 
                   double     takeprofit,  // take profit 
                   datetime   expiration,  // expiration 
                   color      arrow_color  // color 
                   );

在您的情况下,假设 ModBuy 已在代码中某处定义:

ModBuy = OrderModify(  OrderTicket(),      // <-ticket from record OrderSelect()'d
                       OrderOpenPrice(),   // <-price  from current record
                       OrderOpenPrice(),   // <-price  from current record
                       OrderTakeProfit(),  // <-TP     from current record
                       0,                  // ( cannot set P/O expiration for M/O )
                       buycolor            // ( set a color for a GUI marker )
                       );

或者您可以使用任何其他有效值而不是第二个 OrderOpenPrice() 来设置新的止损。

除了满足 MQL4 语法规则外,
还有更多条件:


第一个隐患是数字四舍五入问题

MetaQuotes, Inc. 建议尽可能将浮动值规范化为适当的价格表示。

因此,
只要价格进入服务器端指令{ OrderSend(), OrderModify(), ... },就应该总是在标准化价格到达任何服务器端指令调用之前,通过调用 NormalizeDouble( ... , _Digits ) 准备这样的 aPriceDOMAIN

可能听起来很幼稚,但是 可以避免服务器端拒绝的问题。

添加 NormalizeDouble() 定期调用您的代码作为您的救生衣。


秒,更好的隐患在 STOP_ZONE-s和FREEZE_ZONE-s

虽然不直接可见,但任何经纪人都在其各自的条款和条件中设置了这些参数。

实际上,
这意味着,如果您指示 { OrderSend() | OrderModify() }set / move aPriceDOMAIN 级别设置太接近当前实际值 Ask/Bid(违反 Broker-forbidden STOP_ZONE )

删除/修改aPriceDOMAIN 止盈或止损水平,它们已经设置并且现在在经纪商禁止的范围内 FREEZE_ZONE与实际相差Ask/Bid,
这样的指令将不会被成功接受和执行。

因此,除了调用 NormalizeDouble() 之外,请始终在价格移动 "far" 时等待更长时间,并定期检查是否违反禁止 STOP_ + FREEZE_ 区域在对算法交易项目的订单管理部分进行任何修改之前。

无论如何,欢迎来到 MQL4

的狂野世界

Update: 虽然 Whosebug 不是一个做功课的网站,但让我提出几个解决方案的方向:

for ( int b = OrdersTotal() - 1; b >= 0; b-- ) // ________________________ // I AM NOT A FAN OF db.Pool-looping, but will keep original approach for context purposes
{     if (  ( OrderSelect( b, SELECT_BY_POS, MODE_TRADES ) ) == true )
      {    // YES, HAVE TO OPEN A CODE-BLOCK FOR if()-POSITIVE CASE:
           // ------------------------------------------------------
              double aBidPRICE   = MarketInfo( Symbol(), MODE_BID );       // .UPD
              double anOpenPRICE     = OrderOpenPrice();                   // .SET FROM a db.Pool Current Record
              double aNewTpPRICE     = OrderTakeProfit();                  // .SET FROM a db.Pool Current Record
              double aCurrentSlPRICE = OrderStopLoss();                    // .SET FROM a db.Pool Current Record
              double aNewSlPRICE     = anOpenPRICE;                        // .SET
              double  pnlPOINTs      = ( aBidPRICE - anOpenPRICE )/_Point; // .SET
              double stopPOINTs      = ( aBidPRICE - aNewSlPRICE )/_Point; // .SET
           // ------------------------------------------------------------ // .TEST
              if (                        OP_BUY    == OrderType()        )
                   if (                   Period()  == OrderMagicNumber() )
                        if (             stopPOINTa >  stopLevel          )
                             if (         pnlPOINTs >= breakeven          )
                                  if (  aNewSlPRICE != aCurrentSlPRICE    )
                                  {  // YES, HAVE TO OPEN A BLOCK {...}-CODE-BLOCK FOR THE if()if()if()if()-chain's-POSITIVE CASE:
                                     // -------------------------------------------------------------------------------------------
                                        int aBuyMOD = OrderModify( OrderTicket(),
                                                                   OrderOpenPrice(),
                                                                   NormalizeDouble( aNewSlPRICE, Digits ),
                                                                   NormalizeDouble( aNewTpPRICE, Digits ),
                                                                   0,
                                                                   buycolor
                                                                   );
                                        switch( aBuyMOD )
                                        {   case ( NULL  ): { ...; break; } // FAIL ( ANALYSE ERROR )
                                            default:        { ...; break; } // PASS OrderModify()
                                        }
      }
}

真的很抱歉,我是 Whosebug 的新手,这是我现在根据下面大家的评论和推荐修改后的代码

 **Local Declarations**
  pnlPoints            =  0;
  point                =  MarketInfo(Symbol(),MODE_POINT);
  stopLevel            =  int(MarketInfo(Symbol(),MODE_STOPLEVEL)+MarketInfo (Symbol(),MODE_SPREAD));
  sl                   =  NormalizeDouble(OrderStopLoss(),Digits);
  tp                   =  OrderTakeProfit();
  cmd                  =  OrderType();
  breakeven            =  100;

  **Global Variables**
  double   pnlPoints;
  double   price,sl,tp;
  double   point;
  int      stopLevel;
  int      cmd;
  int      breakeven;
  double   newSL;
                for(int b = OrdersTotal()-1; b>=0; b--)
                {
                if((OrderSelect(b,SELECT_BY_POS,MODE_TRADES))==true)
                price = MarketInfo(Symbol(),MODE_BID);
                newSL = NormalizeDouble(OrderOpenPrice(),Digits);
                pnlPoints = (price - OrderOpenPrice())/point;
                   {
                   if(OrderType()==OP_BUY)
                      if(OrderMagicNumber() == Period())
                         if((price-newSL)/point>=stopLevel)
                            if(pnlPoints>=breakeven)
                               if(sl!=newSL)
                                  ModBuy = OrderModify(OrderTicket(),OrderOpenPrice(),newSL,tp,buycolor);
                                   else if(ModBuy == false)
                                   {
                                   Print("OrderModify failed with error #",GetLastError());
                                   }
                   }              
                }