При переборе ордеров нужное действие выполняется только один раз, а должно - несколько.

 

Подскажите, пожалуйста, в чем тут загвоздка? Даю два куска кода, которые должны закрывать все сделки одного направления:

for(ii=0;ii<OrdersTotal();ii++)
      {
        OrderSelect(ii,SELECT_BY_POS,MODE_TRADES);
        
        if(OrderType()==OP_BUY)
          {
            if(closelong==1)
              {
                OrderClose(OrderTicket(),OrderLots(),Bid,20,Blue);
                return(0);
              }
          }
        if(OrderType()==OP_SELL)
          {
            if(closeshort==1)
              {             
                OrderClose(OrderTicket(),OrderLots(),Ask,20,Red);
                return(0);
              }
          }
      }

и второй:

for(ii=OrdersTotal();ii>0;ii--)
      {
        OrderSelect(ii,SELECT_BY_POS,MODE_TRADES);
        
        if(OrderType()==OP_BUY)
          {
            if(closelong==1)
              {
                OrderClose(OrderTicket(),OrderLots(),Bid,20,Blue);
                return(0);
              }
          }
        if(OrderType()==OP_SELL)
          {
            if(closeshort==1)
              {             
                OrderClose(OrderTicket(),OrderLots(),Ask,20,Red);
                return(0);
              }
          }
      }

Вроде бы все тоже самое, только второй должен закрывать сделки, начиная с последней, а первый - начиная с первой.

Так вот, первый работает правильно, все сделки закрываются, а вот второй закрывает только самую последнюю сделку, а остальные - нет. Почему?

 
так у вас же return(0) стоит!
 
//---------------------------------------------------------------   CloseOrders
bool CloseOrders(int dir, int SysID, string smb)
{
	int i, total = OrdersTotal();	if (total<=0) return(true);
	int ticket[1000], nt=0; double op;

	nt=0;
	for (i=0; i<total; i++)	
	{	
		OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
		if ((OrderType()==dir||dir<0) && OrderMagicNumber()==SysID && OrderSymbol()==smb)
		{ ticket[nt]=OrderTicket(); nt++; }
	}
	for (i=0; i<nt; i++)
	{	
		if (!OrderSelect(ticket[i], SELECT_BY_TICKET)) return(false);
		dir=OrderType();
		if (dir==OP_BUY) op=Bid; else if (dir==OP_SELL) op=Ask;
		if (dir==OP_BUY || dir==OP_SELL)
			if (!OrderClose(ticket[i], OrderLots(), op, 3)) return(false);
		if (dir==OP_BUYLIMIT || dir==OP_SELLLIMIT || dir==OP_BUYSTOP || dir==OP_SELLSTOP)
			if (!OrderDelete(ticket[i])) return(false);
	}
	return(true);
}
 

пример

CloseOrders(OP_BUY, magic, Symbol()); // закрыть покупки с маджиком на ткуцщей валюте эксперта
CloseOrders(OP_BUYLIMIT, magic, "EURUSD"); // закрыть байлимиты на евре
CloseOrders(-1, magic, "GBPUSD"); // закрыть все ордера эксперта на фунте
 
оператор return останавливает выполнение ближней функции а не оператора if или цикла for, просто убери return везде.
 

Но в первом куске тоже стоит return, а там все правильно выполняется...

 
Интересное кино получается. Убрал return из обоих вариантов, так вот, там где обратный отсчет (ii--) все сделки стали закрываться как положено, зато там где перебор прямой (ii++) перестали. Что за ерунда?
 

во втором примере поставь не ii>0 а ii>=0, иначе у тебя нулевой ордер не обработается и еще от OrdersTotal() отними единицу. Кстати, вопрос, нафига ты проверяшь if(closelong==1) и if(closeshort==1), если у тебя до этого и так идет проверка if(OrderType()==OP_BUY) ?? И еще, проскальзывание в 20 пунктов это перебор, поставь 5

вот for(ii=OrdersTotal()-1;ii>=0;ii--)

 
sergeev >>:

Алексей, функция работает нормально?

У меня в старых билдах встречается такой глюк, если ордер уже выбран, и мы его пытаемся ещё раз выбрать, не важно через тикет или просто перебором по позиции, то ордер не выбирается, более того работа с ордером не возможна.

Твоя функция не делает каждый раз выбор одного и того же ордера, но такое возможно... Когда всего один ордер.

 
Azimuth писал(а) >>

Подскажите, пожалуйста, в чем тут загвоздка? Даю два куска кода, которые должны закрывать все сделки одного направления:

и второй:

Вроде бы все тоже самое, только второй должен закрывать сделки, начиная с последней, а первый - начиная с первой.

Так вот, первый работает правильно, все сделки закрываются, а вот второй закрывает только самую последнюю сделку, а остальные - нет. Почему?

'' Список ордеров в терминале является динамическим, в то время как проход в цикле for() будет статическим – если было сказано пройти от 0(нуля) до total-1 (количество ордеров в списке до начала удаления ордеров минус один), то так и будет. Если ордеров было 10, и мы начнем с начала списка (с нулевого ордера по списку), то после прохода от 0 до 4, в списке ордеров останется 5 ордеров, и размещаться они будут опять на позициях от 0 до 5. И проход в цикле от 5 до 9 будет выдавать холостые выстрелы, оставшиеся ордера не будут закрыты или удалены. Правильным будет удаление с конца списка, тогда не будет эффекта обвала. На рисунке показан порядок удаления ордеров с конца списка, размер списка после каждого удаления/закрытия будет уменьшаться, при этом ни один ордер не будет пропущен." - Отрывок из статьи Закрытие и удаление ордеров https://www.mql5.com/ru/articles/mt4

 

Всем большое спасибо, теперь при переборе с конца списка

for(ii=OrdersTotal()-1;ii>=0;ii--)

все ордера закрываются как положено.

Осталось выяснить один момент - почему при переборе с начала списка

for(ii=0;ii<OrdersTotal();ii++)
      {
        OrderSelect(ii,SELECT_BY_POS,MODE_TRADES);
        
        if(OrderType()==OP_BUY)
          {
            if(closelong==1)
              {
                OrderClose(OrderTicket(),OrderLots(),Bid,20,Blue);
                return(0);
              }
          }
        if(OrderType()==OP_SELL)
          {
            if(closeshort==1)
              {             
                OrderClose(OrderTicket(),OrderLots(),Ask,20,Red);
                return(0);
              }
          }
      }

если после OrderClose стоит return, то все работает правильно, а если убрать return, то остаются незакрытые ордера.

И 20 - это проскальзование для 5-ти значных котировок, потому что тестирую на Альпари, а на 4-х значных там 2.