ROBOTRADING - Форум по автоматизированной и ручной торговле на финансовых рынках.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



5100% советник Greezly_2008

Сообщений 1 страница 2 из 2

1

Greezly, который занял 10-е место на чемпионате автоматических торговых систем-экспертов 2007

Советник использует несколько подсистем торговли, с собственными индикаторами и параметрами торговли. Работа, в основном, ведется отложенными ордерами, но ряд подсистем используют и торговлю "по рынку".
Переменных для настройки работы достаточно много, т.е. советник гибко настраивается под ваше видение торговли.
Размер лота можно задавать как в процентах от свободных средств, т.е. с использованием мани-менеджмента, так и фиксированным значением.

Подробнее здесь.

0

2

Код:
//------------------------------------------------------------------
//                                                GREEZLY_2008.mq4  |
//------------------------------------------------------------------

// магические номера ордеров: 777AABB 
// AA - собственный тип ордера, BB - резерв

#define MN_Usual      7770000   // обычный ордер
#define MN_Averaging  7770100   // усредняющий ордер
#define MN_Flating    7770200   // флэтовый ордер, открытый по индикатору Flat для мелкого профита внутри канала
#define MN_Speed      7770300   // ордер, открытый по индикатору Speed при быстром и мощном движении цены

// ВНЕШНИЕ ПЕРЕМЕННЫЕ

extern double TakeProfitB                   = 12;
extern double TakeProfitS                   = 12;
extern double StopLossB                     = 1080;
extern double StopLossS                     = 780;
extern int    TimeStopLoss_Minutes          = 0;     // временной стоп-лосс: время (в минутах), по истечению которого реальный ордер закрывается (0 - не использовать)
extern double TakeProfitForLock             = 0;
extern double StopLossForLock               = 134;
extern double TrailingStop                  = 0;
extern double StepTrailingStop              = 5;     // шаг чувствительности для сдвига TrailingStop

extern double BuyStopLevel                  = 22;    // < 0 - не использовать 
extern double BuyLimitLevel                 = 17; 
extern double SellStopLevel                 = 78; 
extern double SellLimitLevel                = 83; 

extern int    UseOneWayRealOrdersB          = 1;       // использовать однонаправленные открытые позиции BUY
extern int    UseOneWayRealOrdersS          = 1;       // использовать однонаправленные открытые позиции SELL
extern double MinDistanceRealOrdersB        = 390;     // минимально допустимое расстояние между однонаправленными открытыми позициями BUY
extern double MinDistanceRealOrdersS        = 590;     // минимально допустимое расстояние между однонаправленными открытыми позициями SELL
extern int    UseAveragingTakeProfitB       = 0;       // использовать усредняющий TakeProfit для однонаправленных позиций BUY
extern int    UseAveragingTakeProfitS       = 0;       // использовать усредняющий TakeProfit для однонаправленных позиций SELL

extern int    UseAcceleratorIndicator       = 0;       // использовать индикатор ускорения
extern int    iAC_CountBars                 = 3;       // кол-во анализируемых значений индикатора Accelerator
extern int    iAC_CountTimeFrames           = 3;       // кол-во анализируемых периодов (тайм-фреймов) индикатора Accelerator
extern int    iAC_StartTimeFrame            = 0;       // начальный (наименьший) анализируемый период (тайм-фрейм) для индикатора Accelerator

extern int    UseSpeedIndicator             = 1;       // использовать индикатор скорости
extern int    iSP_CountBars                 = 2;       // кол-во анализируемых значений индикатора Speed
extern int    iSP_CountTimeFrames           = 2;       // кол-во анализируемых периодов (тайм-фреймов) индикатора Speed
extern int    iSP_StartTimeFrame            = 1;       // начальный (наименьший) анализируемый период (тайм-фрейм) для индикатора Speed
extern int    iSP_UseForOpenRealOrders      = 0;       // использовать индикатор скорости для открытия реальных ордеров
extern double iSP_MinValueForOpenRealOrders = 0.0005;  // минимальное значение индикатора скорости для открытия реальных ордеров
extern double iSP_UseMinTakeProfit          = 1;       // использовать минимальный тейк-профит для ордеров, открываемых по индикатору Speed
extern double iSP_StopLoss                  = 35;      // стоп-лосс для ордеров, открываемых по индикатору Speed

extern int    CountHighLowLimits            = 2;       // количество используемых ограничений HighLowLimit: "не покупать сверху, не продавать снизу"

extern double iHL_LimitDistance1            = 150;     // максимально допустимое отклонение цены от Low/High для возможности открытия Buy/Sell
extern int    iHL_Period1                   = 4;       // период (тайм-фрейм) для анализа HighLow (час)
extern int    iHL_CountBars1                = 24;      // кол-во анализируемых значений периода iHL_Period для определения Low/High

extern double iHL_LimitDistance2            = 700;     // второй блок ограничений HighLowLimit
extern int    iHL_Period2                   = 6;       // (день)
extern int    iHL_CountBars2                = 15;      // 

extern int    UseFlatIndicator              = 1;       // использовать флэт индикатор для открытия ордеров
extern double iFL_MinWidthCanal             = 20;      // минимально допустимая ширина канала
extern double iFL_MaxWidthCanal             = 40;      // максимально допустимая ширина канала
extern double iFL_MinExtremumsCount         = 2;       // минимально необходимое кол-во экстремумов в канале с каждой стороны (экстремумом считаем значения ниже 1/4 и выше 3/4 ширины канала)
extern int    iFL_Period                    = 1;       // период (тайм-фрейм) для анализа Flat (пятиминутки)
extern int    iFL_CountBars                 = 12;      // кол-во анализируемых значений периода iFL_Period
extern double iFL_StopLoss                  = 25;      // стоп-лосс для ордеров, открываемых по индикатору Flat
extern double iFL_LotSizeMultiply           = 2;       // мультипликатор размера лота для ордеров, открываемых по индикатору Flat

extern int    UseBuy                        = 1;       // использовать Buy
extern int    UseSell                       = 1;       // использовать Sell
extern int    OpenRealOrders                = 1;       // открывать реальные ордера по рынку
extern double Risk                          = 0.1;     // уровень риска, размер лота от остатка свободных средств, если 0, торговля ведется минимальным заданным лотом
extern double BuyDenyLevel                  = 160;     // граничный уровень открытия ордеров BUY  (выше этого уровня ордера не открываются)
extern double SellDenyLevel                 = 155;     // граничный уровень открытия ордеров SELL (ниже этого уровня ордера не открываются)

extern int    MaxOrdersCount                = 0;       // ограничение на кол-во ордеров (0 - не ограничивать)

extern double MinDistanceDeferFromPrice     = 10;      // минимально допустимое расстояние цены открываемых отложенных ордеров от текущей цены
extern double MaxDistanceDeferFromPrice     = 50;      // максимально допустимое расстояние цены открываемых отложенных ордеров от текущей цены
extern double MinDistanceBetweenDefer       = 90;      // минимально допустимое расстояние между однонаправленными отложенными ордерами

extern double MinLotSize                    = 0.1;
extern double MaxLotSize                    = 1000;
extern double StepLotSize                   = 0.1;

