Советник открывает лишние сделки.

 

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

Суть работы советника расскажу на примере сделок на селл.

Советник открывает 1 сделку на селл, выставляет тейк профит 20 пунктов, если цена дошла до тейка закрывает и открывает следующую сделку и так пока не смениться тренд.

Меняется тренд цена идёт против сделки на селл (вверх) и советник как только рыночная цена отходит на 50 или более пунктов от ранее открытой сделки открывает следующую сделку и выставляет новый ТР с учётом открытой сделки и так до бесконечности пока цена не развернётся вниз. Как только цена пошла вниз и цепляет первый ТР, советник закрывает все сделки на селл.

И цикл повторяется, но пред этим как повториться циклу он успевает открыть 2-3 сделки, которые тут-же закрывает, а потом работает как обычно по алгоритму.

Думаю, что как то связана функция которая закрывает все сделки как только цена дойдёт до ТР, но до конца не могу понять, что нужно сделать чтоб предотвратить это открывание и закрывание сделок.

Вот мой код: 

// Открываем первый ордер на продажу    
   
    if(CountTradesSell()==0) // Если количество ордеров ==0, открываем первую сделку 
     {
      ticket=OrderSend(Symbol(),OP_SELL,Lot,Bid,Slippage,0,0,comment,Magic,0,Red);
      if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
        {
         TPSell=NormalizeDouble(Bid-TakeProfit*Point,Digits);
         OrderModifySell=OrderModify(ticket,OrderOpenPrice(),0,TPSell,0);    
        }
     }
               
      if(CountTradesSell()>=1)//Если количество ордеров >= 1, то окрываем второй и последующие ордера
        {
            if(isCloseLastPosSellTake()== True) // Если цена достигла ТР
           {
            
            ClosePosFirstProfitSell(); //Закрываем все сделки
             
           }   
           else     
            
         if(OrderSelect(OrdersTotal()-1,SELECT_BY_POS))
         if(OrderMagicNumber() == Magic && OrderSymbol() ==Symbol())
         if(OrderType() == OP_SELL)
         if( Bid>=NormalizeDouble(OrderOpenPrice()+Step*Point,Digits)) //Сравниваем цену открытия ордера и цену на Step пунктов ниже.
            {  
               ticket=OrderSend(Symbol(),OP_SELL,Lot,Bid,Slippage,0,0,comment,Magic,0,Red);// Выставляем новый ордер
               int t;                                     // Перебираем все ордера от первого до последнего
               for(t=0; t<OrdersTotal(); t++)
               if(OrderSelect(t, SELECT_BY_POS))
               if(OrderMagicNumber() == Magic && OrderSymbol() == Symbol())
               if(OrderType() == OP_SELL)
               {
                 SumOrderOpenPrice=SumOrderOpenPrice + OrderOpenPrice();// Получаем сумму цен открытия всех ордеров
                } 
                 if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))//Выбираем последний открытый ордер
                  { 
                    SredTPSell=SumOrderOpenPrice/CountTradesSell()-NormalizeDouble(PlusTP*Point,Digits);// Цены открытия всех ордеров делим на количество всех ордеров
                    OrderModifyBuy=OrderModify(ticket,OrderOpenPrice(),0,SredTPSell,0);// Модифицируем последний открытый ордер, ставим TakeProfit
                  }
              }
           }
  }
  
 // Функции
  void ClosePosFirstProfitSell() //Функция закрытия всех сделок на SELL
  {
   int i,k=OrdersTotal();

   k=OrdersTotal();
   for(i=k-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
        
         if(OrderType()==OP_SELL) ClosePosSellSelect();
        }
     }
  }
  
  void ClosePosSellSelect()
  {
   bool   fc;
   color  clClose;
   double ll,pAsk,pBid,pp;
   int    it;

   if(OrderType()==OP_SELL)
     {
      for(it=1; it<=NumberOfTry; it++)
        {
         while(!IsTradeAllowed()) Sleep(5000);
         RefreshRates();
         pAsk=MarketInfo(OrderSymbol(), MODE_ASK);
         if(OrderType()==OP_SELL)
           {
            pp=pAsk; clClose=clCloseSell;
           }
         ll=OrderLots();
         fc=OrderClose(OrderTicket(), ll, pp, Slippage, clClose);
        }
     }
  }
  
bool isCloseLastPosSellTake(string sy="", int op=-1, int mn=-1) // Функция определяет есть ли сделки закрытые по ТР
{
  datetime t;
  double   ocp, otp;
  int      dg, i, j=-1, k=OrdersHistoryTotal();

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) {
      if (OrderSymbol()==sy || sy=="") {
        if (OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) {
              if (t<OrderCloseTime()) {
                t=OrderCloseTime();
                j=i;
              }
            }
          }
        }
      }
    }
  }
  if (OrderSelect(j, SELECT_BY_POS, MODE_HISTORY)) {
    dg=MarketInfo(sy, MODE_DIGITS);
    if (dg==0) if (StringFind(OrderSymbol(), "EUR")<0) dg=4; else dg=2;
    ocp=NormalizeDouble(OrderClosePrice(), dg);
    otp=NormalizeDouble(OrderTakeProfit(), dg);
    if (ocp==otp) return(True);
  }
  return(False);
} 

int CountTradesSell() //Функция подсчитывает количество ордеров SELL в рынке 
  {
   int count= 0;
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      
        {
        
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_SELL)
            
               count++;
           }
        }
     }
   return(count);
  }
 
 
Это называется дребезг в системе автоматического управления. Лекарство простое - открывайте новую позицию по цене, худшей, чем закрытая с учетом возможного изменения рынка. Если будет желание - гуглите "петля гистерезиса". 
 
LRA:

Артем! Мельком посмотрел. Может ошибка в комментарии? Шутка...

А вообще программу можно сделать существенно короче. Вместо этих 19 строк:

Достаточно 9

Для отладки удобно использовать алерты:
Alert("Открываем первый");
Alert("Открываем следующие");
Alert("Начали закрывать");
Ну а в данном случае нужно замести еще одну переменную флаг
bool НачалиЗакрывать=false;
Когда начали закрывать флаг поднимаем присваивая true
После закрытия флаг опускаем присваивая false
И когда флаг поднят - открывать ордера запрещено. После окончания закрытия еще можно сделать паузу несколько минут.
if(!НачалиЗакрывать) OrderSend(...

Спасибо! на выходных буду смотреть, я начинающий товарищь поэтому, кода наворотил, сам чувствую, но как его упростить пока знаний не хватает, по результатам отпишусь.
 
tara:
Это называется дребезг в системе автоматического управления. Лекарство простое - открывайте новую позицию по цене, худшей, чем закрытая с учетом возможного изменения рынка. Если будет желание - гуглите "петля гистерезиса". 
Спасибо за термин обязательно погуглю)))
 

Только не читай статью о дребезге на сайте mql5

Если сначала прочтёшь обсуждение статьи, то и читать её не появится желания.

 

Проблема осталась, но удалось сократить количество открытий лишних сделок до 1. В Переменной NumberOfTry изменил количество попыток закрытия ордера до 1 (было 5), левых сделок стало меньше но всё же есть, а как затормозить советника пока функция закрывает ордера я пока не сообразил.

 void ClosePosFirstProfitSell() //Функция закрытия всех сделок на SELL
  {
   int i,k=OrdersTotal();

   k=OrdersTotal();
   for(i=k-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
        
         if(OrderType()==OP_SELL) ClosePosSellSelect();
        }
     }
  }
  
  void ClosePosSellSelect()
  {
   bool   fc;
   color  clClose;
   double ll,pAsk,pBid,pp;
   int    it;

   if(OrderType()==OP_SELL)
     {
      for(it=1; it<=NumberOfTry; it++)
        {
         while(!IsTradeAllowed()) Sleep(5000);
         RefreshRates();
         pAsk=MarketInfo(OrderSymbol(), MODE_ASK);
         if(OrderType()==OP_SELL)
           {
            pp=pAsk; clClose=clCloseSell;
           }
         ll=OrderLots();
         fc=OrderClose(OrderTicket(), ll, pp, Slippage, clClose);
        }
     }
  }
 

С помощью этой функции ClosePosSellSelect() закрываю все сделки, но понять не могу как дать понять советнику, когда эта функция начала работать а когда закончила, чтобы он в этот период не торговал?

void ClosePosSellSelect()
  {
   bool   fc;
   color  clClose;
   double ll,pAsk,pBid,pp;
   int    it;
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
   if(OrderType()==OP_SELL)
     {
      for(it=1; it<=5; it++)
        {
         while(!IsTradeAllowed()) Sleep(100);
         RefreshRates();
         pAsk=MarketInfo(OrderSymbol(), MODE_ASK);
         if(OrderType()==OP_SELL)
           {
            pp=pAsk; clClose=clCloseSell;
           }
         ll=OrderLots();
         fc=OrderClose(OrderTicket(), ll, pp, Slippage, clClose);
        }
     }
  }
 
MasterMihalich:

С помощью этой функции ClosePosSellSelect() закрываю все сделки, но понять не могу как дать понять советнику, когда эта функция начала работать а когда закончила, чтобы он в этот период не торговал?

На этом уровне - никак. И на предыдущем - тоже. 

Нужен флаг окончания работы программы закрытия всех ордеров на уровне программы запроса на это закрытие.  

 
tara:

На этом уровне - никак. И на предыдущем - тоже. 

Нужен флаг окончания работы программы закрытия всех ордеров на уровне программы запроса на это закрытие.  

Чувствую всё правильно говоришь и теоретический, ну процентов на 80 я понимаю о чём ты говоришь, остальное нет. Я над этим уже месяц сижу, для опытного программиста наверно это как 2 пальца обосвальт, но у меня не срабатывает в голове. Может статей каких кинешь ссылок по этой теме, я толком ничего найти не могу, всё вокруг да около?
 
MasterMihalich:
Чувствую всё правильно говоришь и теоретический, ну процентов на 80 я понимаю о чём ты говоришь, остальное нет. Я над этим уже месяц сижу, для опытного программиста наверно это как 2 пальца обосвальт, но у меня не срабатывает в голове. Может статей каких кинешь ссылок по этой теме, я толком ничего найти не могу, всё вокруг да около?
Ни сегодня, ни завтра ничего не кину.
Причина обращения: