Нужна помощь!

 

Помогите, я 3 дня пытаюсь решить проблему и не получается...  Написал советника, он создает сетку из стоп ордеров после того как откроет ордер по указанной цене. Стопы повторяют сами себя после SLTP.


А вот суть проблемы такова, не важно buy или sell, но ордера ниже отметки перевыставляются все, а выше только каждый второй! Все вроде симметрично написано, помогите исправить ошибку. 3 дня убил не могу понять, что не так.

Механика простая. После открытия базового ордера открывается сетка ордеров, заполняется и по закрытию проверяется какой это ордер был, далее ставится false. Каждый тик советник проверяет какие ордера закрытые и можно ли выставить заново.

extern bool BUYSTOPS             = true;
extern double BUY_PRICE          = 0.0;
extern int BS_TRIGGER_DISTANCE   = 20;
extern int BS_ORDERS_ABOVE       = 3;
extern int BS_ORDERS_BELOW       = 3;
extern int DISTANCE_BS_ABOVE     = 100;
extern int DISTANCE_BS_BELOW     = 100;
extern int BS_TP                 = 100;
extern int BS_SL                 = 100;
extern bool REPEAT_BS_ABOVE      = true;
extern bool REPEAT_BS_BELOW      = true;
extern bool REPEAT_BS_AT_PRICE   = true;

extern bool SELLSTOPS            = true;
extern double SELL_PRICE         = 0.0;
extern int SS_TRIGGER_DISTANCE   = 20;
extern int SS_ORDERS_ABOVE       = 3;
extern int SS_ORDERS_BELOW       = 3;
extern int DISTANCE_SS_ABOVE     = 100;
extern int DISTANCE_SS_BELOW     = 100;
extern int SS_TP                 = 100;
extern int SS_SL                 = 100;
extern bool REPEAT_SS_ABOVE      = true;
extern bool REPEAT_SS_BELOW      = true;
extern bool REPEAT_SS_AT_PRICE   = true;

extern double Lots               = 1;
extern int MAGIC_NUMBER          = 91438719;
int BS_FLAG, SS_FLAG, res, OrdersAmount, Order_Type, Ticket;
bool ABOVE, BELOW, BLVL, SLVL, BCheck, SCheck;
double BUY_TRIGGER, SELL_TRIGGER, BS_LVL, SS_LVL, Price, SL, TP, Spread;
double BS_ABOVE[], BS_BELOW[], SS_ABOVE[], SS_BELOW[], BS_ABOVE_CHECK[], BS_BELOW_CHECK[], SS_ABOVE_CHECK[], SS_BELOW_CHECK[];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   OrdersAmount = OrdersTotal();
   ArrayResize(BS_ABOVE,BS_ORDERS_ABOVE);
   ArrayResize(BS_BELOW,BS_ORDERS_BELOW);
   ArrayResize(SS_ABOVE,SS_ORDERS_ABOVE);
   ArrayResize(SS_BELOW,SS_ORDERS_BELOW);
   ArrayResize(BS_ABOVE_CHECK,BS_ORDERS_ABOVE);
   ArrayResize(BS_BELOW_CHECK,BS_ORDERS_BELOW);
   ArrayResize(SS_ABOVE_CHECK,SS_ORDERS_ABOVE);
   ArrayResize(SS_BELOW_CHECK,SS_ORDERS_BELOW);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  if(OrdersTotal() > OrdersAmount)
     OpenedNewOrder();
  if(OrdersTotal() < OrdersAmount)
     CanceledOrder();
   
  Spread = MarketInfo(Symbol(),MODE_SPREAD)*Point();
  
  Trade();
   
return;   
  }
//+------------------------------------------------------------------+

void OpenedNewOrder()
{
   OrdersAmount = OrdersTotal();       
return;
}