extern string EndOfTrading                  = "yyyy.mm.dd hh:mm";   // момент окончания торговли (дата и время в формате "yyyy.mm.dd hh:mm")

bool   PrintComments                 = false;                 // выводить комментарии при торговле      
int    DetailComments                = 0;                     // детализация комментариев (0 - самые важные)      


// ВНУТРЕННИЕ ПЕРЕМЕННЫЕ

int _OP_BUY = 0, _OP_SELL = 1, _OP_BUYLIMIT = 2, _OP_SELLLIMIT = 3, _OP_BUYSTOP = 4, _OP_SELLSTOP = 5;
int _Period[10] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1, 0};

double _Point;

int    Counts[6];                        // кол-во ордеров по типам ордеров
double MinPrices[6], MaxPrices[6];       // минимальные и максимальные цены имеющихся ордеров по типам ордеров
double SumLots[6];                       // общее кол-во лотов по типам ордеров

double miSpeed;                          // производный индикатор относительной скорости: < 0 - цена движется вниз с ускорением; 0 - цена колеблется незначительно; > 0 - цена движется вверх с ускорением
double miAccelerator;                    // производный индикатор ускорения: < 0 - цена ускоряется вниз; 0 - ускорение незначительно; > 0 - цена ускоряется вверх
double iHL_Low[2], iHL_High[2];          // значения Low и High для анализа HighLowLimit
double _iHL_LimitDistance;
bool   iFL_IsFlat;                       // индикатор флэта
double iFL_Low, iFL_High, iFL_Width;     // нижняя, верхняя границы и ширина канала для индикатора флэта
   
int glGetNormalOrderType(int _OrderType)
{
   switch(_OrderType)
   {
      case OP_BUY:       return (_OP_BUY);
      case OP_SELL:      return (_OP_SELL);
      case OP_BUYLIMIT:  return (_OP_BUYLIMIT);
      case OP_BUYSTOP:   return (_OP_BUYSTOP);
      case OP_SELLLIMIT: return (_OP_SELLLIMIT);
      case OP_SELLSTOP:  return (_OP_SELLSTOP);
      default:           return(-1);
   }
 return(-1);   
}

int init()
{
   // корректировка переменных в зависимости от условий торговли
   
   if(TakeProfitB  != 0)  TakeProfitB  = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), TakeProfitB);
   if(TakeProfitS  != 0)  TakeProfitS  = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), TakeProfitS);
   if(StopLossB    != 0)  StopLossB    = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), StopLossB);
   if(StopLossS    != 0)  StopLossS    = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), StopLossS);
   if(iSP_StopLoss != 0)  iSP_StopLoss = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), iSP_StopLoss);
   if(iFL_StopLoss != 0)  iFL_StopLoss = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), iFL_StopLoss);
   
   if(TakeProfitForLock != 0)  TakeProfitForLock = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), TakeProfitForLock);
   if(StopLossForLock   != 0)  StopLossForLock   = MathMax(MarketInfo(Symbol(), MODE_STOPLEVEL), StopLossForLock);

   if(UseAcceleratorIndicator == 1)
   {
      if(iAC_CountBars < 2)        iAC_CountBars       = 2;
      if(iAC_CountBars > 10)       iAC_CountBars       = 10;
      if(iAC_CountTimeFrames < 1)  iAC_CountTimeFrames = 1;
      if(iAC_CountTimeFrames > 5)  iAC_CountTimeFrames = 5;
   }   
   
   if(UseSpeedIndicator == 1)
   {
      if(iSP_CountBars < 2)        iSP_CountBars       = 2;
      if(iSP_CountBars > 10)       iSP_CountBars       = 10;
      if(iSP_CountTimeFrames < 1)  iSP_CountTimeFrames = 1;
      if(iSP_CountTimeFrames > 5)  iSP_CountTimeFrames = 5;
   }   
   
   if(MaxOrdersCount < 0)  MaxOrdersCount = 0;

   MinLotSize  = MathMax(MarketInfo(Symbol(), MODE_MINLOT),  MinLotSize);
   MaxLotSize  = MathMin(MarketInfo(Symbol(), MODE_MAXLOT),  MaxLotSize);
   StepLotSize = MathMax(MarketInfo(Symbol(), MODE_LOTSTEP), StepLotSize);
   
 return(0);
}

int deinit()
{
   
 return(0);
}

