//+------------------------------------------------------------------+
//|                                            Ilan_Pyramid_v1.1.mq4 |
//|                                   Copyright � 2010, Tarakan Corp |
//+------------------------------------------------------------------+

#property copyright "Copyright � 2010, Tarakan Corp"

#include <stdlib.mqh>  // ��� ������� ������ ��������� �� ������ ErrorDescription()

extern     double  IlanTakeProfit   = 10;       // TakeProfit ��� �����
extern     double  PyramidStopLoss  = 10;       // StopLoss ��� ��������

extern     double  IlanStep         = 30;       // ������ ���� �������� ������� �����
extern     double  PyramidStep      = 30;       // ������ ���� �������� ������� ��������

/*extern*/ bool    UseMartingale    = True;     // False - ����� ���� ���������
                                                // True - ����� ���� ������� ������ ������ ������������� �� ����������

extern     double  IlanLotExp       = 1.60;     // ���������� ���������� ����� �����
extern     double  PyramidLotExp    = 1.00;     // ���������� ���������� ����� ��������

// extern  double  IlanStartLot     = 0.01;     // ��������� ������ ���� �����
// extern  double  PyramidStartLot  = 0.01;     // ��������� ������ ���� ��������

// extern  bool    FixLot           = False;    // True - ��������� ��� ������ ����������
extern     int     LotStep          = 1000;     // ��� ���������� ����. ������� � �������� LotStep,
                                                // ��������� ���������� LotSize. ���� ���� 1000 �� ��� 0.01,
                                                // ���� ������ 2000 �� ��� 0.02

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;    // ���������� �����

extern     bool    CheckPyramidOpen = True;     // True - ��������� ������ �������� ����� ���������
                                                // False - ��������� ��� ��������

//===================================================================

double     CurrIlanAvgPrice = 0;
double     CurrIlanTP = 0;
double     CurrPyramidSL = 0;
double     Spread;
string     ExpertName = "Ilan Pyramid v1.1";
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 (��� ������) ��������� �������� - ��������� ���
    if (AccountEquity() <= AccountBalance() * (1 - PercentLoss / 100))
      {
        Print("�������� ", PercentLoss, "% ��������, �������������� �������� ���� �������");
        CloseAllOrders();
      }
    
    // ���� ���������� PercentProfit (��� ������) ��������� �������� - ��������� ���
    if (AccountEquity() >= AccountBalance() * (1 + PercentProfit / 100))
      {
        Print("���������� ", PercentProfit, "% ��������, �������������� �������� ���� �������");
        CloseAllOrders();
      }
  
    //---------------------------------
  
    // ������ ��������
    // 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 (CheckPyramidOpen) CheckPyramid();
    
    //---------------------------------------
    
    // �������  
    
    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);
          }
      }
    
    //-------------------------------
    
    // ������������ ������ (������� StopLoss � TakeProfit)
    
    if (NewBuyOrderPlaced)
      {
        ModifyBuyOrders();
        NewBuyOrderPlaced = False;
      }
      
    if (NewSellOrderPlaced)
      {
        ModifySellOrders();
        NewSellOrderPlaced = False;
      }
    
    //-------------------------------
    
    return(0);    
  }  // --- Exit start() function ---
  
  
//===================================================================

// ���������� ������ ���� ��� ���������� ������ ��������� �����������
// � ������ ������ ���������� -1

double GetLotSize(int TradeType)
  {
    if (CountTrades(TradeType) == 0)
      return(StartLotSize());
    
    double Exponent = 1;
    double LotSize = FindLastLotSize(TradeType);
    
    if (IsIlan(TradeType))
      Exponent = IlanLotExp;
      
    if (IsPyramid(TradeType))
      Exponent = PyramidLotExp;
      
    //----------
    
    if (UseMartingale)
      LotSize = NormalizeDouble(LotSize * Exponent, LotDecimal);
        
    if (AccountFreeMarginCheck(Symbol(), TradeType, LotSize) <= 0)
      {
        Print("������! ��� �������� ������ ����� ", DoubleToStr(LotSize, 2), " �� ������� ��������� �������");
        return(-1);
      }
      
    return(LotSize);
  }

//===================================================================

// ���������� ���������� �������� ������� ��������� �����������
// ���� ����������� �� ������ ���������� ����� ���������� �������� �������

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

// ���������� ������� �� �������� ������� ��������� �����������
// ���� ����������� �� ������ ���������� ����� ������� �� �������� �������

/*double CalculateProfit(int TradeType = -1)
  {
    double Profit = 0;
    
    if (TradeType == OP_BUY || TradeType == -1)
      {
        for (cnt = 0; cnt < ArraySize(BuyOrders); cnt++)
          {
            OrderSelect(BuyOrders[cnt], SELECT_BY_TICKET);
            Profit = Profit + OrderProfit() + OrderCommission() + OrderSwap();
          }
      }
    
    if (TradeType == OP_SELL || TradeType == -1)
      {
        for (cnt = 0; cnt < ArraySize(SellOrders); cnt++)
          {
            OrderSelect(SellOrders[cnt], SELECT_BY_TICKET);
            Profit = Profit + OrderProfit() + OrderCommission() + OrderSwap();
          }
      }    
     
    return(Profit);
  }*/

//===================================================================

// ��������� ��� �������� ������

void CloseAllOrders()
  {
    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);
      }
  }

//===================================================================

// ������������ ��� �������� ������ � ��������� ������� 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 - ������� ����
// Profit - ������ TakeProfit � �������

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

//===================================================================

// ���������� ���� ������ StopLoss ��� �������� ���� � ��������� �����������
// Price - ������� ����
// Stop - ������ StopLoss � �������

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

//===================================================================

// ��������� ����� buy �� ������� �������� ����, � ������ ����� ���������� True
// ���� ����� �� ������ ���������� False

bool OpenBuyOrder()
  {
    int Ticket;
    double LotSize;
    int Trades = ArraySize(BuyOrders);
  
    LotSize = GetLotSize(OP_BUY);
    
    if (IsIlan(OP_BUY))
      Print("��������� Buy, ����, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                          ", ���� ", DoubleToStr(Ask, Digits));
    if (IsPyramid(OP_BUY))
      Print("��������� Buy, ��������, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                          ", ���� ", DoubleToStr(Ask, Digits));
    if (IsEmpty(OP_BUY))
      Print("��������� Buy, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                          ", ���� ", DoubleToStr(Ask, Digits));
            
    if (LotSize > 0)
      {
        RefreshRates();
        Ticket = OrderSend(Symbol(), OP_BUY, LotSize, NormalizeDouble(Ask, Digits),
                             Slip, 0, 0, ExpertName + " - " + (Trades + 1), MagicNumber, 0, Blue);
                                     
        if (Ticket < 0)
          {
            ErrorCode = GetLastError();
            Print("OrderSend Error ", ErrorCode, " - ", ErrorDescription(ErrorCode));
            return(False);
          }
        
        Print("����� ", Trades + 1, ", Buy - ������, ticket #", Ticket);
        
        // ������� ����� ������ � ����� �������        
        ArrayResize(BuyOrders, ArraySize(BuyOrders) + 1); 
        BuyOrders[ArraySize(BuyOrders) - 1] = Ticket;
      }
      
    return(True);
  }

//===================================================================

// ��������� ����� sell �� ������� �������� ����, � ������ ����� ���������� True
// ���� ����� �� ������ ���������� False

bool OpenSellOrder()
  {
    int Ticket;
    double LotSize;
    int Trades = ArraySize(SellOrders);
  
    LotSize = GetLotSize(OP_SELL);
    
    if (IsIlan(OP_SELL))
      Print("��������� Sell, ����, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                            ", ���� ", DoubleToStr(Bid, Digits));
    if (IsPyramid(OP_SELL))
      Print("��������� Sell, ��������, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                            ", ���� ", DoubleToStr(Bid, Digits));
    if (IsEmpty(OP_SELL))
      Print("��������� Sell, ����� ", Trades + 1, ", ��� ", DoubleToStr(LotSize, 2),
                                                            ", ���� ", DoubleToStr(Bid, Digits));
            
    if (LotSize > 0)
      {
        RefreshRates();
        Ticket = OrderSend(Symbol(), OP_SELL, LotSize, NormalizeDouble(Bid, Digits),
                             Slip, 0, 0, ExpertName + " - " + (Trades + 1), MagicNumber, 0, Red);
                                     
        if (Ticket < 0)
          {
            ErrorCode = GetLastError();
            Print("OrderSend Error ", ErrorCode, " - ", ErrorDescription(ErrorCode));
            return(False);
          }
        
        Print("����� ", Trades + 1, ", Sell - ������, ticket #", Ticket);
        
        // ������� ����� ������ � ����� �������
        ArrayResize(SellOrders, ArraySize(SellOrders) + 1); 
        SellOrders[ArraySize(SellOrders) - 1] = Ticket;
      }
      
    return(True);
  }

//===================================================================

// ������������ ������ ��������� �����������
// Price - ����� ������� StopLoss ��� TakeProfit
// ��� �����������, ���������� ��� ����, ������������ TakeProfit
// ��� �����������, ���������� ��� ��������, ������������ StopLoss

void ModifyOrders(int TradeType, double Price)
  {
    double NewStopLoss;
    double NewTakeProfit;
    int Orders[];
    
    if (TradeType == OP_BUY)
      {
        ArrayResize(Orders, ArraySize(BuyOrders));
        ArrayCopy(Orders, BuyOrders);
      }
    else if (TradeType == OP_SELL)
      {
        ArrayResize(Orders, ArraySize(SellOrders));
        ArrayCopy(Orders, SellOrders);
      }
  
    // ������������ ��� ������ ������� Orders[]
    for (cnt = 0; cnt < ArraySize(Orders); cnt++)
      {
        OrderSelect(Orders[cnt], SELECT_BY_TICKET);
          
        if (IsIlan(TradeType)) // ��� ����� ������� TakeProfit
          {
            NewTakeProfit = NormalizeDouble(Price, Digits);
            NewStopLoss = OrderStopLoss();
          }
        
        if (IsPyramid(TradeType)) // ��� �������� ������� StopLoss
          {
            NewTakeProfit = OrderTakeProfit();
            NewStopLoss = /*OrderStopLoss()*/NormalizeDouble(Price, Digits);
            
            /*if (TradeType == OP_BUY)
              {
                // ���� ����� ��� ������ ��� ����� ���� ���� �������
                if (OrderStopLoss() == 0 || (OrderStopLoss() != 0 && Price > OrderStopLoss()))
                  NewStopLoss = NormalizeDouble(Price, Digits);
              }
            else if (TradeType == 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);  
          }
      }  // for (cnt = 0; cnt < ArraySize(Orders); cnt++)
  }

//===================================================================

// ������������ ��� ������ ����������� buy

void ModifyBuyOrders()
  {
    if (IsIlan(OP_BUY)) // ���� buy ������� ��� ����
      {
        CurrIlanAvgPrice = GetAveragePrice(OP_BUY);
        CurrIlanTP = GetTakeProfitPrice(CurrIlanAvgPrice, OP_BUY, IlanTakeProfit);  // ����� TakeProfit
        
        Print("������������ ������ Buy, ����, ����� TakeProfit ", DoubleToStr(CurrIlanTP, Digits));   
        ModifyOrders(OP_BUY, CurrIlanTP);
        
        if (IsPyramid(OP_SELL) && PyramidStopLoss == 0)
          {
            Print("������������ ������ Sell, ��������, ����� StopLoss ", DoubleToStr(CurrIlanTP + Spread, Digits));
            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);
          }
        
        Print("������������ ������ Buy, ��������, ����� StopLoss ", DoubleToStr(CurrPyramidSL, Digits));
        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
        
        Print("������������ ������ Sell, ����, ����� TakeProfit ", DoubleToStr(CurrIlanTP, Digits));
        ModifyOrders(OP_SELL, CurrIlanTP);
        
        if (IsPyramid(OP_BUY) && PyramidStopLoss == 0)
          {
            Print("������������ ������ Buy, ��������, ����� StopLoss ", DoubleToStr(CurrIlanTP - Spread, Digits));
            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);
          }
        
        Print("������������ ������ Sell, ��������, ����� StopLoss ", DoubleToStr(CurrPyramidSL, Digits));
        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 - ��������");
                CheckResult = True;
              }
          
            // ���� ���� ���� ����, �� buy ����� ������
            if ((LastBuyPrice - Ask >= IlanStep * Point))
              {
                BuyTrade = 0;  // buy - ����
                Print("Buy - ����");
                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 - ����");
                CheckResult = True;
              }
          
            // ���� ���� ���� ����, �� sell ����� ���������
            if ((LastSellPrice - Bid >= PyramidStep * Point))
              {
                SellTrade = 1; // sell - ��������
                Print("Sell - ��������");
                CheckResult = True;
              }
          }
      }  // if (IsEmpty(OP_SELL)
      
    return(CheckResult);
  }

//===================================================================

// ���������� ����������� ���� �������� ���� ������� ��������� �����������

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

//===================================================================

// ���������, ������� �� �������� ����������� ��� ����

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

//===================================================================

// ���������, ������� �� �������� ����������� ��� ��������

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

//===================================================================

// ���������� True ���� �������� ����������� �� ���� � �� ��������

bool IsEmpty(int TradeType)
  {
    if ((TradeType == OP_BUY && BuyTrade == -1) || (TradeType == 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;
          }
        if (IsPyramid(OP_BUY))
          {
            CurrPyramidSL = 0;
          }
          
        BuyTrade = -1;
      }
    
    //-------
    
    if (CountTrades(OP_SELL) == 0)
      {
        if (IsIlan(OP_SELL))
          {
            CurrIlanTP = 0;
            CurrIlanAvgPrice = 0;
          }
        if (IsPyramid(OP_SELL))
          {
            CurrPyramidSL = 0;
          }
          
        SellTrade = -1;
      }
  }

//===================================================================

// ������ ��������

/*void TrailingPyramid(int Start, int Stop)
  {
    int Profit;
    int Trade;
    double OldStopLoss;
    double NewStopLoss;
    int Orders[];
    
    if (Stop == 0) return;
    if (!IsPyramid(OP_BUY) && !IsPyramid(OP_SELL)) return;
        
    if (IsPyramid(OP_BUY))
      {
        ArrayResize(Orders, ArraySize(BuyOrders));
        ArrayCopy(Orders, BuyOrders);
      }
    else if (IsPyramid(OP_SELL))
      {
        ArrayResize(Orders, ArraySize(SellOrders));
        ArrayCopy(Orders, SellOrders);
      }
      
    for (cnt = 0; cnt < ArraySize(Orders); cnt++)
      {
        OrderSelect(Orders[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));
                }
            Sleep(1500);
          }  // 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));
                }
            Sleep(1500);
          }  // if (OrderType() == OP_SELL)
        
      }  // for (cnt = 0; cnt < ArraySize(Orders); cnt++)
  }*/
  
//===================================================================

void CheckPyramid()
  {
    // ��������, ���� �� ��������� ����� ��������
    // ���� ����� �������� ������ �������� ��������� �� ����� � �����,
    // �� ����� �� ���������, �� ���� �������� ������� ��� ����� ����� ��� ������
    
    double OldPyramidSL = CurrPyramidSL;
    double NewPyramidSL;
    
    if (SellTradeNow && IsPyramid(OP_SELL))
      {
        if (!CheckPyramidProfit(OP_SELL)) // ����� �����
          {
            Print("�������� - ���������� �������� ������ Sell");
          
            // ����� �� ���������, �� ���� �������
            if (PyramidStopLoss != 0)
              {
                RefreshRates();
                NewPyramidSL = GetStopLossPrice(Bid, OP_SELL, PyramidStopLoss);
                
                // ���� ������� ����� ��� ��� ����� ���� ���� �������
                if ((OldPyramidSL == 0) || (OldPyramidSL != 0 && NewPyramidSL < OldPyramidSL))
                  {
                    CurrPyramidSL = NewPyramidSL;
                    Print("������������ ������ Sell, ��������, ����� StopLoss ", DoubleToStr(CurrPyramidSL, Digits));
                    ModifyOrders(OP_SELL, CurrPyramidSL);
                  }
              }
              
            SellTradeNow = False;  // ����� �� ���������
          }
      }
    
    //------------------
      
    if (BuyTradeNow && IsPyramid(OP_BUY))
      {
        if (!CheckPyramidProfit(OP_BUY)) // ����� �����
          {
            Print("�������� - ���������� �������� ������ Buy");
          
            // ����� �� ���������, �� ���� �������
            if (PyramidStopLoss != 0)
              {
                RefreshRates();
                NewPyramidSL = GetStopLossPrice(Ask, OP_BUY, PyramidStopLoss);
                
                // ���� ������� ����� ��� ��� ����� ���� ���� �������
                if ((OldPyramidSL == 0) || (OldPyramidSL != 0 && NewPyramidSL > OldPyramidSL))
                  {
                    CurrPyramidSL = NewPyramidSL;
                    Print("������������ ������ Buy, ��������, ����� StopLoss ", DoubleToStr(CurrPyramidSL, Digits));
                    ModifyOrders(OP_BUY, CurrPyramidSL);
                  }
              }
              
            BuyTradeNow = False;  // ����� �� ���������
          }
      }
  }

//===================================================================

// ���������, ��������� �� �������� � ����, ���� ����� �������� ������ ��������� ����
// ���������� True ���� ����� ����, False ���� ����� �����

bool CheckPyramidProfit(int TradeType)
  {
    double PyramidProfit = 0;
    
    double CurrPrice;         // ������� �������� ����, �� ������� ������ ��������� �����
    double PyramidLot;        // ����� ������ ��������, ����� �� ����� ���� �� ������� �����
    double PyramidStop;       // StopLoss ��������, ����� �� ����� ���� �� ������� �����
    
    int Correct = (Digits - 4) / 10; // ��������, ���� ����� ������� ���� ����
    if (Correct == 0) Correct = 1;
    
    int Orders[];
    
    if (TradeType == OP_BUY)
      {
        ArrayResize(Orders, ArraySize(BuyOrders));
        ArrayCopy(Orders, BuyOrders);
      }
    else if (TradeType == OP_SELL)
      {
        ArrayResize(Orders, ArraySize(SellOrders));
        ArrayCopy(Orders, SellOrders);
      }
    
    RefreshRates();
    
    //------
    
    // ����, �� ������� ������ ��������� �����
    if (TradeType == OP_BUY)
      CurrPrice = Ask;
    else if (TradeType == OP_SELL)
      CurrPrice = Bid;
    
    //------
    
    // ���, ������� ������ ��������� ����� 
    PyramidLot = GetLotSize(TradeType);
    
    //------
    
    // ������� ����� ����� �������� ������
    if (PyramidStopLoss != 0)
      {
        PyramidStop = GetStopLossPrice(CurrPrice, TradeType, PyramidStopLoss);
      }
    else
      {
        if (CurrIlanTP == 0) // ���� ��� ��� �����
          {
            PyramidStop = GetStopLossPrice(CurrPrice, TradeType, IlanTakeProfit);
          }
        else
          {
            if (TradeType == OP_BUY)
              PyramidStop = CurrIlanTP - Spread;
            else if (TradeType == OP_SELL)
              PyramidStop = CurrIlanTP + Spread;
          }
      }
    
    //------
    
    // ������� ������� ������� ������� ���������� (��� �� ���������) ������
    if (TradeType == OP_BUY)
      PyramidProfit = (PyramidStop - CurrPrice) / Point * Correct * PyramidLot * 10;
    else if (TradeType == OP_SELL)
      PyramidProfit = (CurrPrice - PyramidStop) / Point * Correct * PyramidLot * 10;
    
    //------
      
    // ������ ������� ������� �� ���� ��������� ������� ��������
    for (cnt = 0; cnt < ArraySize(Orders); cnt++)
      {
        OrderSelect(Orders[cnt], SELECT_BY_TICKET);
        
        if (TradeType == OP_BUY)
          PyramidProfit = PyramidProfit + (PyramidStop - OrderOpenPrice()) * Correct / Point * OrderLots() * 10;
        else if (TradeType == OP_SELL)
          PyramidProfit = PyramidProfit + (OrderOpenPrice() - PyramidStop) * Correct / Point * OrderLots() * 10;
      }
    
    //------
      
    if (PyramidProfit > 0)
      return(True);
    else
      return(False);
  }

//===================================================================

// ���������� ���� �������� ���������� ������ buy
// � ������ ������ ���������� -1

double FindLastBuyPrice()
  {
    if (OrderSelect(FindLastTicket(OP_BUY), SELECT_BY_TICKET) > 0)
      return(OrderOpenPrice());
    else
      return(-1);
  }
  
//===================================================================

// ���������� ���� �������� ���������� ������ sell
// � ������ ������ ���������� -1

double FindLastSellPrice()
  {
    if (OrderSelect(FindLastTicket(OP_SELL), SELECT_BY_TICKET) > 0)
      return(OrderOpenPrice());
    else
      return(-1);
  }
  
//===================================================================

// ���������� ������ ���� ���������� ��������� ������ ��������� �����������
// � ������ ������ ���������� -1

double FindLastLotSize(int TradeType)
  {
    if (OrderSelect(FindLastTicket(TradeType), SELECT_BY_TICKET) > 0)
      return(OrderLots());
    else
      return(-1);
  }

//===================================================================

// ���������� ����� ���������� ��������� ������ ��������� �����������
// ���� ����������� �� ������ ���������� ����� ������ ���������� ������
// ���� ����� �� ������ ���������� -1

int FindLastTicket(int TradeType = -1)
  {
    int FindTicket = -1;
    
    if (TradeType == OP_BUY)
      {
        if (ArraySize(BuyOrders) == 0)
          return(-1);
        else
          return(BuyOrders[ArraySize(BuyOrders) - 1]);
      }
    
    if (TradeType == OP_SELL)
      {
        if (ArraySize(SellOrders) == 0)
          return(-1);
        else
          return(SellOrders[ArraySize(SellOrders) - 1]);
      }
    
    // TradeType == -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);
  }

//===================================================================

// ���������� ��������� ������ ���� ��� �������� ������� ��������

double StartLotSize()
  {
    double ResultLot;
    double k;
    
    double LotStepSize = MarketInfo(Symbol(), MODE_LOTSTEP);
    double MinLotSize = MarketInfo(Symbol(), MODE_MINLOT);
    double MaxLotSize = MarketInfo(Symbol(), MODE_MAXLOT);

    if (MinLotSize == 0) MinLotSize = 0.01;
    if (MaxLotSize == 0) MaxLotSize = 100;

    if (LotStepSize > 0)
      k = 1 / LotStepSize;
    else
      k = 1 / MinLotSize;
      
    ResultLot = MathFloor((AccountBalance() / LotStep / 100) * k) / k; 
    
    if (ResultLot < MinLotSize) ResultLot = MinLotSize;
    if (ResultLot > MaxLotSize) ResultLot = MaxLotSize;

    return(ResultLot);
  }

//===================================================================



//===================================================================