Navigation:Home > Content >

Ilan_Pyramid_.mq4

Time: 2016-10-20 | Download file:Ilan_Pyramid_.mq4

//+------------------------------------------------------------------+
//|                                                 Ilan_Pyramid.mq4 |
//|                                   Copyright © 2010, Tarakan Corp |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2010, Tarakan Corp"

#include   // тут функция вывода сообщения об ошибке ErrorDescription()

extern     double  IlanTakeProfit   = 10;       // TakeProfit для илана
extern     double  PyramidStopLoss  = 10;        // StopLoss для пирамиды

extern     double  IlanStep         = 30;       // размер шага открытия ордеров илана
extern     double  PyramidStep      = 30;       // размер шага открытия ордеров пирамиды

extern bool    UseMartingale    = True;     // False - объем лота постоянен и равен IlanStartLot,
                                                // True - объем лота каждого нового ордера увеличивается по экспоненте

extern     double  IlanLotExp       = 1.60;     // экспонента увеличения объема каждого нового ордера илана
extern     double  PyramidLotExp    = 1.00;     // экспонента увеличения объема каждого нового ордера пирамиды

extern     double  IlanStartLot     = 0.01;     // размер лота илана
extern     double  PyramidStartLot  = 0.01;     // размер лота пирамиды
extern     int     LotDecimal       = 2;        // 2 - микролоты 0.01; 1 - мини лоты 0.1; 0 - нормальные лоты 1.0

extern     int     MaxIlanTrades    = 10;       // максимальное количество открытых ордеров илана
extern     int     MaxPyramidTrades = 10;       // максимальное количество ордеров пирамиды

extern bool    UsePyramidTrail  = False; 
extern double  TrailStart       = 10;       // если прибыль по ордеру больше TrailStart, то срабатывает трал
extern double  TrailStop        = 10;       // новый StopLoss выставляется на TrailStop пунктов от текущей цены

extern     double  PercentLoss      = 50.00;    // сколько процентов депозита можно потерять
                                                // прежде чем советник остановится

extern     int     MagicNumber      = 80808;    // магический номер

//+------------------------------------------------------------------+

double     CurrIlanAvgPrice = 0;
double     CurrIlanTP = 0;
double     CurrPyramidSL = 0;
double     Spread;
string     ExpertName = "Ilan Pyramid";
datetime   PrevTime = 0;
int        Slip = 3;
int        Total, cnt;
bool       SellTradeNow = False, BuyTradeNow = False;
bool       NewSellOrderPlaced = False, NewBuyOrderPlaced = False;
double     PercentProfit = 100.00; // когда советник заработает PercentProfit процентов
                                   // депозита, тогда он остановится

int        BuyTrade = -1, SellTrade = -1;      //  0 - направление торгует как Илан
                                               //  1 - направление торгует как Пирамида
                                               // -1 - по направлению нет открытых ордеров

int        ErrorCode;

// массивы с тикетами открытых ордеров советника
int BuyOrders[];      // массив тикетов ордеров buy
int SellOrders[];     // массив тикетов ордеров sell

//+------------------------------------------------------------------+

int init()
  {
    return(0);
  }
  
//+------------------------------------------------------------------+

int deinit()
  {
    return(0);
  }
  
//+------------------------------------------------------------------+