int start()
{
   int    _OrderType, _OrderMagicNumber, NormalOrderType; 
   double Lots, _Volume, _OrderOpenPrice, _OrderLots, _OrderStopLoss, _OrderTakeProfit;
   double CurrentPrice, CurrentFigure, NearestRealPrice, NearestDeferPrice, NeedDistance;
   double _Low, _High; 
   int    ticket, type, typedefer;
   int    i, j, k, total;
   bool   MayOpenDeferOrder, MayOpenRealOrder;
   string typestr;
   
   _Point = 1.0 / MathPow(10, Digits);  
   
   
   // ПРОВЕРКИ НА ВОЗМОЖНОСТЬ РАБОТЫ

   // проверка даты окончания торговли
   
   if((EndOfTrading != "yyyy.mm.dd hh:mm") && (StringTrimLeft(EndOfTrading) != ""))
   {
      datetime _EndOfTrading;

      _EndOfTrading = StrToTime(StringTrimLeft(EndOfTrading));
      
      if(_EndOfTrading > D'2007.01.01 00:00') 
        if(Time[0] > _EndOfTrading)
        {
           if(PrintComments)  Print("Запрещена торговля после ", EndOfTrading); 
           return(0);
        }   
   }
   
   total = OrdersTotal();
   for(i = 0; i < total; i++)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         return(0);
      }

      if(OrderSymbol() != Symbol())  continue;   // пропускаем позиции не по текущей валютной паре
      
   }   
   
   // РАСЧЕТ ИНДИКАТОРОВ
   
   //   индикатор ускорения Accelerator
   
   miAccelerator = 0;
   
   if(UseAcceleratorIndicator == 1)
   {
      double iAC_Val[10][10]; 
      int    iAC_Dir[10];
      
      for(i = 0; i < iAC_CountTimeFrames; i++)
      {
         for(j = 0; j < iAC_CountBars; j++)
           iAC_Val[i][j] = iAC(NULL, _Period[iAC_StartTimeFrame + i], j);
         
         if     (iAC_Val[i][iAC_CountBars - 2] > iAC_Val[i][iAC_CountBars - 1])  iAC_Dir[i] = 1;
         else if(iAC_Val[i][iAC_CountBars - 2] < iAC_Val[i][iAC_CountBars - 1])  iAC_Dir[i] = -1;
         else
         {
            iAC_Dir[i] = 0;
            break;
         }   
         
         for(j = iAC_CountBars - 3; j >= 0; j--)
         {
            if((iAC_Dir[i] == 1) && (iAC_Val[i][j] <= iAC_Val[i][j + 1]))
            {
               iAC_Dir[i] = 0;
               break;
            }  
            else
            if((iAC_Dir[i] == -1) && (iAC_Val[i][j] >= iAC_Val[i][j + 1]))
            {
               iAC_Dir[i] = 0;
               break;
            }  
         }
      }    
      
      miAccelerator = iAC_Dir[0];
      
      for(i = 1; i < iAC_CountTimeFrames; i++)
      {
         if(iAC_Dir[i] != miAccelerator)
         {
            miAccelerator = 0;
            break;
         }
      }   
      
      // если имеем значительное ускорение, определим значение ускорения
      
      if(miAccelerator != 0)  miAccelerator = iAC_Val[0][0] - iAC_Val[0][1]; 
   }

   //   индикатор скорости Speed

   miSpeed = 0;
   
   if(UseSpeedIndicator == 1)
   {
      double iSP_Val[10][10]; 
      int    iSP_Dir[10];
      double iPrice1, iPrice2;
      
      for(i = 0; i < iSP_CountTimeFrames; i++)
      {
         for(j = 0; j < iSP_CountBars; j++)
         {
            // используем взвешенную цену закрытия PRICE_WEIGHTED: (high + low + close + close) / 4
            
            iPrice1 = (iHigh(NULL, _Period[iSP_StartTimeFrame + i], j + 2) + iLow(NULL, _Period[iSP_StartTimeFrame + i], j + 2) + iClose(NULL, _Period[iSP_StartTimeFrame + i], j + 2) * 2) / 4;
            iPrice2 = (iHigh(NULL, _Period[iSP_StartTimeFrame + i], j + 1) + iLow(NULL, _Period[iSP_StartTimeFrame + i], j + 1) + iClose(NULL, _Period[iSP_StartTimeFrame + i], j + 1) * 2) / 4;
            
            if(iPrice1 > 0)  iSP_Val[i][j] = (iPrice2 - iPrice1) / iPrice1; 
            else             iSP_Val[i][j] = 0;
         }   
         
         if((i == 0) && (iSP_StartTimeFrame == 0))
         {
            if     (Bid > iOpen(NULL, _Period[0], 0))  iSP_Dir[0] = 1;
            else if(Bid < iOpen(NULL, _Period[0], 0))  iSP_Dir[0] = -1;
            else 
            {
               if     (iSP_Val[i][0] > 0) iSP_Dir[i] = 1;
               else if(iSP_Val[i][0] < 0) iSP_Dir[i] = -1;
               else                       
               { 
                  iSP_Dir[i] = 0;
                  break;
               }   
            }
         }
         else
         {            
            if     (iOpen(NULL, _Period[iSP_StartTimeFrame + i], 0) > iClose(NULL, _Period[iSP_StartTimeFrame + i], 1)) iSP_Dir[i] = 1;
            else if(iOpen(NULL, _Period[iSP_StartTimeFrame + i], 0) < iClose(NULL, _Period[iSP_StartTimeFrame + i], 1)) iSP_Dir[i] = -1;
            else 
            {
               if     (iSP_Val[i][0] > 0) iSP_Dir[i] = 1;
               else if(iSP_Val[i][0] < 0) iSP_Dir[i] = -1;
               else                       
               { 
                  iSP_Dir[i] = 0;
                  break;
               }   
            }
         }   
         
         if(iSP_Val[i][iSP_CountBars - 1] * iSP_Dir[i] <= 0)  // первый бар и направление имеют разные знаки
         {
            iSP_Dir[i] = 0;
            break;
         }
         
         for(j = iSP_CountBars - 2; j >= 0; j--)
         {
            if((iSP_Dir[i] == 1) && (iSP_Val[i][j] <= iSP_Val[i][j + 1]))
            {
               iSP_Dir[i] = 0;
               break;
            }  
            else
            if((iSP_Dir[i] == -1) && (iSP_Val[i][j] >= iSP_Val[i][j + 1]))
            {
               iSP_Dir[i] = 0;
               break;
            }  
         }
      }    
      
      miSpeed = iSP_Dir[0];
      
      for(i = 1; i < iSP_CountTimeFrames; i++)
      {
         if(iSP_Dir[i] != miSpeed)
         {
            miSpeed = 0;
            break;
         }
      }   
      
      // если имеем движение с увеличивающейся скоростью, определим текущую мгновенную скорость
      
      if(miSpeed != 0)  
      {
         iPrice1 = iOpen(NULL, _Period[0], 0);
         iPrice2 = Bid;
         
         if((iSP_StartTimeFrame == 0) && (iPrice1 != iPrice2) && (iPrice1 > 0))  miSpeed = (iPrice2 - iPrice1) / iPrice1; 
         else                                                                    miSpeed = iSP_Val[0][0]; 
      }   
   }

   //    расчет значений Low и High для анализа HighLowLimit
   
   if(CountHighLowLimits > 0)
   {
      int _iHL_CountBars, _iHL_Period;

      for(k = 0; k < CountHighLowLimits; k++)
      {
         iHL_Low[k]  = 0;   
         iHL_High[k] = 0;
      
         switch(k)
         {
            case 0 : _iHL_Period = iHL_Period1;  _iHL_CountBars = iHL_CountBars1;  break;
            case 1 : _iHL_Period = iHL_Period2;  _iHL_CountBars = iHL_CountBars2;  break;
            default: continue;     
         }
         
         for(i = 0; i < _iHL_CountBars; i++)
         {
            _Low  = iLow( NULL, _Period[_iHL_Period], i);
            _High = iHigh(NULL, _Period[_iHL_Period], i);  
         
            if(_Low > 0)
              if((iHL_Low[k]  == 0) || (_Low < iHL_Low[k]))    iHL_Low[k]  = _Low;

            if(_High > 0)
              if((iHL_High[k] == 0) || (_High > iHL_High[k]))  iHL_High[k] = _High;
         }
      }   
   }

   // индикатор флэта
   
   if(UseFlatIndicator == 1)
   {
      int _CountLow, _CountHigh, _PrevLowHigh;
      
      iFL_IsFlat = false;
      iFL_Low    = 0;
      iFL_High   = 0;
      iFL_Width  = 0;
      
      for(i = 0; i < iFL_CountBars; i++)
      {
         _Low  = iLow( NULL, _Period[iFL_Period], i);
         _High = iHigh(NULL, _Period[iFL_Period], i);  
      
         if(_Low > 0)
           if((iFL_Low  == 0) || (_Low < iFL_Low))    iFL_Low  = _Low;

         if(_High > 0)
           if((iFL_High == 0) || (_High > iFL_High))  iFL_High = _High;
      }
      
      iFL_Width = iFL_High - iFL_Low;
      
      if((iFL_High > 0) && (iFL_Low > 0) && (iFL_Width >= iFL_MinWidthCanal * _Point) && (iFL_Width <= iFL_MaxWidthCanal * _Point))
      {
         _CountLow = 0;  _CountHigh = 0;  _PrevLowHigh = 0;
         
         for(i = 0; i < iFL_CountBars; i++)
         {
            _Low  = iLow( NULL, _Period[iFL_Period], i);
            _High = iHigh(NULL, _Period[iFL_Period], i);  
      
            if((_Low > 0)  && (_Low  < (iFL_Low  + iFL_Width / 4)) && (_PrevLowHigh >= 0))
            {
               _PrevLowHigh = -1;
               _CountLow = _CountLow + 1;
            } 
            
            if((_High > 0) && (_High > (iFL_High - iFL_Width / 4)) && (_PrevLowHigh <= 0))
            {
               _PrevLowHigh = 1;
               _CountHigh = _CountHigh + 1;
            } 
         }
         
         if((_CountLow >= iFL_MinExtremumsCount) && (_CountHigh >= iFL_MinExtremumsCount))
         {
            iFL_IsFlat = true;
         }   
      }  
   }


   // АНАЛИЗ И КОНТРОЛЬ ТЕКУЩИХ ОРДЕРОВ

   if(!glAnalizCurrentOrdersState())  return(0);


   // контроль открытых ордеров по временному стоп-лоссу
   
  if(TimeStopLoss_Minutes > 0) 
   {
      total = OrdersTotal();

      for(i = total - 1; i >= 0; i--)
      {
         OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
         
         if(OrderSymbol() != Symbol())  continue;   // пока пропускаем позиции не по текущей валютной паре
         
         if((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
         {
            if((TimeCurrent() - OrderOpenTime()) > TimeStopLoss_Minutes * 60)
            {
               if(PrintComments)  Print("Удаляем открытый ордер по временному стоп-лоссу."); 
               glOrderClose();            
            }
         }
      }
   }


   if((Counts[_OP_BUY] != 0) && (Counts[_OP_BUYLIMIT] != 0))
   {
      glDeleteAllDeferOrders(_OP_BUYLIMIT, Symbol());
   }   
   
   if((Counts[_OP_SELL] != 0) && (Counts[_OP_SELLLIMIT] != 0)) 
   {
      glDeleteAllDeferOrders(_OP_SELLLIMIT, Symbol());
   }   
   
   if((Counts[_OP_BUY] != 0) && (Counts[_OP_BUYSTOP] != 0))  
   {
      glDeleteAllDeferOrders(_OP_BUYSTOP, Symbol(), MinPrices[_OP_BUY], 0);
   } 
   if((Counts[_OP_SELL] != 0) && (Counts[_OP_SELLSTOP] != 0))
   {  
      glDeleteAllDeferOrders(_OP_SELLSTOP, Symbol(), 0, MaxPrices[_OP_SELL]);
   }   
   
   // анализ и корректировка "замков"
   
   if((Counts[_OP_BUY] != 0) && (Counts[_OP_SELL] != 0)) 
   {
      
      if(((TakeProfitForLock != 0) && ((TakeProfitForLock != TakeProfitB) || (TakeProfitForLock != TakeProfitS))) ||
         ((StopLossForLock   != 0) && ((StopLossForLock   != StopLossB)   || (StopLossForLock   != StopLossS))))
      {
         CurrentPrice = (Ask + Bid) / 2;
      
         total = OrdersTotal();
         for(i = 0; i < total; i++)
         {
            if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               Print("Ошибка получения текущего ордера OrderSelect(): ", GetLastError());   
               return(0);
            }

            if(OrderSymbol() != Symbol())  continue;   // пропускаем позиции не по текущей валютной паре
            
            _OrderType        = OrderType();
            _OrderOpenPrice   = OrderOpenPrice();
            _OrderTakeProfit  = OrderTakeProfit();
            _OrderStopLoss    = OrderStopLoss();
            _OrderMagicNumber = OrderMagicNumber();
      
            if(_OrderMagicNumber == MN_Averaging)  continue;  // усредняющие ордера пропускаем
            
            if((_OrderType == OP_BUY) && (_OrderOpenPrice == MinPrices[_OP_BUY]))
            {
               if(_OrderTakeProfit < (_OrderOpenPrice + TakeProfitForLock * _Point))  // TakeProfit меньше заданного для замков
               {
                  if(OrderModify(OrderTicket(), _OrderOpenPrice, _OrderStopLoss, _OrderOpenPrice + TakeProfitForLock * _Point, 0))
                  {
                     _OrderTakeProfit = _OrderOpenPrice + TakeProfitForLock * _Point;
                  }   
               }
               
               if((StopLossForLock != 0) && (_OrderOpenPrice > MaxPrices[_OP_SELL]) &&
                  ((_OrderOpenPrice - MaxPrices[_OP_SELL]) > 2.2 * StopLossForLock * _Point) &&
                  (MathAbs(_OrderOpenPrice - CurrentPrice) < MathAbs(MaxPrices[_OP_SELL] - CurrentPrice)) &&
                  (_OrderStopLoss < (_OrderOpenPrice - StopLossForLock * _Point)))
               {
                  if(OrderModify(OrderTicket(), _OrderOpenPrice, _OrderOpenPrice - StopLossForLock * _Point, _OrderTakeProfit, 0))
                  {
                     _OrderStopLoss = _OrderOpenPrice - StopLossForLock * _Point;
                  }   
               }
            }
            else if((_OrderType == OP_SELL) && (_OrderOpenPrice == MaxPrices[_OP_SELL]))
            {
               if(_OrderTakeProfit > (_OrderOpenPrice - TakeProfitForLock * _Point))  // TakeProfit меньше заданного для замков
               {
                  if(OrderModify(OrderTicket(), _OrderOpenPrice, _OrderStopLoss, _OrderOpenPrice - TakeProfitForLock * _Point, 0))
                  {
                     _OrderTakeProfit = _OrderOpenPrice - TakeProfitForLock * _Point;
                  }   
               }

               if((StopLossForLock != 0) && (_OrderOpenPrice < MinPrices[_OP_BUY]) &&
                  ((MinPrices[_OP_BUY] - _OrderOpenPrice) > 2.2 * StopLossForLock * _Point) &&
                  (MathAbs(_OrderOpenPrice - CurrentPrice) < MathAbs(MinPrices[_OP_BUY] - CurrentPrice)) &&
                  (_OrderStopLoss > (_OrderOpenPrice + StopLossForLock * _Point)))
               {
                  if(OrderModify(OrderTicket(), _OrderOpenPrice, _OrderOpenPrice + StopLossForLock * _Point, _OrderTakeProfit, 0))
                  {
                     _OrderStopLoss = _OrderOpenPrice + StopLossForLock * _Point;
                  }   
               }
            }
         }   
      }
   }
   
   // проверка на индикаторе Accelerator/Decelerator
   
   if((UseAcceleratorIndicator == 1) && (miAccelerator != 0))
   {
      
      if(miAccelerator > 0)
      {
         glDeleteAllDeferOrders(_OP_SELLLIMIT, Symbol());
      }
         
      if(miAccelerator < 0)  
      {
         glDeleteAllDeferOrders(_OP_BUYLIMIT, Symbol());
      }   
   }
   
   // проверка на индикаторе Speed
   
   if((UseSpeedIndicator == 1) && (miSpeed != 0))
   {
      
      if((miSpeed > 0) && (Counts[_OP_SELLLIMIT] > 0) && (MinPrices[_OP_SELLLIMIT] < (Bid + 20 * _Point)))
      {
         glDeleteAllDeferOrders(_OP_SELLLIMIT, Symbol());
      }
         
      if((miSpeed < 0) && (Counts[_OP_BUYLIMIT] > 0) && (MaxPrices[_OP_BUYLIMIT] > (Ask - 20 * _Point)))  
      { 
         glDeleteAllDeferOrders(_OP_BUYLIMIT, Symbol());
      }   
   }
   
   // проверка HughLowLimit
   
   if(CountHighLowLimits > 0)
   {
      // удаляем все STOP ордера, расположенные в опасных зонах (BUY слишком высоко, SELL слишком низко)
      
      for(k = 0; k < CountHighLowLimits; k++)
      {
         switch(k)
         {
            case 0 : _iHL_LimitDistance = iHL_LimitDistance1;  break;
            case 1 : _iHL_LimitDistance = iHL_LimitDistance2;  break;
            default: continue;     
         }
         
         if((Counts[_OP_BUYSTOP] != 0) && (iHL_Low[k] > 0) && (MaxPrices[_OP_BUYSTOP] >= (iHL_Low[k] + _iHL_LimitDistance * _Point)))  
         {
            glDeleteAllDeferOrders(_OP_BUYSTOP, Symbol(), iHL_Low[k] + _iHL_LimitDistance * _Point, 0);
         }
         
         if((Counts[_OP_SELLSTOP] != 0) && (iHL_High[k] > 0) && (MinPrices[_OP_SELLSTOP] <= (iHL_High[k] - _iHL_LimitDistance * _Point))) 
         {
            glDeleteAllDeferOrders(_OP_SELLSTOP, Symbol(), 0, iHL_High[k] - _iHL_LimitDistance * _Point);
         }   
      }   
   }   
   
   // Контроль открытых позиций по TrailingStop
 
   total = OrdersTotal();

  if(TrailingStop > 0) 
   {
      for(i = 0; i < total; i++)
      {
         OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
         
         if(OrderSymbol() != Symbol())  continue;   // пока пропускаем позиции не по текущей валютной паре
         
         if(OrderType() == OP_BUY)
         {
            if(Bid > (OrderOpenPrice() + _Point * TrailingStop))
            {
               if((OrderStopLoss() == 0) || (OrderStopLoss() < (Bid - _Point * (TrailingStop + StepTrailingStop))))
               {
                  OrderModify(OrderTicket(), OrderOpenPrice(), Bid - _Point * TrailingStop, OrderTakeProfit(), 0);
               }
            }
         }
         else if(OrderType() == OP_SELL)
         {
            if(Ask < (OrderOpenPrice() - _Point * TrailingStop))
            {
               if((OrderStopLoss() == 0) || (OrderStopLoss() > (Ask + _Point * (TrailingStop + StepTrailingStop))))
               {
                  OrderModify(OrderTicket(), OrderOpenPrice(), Ask + _Point * TrailingStop, OrderTakeProfit(), 0);
               }
            }
         }
      }
   }

   // выполняем окончательный анализ текущего состояния после выполненных модификаций

   if(!glAnalizCurrentOrdersState())  return(0);
   
   
   // MONEY MANAGEMENT
   
   //   определение размера лота
   
   if(Risk > 0)  Lots = glDoubleRound(AccountFreeMargin() / 1000.0 * Risk, StepLotSize);
   else          Lots = MinLotSize;
   
   if(Lots < MinLotSize)  Lots = MinLotSize;
   if(Lots > MaxLotSize)  Lots = MaxLotSize;


   // ОТКРЫТИЕ НОВЫХ ОРДЕРОВ
   
   if(AccountFreeMargin() < (1000 * Lots))   
   {
      if((Counts[_OP_BUY] + Counts[_OP_SELL]) == 0)  
      {
         return(0);
      }   
   }

   for(i = 0; i < 2; i++)
   {
      if(MaxOrdersCount != 0)
        if((Counts[_OP_BUY] + Counts[_OP_SELL]) >= MaxOrdersCount)  break;   // открыто максимальное кол-во ордеров, больше открывать нельзя
   
      if(i == 0)   // BUY
      {
         if(UseBuy == 0)  continue;
         
         type         = _OP_BUY;
         typestr      = "BUY";
         CurrentPrice = Ask;
      }
      else         // SELL 
      {
         if(UseSell == 0)  continue;

         type         = _OP_SELL;
         typestr      = "SELL";
         CurrentPrice = Bid;
      }
      
      // рассчитываем фигуру текущей цены
      
      CurrentFigure = (MathFloor((CurrentPrice / _Point) / 100) * 100) * _Point;
   
   
      // ОТКРЫТИЕ РЕАЛЬНЫХ ОРДЕРОВ
      
      if(OpenRealOrders == 1)
      {
         MayOpenRealOrder = false;  
         
         //   на основании индикатора флэт
         
         if((UseFlatIndicator == 1) && iFL_IsFlat) 
         {
            if((type == _OP_BUY) && (CurrentPrice > iFL_Low) && (CurrentPrice <= (iFL_Low + iFL_Width / 4)))
            {
               if((iOpen( NULL, _Period[0], 0) >= iClose( NULL, _Period[0], 1)) && 
                  (iClose( NULL, _Period[0], 1) > iClose( NULL, _Period[0], 2)) && (iClose( NULL, _Period[0], 2) > iClose( NULL, _Period[0], 3)))
               {     
                  MayOpenRealOrder = true;  
               
                  _OrderType       = OP_BUY;
                  _OrderOpenPrice  = CurrentPrice;
                  _OrderTakeProfit = _OrderOpenPrice + NormalizeDouble(iFL_Width / 2, Digits);
                  
                  if(TakeProfitB > 0) 
                  {
                     if(_OrderTakeProfit > (_OrderOpenPrice + TakeProfitB * _Point))  _OrderTakeProfit = _OrderOpenPrice + TakeProfitB * _Point;
                  }   
               
                  if(iFL_StopLoss   > 0)  _OrderStopLoss = _OrderOpenPrice - iFL_StopLoss * _Point;   
                  else if(StopLossB > 0)  _OrderStopLoss = _OrderOpenPrice - StopLossB * _Point;   
                  else                    _OrderStopLoss = 0;
               }
            }   
      
            if((type == _OP_SELL) && (CurrentPrice < iFL_High) && (CurrentPrice >= (iFL_High - iFL_Width / 4)))
            {
               if((iOpen( NULL, _Period[0], 0) <= iClose( NULL, _Period[0], 1)) && 
                  (iClose( NULL, _Period[0], 1) < iClose( NULL, _Period[0], 2)) && (iClose( NULL, _Period[0], 2) < iClose( NULL, _Period[0], 3)))
               {     
                  MayOpenRealOrder = true;  
               
                  _OrderType       = OP_SELL;
                  _OrderOpenPrice  = CurrentPrice;
                  _OrderTakeProfit = _OrderOpenPrice - NormalizeDouble(iFL_Width / 2, Digits);   
               
                  if(TakeProfitS > 0)
                  {
                     if(_OrderTakeProfit < (_OrderOpenPrice - TakeProfitS * _Point))  _OrderTakeProfit = _OrderOpenPrice - TakeProfitS * _Point;
                  }   
                  
                  if(iFL_StopLoss   > 0)  _OrderStopLoss = _OrderOpenPrice + iFL_StopLoss * _Point;   
                  else if(StopLossS > 0)  _OrderStopLoss = _OrderOpenPrice + StopLossS * _Point;   
                  else                    _OrderStopLoss = 0;
               }
            }   
            
            if(MayOpenRealOrder)  _OrderMagicNumber = MN_Flating;
         }   
         
         //   на основании индикатора SPEED
         
         if(!MayOpenRealOrder && (UseSpeedIndicator == 1) && (iSP_UseForOpenRealOrders == 1) && (MathAbs(miSpeed) > iSP_MinValueForOpenRealOrders))
         {
            if((type == _OP_BUY) && (miSpeed > 0))
            {
               MayOpenRealOrder = true;  
            
               _OrderType       = OP_BUY;
               _OrderOpenPrice  = CurrentPrice;
               
               if(iSP_UseMinTakeProfit == 1)  _OrderTakeProfit = _OrderOpenPrice + MarketInfo(Symbol(), MODE_STOPLEVEL) * _Point;
               else                           _OrderTakeProfit = _OrderOpenPrice + TakeProfitB * _Point;
               
               if(iSP_StopLoss   > 0)  _OrderStopLoss = _OrderOpenPrice - iSP_StopLoss * _Point;   
               else if(StopLossB > 0)  _OrderStopLoss = _OrderOpenPrice - StopLossB * _Point;   
               else                    _OrderStopLoss = 0;
            }
            
            if((type == _OP_SELL) && (miSpeed < 0))
            {
               MayOpenRealOrder = true;  
            
               _OrderType       = OP_SELL;
               _OrderOpenPrice  = CurrentPrice;

               if(iSP_UseMinTakeProfit == 1)  _OrderTakeProfit = _OrderOpenPrice - MarketInfo(Symbol(), MODE_STOPLEVEL) * _Point;
               else                           _OrderTakeProfit = _OrderOpenPrice - TakeProfitS * _Point;
               
               if(iSP_StopLoss   > 0)  _OrderStopLoss = _OrderOpenPrice + iSP_StopLoss * _Point;   
               else if(StopLossS > 0)  _OrderStopLoss = _OrderOpenPrice + StopLossS * _Point;   
               else                    _OrderStopLoss = 0;
            }
            
            if(MayOpenRealOrder)  _OrderMagicNumber = MN_Speed;
         }
         
         if(MayOpenRealOrder)  
         {
            if(!glCheckOrderBeforeAdding(_OrderOpenPrice, type, _OrderType, CurrentPrice))  MayOpenRealOrder = false;  
         }      
      
         if(MayOpenRealOrder)  
         {
            if(!glCheckDistanceFromOneWayReal(_OrderOpenPrice, type, typestr, NearestRealPrice))  MayOpenRealOrder = false;
         }      
      
         if(MayOpenRealOrder)  
         {
            if(!glCheckHighLowLimit(_OrderOpenPrice, type, typestr))  MayOpenRealOrder = false;
         }      
         
         if(MayOpenRealOrder)  
         {
            if(!glCheckOpenOrdersBeforeAdding(_OrderOpenPrice, _OrderType, CurrentPrice))  MayOpenRealOrder = false;  
         }  
         
         // открытие реального ордера
         
         if(MayOpenRealOrder)
         {
            _Volume = Lots;
            
            if(_OrderMagicNumber == MN_Flating)
            {
               if((iFL_LotSizeMultiply > 0) && (iFL_LotSizeMultiply != 1))
               {
                  _Volume = glDoubleRound(Lots * iFL_LotSizeMultiply, StepLotSize); 
                    
                  if(_Volume > MaxLotSize)  _Volume = MaxLotSize;
               }
               
            }   
            else if(_OrderMagicNumber == MN_Speed)
            {
            }
            
            ticket = OrderSend(Symbol(), _OrderType, _Volume, _OrderOpenPrice, 0, _OrderStopLoss, _OrderTakeProfit, "zdima", _OrderMagicNumber, 0, Green);
            
            if(ticket > 0)
            {
               if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))  
               {
                  if(!glAnalizCurrentOrdersState())  return(0);
                  continue;
               }   
            }
            else Print("Ошибка открытия ", typestr, " ордера (Lots = ", Lots, "): ", GetLastError());   
         }
      }
      
   
      // ДОБАВЛЕНИЕ ОТЛОЖЕННЫХ ОРДЕРОВ ПО УРОВНЯМ 

      for(j = 0; j < 2; j++)    
      {
         _OrderMagicNumber = MN_Usual;   
         
         if(j == 0)   // STOP
         {
            if(type == _OP_BUY)
            {
               if(BuyStopLevel < 0)  continue;
                           
               _OrderType   = OP_BUYSTOP;
               typedefer    = _OP_BUYSTOP;
               typestr = "BUY STOP";
               
               if(CurrentPrice < (CurrentFigure + BuyStopLevel * _Point))  
                 _OrderOpenPrice = CurrentFigure + BuyStopLevel * _Point;
               else
                 _OrderOpenPrice = CurrentFigure + (100 + BuyStopLevel) * _Point;
            }
            else
            {
               if(SellStopLevel < 0)  continue;
                           
               _OrderType   = OP_SELLSTOP;
               typedefer    = _OP_SELLSTOP;
               typestr = "SELL STOP";
               
               if(CurrentPrice < (CurrentFigure + SellStopLevel * _Point))  
                 _OrderOpenPrice = CurrentFigure - (100 - SellStopLevel) * _Point;
               else
                 _OrderOpenPrice = CurrentFigure + SellStopLevel * _Point;
            }   
         }
         else        // LIMIT
         {
            if(type == _OP_BUY)
            {
               if(BuyLimitLevel < 0)  continue;
                           
               _OrderType   = OP_BUYLIMIT;
               typedefer    = _OP_BUYLIMIT;
               typestr = "BUY LIMIT";
               
               if(CurrentPrice < (CurrentFigure + BuyLimitLevel * _Point))  
                 _OrderOpenPrice = CurrentFigure - (100 - BuyLimitLevel) * _Point;
               else
                 _OrderOpenPrice = CurrentFigure + BuyLimitLevel * _Point;
            }
            else
            {
               if(SellLimitLevel < 0)  continue;
                           
               _OrderType   = OP_SELLLIMIT;
               typedefer    = _OP_SELLLIMIT;
               typestr = "SELL LIMIT";
               
               if(CurrentPrice < (CurrentFigure + SellLimitLevel * _Point))  
                 _OrderOpenPrice = CurrentFigure + SellLimitLevel * _Point;
               else
                 _OrderOpenPrice = CurrentFigure + (100 + SellLimitLevel) * _Point;
            }   
         }    
         
         if(type == _OP_BUY)
         {
            _OrderTakeProfit = _OrderOpenPrice + TakeProfitB * _Point;   
            
            if(StopLossB > 0)  _OrderStopLoss = _OrderOpenPrice - StopLossB * _Point;   
            else               _OrderStopLoss = 0;
         }
         else
         {
            _OrderTakeProfit = _OrderOpenPrice - TakeProfitS * _Point;   
            
            if(StopLossS > 0)  _OrderStopLoss = _OrderOpenPrice + StopLossS * _Point;
            else               _OrderStopLoss = 0;   
         }
         
      
         MayOpenDeferOrder = true;   // разрешение на открытие текущего отложенного ордера

         // проверка возможности добавления ордера

         if(MayOpenDeferOrder)  
         {
            if(!glCheckOrderBeforeAdding(_OrderOpenPrice, type, _OrderType, CurrentPrice))  MayOpenDeferOrder = false;  
         }      
      
         // проверка на расстояние цены открытия от текущей цены

         if(MayOpenDeferOrder)
         {
            if(MinDistanceDeferFromPrice != 0)
              if(MathAbs(_OrderOpenPrice - CurrentPrice) < (MinDistanceDeferFromPrice * _Point))  MayOpenDeferOrder = false;

            if(MaxDistanceDeferFromPrice != 0)
              if(MathAbs(_OrderOpenPrice - CurrentPrice) > (MaxDistanceDeferFromPrice * _Point))  MayOpenDeferOrder = false;
         }
         
         if(MayOpenDeferOrder)
         {
            if((Counts[type] > 0) && (j == 1))  MayOpenDeferOrder = false;
         }
         
         
         if(MayOpenDeferOrder)
         {
            if(Counts[typedefer] > 0)
            {
               if((typedefer == _OP_BUYSTOP) || (typedefer == _OP_SELLLIMIT))  NearestDeferPrice = MinPrices[typedefer];  
               else                                                            NearestDeferPrice = MaxPrices[typedefer];   
               
               NeedDistance = MinDistanceBetweenDefer * _Point;
               
               if((typedefer == _OP_BUYSTOP) || (typedefer == _OP_SELLLIMIT)) 
               {
                  if(_OrderOpenPrice > NearestDeferPrice - NeedDistance)  MayOpenDeferOrder = false;
               }
               else
               {
                  if(_OrderOpenPrice < NearestDeferPrice + NeedDistance)  MayOpenDeferOrder = false;
               }   
            }
         }      
         
         
         if(MayOpenDeferOrder && (Counts[type] > 0))
         {
            if(glCheckDistanceFromOneWayReal(_OrderOpenPrice, type, typestr, NearestRealPrice))
            {
               // открытие однонаправленной позиции разрешено


               if(((type == _OP_BUY)  && (UseAveragingTakeProfitB == 1)) ||
                  ((type == _OP_SELL) && (UseAveragingTakeProfitS == 1)))
               {
                  _OrderTakeProfit = (_OrderOpenPrice + NearestRealPrice) / 2;  // усредняем TakeProfit для получения безубытка посредине
                  _OrderMagicNumber = MN_Averaging;   
               }
            }
            else MayOpenDeferOrder = false;
         }
    
         
         if(MayOpenDeferOrder && (UseAcceleratorIndicator == 1))
         {
            
            if(j == 1)
            {
               if((type == _OP_BUY)  && (miAccelerator < 0)) 
               {
                  MayOpenDeferOrder = false;
               }
                  
               if((type == _OP_SELL) && (miAccelerator > 0))  
               {
                  MayOpenDeferOrder = false;
               }   
            }
         }
         
         // проверка на индикаторе Speed
         
         if(MayOpenDeferOrder && (UseSpeedIndicator == 1))
         {
            
            if(j == 1)
            {
               if((type == _OP_BUY)  && (miSpeed < 0))  
               {
                  MayOpenDeferOrder = false;
               }   
               
               if((type == _OP_SELL) && (miSpeed > 0))  
               {
                  MayOpenDeferOrder = false;
               }   
            }
         }
         
         // проверка ограничения HighLowLimit: "не покупать сверху, не продавать снизу"
         
         if(MayOpenDeferOrder && (CountHighLowLimits > 0))
         {
            if(!glCheckHighLowLimit(_OrderOpenPrice, type, typestr))  MayOpenDeferOrder = false;
         }
           
         // проверка открытых реальных и отложенных ордеров перед добавлением текущего
         
         if(MayOpenDeferOrder)  
         {
            if(!glCheckOpenOrdersBeforeAdding(_OrderOpenPrice, _OrderType, CurrentPrice))  MayOpenDeferOrder = false;  
         }      
           
         // открываем отложенный ордер       
   
         if(MayOpenDeferOrder)
         {
            _Volume = Lots;
            
            ticket = OrderSend(Symbol(), _OrderType, _Volume, _OrderOpenPrice, 0, _OrderStopLoss, _OrderTakeProfit, "zdima", _OrderMagicNumber, 0, Green);
            
            if(ticket > 0)
            {
               if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))  
               {
                  if(!glAnalizCurrentOrdersState())  return(0);
               }   
            }
            else Print("Ошибка открытия ", typestr, " ордера (Lots = ", Lots, "): ", GetLastError());   
         }
      }
   }

 return(0);
}

// проверка открытых реальных и отложенных ордеров перед добавлением текущего

bool glCheckOrderBeforeAdding(double _OrderOpenPrice, int type, int _OrderType, double CurrentPrice)
{
   if(type == _OP_BUY)
   {
      if(UseBuy == 0)  return(false);   
      if((_OrderType == OP_BUY) && (OpenRealOrders == 0))  return(false);   
      if((BuyDenyLevel > 0) && (_OrderOpenPrice >= BuyDenyLevel))  return(false);   
   }
   
   if(type == _OP_SELL)
   {
      if(UseSell == 0)  return(false);   
      if((_OrderType == OP_SELL) && (OpenRealOrders == 0))  return(false);   
      if((SellDenyLevel > 0) && (_OrderOpenPrice <= SellDenyLevel))  return(false);   
   }
   
 return(true);  
}

// проверка открытых реальных и отложенных ордеров перед добавлением текущего

bool glCheckOpenOrdersBeforeAdding(double _OrderOpenPrice, int _OrderType, double CurrentPrice)
{
   int i, j, k, total;
   
   if((_OrderType == OP_BUY) || (_OrderType == OP_BUYLIMIT))
   {
      if(!glDeleteAllDeferOrders(OP_BUYLIMIT, Symbol()))  return(false);
   }

   if((_OrderType == OP_SELL) || (_OrderType == OP_SELLLIMIT))
   {
      if(!glDeleteAllDeferOrders(OP_SELLLIMIT, Symbol()))  return(false);
   }
   
   // проверяем ограничение на кол-во ордеров и одновременно удаляем менее значимые ордера
    
   if(MaxOrdersCount != 0)
   {
      int    CurrentOrderType, OrderTicketMaxDistance;
      double CurrentDistance, MaxDistance;
             
      total = OrdersTotal();
    
      while(total >= MaxOrdersCount) 
      {
         MaxDistance = 0;
         
         for(i = 0; i < total; i++)
         {
            if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               Print("Ошибка получения текущего ордера OrderSelect(): ", GetLastError());   
               continue;
            }

            if(OrderSymbol() != Symbol())  continue;   // пропускаем позиции не по текущей валютной паре
            
            CurrentOrderType = OrderType();
            
            if     ((CurrentOrderType == OP_BUYLIMIT)  || (CurrentOrderType == OP_BUYSTOP))   CurrentDistance = MathAbs(Ask - OrderOpenPrice());
            else if((CurrentOrderType == OP_SELLLIMIT) || (CurrentOrderType == OP_SELLSTOP))  CurrentDistance = MathAbs(Bid - OrderOpenPrice());
            else continue;
            
            if(CurrentDistance > MaxDistance)
            {
               MaxDistance            = CurrentDistance;
               OrderTicketMaxDistance = OrderTicket();  
            } 
         }    
         
         if(MaxDistance > MathAbs(_OrderOpenPrice - CurrentPrice))   // есть более дальние отложенные ордера
         {
            // удаляем самый дальний отложенный ордер
            
            if(OrderDelete(OrderTicketMaxDistance)) 
            {
               total = OrdersTotal();   // для повторной проверки
            }
            else  return(false);
         }
         else  return(false);
      }        
   }
  
  return(true);     
}

