Скачать MetaTrader 5

Помогите отредактировать код, пожалуйста

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Andrey Pototskiy
198
Andrey Pototskiy  

Коллеги, пожалуйста, помогите. Своих мозгов не хватает.

Нужно, чтобы робот, который выставил лимитные ордера, при закрытии открытой позиции (не важно, по стопу или профиту) удалил бы оставшуюся отложку, но не всякую, а ту, магический номер которой равен тикету закрытой позиции.

 

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

input double   lot                  = 0.2;
input double   TakeProfitPips       = 50;
input double   StopLossPips         = 200;

int               bar=0;
int               shift=1;
int               tiket;
int               otkt;
double            price;
int               cnt;
double            TPp,SLp;
int               tkt;
int               n;
int               type;

    int _OrdersTotal = 0;
    // кол-во позиций, соответствующих критериям (текущий инструмент и заданный MagicNumber),
    // состоянием на текущий тик
    int now_OrdersTotal = 0;
    // кол-во позиций, соответствующих критериям (текущий инструмент и заданный MagicNumber),
    // состоянием на предыдущий тик
    static int pre_OrdersTotal = 0;
    // массив открытых позиций состоянием на текущий тик
    int now_OrdersArray[][2]; // [№ в списке][№ тикета, тип позиции]
    // текущий номер позиции в массиве now_OrdersArray (для перебора)
    int now_CurOrder = 0;
    // текущий номер позиции в массиве pre_OrdersArray (для перебора)
    int pre_CurOrder = 0;
    // массив для хранения количества закрытых позиций каждого типа
    int now_ClosedOrdersArray[6][3]; // [тип ордера][тип закрытия] 
 
    // временные флаги
    bool OrderClosed = true, PendingOrderOpened = false;
    // временные переменные
   

    int pre_OrdersArray[][2]; // [количество позиций][№ тикета, тип позиции]
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }


void OnTick()

  {

        if(OrdersTotal()== 0 && iTime(Symbol(),PERIOD_M1,1)==D'14.01.16 16:30')

        {
        
         price=Open[shift];

         tiket=OrderSend(Symbol(),OP_SELLLIMIT,lot,price,3,price+StopLossPips*Point,price-TakeProfitPips*Point);
         if(tiket<0)
           {
            Print("Ошибка OrderSend № - ",GetLastError());
           }
        }

     

   if(OrdersTotal()!=0)
     {
      for(cnt=0; cnt<OrdersTotal(); cnt++)

         OrderSelect(cnt,SELECT_BY_POS); // Если есть следующий
        {                                    // Анализ ордеров:
         price=OrderOpenPrice();
         otkt = OrderTicket();
         n=otkt;
         //--------------------------------------------------------------

 
         if(OrderType()==OP_SELL && OrderMagicNumber()==0)

           {
            tiket=OrderSend(Symbol(),OP_SELLLIMIT,lot*3,price+100*Point,1,price+StopLossPips*Point,price-TakeProfitPips*Point,"My order",n);
            tiket=OrderSend(Symbol(),OP_SELLLIMIT,lot*9,price+200*Point,1,price+StopLossPips*Point,price-TakeProfitPips*Point,"My order",n);
           }
        }

     }

  
        _OrdersTotal = OrdersTotal(); // запоминаем общее количество позиций
        ArrayResize( now_OrdersArray, _OrdersTotal ); // изменяем размер массива открытых позиций под текущее кол-во
        ArrayInitialize( now_OrdersArray, 0.0 ); // обнуляем массив
        now_OrdersTotal = 0; // обнуляем количество позиций, соответствующих критериям
        ArrayInitialize( now_ClosedOrdersArray, 0.0 ); // обнуляем массивы закрытых позиций и сработавших ордеров
       
 
        //+------------------------------------------------------------------+
        //| Перебираем все позиции и записываем в массив 
        //+------------------------------------------------------------------+
        for ( int z = _OrdersTotal - 1; z >= 0; z -- )
        {
            if ( OrderSelect( z, SELECT_BY_POS ) )
           
            {
                now_OrdersArray[now_OrdersTotal][0] = OrderTicket();
                now_OrdersArray[now_OrdersTotal][1] = OrderType();
                now_OrdersTotal ++;
            }
        }
        
        ArrayResize( now_OrdersArray, now_OrdersTotal ); // изменяем размер массива открытых позиций под кол-во позиций, соответствующих критериям
 
        //+------------------------------------------------------------------+
        //| Перебираем список позиций предыдущего тика, и считаем сколько закрылось позиций и
        //| сработало отложенных ордеров
        //+------------------------------------------------------------------+
        for ( pre_CurOrder = 0; pre_CurOrder < pre_OrdersTotal; pre_CurOrder ++ )
        {
            tkt = pre_OrdersArray[pre_CurOrder][0]; // запоминаем тикет и тип ордера
            type   = pre_OrdersArray[pre_CurOrder][1];
            
            OrderClosed = true; // предпологаем, что если это позиция, то она закрылась
           
            for ( now_CurOrder = 0; now_CurOrder < now_OrdersTotal; now_CurOrder ++ ) // перебираем все позиции из текущего списка открытых позиций
            {
                if ( tkt == now_OrdersArray[now_CurOrder][0] ) // если позиция с таким тикетом есть в списке,
                {   OrderClosed = false; // значит позиция не была закрыта (ордер не был удалён)
                    break;
                }
            }
           
            if ( OrderClosed )  // если была закрыта позиция (удалён ордер),
            {
                
                if (OrderSelect( tkt, SELECT_BY_TICKET )) // выбиаем ее
               
                    n = tkt; // присваеваем n номер тикета
                
            }   
      }  
     
        //+------------------------------------------------------------------+
        //| Удаляем ордер с магическим номером = тикету закрытой ранее позиции 
        //+------------------------------------------------------------------+
     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
        {
            if ( OrderSelect( z, SELECT_BY_POS ) )
            otkt = OrderTicket();
            if (n == OrderMagicNumber ())
             {OrderDelete( otkt );}
         }
         
         return;
      }
Andrey Ziablytsev
1722
Andrey Ziablytsev  
Andrey Pototskiy:

Коллеги, пожалуйста, помогите. Своих мозгов не хватает.

Нужно, чтобы робот, который выставил лимитные ордера, при закрытии открытой позиции (не важно, по стопу или профиту) удалил бы оставшуюся отложку, но не всякую, а ту, магический номер которой равен тикету закрытой позиции.

 

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

как то хитрО у Вас)))))))

позволю се предложить вариант покороче

   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
       (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT)) //перебираем активные лимитные ордера
      {
         int magic = OrderMagicNumber();
         if (OrderSelect(magic, SELECT_BY_TICKET) && OrderCloseTime()!=0) //ордер с тикетом равным маджику закрыт
         {
            OrderDelete(i);
         }
      }
   }
не проверил правда, но примерно это оно;)
Andrey Pototskiy
198
Andrey Pototskiy  
Andrey Ziablytsev:

как то хитрО у Вас)))))))

позволю се предложить вариант покороче

не проверил правда, но примерно это оно;)

Андрей, спасибо. Только я не совсем понимаю (опыта и знаний не хватает пока). В Вашем коде получается, что робот ищет именно лимитный ордер, определяет его маджик и сразу удаляет. А маджик не важно какой. А мне надо, чтобы удалялся ордер обязательно с маджиком, который равен тикету только что закрытой позиции. Т.о. надо, чтобы триггером для удаления было именно событие закрытия позиции. Для меня не важно в данном случае, как эта позиция закрылась (просто по условию получится, что если закрытие по СЛ, то лимитов не остается, которые надо удалять. Но если детализировать и делать все правильно, то триггер - это ТП. 

 Но реально это я могу чего- то не понимать (только 2 месяца назад начал учить язык, а до этого никак не программист). Поэтому поясните, пожалуйста, если чего-то не понимаю. 

Ihor Herasko
13224
Ihor Herasko  
Andrey Pototskiy:

Андрей, спасибо. Только я не совсем понимаю (опыта и знаний не хватает пока). В Вашем коде получается, что робот ищет именно лимитный ордер, определяет его маджик и сразу удаляет. А маджик не важно какой.

Мэджик важно, какой. Условие:

if (OrderSelect(magic, SELECT_BY_TICKET) && OrderCloseTime()!=0)

как раз следит за тем, чтобы был удален именно тот ордер, который соответствует тикету ранее открытого рыночного ордера. 

Единственный неверный момент в приведенном коде - в OrderDelete нужно передать тикет ордера, а не его порядковый номер в списке. Поэтому правильнее будет так:

for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
       (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT)) //перебираем активные лимитные ордера
      {
         int magic = OrderMagicNumber();
         int ticket = OrderTicket();
         if (OrderSelect(magic, SELECT_BY_TICKET) && OrderCloseTime()!=0) //ордер с тикетом равным маджику закрыт
         {
            OrderDelete(ticket);
         }
      }
   }

При таком подходе не нужно никаких массивов, которые отслеживают имеющиеся рыночные ордера.  

Dmitry Fedoseev
46557
Dmitry Fedoseev  
Andrey Ziablytsev:

как то хитрО у Вас)))))))

позволю се предложить вариант покороче

не проверил правда, но примерно это оно;)

Поправочка небольшая:

   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
       (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT)) //перебираем активные лимитные ордера
      {  
         int del=OrderTicket();     
         int magic = OrderMagicNumber();
         if (OrderSelect(magic, SELECT_BY_TICKET) && OrderCloseTime()!=0) //ордер с тикетом равным маджику закрыт
         {
            OrderDelete(del);
         }
      }
   }
Andrey Pototskiy
198
Andrey Pototskiy  
Ihor Herasko:

Мэджик важно, какой. Условие:

как раз следит за тем, чтобы был удален именно тот ордер, который соответствует тикету ранее открытого рыночного ордера. 

Единственный неверный момент в приведенном коде - в OrderDelete нужно передать тикет ордера, а не его порядковый номер в списке. Поэтому правильнее будет так:

При таком подходе не нужно никаких массивов, которые отслеживают имеющиеся рыночные ордера.  

Спасибо. Как я понимаю OrderCloseTime()!=0 - ключевое правило, которое исключает пока еще существующие ордера. 
Andrey Pototskiy
198
Andrey Pototskiy  
Большое спасибо всем! Попробую вечером протестить
Ihor Herasko
13224
Ihor Herasko  
Andrey Pototskiy:
Спасибо. Как я понимаю OrderCloseTime()!=0 - ключевое правило, которое исключает пока еще существующие ордера. 
Ордера, у которых время закрытия равно нулю, это ордера из рабочего списка. Те, которые имеют время закрытия более нуля, это ордера из истории счета, т. е. закрытые или удаленные.
Andrey Pototskiy
198
Andrey Pototskiy  
Ihor Herasko:
Ордера, у которых время закрытия равно нулю, это ордера из рабочего списка. Те, которые имеют время закрытия более нуля, это ордера из истории счета, т. е. закрытые или удаленные.
Понятно. Огромное спасибо. Все работает!
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий