我的EA做了一个重复输入 - 页 7

 

如果我使用睡眠,我将失去虱子?

能否与我分享?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

如果我使用睡眠,我将失去虱子?

能否与我分享?

这取决于你的策略。由于 "双重交易 "的问题只有在你的交易代码在每个点上执行时才会发生,你可能有一个依赖点的策略。所以你要评估一下,如果你在延迟(睡眠)期间损失了ticks,会有什么后果。

 
angevoyageur:

这取决于你的策略。由于 "双重交易 "的问题只有在你的交易代码在每一个点上执行时才会发生,你可能有一个依赖点的策略。所以你要评估一下,如果你在延迟(睡眠)期间损失了tick,会有什么后果。

因此,如果我睡了800分钟

意味着我在接下来的800毫秒内会失去点数?在我进入交易后,我的EA什么也不做,只是坐在那里直到TP或SL或等待时间退出。

所以,如果我使用睡眠,我的策略是可以的?

调用refreshrates()是否能找回点位?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

所以如果我睡了800

意味着我在接下来的800毫秒内失去了点子?在我进入交易后,我的EA什么也不做,只是坐在那里直到TP或SL或等待时间退出。

所以,如果我使用睡眠,我的策略是可以的?

调用refreshrates()是否能找回点位?

doshur, 你失去的点数就是你失去的,没有回溯机。

关于文档,https://www.mql5.com/en/docs/common/sleep,该函数在指定的时间间隔内暂停执行当前的专家顾问或脚本。

因此,即使是OnTimer事件也会被暂停,可能是因为EA只使用一个线程。

因此,使用一个固定的睡眠不是一个明确的解决方案,只是 "数字学",也就是说,如果延迟低于你的值,这是一个变通方法。

这就是为什么我建议在打开交易后循环测试PositionSelect,仔细检查PositionOpen的执行和返回,作为一个比Sleep()更好的解决方法,这也证明了问题的原因(根据angevoyageur 的测试)。

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 

这就是我现在使用的东西。我应该在哪里以更优雅的方式编码图利提供的解决方法呢?

//
         {
            Price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

            if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
         }
 
doshur:

这就是我现在使用的东西。我应该在哪里以更优雅的方式编码图利提供的解决方法呢?

你好,doshur,我在我的一个EA中也有重复输入 的问题。事实上,这些问题只有在我交易高流动性资产时才会发生。即使在设置订单以异步模式发送后,EA "显然 "等待服务器响应以更新PositionsTotal()的时间过长......同时,其他进入的ticks触发了发送第二个订单的条件......在葡萄牙论坛,我发布了一个解决方法,我想在这里分享。

这个想法很简单。

//--- global variables
CTrade trade;
bool position_opened=false;

//--- inside OnTick()
if( conditions to open && position_opened==false )
  {
   //--- set the global variable to true to avoid duplicate orders
   position_opened=true;
   trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment");
  }

这段代码的唯一问题是服务器不接受订单的情况,所以你需要 "重置 "全局变量......你可以使用这个。

MqlTradeResult mresult;

//--- 
if(mresult.retcode==10009 || mresult.retcode==10008)
  {Print("Success!");}
else 
  {
   Print("Error = ",GetLastError());
   ResetLastError();
   //--- Sets the global variable to false
   position_opened=false;
   return;
  }

