История ордеров

 

Всем привет! Столкнулся с проблемой... сделал робота, который читает историю и открывает сделку.. пример выглядит так: Закрылся ордер на продажу по тейку.. открывается новый ордер на продажу итд... Вопрос в том что если одновременно закроется 2 ордера, то откроется только 1 ордер,  а не 2... Как прочитать эти последние 2 ордера, чтобы открылись новые 2?? Проблема выходит когда одновременно закрываются ордера... читает только 1 ордер вместо 2 или 3 одновременно закрывшихся!


void check_history_buy()
{ 
   for(int i=OrdersHistoryTotal(); i>=OrdersHistoryTotal()-1; i--)
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderSymbol()==Symbol() && ((OrderMagicNumber()==Magic) || (OrderMagicNumber()!=Magic)))
        { 
         int        nOrderType     = OrderType();
         int        nOrderTicket   = OrderTicket();
         datetime   OrderCloseT=OrderCloseTime();
    
          {
          if(nOrderType==OP_BUY && OrderStopLoss()>=OrderClosePrice() &&((StringFind( OrderComment(), "[sl]" ) == 0) || (StringFind( OrderComment(), "Pithecophaga Jefferyi[sl]" )) == 0)) {bbuyp=1;}
          if(nOrderType==OP_BUY && OrderTakeProfit()<=OrderClosePrice()&& ((StringFind( OrderComment(), "[tp]" ) == 0)||(StringFind( OrderComment(), "Pithecophaga Jefferyi[tp]" ) == 0))) { bbuy=1;}

          }
      }
}


 

 

у Вас код некорректно ищет последний ордер, должно быть примерно так:

//_______________________________________________________________________
int LastfOrder(int magic_) 
  {
   int i,k=OrdersHistoryTotal();
   string sy=Symbol();
   datetime t,lasttime=0;
   int ticket=-1;
   for(i=0; i<k; i++) 
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) 
        {
         if((OrderMagicNumber()==magic_) && (OrderSymbol()==sy))
           {
            t = OrderCloseTime();
            if(t>lasttime)
              {
               lasttime= t;
               ticket = OrderTicket();
              }
           }
        }
     }
   return(ticket);
  }
//_______________________________________________________________________

искать нужно по времени закрытия ордера - самое большое время (для ордера с магиком и по символу инструмента) и будет временем закрытия последнего ордера

а в части решения Вашей задачи - в один проход по циклу перебора ордеров можно решить, но нужно в массив загнать время всех ордеров, затем этот массив отсортировать и последние 2 элемента массива и будут то, что Вы ищите, но затем придется сопоставить время и № тикета ордера (нет под рукой примера, я использовал структуру в которой сразу заполнял и время и тикеты)

или решайте в два прохода по циклу перебора ордеров - нашли самый последний ордер и ищите самый последний ордер еще раз и сравнивайте с найденным временем на == - если ==, то не запоминать 

 
Aibek Mugiynov:

Всем привет! Столкнулся с проблемой... сделал робота, который читает историю и открывает сделку.. пример выглядит так: Закрылся ордер на продажу по тейку.. открывается новый ордер на продажу итд... Вопрос в том что если одновременно закроется 2 ордера, то откроется только 1 ордер,  а не 2... Как прочитать эти последние 2 ордера, чтобы открылись новые 2?? Проблема выходит когда одновременно закрываются ордера... читает только 1 ордер вместо 2 или 3 одновременно закрывшихся! 

Для начала нужно хотя бы попытаться прочесть больше одного ордера. Ведь итераций цикла с исполнением тела цикла всего одна - когда i = OrdersHistoryTotal() - 1. Первая итерация (когда i = OrdersHostoryTotal()) заведомо обречена на провал, т. к. элемента списка с таким индексом не существует. Таким образом, нужно хотя бы заголовок цикла подправить (здесь читается два последних ордера):

int nToIndex = OrdersHistoryTotal() - 2;
for (int i = OrdersHistoryTotal() - 1; i >= nToIndex; i--)

Далее потребуется полностью менять подход к решению задачи. Ведь по результату выполнения цикла будет получено только одно значение - открыться в том же направлении или в противоположном. А раз требуется открытие нескольких ордеров, то и сигналов должно быть несколько. Навскидку, потребуется организация массива сигналов.

 
Тогда сохраняйте переменную количества открытых позиций. И когда произошло закрытие, то-есть открытых стало меньше чем ваше число. Проверяйтесь на недостающие количество.
 