void CanceledOrder()
{  
   OrdersAmount = OrdersTotal();
     
   for(int i=(OrdersHistoryTotal()-1); i < (OrdersHistoryTotal());i++)
   {  
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC_NUMBER)
         {
            Price = OrderOpenPrice();                       
            if(OrderType() == OP_BUY || OrderType() == OP_BUYSTOP || OrderType() == OP_BUYLIMIT)               
            {
               if(REPEAT_BS_AT_PRICE)
               {
                  if(Price == BUY_PRICE)
                     BS_FLAG = 0;
               }
               if(REPEAT_BS_ABOVE)
               {
                  for(int b=BS_ORDERS_ABOVE; b>0; b--)
                  {
                     if(Price == BS_ABOVE[b-1])
                        BS_ABOVE_CHECK[b-1]=false;
                  }
               }
               if(REPEAT_BS_BELOW)
               {
                  for(int b=BS_ORDERS_BELOW; b>0; b--)
                  {
                     if(Price == BS_BELOW[b-1])
                        BS_BELOW_CHECK[b-1]=false;
                  }   
               }
            }
            if(OrderType() == OP_SELL || OrderType() == OP_SELLSTOP || OrderType() == OP_SELLLIMIT)
            {  
               if(REPEAT_SS_AT_PRICE)
               {
                  if(Price == SELL_PRICE)
                     SS_FLAG = 0;
               } 
               if(REPEAT_SS_ABOVE)
               {
                  for(int s=SS_ORDERS_ABOVE; s>0; s--)
                  {
                     if(Price == SS_ABOVE[s-1])
                        SS_ABOVE_CHECK[s-1]=false;
                  }
               }
               if(REPEAT_SS_BELOW)
               {
                  for(int s=SS_ORDERS_BELOW; s>0; s--)
                  {
                     if(Price == SS_BELOW[s-1])
                        SS_BELOW_CHECK[s-1]=false;
                  }
               }            
            }  
         }                   
   }
return;
}


void Relist()
{
   if(BLVL==true)
   {
      for(int b=BS_ORDERS_ABOVE; b>0; b--)
      {  
         if(BS_ABOVE_CHECK[b-1]==false && Bid <= (BS_ABOVE[b-1] - BS_TRIGGER_DISTANCE*Point() - Spread))
         {
            
            SL = 0;
            TP = 0;
            if(BS_SL != 0)
            {
               SL = (BS_ABOVE[b-1]-BS_SL*Point());
            }
            if(BS_TP != 0)
            {
               TP = (BS_ABOVE[b-1]+BS_TP*Point());
            }
            res=OrderSend(Symbol(),OP_BUYSTOP,Lots,BS_ABOVE[b-1],0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);         
            if(res>0) BS_ABOVE_CHECK[b-1]=true;
         }
      }
      for(int b=BS_ORDERS_BELOW; b>0; b--)
      {  
         if(BS_BELOW_CHECK[b-1]==false && Bid <= (BS_BELOW[b-1] - BS_TRIGGER_DISTANCE*Point() - Spread))
         {
            
            SL = 0;
            TP = 0;
            if(BS_SL != 0)
            {
               SL = (BS_BELOW[b-1]-BS_SL*Point());
            }
            if(BS_TP != 0)
            {
               TP = (BS_BELOW[b-1]+BS_TP*Point());
            }
            res=OrderSend(Symbol(),OP_BUYSTOP,Lots,BS_BELOW[b-1],0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);         
            if(res>0) BS_BELOW_CHECK[b-1]=true;
         }
      }
    }
    if(SLVL==true)
    {  
      for(int s=SS_ORDERS_ABOVE; s>0; s--)
      {  
         if(SS_ABOVE_CHECK[s-1]==false && Bid >= (SS_ABOVE[s-1] + SS_TRIGGER_DISTANCE*Point()))
         {
            SL = 0;
            TP = 0;
            if(SS_SL != 0)
            {
               SL = (SS_ABOVE[s-1]+SS_SL*Point());
            }
            if(SS_TP != 0)
            {
               TP = (SS_ABOVE[s-1]-SS_TP*Point());
            }
            res=OrderSend(Symbol(),OP_SELLSTOP,Lots,SS_ABOVE[s-1],0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);         
            if(res>0) SS_ABOVE_CHECK[s-1]=true;
         }
      }
      for(int s=SS_ORDERS_BELOW; s>0; s--)
      {  
         if(SS_BELOW_CHECK[s-1]==false && Bid >= (SS_BELOW[s-1] + SS_TRIGGER_DISTANCE*Point()))
         {
            SL = 0;
            TP = 0;
            if(SS_SL != 0)
            {
               SL = (SS_BELOW[s-1]+SS_SL*Point());
            }
            if(SS_TP != 0)
            {
               TP = (SS_BELOW[s-1]-SS_TP*Point());
            }
            res=OrderSend(Symbol(),OP_SELLSTOP,Lots,SS_BELOW[s-1],0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);         
            if(res>0) SS_BELOW_CHECK[s-1]=true;
         }
      }
   }
return;
}

