//+------------------------------------------------------------------+
//|                                               e-Droba-ZigZag.mq4 |
//|                                  Copyright © 2010, Michelangelo® |
//|                                                www.fxgeneral.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Michelangelo®"
#property link      "www.fxgeneral.com"
#define MAGICMA  20100930

extern int     ExtDepth      = 6;
extern int     ExtDeviation  = 5;
extern int     ExtBackstep   = 11;
extern int     _point        = 5;
extern double  _lots         = 0.1;
extern int     _takeProfit   = 1000;
extern int     _stopLoss     = 400;
extern int     BBUSize       = 100;    //размер в пунктах после которого стоп переносим в безубыток
extern int     BBUSizepip    = 100;    //безубыток в пунктах
extern bool    _trailingStop = true;
extern int     _maPeriod     = 150;

// MM start
extern string  MM_SETUP     = "Money managment setup";
extern string _s1             = "redefinition  minLot, maxLot, stepLot - if = 0, autodefinition";
extern double s_minLot        = 0;
extern double s_maxLot        = 0;
extern double s_stepLot       = 0;
extern string s2="---";
extern double DecreaseFactor  = 3;

extern string _s2             = "Percent of free margin";
extern double MaximumRisk     = 0;
extern string _s3             = "or fixed lot";
extern bool fixedLots         = true;
extern double Lot             = 0.1;

double minLot;
double stepLot;
double maxLot;

double _lastExtremum=0.0;
double _currentExtremum=0.0;
double _previousExtremum=0.0;
int _extType=-1;
double _workLots=0.0;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   minLot = s_minLot;
   stepLot = s_stepLot; 
   maxLot = s_maxLot;

   if (s_minLot == 0)
   {
      Print("Автоматическое определение минимального лота");
      Comment("Автоматическое определение минимального лота");
      minLot = MarketInfo(Symbol(),MODE_MINLOT);
   }
   Print("Размер минимального лота: " + minLot);
   Comment("Размер минимального лота: " + minLot);
   Print("---");

   if (s_maxLot == 0)
   {
      Print("Автоматическое определение максимального лота");
      Comment("Автоматическое определение максимального лота");
      maxLot = MarketInfo(Symbol(),MODE_MAXLOT);
   }
   Print("Размер максимального лота: " + maxLot);
   Comment("Размер максимального лота: " + maxLot);
   Print("---");

   if (s_stepLot == 0)
   {
      Print("Автоматическое определение минимального шага лота");
      Comment("Автоматическое определение минимального шага лота");
      stepLot = MarketInfo(Symbol(),MODE_LOTSTEP);
   }
   Print("Размер минимального шага лота: " + stepLot);
   Comment("Размер минимального шага лота: " + stepLot);
   Print("---");
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   int err1;
   int ticket=0;
   double _sl=0.0, _tp=0.0;
   double _price=0.0;
   double _ma=0.0;

 if(BBUSize>0){err1=BBU();}
   
//----
   if (Volume[0]>1) return;
   if (_trailingStop) _TrailingStop();
   _ma=iMA(Symbol(),0,_maPeriod,0,0,PRICE_CLOSE,0);
   _lastExtremum=GetExtremumZZPrice(1);
   Comment (_lastExtremum);
   if (Close[0]<_lastExtremum){
      if (_extType!=OP_BUYSTOP){
//         _CheckOrder(OP_BUYSTOP);
         _price=NormalizeDouble((_lastExtremum+_point*Point),Digits);
        /* if (_stopLoss>0)*/ _sl=NormalizeDouble(_ma-10*Point,Digits);
         if (_takeProfit>0) _tp=NormalizeDouble(_price+_takeProfit*Point,Digits);
         _extType=OP_BUYSTOP;
        if (_lastExtremum>_ma)
         ticket=OrderSend(Symbol(),_extType,fLots(),_price,5,_sl,_tp,"e-Droba",MAGICMA,0,0);
      }
   }
   if (Close[0]>_lastExtremum){
      if (_extType!=OP_SELLSTOP){
//         _CheckOrder(OP_SELLSTOP);
         _price=NormalizeDouble((_lastExtremum-_point*Point),Digits);
        /* if (_stopLoss>0)*/ _sl=NormalizeDouble(_ma+10*Point,Digits);
         if (_takeProfit>0) _tp=NormalizeDouble(_price-_takeProfit*Point,Digits);
         _extType=OP_SELLSTOP;
         if (_lastExtremum<_ma)
         ticket=OrderSend(Symbol(),_extType,fLots(),_price,5,_sl,_tp,"e-Droba",MAGICMA,0,0);
      }
   }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