// проверка расстояния открываемого ордера от открытых реальных однонаправленных позиций

bool glCheckDistanceFromOneWayReal(double _OrderOpenPrice, int type, string typestr, double& NearestRealPrice)
{
   double NeedDistance;
   
   if(Counts[type] == 0)  return(true);

   if((type == _OP_BUY)  && (UseOneWayRealOrdersB == 0))  return(false);
   if((type == _OP_SELL) && (UseOneWayRealOrdersS == 0))  return(false);
   
   if(type == _OP_BUY)  
   {
      NearestRealPrice = MinPrices[type];  
      NeedDistance     = Counts[type] * MinDistanceRealOrdersB * _Point;
   }   
   else 
   {
      NearestRealPrice = MaxPrices[type];  
      NeedDistance     = Counts[type] * MinDistanceRealOrdersS * _Point;
   }

   if(type == _OP_BUY) 
   {
      if(_OrderOpenPrice > NearestRealPrice - NeedDistance)  return(false);
   }
   else
   {
      if(_OrderOpenPrice < NearestRealPrice + NeedDistance)  return(false);
   }   

  return(true);    
}

// проверка открываемого ордера на индикаторе HighLowLimit

bool glCheckHighLowLimit(double _OrderOpenPrice, int type, string typestr)
{
   int i, j, k, total;
   
   for(k = 0; k < CountHighLowLimits; k++)
   {
      switch(k)
      {
         case 0 : _iHL_LimitDistance = iHL_LimitDistance1;  break;
         case 1 : _iHL_LimitDistance = iHL_LimitDistance2;  break;
         default: continue;     
      }

      if((type == _OP_BUY) && (iHL_Low[k] > 0) && (_OrderOpenPrice >= (iHL_Low[k] + _iHL_LimitDistance * _Point)))  
      {
         return(false);
      }   
   
      if((type == _OP_SELL) && (iHL_High[k] > 0) && (_OrderOpenPrice <= (iHL_High[k] - _iHL_LimitDistance * _Point))) 
      {
         return(false);
      }   
   }  
  
  return(true);    
}


// функция для анализа текущего состояния ордеров

bool glAnalizCurrentOrdersState()
{
   int    i, j, k, total;
   int    _OrderType, NormalOrderType; 
   double _OrderOpenPrice, _OrderLots;

   total = OrdersTotal();

   for(i = 0; i < 6; i++)
   {
      MinPrices[i] = -1;
      MaxPrices[i] = -1;
      SumLots[i]   = 0;
      Counts[i]    = 0;
   }
   
   for(i = 0; i < total; i++)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         Print("Ошибка получения текущего ордера OrderSelect(): ", GetLastError());   
         return(false);
      }

      if(OrderSymbol() != Symbol())  continue;   // пропускаем позиции не по текущей валютной паре
      
      // определяем параметры текущего ордера

      _OrderType      = OrderType();
      _OrderOpenPrice = OrderOpenPrice();
      _OrderLots      = OrderLots(); 
      
      NormalOrderType = glGetNormalOrderType(_OrderType);
      if(NormalOrderType == -1)
      {
         Print("Ошибка определения типа текущего ордера: OrderType() = ", _OrderType);  
         return(false);
      }
      
      Counts[NormalOrderType] = Counts[NormalOrderType] + 1;
      
      // определяем максимальные и минимальные цены
      
      if((MinPrices[NormalOrderType] == -1) || (_OrderOpenPrice < MinPrices[NormalOrderType]))  MinPrices[NormalOrderType] = _OrderOpenPrice; 
      if((MaxPrices[NormalOrderType] == -1) || (_OrderOpenPrice > MaxPrices[NormalOrderType]))  MaxPrices[NormalOrderType] = _OrderOpenPrice; 

      SumLots[NormalOrderType] = SumLots[NormalOrderType] + _OrderLots;
   } 
 
 return(true);  
}