вот набросал скрипт, в теории должен работать - проверить не могу, на работе дежурю

#property strict
#property show_inputs

input int Magic = 1234567;
void OnStart()
  {
      datetime t_order;
      int tickets[3];
      t_order = TimeCurrent();
      tickets[0] = LastfOrder(Magic,t_order);
      for(int i=1;i<3;i++){
         tickets[i] = LastfOrder(Magic,t_order);   
      }
  }
//_______________________________________________________________________
int LastfOrder(int magic_,datetime &starttime_)
  {
   int i,k=OrdersHistoryTotal();
   string sy=Symbol();
   datetime t,lasttime=0;
   int ticket=-1;
   for(i=0; i<k; i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if((OrderMagicNumber()==magic_) && (OrderSymbol()==sy))
           {
            t=OrderCloseTime();
            if(t<starttime_)
              {
               if(t>lasttime)
                 {
                  lasttime=t;
                  ticket=OrderTicket();
                 }
              }
           }
        }
     }
   starttime_ = lasttime;
   return(ticket);
  }
//_______________________________________________________________________
единственное, что меня смущает - это фраза, что несколько ордеров могут закрыться одновременно, тип datetime имеет дискретность 1сек, если этого недостаточно, тогда нужно сравнивать время закрытия ордеров на >= и потом с № тикетов еще сравнивать
 
Igor Makanu:

вот набросал скрипт, в теории должен работать - проверить не могу, на работе дежурю

Больше всего нравится Starttime=Lasttime. 

 
Алексей Тарабанов:

Больше всего нравится Starttime=Lasttime. 

работать будет, не захотел переменные плодить, вот и вернул по ссылке время, если хотите то можете переписать в виде:

int LastfOrder(int magic_,datetime starttime_,datetime &lasttime)
  {
   lasttime=0;
....

можно еще и спросить почему ф-ция может возвращать и несуществующие тикеты ......

старался пример дать, вроде получилось

 
Igor Makanu:

вот набросал скрипт, в теории должен работать - проверить не могу, на работе дежурю

единственное, что меня смущает - это фраза, что несколько ордеров могут закрыться одновременно, тип datetime имеет дискретность 1сек, если этого недостаточно, тогда нужно сравнивать время закрытия ордеров на >= и потом с № тикетов еще сравнивать

Спасибо большое!!! Ваш скрипт работает. Я теперь не могу решить последний момент, это когда у меня по тейку закрылись 5 ордеров, соответственно у всех время закрытия одинаковое.. значит нужно прочесть последние 5 ордеров, если закрылись 5 по тейку одновременно..
  

  {
      datetime t_order;
      int tickets[3];
      t_order = TimeCurrent();
      tickets[0] = LastfOrder(Magic,t_order);
      for(int i=1;i<3;i++){
         tickets[i] = LastfOrder(Magic,t_order);   
      }
  }
 
Aibek Mugiynov:

Спасибо большое!!! Ваш скрипт работает. Я теперь не могу решить последний момент, это когда у меня по тейку закрылись 5 ордеров, соответственно у всех время закрытия одинаковое.. значит нужно прочесть последние 5 ордеров, если закрылись 5 по тейку одновременно..
  

ну решите эту задачу в 2 цикла перебора моим скриптом:

1. нашли самый последний закрытый ордер и запомните его время

2. ищите ордера со временем >=  времени закрытия последнего ордера (можно и на знак == искать, но обычно лучше искать на сравнение чем на равенство)

ЗЫ: сложная у Вас задача... а не проще было бы все таки запоминать тикеты при открытии ордеров в массив, и потом по № тикетов анализировать закрытые ордера?

 

попробуйте так будет работать?

#property strict
#property show_inputs

input int Magic = 1234567;
void OnStart()
  {
      datetime t_order;
      int tickets[5];
      t_order = TimeCurrent();
      tickets[0] = LastfOrder(Magic,t_order);
      for(int i=1;i<5;i++){
         tickets[i] = LastfOrder(Magic,t_order,true);   
      }
  }
//_______________________________________________________________________
int LastfOrder(int magic_,datetime &starttime_,bool equally=false)
  {
   int i,k=OrdersHistoryTotal();
   string sy=Symbol();
   datetime t,lasttime=0;
   int ticket=-1;
   for(i=0; i<k; i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if((OrderMagicNumber()==magic_) && (OrderSymbol()==sy))
           {
            t=OrderCloseTime();
            if(t<starttime_ || (equally&&(t==starttime_ )))
              {
               if(t>lasttime)
                 {
                  lasttime=t;
                  ticket=OrderTicket();
                 }
              }
           }
        }
     }
   starttime_ = lasttime;
   return(ticket);
  }