int start()
  {
    // если потеряно PercentLoss (или больше) процентов депозита
    // или заработано PercentProfit процентов депозита - закрываем все
    if (AccountEquity() >= AccountBalance() * (1 + PercentProfit / 100)
          || AccountEquity() <= AccountBalance() * (1 - PercentLoss / 100))
      {
        CloseThisSymbolAll();
      }
  
    //---------------------------------
  
    // тралим пирамиду
    if (UsePyramidTrail)
      TrailingPyramid(TrailStart, TrailStop);
      
    //---------------------------------
  
    if (PrevTime == Time[0])
      return(0);      
      
    PrevTime = Time[0];
    
    //---------------------------------
    
    Spread = MarketInfo(Symbol(), MODE_SPREAD) * Point;
    
    RefreshOrders();  // пересчитаем все открытые ордеры
    RefreshTrades();  // проверим BuyTrade и SellTrade
    
    //---------------------------------
    
    // не пора ли открывать очередной ордер
    
    if (CheckBuyTrade()) BuyTradeNow = True;
    if (CheckSellTrade()) SellTradeNow = True;
      
    //---------------------------------------
    
    // торгуем
      
    if (SellTradeNow)
      {
        for (cnt = 0; cnt < 3; cnt++) // три попытки открыть ордер
          {
            if (OpenSellOrder())
              {
                NewSellOrderPlaced = True;  // новый ордер открыт
                SellTradeNow = False;
                break;
              }
            Sleep(2000);
          }
      }
    
    //-------
    
    if (BuyTradeNow)
      {
        for (cnt = 0; cnt < 3; cnt++) // три попытки открыть ордер
          {
            if (OpenBuyOrder())
              {
                NewBuyOrderPlaced = True;  // новый ордер открыт
                BuyTradeNow = False;
                break;
              }
            Sleep(2000);
          }
      }
    
    //-------------------------------
    
    // модифицируем все ордеры (двигаем PyramidStopLoss и IlanTakeProfit)
    
    if (NewBuyOrderPlaced)
      {
        ModifyBuyOrders();
        NewBuyOrderPlaced = False;
      }
      
    if (NewSellOrderPlaced)
      {
        ModifySellOrders();
        NewSellOrderPlaced = False;
      }
    
    //-------------------------------
    
    return(0);    
  }  // --- Exit start() function ---
  
  
//+------------------------------------------------------------------+

// возвращает размер лота для очередного ордера заданного направления

double GetLotSize(int aTradeType)
  {
    double tLots;
    double tExponent;
    int Trades = CountTrades(aTradeType);
    
    if (IsIlan(aTradeType))
      {
        tLots = IlanStartLot;
        tExponent = IlanLotExp;
      }
    
    if (IsPyramid(aTradeType))
      {
        tLots = PyramidStartLot;
        tExponent = PyramidLotExp;
      }
    
    if (IsEmpty(aTradeType)) // берем размер меньшего лота
      {
        if (IlanStartLot < PyramidStartLot)
          {
            tLots = IlanStartLot;
            tExponent = IlanLotExp;
          }
        else
          {
            tLots = PyramidStartLot;
            tExponent = PyramidLotExp;
          }
      }
    
    //----------
    
    if (UseMartingale)
      tLots = NormalizeDouble(tLots * MathPow(tExponent, Trades), LotDecimal);
        
    if (AccountFreeMarginCheck(Symbol(), aTradeType, tLots) <= 0)
      return(-1);  // после открытия ордера не останется свободных средств
    
    if (GetLastError() == 134)
      return(-1);  // ошибка ERR_NOT_ENOUGH_MONEY - не хватает свободных средств
      
    return(tLots);
  }

//+------------------------------------------------------------------+

// возвращает количество открытых ордеров советника заданного направления

int CountTrades(int aTradeType = -1)
  {
    if (aTradeType == OP_BUY)
      return(ArraySize(BuyOrders));
    
    if (aTradeType == OP_SELL)
      return(ArraySize(SellOrders));
      
    // aTradeType == -1
    
    return(ArraySize(BuyOrders) + ArraySize(SellOrders));
  }
  
//+------------------------------------------------------------------+

/*double CalculateProfit()
  {
    double Profit = 0;
   
    for (cnt = 0; cnt < ArraySize(BuyOrders); cnt++)
      {
        OrderSelect(BuyOrders[cnt], SELECT_BY_TICKET);
        Profit = Profit + OrderProfit() + OrderCommission() + OrderSwap();
      }
     
    return(Profit);
  }*/

//+------------------------------------------------------------------+

void CloseThisSymbolAll()
  {
    for (cnt = OrdersTotal() - 1; cnt >= 0; cnt--)
      {
        OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
        
        if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber)
          continue;
          
        if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
          {
            if (OrderType() == OP_BUY)
              OrderClose(OrderTicket(), OrderLots(), Bid, Slip, Lime);
              
            if (OrderType() == OP_SELL)
              OrderClose(OrderTicket(), OrderLots(), Ask, Slip, HotPink);
          }
          
        Sleep(2000);
      }
  }

//+------------------------------------------------------------------+

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

double FindLastBuyPrice()
  {
    if (ArraySize(BuyOrders) == 0)
      return(0);
  
    OrderSelect(BuyOrders[ArraySize(BuyOrders) - 1], SELECT_BY_TICKET);
    return(OrderOpenPrice());
  }
  
//+------------------------------------------------------------------+

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

double FindLastSellPrice()
  {
    if (ArraySize(SellOrders) == 0)
      return(0);
  
    OrderSelect(SellOrders[ArraySize(SellOrders) - 1], SELECT_BY_TICKET);
    return(OrderOpenPrice());
  }
  
//+------------------------------------------------------------------+

// возвращает тикет последнего открытого ордера заданного направления
// по-умолчанию - тикет самого последнего ордера любого направления

/*int FindLastTicket(int aTradeType = -1)
  {
    int FindTicket = -1;
    
    if (aTradeType == OP_BUY)
      {
        if (ArraySize(BuyOrders) == 0)
          return(-1);
        else
          return(BuyOrders[ArraySize(BuyOrders) - 1]);
      }
    
    if (aTradeType == OP_SELL)
      {
        if (ArraySize(SellOrders) == 0)
          return(-1);
        else
          return(SellOrders[ArraySize(SellOrders) - 1]);
      }
    
    // aTradeType == -1
  
    if (ArraySize(BuyOrders) != 0)
      FindTicket = BuyOrders[ArraySize(BuyOrders) - 1];
    
    if (ArraySize(SellOrders) != 0)
      if (SellOrders[ArraySize(SellOrders) - 1] > FindTicket)
        FindTicket = SellOrders[ArraySize(SellOrders) - 1];
    
    return(FindTicket);
  }*/

//+------------------------------------------------------------------+

// пересчитывет все открытые ордеры и заполняет массивы BuyOrders[]
// и SellOrders[] номерами тикетов открытых ордеров советника
// тикеты в массивах сортируются по возрастанию

void RefreshOrders()
  {
    int Count;
    int Ticket, OldTicket;
    int FindTicket = 0, LastFindTicket;
    
    ArrayResize(BuyOrders, 0);
    ArrayResize(SellOrders, 0);
  
    while (True)
      {
        LastFindTicket = FindTicket;
        FindTicket = 0;
        OldTicket = 0;
      
        // ищем минимальный тикет среди ордеров советника
        for (cnt = OrdersTotal() - 1; cnt >= 0; cnt--)
          {
            OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
        
            if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber)
              continue;
          
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
              {
                if (OrderType() == OP_BUY || OrderType() == OP_SELL)
                  {
                    Ticket = OrderTicket();
                    if (Ticket < OldTicket || OldTicket == 0)
                      {
                        if (LastFindTicket != 0 && Ticket <= LastFindTicket)
                          continue;
                    
                        FindTicket = Ticket;
                        OldTicket = FindTicket;
                      }
                  }
              }
          }  // for (cnt = OrdersTotal() - 1; cnt >= 0; cnt--)
          
        if (FindTicket == 0)
          {
            break;
          }
        else
          {
            OrderSelect(FindTicket, SELECT_BY_TICKET);
          
            if (OrderType() == OP_BUY)  // в BuyOrders[]
              {
                ArrayResize(BuyOrders, ArraySize(BuyOrders) + 1);
                BuyOrders[ArraySize(BuyOrders) - 1] = FindTicket;
              }
            else if (OrderType() == OP_SELL)  // в SellOrders[]
              {
                ArrayResize(SellOrders, ArraySize(SellOrders) + 1);
                SellOrders[ArraySize(SellOrders) - 1] = FindTicket;
              }
            
          }
      }  // while (True)
  }

//+------------------------------------------------------------------+

// возврвщает цуну уровня TakeProfit для заданной цены Price и заданного направления aTradeType
// Profit - размер TakeProfit в пунктах

double GetTakeProfitPrice(double Price, int aTradeType, double Profit)
  {
    double ResultPrice;
  
    double tp = Profit * Point;
    double MinStopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
    
    if (tp < MinStopLevel)
      tp = MinStopLevel;
    
    if (aTradeType == OP_BUY)
      ResultPrice = Price + tp;
      
    if (aTradeType == OP_SELL)
      ResultPrice = Price - tp;
    
    return(ResultPrice);
  }

//+------------------------------------------------------------------+

// возврвщает цуну уровня StopLoss для заданной цены Price и заданного направления aTradeType
// Stop - размер StopLoss в пунктах

