循环和关闭或删除订单 - 页 5

 
Eleni Anna Branou:

请使用</>按钮来插入你的代码。


我很抱歉......这里是正确的格式。

OrdersTotal()不正确...

我对使用OrdersTotal() 的循环代码序列没有给出正确的结果感到惊讶(在两个不同的经纪商那里观察到)。

我在Linux Ubuntu-MATE 16.04桌面上使用MT4 1090版本,运行WINE 3.0。

这是我一直在使用的东西...

这里是。

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

我注意到在两个不同的经纪商那里,OrdersTotal()的值并不总是与MT4经纪商的'Trade'标签中显示的一致。 最初,我认为是经纪商导致OrdersTotal()不能正常工作。当我在第二个经纪商那里注意到时,我开始怀疑MT4是否有一个内部'问题',或者我的代码是错误的,或者这是否是一个与服务器同步的问题 ....?

在阅读了这个论坛主题后,我想知道我是否可以通过改变for...循环来获得更好的结果。

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
或者,是否有一个标志或一行代码可以确保OrdersTotal()在OnTick()事件中被正确同步?

任何关于这个问题的澄清都将是非常有帮助的,我们将非常感激!

 
Simon Gniadkowski:

这是我看到的最常见的错误之一,部分原因可能是由于像Expert Advisor Builder这样的垃圾。 因此,我认为现在是时候为这个问题建立一个专门的主题,以便将来可以链接到它,供人们参考。

问题

让我们举个简单的例子;我们想要一个函数来关闭我们EA的所有未结订单,有很多例子,但让我们从头开始创建一个。

我们需要一个循环,因为我们想关闭特定EA的所有订单, 这个循环,我们将有代码来选择订单,代码来检查它是正确的符号和魔法数字,最后代码来关闭订单。

这段代码是坏的.. . 不要使用它.. . 我将在下一节中解释原因 .

解释

让我们通过上面的代码......一行一行的,一个一个的订单......来工作。

让我们假设我们有以下要关闭的订单,他们都有相同的魔法号码和符号,所以我们希望我们的代码能将他们全部关闭。

位置 票号
0111
1222
2333
3444
4555

循环的第一次运行。

PositionIndex的初始值是0,所以位置0的订单被选中,票号是111,这个订单被成功删除,其余订单的位置变化如下。

位置 票号
0222
1333
2444
3555

循环的第二次运行。

现在PositionIndex 的值是1,所以位置1的订单被选中,票号333, 这个订单被 成功 删除,其余订单的位置变化 如下

位置 票号
0222
1444
2555

循环的第三次运行。

现在 PositionIndex的值 是2,所以位置2的订单被选中,票号是555, 这个订单被 成功 删除,其余订单的位置变化 如下

位置 票号
0222
1444

循环的第四次运行。

现在 PositionIndex的值 是3 OrderSelect()试图选择位置3的订单,但失败了,继续执行代码到循环中的下一个值。


循环的第5次和最后一次运行。

现在 PositionIndex是4,OrderSelect()试图选择位置4的订单, 但失败了,Continue将代码执行到循环中的下一个值。 ...循环已经结束。


我们现在只剩下2个订单,即222和444号票,它们本应被关闭,但却没有。

解决方案

下面的代码是在关闭未结订单或删除待定 订单时的正确做法 ......

关键的区别是,该循环从(TotalNumberOfOrders - 1 ) 递减0

让我们再一次通过上面的代码 ...... 一行一行地,一个一个订单地 ......

我们有和之前一样的订单。

位置 票数
0111
1222
2333
3444
4555

循环的第一次运行。

PositionIndex的初始值是TotalNumberOfOrders-1,等于5-1=4, 所以位置4的订单被选中,票号555,这个订单被成功删除,其余订单的位置变化如下。

位置 票号
0111
1222
2333
3444

循环的第二次运行。

现在PositionIndex 的值是3,所以位置3的订单被选中,票号444, 这个订单被 成功 删除,其余订单的位置变化 如下

位置 票号
0111
1222
2333

循环的第三次运行。

现在 PositionIndex的值 是2,所以位置2的订单被选中,票号333, 这个订单被 成功 删除,其余订单的位置变化 如下

位置 票号
0111
1222

循环的第4次运行。

现在 PositionIndex的值 是1,所以位置1的订单被选中,票号222, 这个订单被 成功 删除,其余订单的位置变化 如下

位置 票号
0111

第五次也是最后一次运行循环。

现在 PositionIndex 的值 是0 ,所以位置0的订单被选中,票号111, 这个订单被 成功 删除,值0是循环的最后一个有效值 . . . 循环已经结束。

我们已经成功删除了所有匹配的订单 . .

链接到这个主题。 循环和关闭或删除订单

非常感谢!这是很清楚的解释。
 
编码员们好。
事实上,我有一个代码,我相信我已经做对了,但选择对我来说不起作用,因为我无法读取所选订单的OpenPrice。其他一切都很好,只是提供了这部分代码。我不知道为什么。
整个代码有4个部分,我需要在订单发送后立即调用OrderOpenPrice...。OrderSend工作良好,OrderSelect不会得到我需要的结果。如果你能帮助,请参考代码的1个部分。
谢谢你。
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

感谢亲爱的Simon Gniadkowski。

你的帖子真的节省了我的时间。

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

这是我建议的关闭市场订单的代码

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

我建议,如果使用前向循环,这是正确的方法(遵守美国经纪商的先进先出规则)。

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

在前向循环中。

  1. OrderTotal()函数在for循环内使用,在每次循环迭代时更新剩余的未结订单数量,以避免索引超出数组范围
  2. 每关闭一个订单,索引i就会被递减,以避免跳过一些订单。
 
amrali: 索引i随着每个订单的关闭而递减,以避免跳过一些订单。
在存在多个订单的情况下(一个EA多个图表,多个EA,手动交易,),当你在等待当前的操作(关闭,删除,修改)完成时,其他订单上的任何数量的 操作 可能同时发生,并改变了位置索引。
  1. 对于非 先进先出(美国经纪商)(或 EA每个符号只开一个订单),你可以 简单地 在一个位置循环中倒数,你不会错过订单。要养成经常倒数的习惯。
    循环和关闭或删除订单 - MQL4编程论坛
    对于 先进先出(美国经纪商,) 你(可能)处理每个符号的多个订单,你必须 找到最早的订单,关闭它,在操作成功 后,重新处理所有剩余的位置。
    按先进先出规则关闭订单 - Strategy Tester - MQL4编程论坛 - Page 2 #16

  2. 检查OrderSelect,以防早期头寸被删除。
    什么是函数的返回值?我如何使用它们?- MQL4编程论坛
    MQL4程序中的常见错误以及如何避免这些错误 - MQL4文章
  3. 如果 你(可能)处理多个订单,必须 在服务器调用后调用RefreshRates(),如果你想在下一个订单/服务器调用中使用预定义变量(Bid/Ask)或(独立于方向,使用)OrderClosePrice()
 

你会知道这对我有多大帮助。不仅仅是我正在研究的代码,而是我完全的理解。它现在工作得很完美,而且我有了以不同方式实现它的理解。

真的非常感谢这些信息。