//_______________________________________________________________________
 
Igor Makanu:

попробуйте так будет работать?

Не поможете с подобной ситуацией для советника, чтобы проверялись последние 4 открытых ордера? Если 4 ордера открыты одновременно то начиналось вычисление общего профита и далее закрытие.

//+------------------------------------------------------------------+
//|         Советник, выставляет 4 ордера по 4м валютам              |
//+------------------------------------------------------------------+
#property strict
//+------------------------------------------------------------------+
extern string  SYMBOL1        = "EURUSD"; //первый символ, если не указан, то не выставляется
extern string  SYMBOL2        = "GBPUSD"; //второй символ, если не указан, то не выставляется
extern string  SYMBOL3        = "EURGBP"; //третий символ, если не указан, то не выставляется
extern string  SYMBOL4        = "GBPJPY"; //четвертый символ, если не указан, то не выставляется
extern double  LOT1           = 0.1;      //лот первого инструмента
extern double  LOT2           = 0.1;      //лот второго инструмента
extern double  LOT3           = 0.1;      //лот третьего инструмента
extern double  LOT4           = 0.1;      //лот четвертого инструмента
extern int     TYPE1          = OP_BUY;   //тип ордера первого инструмента
extern int     TYPE2          = OP_SELL;  //тип ордера второго инструмента
extern int     TYPE3          = OP_BUY;   //тип ордера третьего инструмента
extern int     TYPE4          = OP_SELL;  //тип ордера четвертого инструмента
extern int     Slippage       = 30;       //проскальзывание 
extern double  obpr           = 10;       //Общий профит
extern int     Magic          = 777888;