// функция удаляет все отложенные ордера
// [MinPrice...MaxPrice] - диапазон цен (условие) удаляемых ордеров, если какая-то граница равна 0, она не используется

bool glDeleteAllDeferOrders(int type = -1, string symbol = "", double MinPrice = 0, double MaxPrice = 0)
{  
   int    i, j, k, total;
   int    _OrderType;
   double _OrderOpenPrice;
   bool   success = true;

   total = OrdersTotal();

   for(i = total - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         _OrderType      = OrderType();
         _OrderOpenPrice = OrderOpenPrice();
         
         if(((type == -1) || (_OrderType == type)) && ((symbol == "") || (OrderSymbol() == symbol)))     
         {
            if(type == -1)
               if((_OrderType == OP_BUY) || (_OrderType == OP_SELL))  continue;   // это реальный ордер, пропускаем
          
            if((MinPrice != 0) && (_OrderOpenPrice < MinPrice))  continue;       
            if((MaxPrice != 0) && (_OrderOpenPrice > MaxPrice))  continue;       
            
            if(!OrderDelete(OrderTicket())) success = false;
         }   
      }
      else success = false;
   }   
   
 return(success);
}


// ------  Округление вещественного числа с точностью Eps  ------

double glDoubleRound(double Val, double Eps)
{
   int    CEps;
   int    k = 1;
   double Dop, RDop;

   if(Eps == 0)  return(Val);

   while((Eps * k) < 1)  k = k * 10;

   CEps = Eps * k;

   Dop = MathFloor(Val * k);

   if(MathAbs(Val * k - Dop) > 0.5 )  Dop++;

   RDop = Dop / CEps;

   if(RDop != MathRound(RDop))
   {
      if(MathAbs(RDop - MathFloor(RDop)) > 0.5)  RDop = MathFloor(RDop) + 1;
      else                                       RDop = MathFloor(RDop);
      
      Dop = RDop * CEps;
   }

 return(Dop / k); 
}

bool glOrderClose(double price = -1, double slippage = 0)
{  
   int  i, j, k, total;
   int  err;
   bool success = false;
   
   if(price == -1)  price = glGetCurrentClosePrice();
   
   // предпринимаем 5 попыток с интервалом в 1 сек.
   
   for(i = 0; i < 5; i++)
   {
      if(OrderClose(OrderTicket(), OrderLots(), price, slippage))
      {
         success = true;
         break;
      }   
      else  
      {  
         err = GetLastError();
         Print("OrderClose failed, Error: ", err);
         if(err > 4000) break;
         Sleep(1000);
         RefreshRates();
         price = glGetCurrentClosePrice();
      }
   }
   
 return(success);
} 


// функция возвращает возможную соответствующую цену закрытия текущего ордера

double glGetCurrentClosePrice()
{
   double price;
   
   if(OrderSymbol() == Symbol())  
   {
      if(OrderType() == OP_BUY)  price = Bid;
      else                       price = Ask;
   }
   else
   {
      if(OrderType() == OP_BUY)  price = MarketInfo(OrderSymbol(), MODE_BID);
      else                       price = MarketInfo(OrderSymbol(), MODE_ASK);
   }   
 
 return(price);  
}

0