【问题标题】:Why MQL4 OrderModify() will not modify the order when backtesting?为什么 MQL4 OrderModify() 在回测时不会修改订单?
【发布时间】:2016-04-23 20:57:29
【问题描述】:

我正在尝试在 MetaTrader 4 中为我的公开市场订单添加止损,当头寸获得 100 点“有利”时,这是相等的到订单开盘价;

OrderStopLoss() == OrderOpenPrice()

但这并没有发生。

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

好的,这就是我目前所拥有的,一个用于买入的循环,一个用于卖出的循环。正如我被建议做的那样,我还对“双打”进行了规范化,并且还在顶部声明了 BuyMod 和 SellMod 为“真”。这应该确保默认值不会诉诸 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

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

【问题讨论】:

  • 在更新的代码段上:tp 问题仍然存在,OrderModify() 之后的 Print() 仍然缺失。
  • 虽然 StackOverflow 不是 Do-a-Homework 网站,但让我在下面的更新中提出解决方案的一些方向
  • 对不起,什么 tp 问题&我想在订单修改失败时打印所有错误。我现在很困惑的原因是因为这与 OrderClose 的格式相同并且没有问题。我有一个完全编码的策略,非常有利可图。现在我正在向其中添加这一部分,我不明白为什么这很难实现。
  • tp 问题在您关于同一主题的第二个或第三个问题中得到了解释 >>> stackoverflow.com/a/36743552/3666197 另外,您更新的代码仍然对值进行零自诊断用于OrderModify() 呼叫和GetLastError()。除了执行这两个步骤之外,几乎没有其他方法可以诊断故障的根本原因。或者聘请该领域的一些专业服务人员通过知识外包来解决您的问题。在团队中拥有数百人*年的经验,没有人可以拥有相同的、相同的知识库。但肯定可以买到缺失的部分。
  • 我还要说一下,OrderClose() 的函数调用签名与 OrderModify() 的函数调用签名截然不同。检查MQL4 IDE 文档并仔细查看差异。

标签: algorithmic-trading mql4 metatrader4 mt4


【解决方案1】:

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


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

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

因此,
无论价格进入服务器端指令{ OrderSend(), OrderModify(), ... },人们都应始终准备这样的aPriceDOMAIN
通过调用到 NormalizeDouble( ... , _Digits ),在标准化价格到达任何服务器端指令调用之前。

听起来可能有点幼稚,但可以为您解决服务器端拒绝的问题。

定期将NormalizeDouble() 调用添加到您的代码中,作为您的救生背心。


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

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

在实践中,
这意味着,如果您指示 { OrderSend() | OrderModify() } 设置 / 移动 aPriceDOMAIN 级别设置得太接近当前实际 Ask/Bid(违反经纪人禁止的STOP_ZONE

删除/修改aPriceDOMAIN的止盈或止损水平,即已经设置并且现在,在 Broker-forbidden FREEZE_ZONE 与实际 Ask/Bid 的距离内,
这样的指令将不会成功接受并执行。

因此,除了致电NormalizeDouble() 之外,请在价格移动“足够远”时等待更长的时间,并定期检查是否违反了禁止的STOP_ + FREEZE_ 区域,然后再在您的订单管理部分进行任何修改您的算法交易项目。

不管怎样,欢迎来到MQL4的狂野世界

Update: 虽然 StackOverflow 不是一个 Do-a-Homework 网站,但让我提出一些解决方案的方向:

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()
                                        }
      }
}

【讨论】:

  • NormalamizeDouble 听起来像是一个计划,但我的经纪商 StopLevels 范围为 20-30,而我将盈亏平衡点编码为 100 点到好点,远高于止损水平。但我会加倍尝试 Normalize。谢谢 :)
  • A STOPLEVEL 大约 20-30 意味着您的代码必须等待,直到 Ask / Bid 达到在经纪人确认 &接受要执行的此类设置。
  • 好的,所以我很清楚,如果我将盈亏平衡值设置为 100 点,这意味着我需要等待 120-130 点才能将止损值移动到开盘价?
  • 全局变量 double pnlPoints;双倍价格,sl,tp;双点;诠释停止水平;诠释 cmd;双newSL; 本地声明 pnlPoints = 0 point = MarletInfo((Symbol(),MODE_POINT)); pnlPoints = 0;点 = MarketInfo(Symbol(),MODE_POINT); stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL)+MarketInfo(Symbol(),MODE_SPREAD)); sl = NormalizeDouble(OrderStopLoss(),Digits); tp = OrderTakeProfit(); cmd = OrderType();
  • 对,您需要等待 100 + STOPLEVEL 点才能获得实际 XTO 价格(询问 OP_SELL)允许您将 SL 移近 -100 点(接近实际 XTO 价格跟踪 SL 接近度,即大于等于经纪人定义的 STOPLEVEL 距离),同时不接触任何 FREEZELEVEL 区域。
【解决方案2】:

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

OrderStopLoss() == OrderModify() 将评估为 false,而 == 又将评估为 0,因为 == 是一个比较运算符。

OrderStopLoss() 是对另一个内置函数(不是变量)的调用,您无法向其中保存任何内容,因此 OrderStopLoss() = 4 不会也不行。

来自 MQL4 文档:

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() 来设置新的止损。

【讨论】:

  • 感谢您的回复,我已将“双重止损”更改为 OrderOpenPrice(),当仓位达到 100 点时,它仍然没有为仓位添加止损。就好像某些东西被系统阻止读取一样。添加了 GetLastError() - 没有,在日志中查看 - 没有。代码也可能不存在。现在,我对此束手无策-我只是无法锻炼为什么这没有按照我的编程去做。 bool =ModBuy 在全局变量中。
  • ModBuy = OrderModify(0,0,OrderOpenPrice(),0,0,buycolor);
【解决方案3】:

真的很抱歉,我是Stackoverflow的新手,这是我现在根据大家的cmets和推荐修改的代码

 **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());
                                   }
                   }              
                }

【讨论】:

  • 您可能想知道,这里使用的OrderModify() 呼叫签名(我也进一步复制到其他地方,最近才更正)是错误的。 MQL4 文档要求在调用中还包含一个 OrderExpiration 值,即使该订单当前不再是挂单。查看文档和IDE工具提示,这有助于提醒函数调用参数的顺序。
  • 我认为这是我和我的帐户所特有的,它阻止了这种情况的发生 - 没有理由不发生这种情况。
猜你喜欢
  • 2016-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
相关资源
最近更新 更多