double GetStopLossPrice(double Price, int aTradeType, double Stop)
  {
    double ResultPrice;
  
    double sl = Stop * Point;
    double MinStopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
    
    if (sl < MinStopLevel)
      sl = MinStopLevel;
    
    if (aTradeType == OP_BUY)
      {
        ResultPrice = Price - sl;
        if (NormalizeDouble((Price - ResultPrice) - MinStopLevel, 8) == 0)
          ResultPrice = ResultPrice - Spread;
      }
      
    if (aTradeType == OP_SELL)
      {
        ResultPrice = Price + sl;
        if (NormalizeDouble((ResultPrice - Price) - MinStopLevel, 8) == 0)
          ResultPrice = ResultPrice + Spread;
      }
    
    return(ResultPrice);
  }

//+------------------------------------------------------------------+

// открывает ордер buy

bool OpenBuyOrder()
  {
    int Ticket;
    double LotSize;
  
    LotSize = GetLotSize(OP_BUY);
            
    if (LotSize > 0)
      {
        RefreshRates();
        Ticket = OrderSend(Symbol(), OP_BUY, LotSize, NormalizeDouble(Ask, Digits),
                             Slip, 0, 0, ExpertName, MagicNumber, 0, Blue);
                                     
        if (Ticket < 0)
          {
            ErrorCode = GetLastError();
            Print("OrderSend Error ", ErrorCode, " - ", ErrorDescription(ErrorCode));
            return(False);
          }
        
        // добавим тикет ордера в конец массива        
        ArrayResize(BuyOrders, ArraySize(BuyOrders) + 1); 
        BuyOrders[ArraySize(BuyOrders) - 1] = Ticket;
      }
      
    return(True);
  }

//+------------------------------------------------------------------+

// открывает ордер sell

bool OpenSellOrder()
  {
    int Ticket;
    double LotSize;
  
    LotSize = GetLotSize(OP_SELL);
            
    if (LotSize > 0)
      {
        RefreshRates();
        Ticket = OrderSend(Symbol(), OP_SELL, LotSize, NormalizeDouble(Bid, Digits),
                             Slip, 0, 0, ExpertName, MagicNumber, 0, Red);
                                     
        if (Ticket < 0)
          {
            ErrorCode = GetLastError();
            Print("OrderSend Error ", ErrorCode, " - ", ErrorDescription(ErrorCode));
            return(False);
          }
        
        // добавим тикет ордера в конец массива
        ArrayResize(SellOrders, ArraySize(SellOrders) + 1); 
        SellOrders[ArraySize(SellOrders) - 1] = Ticket;
      }
      
    return(True);
  }

//+------------------------------------------------------------------+

// модифицирует ордеры заданного направления, Price - уровень StopLoss или TakeProfit
// для направления, торгующего как илан, подтягивает TakeProfit
// для направления, торгующего как пирамида, подтягивает StopLoss

void ModifyOrders(int aTradeType, double Price)
  {
    double NewStopLoss;
    double NewTakeProfit;
    int TempOrders[];
    
    if (aTradeType == OP_BUY)
      {
        ArrayResize(TempOrders, ArraySize(BuyOrders));
        ArrayCopy(TempOrders, BuyOrders);
      }
    else if (aTradeType == OP_SELL)
      {
        ArrayResize(TempOrders, ArraySize(SellOrders));
        ArrayCopy(TempOrders, SellOrders);
      }
  
    // модифицируем все ордеры массива TempOrders[]
    for (cnt = 0; cnt < ArraySize(TempOrders); cnt++)
      {
        OrderSelect(TempOrders[cnt], SELECT_BY_TICKET);
          
        if (IsIlan(aTradeType)) // для илана двигаем IlanTakeProfit
          {
            NewTakeProfit = NormalizeDouble(Price, Digits);
            NewStopLoss = OrderStopLoss();
          }
        
        if (IsPyramid(aTradeType)) // для пирамиды двигаем PyramidStopLoss
          {
            NewTakeProfit = OrderTakeProfit();
            NewStopLoss = OrderStopLoss();
            
            if (aTradeType == OP_BUY)
              {
                // если стопа нет совсем или новый стоп выше старого
                // if (OrderStopLoss() == 0 || (OrderStopLoss() != 0 && Price > OrderStopLoss()))
                  NewStopLoss = NormalizeDouble(Price, Digits);
              }
            else if (aTradeType == OP_SELL)
              {
                // если стопа нет совсем или новый стоп ниже старого
                // if (OrderStopLoss() == 0 || (OrderStopLoss() != 0 && Price < OrderStopLoss()))
                  NewStopLoss = NormalizeDouble(Price, Digits);
              }
          }
          
        if (NewStopLoss != OrderStopLoss() || NewTakeProfit != OrderTakeProfit())
          {
            if (!OrderModify(OrderTicket(), OrderOpenPrice(), NewStopLoss, NewTakeProfit, 0, Yellow))
              {
                ErrorCode = GetLastError();
                Print("Order #", OrderTicket(), " - OrderModify Error ",
                                 ErrorCode, " - ", ErrorDescription(ErrorCode));
              }
            Sleep(2000);  
          }
      }
  }

//+------------------------------------------------------------------+

// модифицирует все ордеры направления buy

void ModifyBuyOrders()
  {
    if (IsIlan(OP_BUY)) // если buy торгует как илан
      {
        CurrIlanAvgPrice = GetAveragePrice(OP_BUY);
        CurrIlanTP = GetTakeProfitPrice(CurrIlanAvgPrice, OP_BUY, IlanTakeProfit);  // новый TakeProfit
           
        ModifyOrders(OP_BUY, CurrIlanTP);
        
        if (IsPyramid(OP_SELL) && PyramidStopLoss == 0)
          {
            ModifyOrders(OP_SELL, CurrIlanTP + Spread);
          }
      }
    
    //-----------
          
    if (IsPyramid(OP_BUY)) // если buy торгует как пирамида
      {
        if (PyramidStopLoss == 0)  // если StopLoss пирамиды равен TakeProfit илана
          {
            // если у илана еще нет TakeProfit - вычислим его
            if (IsIlan(OP_SELL) && CurrIlanAvgPrice == 0 && CurrIlanTP == 0)
              {
                CurrIlanAvgPrice = GetAveragePrice(OP_SELL);
                CurrIlanTP = GetTakeProfitPrice(CurrIlanAvgPrice, OP_SELL, IlanTakeProfit);
              }
          
            if (CurrIlanTP == 0) // если еще нет илана
              CurrPyramidSL = GetStopLossPrice(FindLastBuyPrice(), OP_BUY, IlanTakeProfit);
            else
              CurrPyramidSL = CurrIlanTP - Spread;
          }
        else // у пирамиды свой StopLoss
          {
            CurrPyramidSL = GetStopLossPrice(FindLastBuyPrice(), OP_BUY, PyramidStopLoss);
          }
        
        ModifyOrders(OP_BUY, CurrPyramidSL);
      }  // if (IsPyramid(OP_BUY))
  }

//+------------------------------------------------------------------+

// модифицирует все ордеры направления sell

void ModifySellOrders()
  {
    if (IsIlan(OP_SELL)) // если sell торгует как илан
      {
        CurrIlanAvgPrice = GetAveragePrice(OP_SELL);
        CurrIlanTP = GetTakeProfitPrice(CurrIlanAvgPrice, OP_SELL, IlanTakeProfit);  // новый TakeProfit
        
        ModifyOrders(OP_SELL, CurrIlanTP);
        
        if (IsPyramid(OP_BUY) && PyramidStopLoss == 0)
          {
            ModifyOrders(OP_BUY, CurrIlanTP - Spread);
          }
      }
    
    //-----------
          
    if (IsPyramid(OP_SELL)) // если sell торгует как пирамида
      {
        if (PyramidStopLoss == 0)  // StopLoss пирамиды равен TakeProfit илана
          {
            // если у илана еще нет TakeProfit - вычислим его
            if (IsIlan(OP_BUY) && CurrIlanAvgPrice == 0 && CurrIlanTP == 0)
              {
                CurrIlanAvgPrice = GetAveragePrice(OP_BUY);
                CurrIlanTP = GetTakeProfitPrice(CurrIlanAvgPrice, OP_BUY, IlanTakeProfit);
              }
          
            if (CurrIlanTP == 0) // если еще нет илана
              CurrPyramidSL = GetStopLossPrice(FindLastSellPrice(), OP_SELL, IlanTakeProfit);
            else
              CurrPyramidSL = CurrIlanTP + Spread;
          }
        else // у пирамиды свой StopLoss
          {
            CurrPyramidSL = GetStopLossPrice(FindLastSellPrice(), OP_SELL, PyramidStopLoss);
          }
        
        ModifyOrders(OP_SELL, CurrPyramidSL);
      }  // if (IsPyramid(OP_SELL))
  }