void Trade()
{  
   Relist();
   
   BUY_TRIGGER = BUY_PRICE - Spread - BS_TRIGGER_DISTANCE*Point();
   if(Bid <= BUY_TRIGGER)
   {
      ABOVE = true;
   }
   if(BUYSTOPS == true && BUY_PRICE != 0)
   {
      if(ABOVE && Bid >= BUY_TRIGGER && BS_FLAG == 0)
      {   
         SL = 0;
         TP = 0;
         if(BS_SL != 0)
         {
            SL = (BUY_PRICE-BS_SL*Point());
         }
         if(BS_TP != 0)
         {
            TP = (BUY_PRICE+BS_TP*Point());
         }
         res=OrderSend(Symbol(),OP_BUYSTOP,Lots,BUY_PRICE,0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);
         if(res<0)
            Print("BUY Failed ", GetLastError());
         else
         {
            BS_FLAG = 1;
            if(!BLVL)
            {
               BLVL = true;
               for(int b=BS_ORDERS_ABOVE; b>0; b--)
               {
                  BS_LVL = BUY_PRICE + b*DISTANCE_BS_ABOVE*Point();                 
                  BS_ABOVE[b-1]=BS_LVL;
                  BS_ABOVE_CHECK[b-1]=false;
               }
               for(int b=BS_ORDERS_BELOW; b>0; b--)
               {  
                  BS_LVL = BUY_PRICE - b*DISTANCE_BS_BELOW*Point();     
                  BS_BELOW[b-1]=BS_LVL; 
                  BS_BELOW_CHECK[b-1]=false;       
               }   
            }
         }
      }
   }
   
   SELL_TRIGGER = SELL_PRICE + SS_TRIGGER_DISTANCE*Point();
   if(Bid >= SELL_TRIGGER)
   {
      BELOW = true;
   }
   if(SELLSTOPS == true && SELL_PRICE != 0)
   {
      if(BELOW && Bid <= SELL_TRIGGER && SS_FLAG == 0)
      {
         SL = 0;
         TP = 0;
         if(SS_SL != 0)
         {
            SL = SELL_PRICE+SS_SL*Point();
         }
         if(SS_TP != 0)
         {
            TP = SELL_PRICE-SS_TP*Point();
         }
         res=OrderSend(Symbol(),OP_SELLSTOP,Lots,SELL_PRICE,0,SL,TP,NULL,MAGIC_NUMBER,0,clrYellow);
         if(res<0)
            Print("SELL Failed ", GetLastError()); 
         else
         {
            SS_FLAG = 1;
            if(!SLVL)
            {
               SLVL = true;
               for(int s=SS_ORDERS_ABOVE; s>0; s--)
               {       
                  SS_LVL = SELL_PRICE + s*DISTANCE_SS_ABOVE*Point(); 
                  SS_ABOVE[s-1]=SS_LVL;
                  SS_ABOVE_CHECK[s-1]=false;
               }
               for(int s=SS_ORDERS_BELOW; s>0; s--)
               {            
                  SS_LVL = SELL_PRICE - s*DISTANCE_SS_BELOW*Point();   
                  SS_BELOW[s-1]=SS_LVL;
                  SS_BELOW_CHECK[s-1]=false;
               }
            }
         }   
      }
   }
return;
}
Файлы:
1.png  44 kb
2.png  37 kb
 

Думаю никто ковырятся в твоём коде не будет.

Он слишком громоздко написан. 

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

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

 

double distance=first_distance; 

if(OrdersTotal()==0)

{

for(int i=0;i<orders_to_open;i++) 

{ 

buy_stop(distance);

 sell_stop(distance);

 distance+=step;

}

} 
 
for(int i=(OrdersHistoryTotal()-1); i < (OrdersHistoryTotal());i++)

Если надо последний ордер то просто без цыкла. Смысл с него если делаешь одну итерацию?

if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY))

 

P.S. Когда отложенный ордер стаёт рыночным и закрывается то он будет последним в списке исторических ордеров. 

 
Vasyl Nosal:

...P.S. Когда отложенный ордер стаёт рыночным и закрывается то он будет последним в списке исторических ордеров. 

Неверное утверждение. Смотря как история счета отсортирована в терминале. И если он закрылся вчера, а история счета настроена так, что показывать только сегодняшнюю историю, то советник вообще ордер в истории не увидит.
 
Oksana Berenko:
Неверное утверждение. Смотря как история счета отсортирована в терминале. И если он закрылся вчера, а история счета настроена так, что показывать только сегодняшнюю историю, то советник вообще ордер в истории не увидит.
Сортировка не имеет значения.
 
Vasyl Nosal:
Сортировка не имеет значения.
Только что проверила, вы правы. Имеет значение только то, что загружено во вкладке "история счета"
 
Vasyl Nosal:
Сортировка не имеет значения.
Сортировка имеет значение - если терминал закрывался
 
for(int i=(OrdersHistoryTotal()-1); i < (OrdersHistoryTotal());i++)
Что делает этот цикл?
 
Nikita Solodko:
Что делает этот цикл?
Этот цикл что-то делает один раз