//============================================================================
void start()
  {
   double pa1=0, pa2=0;
   int i;
   int p1=0,p2=0;
   for(i=OrdersTotal()-1; i>=0; i--)
     {//Проверяем профит
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==Magic)
       {//Подсчитываем общий профит
        if(p1<=2 && (OrderSymbol()==SYMBOL1 || OrderSymbol()==SYMBOL2)) {pa1=pa1+OrderProfit()+OrderSwap()+OrderCommission(); p1++;}
        if(p2<=2 && (OrderSymbol()==SYMBOL3 || OrderSymbol()==SYMBOL4)) {pa2=pa2+OrderProfit()+OrderSwap()+OrderCommission(); p2++;}
       }
     }
   if(pa1>=obpr) close_orders(1); //Закрываем две пары, если они в сумме >= общему профиту
   if(pa2>=obpr) close_orders(2);
   
   int s=0;
   for(i=OrdersTotal()-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==Magic) s++;
     }
   if(s>2) return;

   int    Digit=(int)MarketInfo(SYMBOL1,MODE_DIGITS);
   double Poin=MarketInfo(SYMBOL1,MODE_POINT);
   double ASK=NormalizeDouble(MarketInfo(SYMBOL1,MODE_ASK),Digit);
   double BID=NormalizeDouble(MarketInfo(SYMBOL1,MODE_BID),Digit);
   if(SYMBOL1!="")
     {
      if(TYPE1==OP_BUY)
        {
         if(OrderSend(SYMBOL1,OP_BUY,LOT1,ASK,Slippage,0,0,"1й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер BUY  лот ",LOT1," ",SYMBOL1);
         else Alert(SYMBOL1," send order BAY error ",GetLastError(),"  ",MarketInfo(SYMBOL1,MODE_ASK),"  ",LOT1);
        }
      if(TYPE1==OP_SELL)
        {
         if(OrderSend(SYMBOL1,OP_SELL,LOT1,BID,Slippage,0,0,"1й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер SELL  лот ",LOT1," ",SYMBOL1);
         else Alert(SYMBOL1," send order SELL error ",GetLastError(),"  ",MarketInfo(SYMBOL1,MODE_ASK),"  ",LOT1);
        }
     }
   if(SYMBOL2!="")
     {
      Digit=(int)MarketInfo(SYMBOL2,MODE_DIGITS);
      Poin=MarketInfo(SYMBOL2,MODE_POINT);
      ASK=NormalizeDouble(MarketInfo(SYMBOL2,MODE_ASK),Digit);
      BID=NormalizeDouble(MarketInfo(SYMBOL2,MODE_BID),Digit);
      if(TYPE2==OP_BUY)
        {
         if(OrderSend(SYMBOL2,OP_BUY,LOT2,ASK,Slippage,0,0,"2й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер BUY  лот ",LOT2," ",SYMBOL2);
         else Alert(SYMBOL2," send order BAY error ",GetLastError(),"  ",MarketInfo(SYMBOL2,MODE_ASK),"  ",LOT2);
        }
      if(TYPE2==OP_SELL)
        {
         if(OrderSend(SYMBOL2,OP_SELL,LOT2,BID,Slippage,0,0,"2й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер SELL  лот ",LOT2," ",SYMBOL2);
         else Alert(SYMBOL2," send order SELL error ",GetLastError(),"  ",MarketInfo(SYMBOL2,MODE_ASK),"  ",LOT2);
        }
     }
   if(SYMBOL3!="")
     {
      Digit=(int)MarketInfo(SYMBOL3,MODE_DIGITS);
      Poin=MarketInfo(SYMBOL3,MODE_POINT);
      ASK=NormalizeDouble(MarketInfo(SYMBOL3,MODE_ASK),Digit);
      BID=NormalizeDouble(MarketInfo(SYMBOL3,MODE_BID),Digit);
      if(TYPE3==OP_BUY)
        {
         if(OrderSend(SYMBOL3,OP_BUY,LOT3,ASK,Slippage,0,0,"3й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер BUY  лот ",LOT3," ",SYMBOL3);
         else Alert(SYMBOL3," send order BAY error ",GetLastError(),"  ",MarketInfo(SYMBOL3,MODE_ASK),"  ",LOT3);
        }
      if(TYPE3==OP_SELL)
        {
         if(OrderSend(SYMBOL3,OP_SELL,LOT3,BID,Slippage,0,0,"3й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер SELL  лот ",LOT3," ",SYMBOL3);
         else Alert(SYMBOL3," send order SELL error ",GetLastError(),"  ",MarketInfo(SYMBOL3,MODE_ASK),"  ",LOT3);
        }
     }
   if(SYMBOL4!="")
     {
      Digit=(int)MarketInfo(SYMBOL4,MODE_DIGITS);
      Poin=MarketInfo(SYMBOL4,MODE_POINT);
      ASK=NormalizeDouble(MarketInfo(SYMBOL4,MODE_ASK),Digit);
      BID=NormalizeDouble(MarketInfo(SYMBOL4,MODE_BID),Digit);
      if(TYPE4==OP_BUY)
        {
         if(OrderSend(SYMBOL4,OP_BUY,LOT4,ASK,Slippage,0,0,"4й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер BUY  лот ",LOT4," ",SYMBOL4);
         else Alert(SYMBOL4," send order BAY error ",GetLastError(),"  ",MarketInfo(SYMBOL4,MODE_ASK),"  ",LOT4);
        }
      if(TYPE4==OP_SELL)
        {
         if(OrderSend(SYMBOL4,OP_SELL,LOT4,BID,Slippage,0,0,"4й_ордер",Magic,0,Blue)!=-1)
            Alert("Ордер SELL  лот ",LOT4," ",SYMBOL4);
         else Alert(SYMBOL4," send order SELL error ",GetLastError(),"  ",MarketInfo(SYMBOL4,MODE_ASK),"  ",LOT4);
        }
     }
   return;
  } 

//=====================================================================
void close_orders(int para)
{
bool err;
int p1=0, p2=0; //удаляем только два последних ордера
for(int i=OrdersTotal()-1; i>=0; i--)
  {
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==Magic)
    {
     if(p1<=2 && para==1 && (OrderSymbol()==SYMBOL1 || OrderSymbol()==SYMBOL2)) 
      {
       if(OrderType()==OP_BUY)  err=OrderClose(OrderTicket(),OrderLots(), Bid, 30,clrNONE);
       if(OrderType()==OP_SELL) err=OrderClose(OrderTicket(),OrderLots(), Ask, 30,clrNONE);
       p1++;
      }
     if(p2<=2 && para==2 && (OrderSymbol()==SYMBOL3 || OrderSymbol()==SYMBOL4))
      {
       if(OrderType()==OP_BUY)  err=OrderClose(OrderTicket(),OrderLots(), Bid, 30,clrNONE);
       if(OrderType()==OP_SELL) err=OrderClose(OrderTicket(),OrderLots(), Ask, 30,clrNONE);
       p2++;
      }
    }
  }
return;
}