因此,在发送的第一个订单返回错误的情况下,全局变量将被设置为假,这样EA就可以发送另一个订单。然而,我不得不说,我只在股票和期货中测试了这段代码,而不是在外汇市场... :-(

 
Malacarne:

你好doshur,我的一个EA也有重复输入的问题。事实上,这些问题只有在我交易高流动性资产时才会出现。即使在设置订单以异步模式发送后,EA "显然 "等待服务器响应以更新PositionsTotal()的时间过长......与此同时,其他传入的ticks触发了发送第二个订单的条件......在葡萄牙论坛,我发布了一个解决方法,我想在此分享。

这个想法很简单。

这段代码的唯一问题是服务器不接受订单的情况,所以你需要 "重置 "全局变量......你可以使用这个。

因此,在发送的第一个订单返回错误的情况下,全局变量将被设置为假,这样EA就可以发送另一个订单。然而,我不得不说,我只在股票和期货中测试了这段代码,而不是在外汇市场... :-(

这似乎是可行的。让我们看看figurelliangevoyageur 是否对这个解决方法有任何意见...
 
doshur:
这似乎是可行的。让我们看看figurelliangevoyageur 是否对这个解决方法有什么意见......

Malacarne提出的这个解决方案(我将提出一些调整)非常好,因为对我来说,这不是一个变通办法(如Malacarne谦虚地说),而是解决这个问题的一个优雅和正确的方法。

在我看来,最初的重复输入问题不是MT5的错误,而是一个编码错误,因为帮助中提到。

"PositionOpen(...)方法的成功完成并不总是意味着交易操作的成功执行有必要 使用ResultRetcode()ResultDeal()返回的值来 检查交易请求的结果(交易服务器返回代码)。"

因此,我建议做一些小的改动,以便对任何市场条件有更强的适应性。

1)测试PostionOpen()的返回值,比如说,和原代码一样。

if (trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")) position_opened=true;

2)对ResultRetcode()进行更完整的处理,因为你可以有其他相关的位置打开,如 10010 -TRADE_RETCODE_DONE_PARTIAL - 只有部分请求完成。另外,10008 - TRADE_RETCODE_PLACED - 下订单对我来说不是成功,只是10009 -TRADE_RETCODE_DONE -请求完成,而且这是 异步信息,所以Malacarne代码的第二部分可以考虑这个和/或交易票据,在交易执行后也是如此。

总之,对我来说,我们现在已经走在正确的道路上了,而且是最后的切割。

 
Malacarne:

你好doshur,我的一个EA也有重复输入的问题。事实上,这些问题只有在我交易高流动性资产时才会发生。即使在设置订单以异步模式发送后,EA "显然 "等待服务器响应以更新PositionsTotal()的时间过长......与此同时,其他传入的ticks触发了发送第二个订单的条件......在葡萄牙论坛,我发布了一个解决方法,我想在此分享。

这个想法很简单。

这段代码的唯一问题是服务器不接受订单的情况,所以你需要 "重置 "全局变量......你可以使用这个。

因此,在发送的第一个订单返回错误的情况下,全局变量将被设置为假,这样EA就可以发送另一个订单。然而,我不得不说,我只在股票和期货中测试了这段代码,而不是在外汇市场... :-(

这是一个有效的方法,但是你必须在平仓时将你的全局变量position_opened重置为false。你是怎么做的?

关于你的实现,一些细节。

  1. 没有必要将 position_opened 设为 true,然后在出现错误时再设为 false。
  2. 你正在使用 CTrade 类的一个对象,所以不需要使用一个新的MqlTradeResult 结构。
  3. 正如 figurelli 在他的帖子中指出的,你必须检查 PositionOpen 的返回值。
  4. 该类的名称是 CTrade,而不是 Ctrade。Mql5 是区分大小写的。
  5. position_opened是一个bool,不需要把它和false比较。如果你这样做,你必须使用'=='而不是'='。

所以,这里是修改后的代码(已编译但未测试)。

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- global variables
CTrade trade;
bool position_opened=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   bool conditions_to_open;
   ENUM_ORDER_TYPE order_type;
   double lot;
   double price,sl,tp;

//---...set variables

//--- inside OnTick()
   if(conditions_to_open && !position_opened) //-- Or position_opened==false
     {
      if(trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")
         && 
         (trade.ResultRetcode()==10009 || trade.ResultRetcode()==10008)) //-- Or others condition according to your needs
        {
         //--- set the global variable to true to avoid duplicate orders
         position_opened=true;
         Print("Success!");
        }
      else
        {
         Print("Error = ",GetLastError(), "trade error = ", trade.ResultRetcode());
         //--- Sets the global variable to false
         // position_opened=false;                                         //-- Not needed as position_opened is already false
         return;
        }

     }
//--- 
  }
//+------------------------------------------------------------------+
 
figurelli:

...

在我看来,原来的重复输入问题并不是MT5的错误,而是一个编码错误,因为帮助中说到。

"PositionOpen(...)方法的成功完成并不总是意味着交易操作的成功执行有必要 使用ResultRetcode()ResultDeal()返回的值来 检查交易请求的结果(交易服务器返回代码)

我不认为这与本主题的问题有关。我们得到的问题是,如果请求被成功填满,并且打开了一个头寸。但这个头寸是在交易服务器上建立的,我们遇到的问题是,当有一个比平时更重要的延迟时,MT5终端在一个新的tick已经被处理之后才被通知这个新的头寸。

这不是一个错误,因为它是这样设计的。但在我看来,对于一个明确允许同步和异步交易请求的平台来说,这是一个糟糕的设计。我们在这里讨论的是一个应该是同步的请求,但事实上它并不是真正的同步,因为当你从服务器得到请求的回复时(上面代码中的trade.ResultRetCode),我们仍然需要等待MT5平台被告知并更新交易结果。(我通过这个主题了解了所有这些)。

因此,我建议做一些小的改动,以便对任何市场情况有更强的适应性。

1) 测试PostionOpen()的返回值,比如说,和原来的代码一样。

2)对ResultRetcode()进行更完整的处理,因为你可以有其他相关的位置打开,如 10010 -TRADE_RETCODE_DONE_PARTIAL - 只有部分请求完成。另外,10008 - TRADE_RETCODE_PLACED - 下订单对我来说不是成功,只是10009 -TRADE_RETCODE_DONE -请求完成,而且这是异步信息,所以Malacarne代码的第二部分可以考虑这个和/或交易票据,在交易执行后也是如此。

总之,对我来说,我们现在已经走在正确的道路上了,而且是最后的切割。

当然,你是完全正确的,我们必须检查PositionOpen的返回值和交易结果的返回代码。然而,ResultRetCode是同步的,MT5数据库对头寸(交易和订单)的更新才是异步的。我用你的建议做的测试 证明了这一点,因为我使用的代码当然是检查交易请求的返回值。