//+------------------------------------------------------------------+

// проверяет, не пора ли открывать ордер buy

bool CheckBuyTrade()
  {
    int Step;
    int MaxTrades;
    double LastBuyPrice;
    bool CheckResult = False;
  
    if (IsIlan(OP_BUY)) MaxTrades = MaxIlanTrades;
    if (IsPyramid(OP_BUY)) MaxTrades = MaxPyramidTrades;
    
    //-------
      
    LastBuyPrice = FindLastBuyPrice();
    
    if (CountTrades(OP_BUY) > 0 && CountTrades(OP_BUY) < MaxTrades)
      {
        if (IsIlan(OP_BUY) && LastBuyPrice - Ask >= IlanStep * Point) // цена идет вниз
          CheckResult = True;
          
        if (IsPyramid(OP_BUY) && Ask - LastBuyPrice >= PyramidStep * Point) // цена идет вверх
          CheckResult = True;
      }
        
    //--------
        
    if (IsEmpty(OP_BUY)) // buy пока не определился
      {
        if (CountTrades(OP_BUY) == 0)
          {
            CheckResult = True;
          }
        else
          {
            // если цена ушла вверх, то buy будет пирамидой
            if ((Ask - LastBuyPrice >= PyramidStep * Point))
              {
                BuyTrade = 1; // buy - пирамида
                Print("Buy Is Pyramid");
                CheckResult = True;
              }
          
            // если цена ушла вниз, то buy будет иланом
            if ((LastBuyPrice - Ask >= IlanStep * Point))
              {
                BuyTrade = 0;  // buy - илан
                Print("Buy Is Ilan");
                CheckResult = True;
              }
          }
      }  // if (IsEmpty(OP_BUY)
      
    return(CheckResult);
  }

//+------------------------------------------------------------------+

// проверяет, не пора ли открывать ордер sell

bool CheckSellTrade()
  {
    int Step;
    int MaxTrades;
    double LastSellPrice;
    bool CheckResult = False;
  
    if (IsIlan(OP_SELL)) MaxTrades = MaxIlanTrades;
    if (IsPyramid(OP_SELL)) MaxTrades = MaxPyramidTrades;
    
    //-------
      
    LastSellPrice = FindLastSellPrice();
    
    if (CountTrades(OP_SELL) > 0 && CountTrades(OP_SELL) < MaxTrades)
      {
        if (IsIlan(OP_SELL) && Bid - LastSellPrice >= IlanStep * Point) // цена идет вверх
          CheckResult = True;
          
        if (IsPyramid(OP_SELL) && LastSellPrice - Bid >= PyramidStep * Point) // цена идет вниз
          CheckResult = True;
      }
        
    //--------
        
    if (IsEmpty(OP_SELL)) // sell пока не определился
      {
        if (CountTrades(OP_SELL) == 0)
          {
            CheckResult = True;
          }
        else
          {
            // если цена ушла вверх, то sell будет иланом
            if ((Bid - LastSellPrice >= IlanStep * Point))
              {
                SellTrade = 0; // sell - илан
                Print("Sell Is Ilan");
                CheckResult = True;
              }
          
            // если цена ушла вниз, то sell будет пирамидой
            if ((LastSellPrice - Bid >= PyramidStep * Point))
              {
                SellTrade = 1; // sell - пирамида
                Print("Sell Is Pyramid");
                CheckResult = True;
              }
          }
      }  // if (IsEmpty(OP_SELL)
      
    return(CheckResult);
  }

//+------------------------------------------------------------------+

// возвращает усредненную цену открытия всех ордеров заданного направления

double GetAveragePrice(int aTradeType)
  {
    double ResultPrice = 0;
    double Count = 0;
    int TempOrders[];
        
    if (aTradeType == OP_BUY)
      {
        ArrayResize(TempOrders, ArraySize(BuyOrders));
        ArrayCopy(TempOrders, BuyOrders);
      }
    else if (aTradeType == OP_SELL)
      {
        ArrayResize(TempOrders, ArraySize(SellOrders));
        ArrayCopy(TempOrders, SellOrders);
      }
    
    for (cnt = 0; cnt < ArraySize(TempOrders); cnt++)
      {
        OrderSelect(TempOrders[cnt], SELECT_BY_TICKET);
    
        ResultPrice = ResultPrice + OrderOpenPrice() * OrderLots();
        Count = Count + OrderLots();
      }
      
    if (ArraySize(TempOrders) > 0)
      ResultPrice = NormalizeDouble(ResultPrice / Count, Digits);
    
    return(ResultPrice);
  }