double GetExtremumZZPrice(int ne=0) {
   double zz;   
   int    i, k=iBars(Symbol(), 0), ke=0;
   for (i=1; i<k; i++) {
      zz=iCustom(Symbol(),0, "ZigZag", ExtDepth,ExtDeviation,ExtBackstep,0,i);
      if (zz!=0) {
         ke++;
         if (ke>ne) return(zz);     
      }   
   }   
   return(0); 
} 
//+------------------------------------------------------------------+
/*int _CheckOrder(int _checkType=0){
   int i;
   if (OrdersTotal()>0){
      for (i=0; i<=OrdersTotal()-1; i++){
         if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
            if (OrderType()==_checkType && OrderMagicNumber()==MAGICMA) OrderDelete(OrderTicket());
         }
      }
   }
   return(0);
}*/
//+------------------------------------------------------------------+
int  BBU()
{//описание функции http://fxnow.ru/blog/programming_mql4/2.html
int i;bool err;
   for( i=1; i<=OrdersTotal(); i++)         
   {
      if(OrderSelect(i-1,SELECT_BY_POS)==true) 
       {   
        if(BBUSize>0 && OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA && OrderStopLoss()<OrderOpenPrice())  
        {                
         if(Bid-OrderOpenPrice()>=BBUSize*Point && BBUSize>0 )
          {
           Print("ПОРА В БезуБыток");
           err=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+BBUSizepip*Point,OrderTakeProfit(),0,Green);
           if(err==false){return(-1);}
          }//if(Bid-OrderOpenPrice()
         }//if(BBUSize>0
        }//if(OrderSelect(i
            
       if(OrderSelect(i-1,SELECT_BY_POS)==true) 
       {
        if(BBUSize>0 && OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA && (OrderStopLoss()>OrderOpenPrice() || OrderStopLoss()==0))  
        {        
         if(OrderOpenPrice()-Ask>=BBUSize*Point && BBUSize>0)
          {
           Print("ПОРА В БезуБыток");
           err=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-BBUSizepip*Point,OrderTakeProfit(),0,Green);
           if(err==false){return(-1);}
          }//if(OrderOpenPrice()
         }//if(BBUSize>0 
       }// if(OrderSelect
    }// for( i=1;
return(0);
}
//+------------------------------------------------------------------+
void _TrailingStop(){
   int i;
   double _stopLossSell=NormalizeDouble(iMA(Symbol(),0,_maPeriod,0,0,PRICE_CLOSE,0)+10*Point,Digits),
          _stopLossBuy=NormalizeDouble(iMA(Symbol(),0,_maPeriod,0,0,PRICE_CLOSE,0)-10*Point,Digits),
          _stopLossSellF=NormalizeDouble(iFractals(Symbol(),0,MODE_UPPER,3),Digits),
          _stopLossBuyF=NormalizeDouble(iFractals(Symbol(),0,MODE_LOWER,3),Digits);
   if (OrdersTotal()>0){
      for (i=OrdersTotal()-1; i>=0; i--){
         if (OrderSelect(i, SELECT_BY_POS)){
            if (OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA){
               if (OrderType()==OP_BUY && OrderStopLoss()<OrderOpenPrice()){
                  while (IsTradeContextBusy()) Sleep(1000);
                  RefreshRates();
                  OrderModify(OrderTicket(),OrderOpenPrice(),_stopLossBuy,OrderTakeProfit(),OrderExpiration(),CLR_NONE);
               }
               if (OrderType()==OP_BUY && OrderStopLoss()>OrderOpenPrice() && OrderStopLoss()<_stopLossBuyF){
                  while (IsTradeContextBusy()) Sleep(1000);
                  RefreshRates();
                  OrderModify(OrderTicket(),OrderOpenPrice(),_stopLossBuyF,OrderTakeProfit(),OrderExpiration(),CLR_NONE);
               }
               if (OrderType()==OP_SELL && OrderStopLoss()>OrderOpenPrice()){
                  while (IsTradeContextBusy()) Sleep(1000);
                  RefreshRates();
                  OrderModify(OrderTicket(),OrderOpenPrice(),_stopLossSell,OrderTakeProfit(),OrderExpiration(),CLR_NONE);
               }
               if (OrderType()==OP_SELL && OrderStopLoss()<OrderOpenPrice() && OrderStopLoss()>_stopLossSellF && _stopLossSellF!=0.0){
                  while (IsTradeContextBusy()) Sleep(1000);
                  RefreshRates();
                  OrderModify(OrderTicket(),OrderOpenPrice(),_stopLossSellF,OrderTakeProfit(),OrderExpiration(),CLR_NONE);
               }
            }
         }
      }
   }
return;
}
//-------
double fLots()
   {
      if (fixedLots) return(Lot);
      return(LotsOptimized());
       
   }

double LotsOptimized()
  {
   double z_lot;
   int    z_orders=HistoryTotal();     // history orders total
   int    z_losses=0;                  // number of losses orders without a break
//---- select lot size
   z_lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/100/1000.0,2);
//---- calcuulate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int z_i=z_orders-1;z_i>=0;z_i--)
        {
         if(OrderSelect(z_i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
         //----
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) z_losses++;
        }
      if(z_losses>1) z_lot=NormalizeDouble(z_lot-z_lot*z_losses/DecreaseFactor,1);
     }
//---- return lot size
   z_lot=NormalizeDouble(z_lot/stepLot,0)*stepLot;
   if(z_lot<minLot) z_lot=minLot;
   if(z_lot>maxLot) z_lot=maxLot;
   
   return(z_lot);
  }