//+------------------------------------------------------------------+

// проверяет, торгует ли заданное направление как илан

bool IsIlan(int aTradeType)
  {
    if ((aTradeType == OP_BUY && BuyTrade == 0) || (aTradeType == OP_SELL && SellTrade == 0))
      return(True);
    else
      return(False);
  }

//-----------------------

// проверяет, торгует ли заданное направление как пирамида

bool IsPyramid(int aTradeType)
  {
    if ((aTradeType == OP_BUY && BuyTrade == 1) || (aTradeType == OP_SELL && SellTrade == 1))
      return(True);
    else
      return(False);
  }

//-----------------------

// возвращает True если заданное направление не илан и не пирамида

bool IsEmpty(int aTradeType)
  {
    if ((aTradeType == OP_BUY && BuyTrade == -1) || (aTradeType == OP_SELL && SellTrade == -1))
      return(True);
    else
      return(False);
  }

//+------------------------------------------------------------------+

// проверяет BuyTrade и SellTrade

void RefreshTrades()
  {
    if (CountTrades(OP_BUY) == 0)
      {
        if (IsIlan(OP_BUY))
          {
            CurrIlanTP = 0;
            CurrIlanAvgPrice = 0;
          }
          
        BuyTrade = -1;
      }
    
    //-------
    
    if (CountTrades(OP_SELL) == 0)
      {
        if (IsIlan(OP_SELL))
          {
            CurrIlanTP = 0;
            CurrIlanAvgPrice = 0;
          }
          
        SellTrade = -1;
      }
  }

//+------------------------------------------------------------------+

// тралит пирамиду
void TrailingPyramid(int Start, int Stop)
  {
    int Profit;
    int Trade;
    double OldStopLoss;
    double NewStopLoss;
    int TempOrders[];
    
    if (Stop == 0) return;
    if (!IsPyramid(OP_BUY) && !IsPyramid(OP_SELL)) return;
        
    if (IsPyramid(OP_BUY))
      {
        ArrayResize(TempOrders, ArraySize(BuyOrders));
        ArrayCopy(TempOrders, BuyOrders);
      }
    else if (IsPyramid(OP_SELL))
      {
        ArrayResize(TempOrders, ArraySize(SellOrders));
        ArrayCopy(TempOrders, SellOrders);
      }
      
    for (cnt = 0; cnt < ArraySize(TempOrders); cnt++)
      {
        OrderSelect(TempOrders[cnt], SELECT_BY_TICKET);
        
        if (OrderType() == OP_BUY)
          {
            Profit = NormalizeDouble((Bid - OrderOpenPrice()) / Point, 0);  // прибыль в пунктах
            if (Profit < Start)
              continue;
            OldStopLoss = OrderStopLoss();
            NewStopLoss = Bid - (Stop * Point);
            if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss > OldStopLoss))
              if (!OrderModify(OrderTicket(), OrderOpenPrice(), NewStopLoss, OrderTakeProfit(), 0))
                {
                  ErrorCode = GetLastError();
                  Print("Order #", OrderTicket(), " - OrderModify Error ",
                                   ErrorCode, " - ", ErrorDescription(ErrorCode));
                }
          }  // if (OrderType() == OP_BUY)
              
        if (OrderType() == OP_SELL)
          {
            Profit = NormalizeDouble((OrderOpenPrice() - Ask) / Point, 0);  // прибыль в пунктах
            if (Profit < Start)
              continue;
            OldStopLoss = OrderStopLoss();
            NewStopLoss = Ask + (Stop * Point);
            if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss < OldStopLoss))
              if (!OrderModify(OrderTicket(), OrderOpenPrice(), NewStopLoss, OrderTakeProfit(), 0))
                {
                  ErrorCode = GetLastError();
                  Print("Order #", OrderTicket(), " - OrderModify Error ",
                                   ErrorCode, " - ", ErrorDescription(ErrorCode));
                }
          }  // if (OrderType() == OP_SELL)
          
        Sleep(2000); // пауза 0.2 секунды
      }  // for (cnt = 0; cnt < ArraySize(Orders); cnt++)
  }
  
//+------------------------------------------------------------------+

Recommend