//+-------------------------------------------------------------------------------+ 
//|                                                                   Cci_Wpr.mq4 |
//|                                                   original template by mladen |
//|                                                           this mod by mrtools |
//+-------------------------------------------------------------------------------+
#property copyright "http://www.forex-tsd.com/"
#property link      "http://www.forex-tsd.com/"
#include <stdlib.mqh>
#include <stderror.mqh>
#define  PAUSE_BEFORE_RETRY 500

//
//
//
//
//

extern string  Trade                      = "+---Trade Management---+";
extern bool    EcnBroker                  = true;
extern bool    NoHedge                    = false;
extern bool    UseAutoMagic               = false;
extern int     ManualMagic                = 19283745;
extern bool    UseAutomaticMM             = false;
extern bool    AllowMultipleTradesOnBar   = false;
extern bool    AllowOnlyOneActiveTrade    = true;
extern double  Risk                       = 1.50;
extern double  BaseLot                    = 0.03;
extern bool    CloseOnTrendChange         = true;

extern string  Positions                  = "+---Positions Settings---+";
extern double  TakeProfitPips             = 450;
extern double  StopLossPips               = 60;
extern double  lTrailingStop              = 20;
extern double  sTrailingStop              = 20;
extern bool    TrailOnlyWhenInProfit      = false;
extern double  CloseWhenProfit            = 450;
extern double  CloseWhenLoss              = 50;
extern bool    AllSymbolsForProfitAndLoss = false;
extern bool    StopWhenClosedAllTrades    = false;
extern bool    SpreadProtection           = false; // If the spread is widen than normal (News time) we will not open positions or continue positions until it normalize
extern int     PipTolerance               = 2;     // value in pips over normal spread to activate the SpreadProtection.


extern string  Kumo                      = "+---Ichimoku Kumo---+";
extern int     ichTf                      = 0;
extern int     Tenkan                     = 9;
extern int     Kijun                      = 26;
extern int     Senkou                     = 52;
extern int     ichibar                    = 1; 

extern string  NRTR                       = "+---NRTR Filter---+";
extern bool    UseNrtr                    = false;
extern int     ATR                        = 14;
extern double  Coefficient                = 4;
extern int     nrtrbar                    = 1;

extern string  RSIf                       = "+---RSI Filter---+";
extern bool    UseRsi                     = true;
extern int     PeriodRSI                  = 7;
extern int     RsiPrice                   = 0;
extern double  levelOb                    = 70;
extern double  levelOs                    = 30;
extern int     rsibar                     = 1;

extern string  PSARf                      = "+---PSAR Filter---+";
extern bool    UsePsar                    = false;
extern double  AccStep                    = 0.02;
extern double  AccLimit                   = 0.2;
extern int     PriceHigh                  = PRICE_HIGH;
extern int     PriceLow                   = PRICE_LOW;
extern int     sarbar                     = 1;

extern string  voltyTrailingStop          = "+---Volty trailing stop settings (if used)---+";
extern bool    UseVoltyTrailingStop       = true;
extern int     vol_timeFrame              = 60;
extern int     Price                      = 0;
extern double  Length                     = 2;
extern double  Phase                      = 0;
extern bool    Double                     = false;
extern int     AtrLength                  = 10; 
extern double  Kv                         = 4;  
extern double  MoneyRisk                  = 1; 
extern int     vol_barToUse               = 1;    
extern int     Volty_initialStopLoss      = 50;

extern string  TimeFilter                 = "+---Time Filter settings---+";
extern string  Trade_startFrom            = "00:00";
extern string  Trade_endAt                = "23:00";

extern string  cf                         = "+---Setting for Friday positions close---+";
extern bool    CloseOnFriday              = true;
extern int     FridayCloseHour            = 21;
extern int     FridayCloseMinute          = 59; 

extern string  Other                      = "+---Other---+";
extern int     AllowedSlippage            = 5;
extern bool    showMessages               = true;
extern bool    CheckEveryTick             = true;
extern int     Magic                      = 888;   // magic number required if you use different settings on a same pair, same timeframe

//
//
//
//
//

int     NumberOfTries = 5;
int     digit = 0;
int     MagicNumber;
int     DontContinue;
double  Spread,WorstSpread,NormalSpread;
double  pipMultiplier = 1;
bool    dummyResult;
string  strSymbol;

//
//
//
//
//

double  pPoint;
string  s_symbol;
string  IEAMessagesID;
int     IEAMessagesIDLength;
#define IEAMessagesIDMagic EMPTY_VALUE
#define IEAMessagesIDExSep "-ex:"

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   s_symbol = Symbol();
   pPoint = MarketInfo(s_symbol,MODE_POINT);
   if (UseAutoMagic) MagicNumber = GetMagic();
               else  MagicNumber = ManualMagic;  
   
   //
   //
   //
   //
   //
                 
   digit  = MarketInfo(s_symbol,MODE_DIGITS);
   if (digit==2 || digit==4) pipMultiplier = 1;
   if (digit==3 || digit==5) pipMultiplier = 10;
   if (digit==6)             pipMultiplier = 100;
   
   //
   //
   //
   //
   //
   
   NormalSpread = MarketInfo(s_symbol,MODE_SPREAD)/MathPow(10,Digits%2);
   
   //
   //
   //
   //
   //
            
   if (AllSymbolsForProfitAndLoss)
            IEAMessagesID = "IchiNrtr"+MagicNumber;
   else     IEAMessagesID = "IchiNrtr"+MagicNumber+s_symbol;
   IEAMessagesIDLength = StringLen(IEAMessagesID);
   
return(0);
}
int deinit() { return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define __trendUp       1
#define __trendDown    -1
#define __trendNeutral  0

//
//
//
//
//

int start()
{     
   if (!CheckTerminalStatus()) return(0);       

   //
   //
   //
   //
   //

/*
   
//|-----------MoveStopLoss to Volty Function Call

   strSymbol=Symbol();
   if((!CheckEveryTick) && (Volume[0]==1)) // Go for it on first tick only
     {
      MoveStopsToVolty(Magic);
      return(0);
     }
     if(CheckEveryTick) MoveStopsToVolty(Magic); // Check for Stop move every tick
*/

   //
   //
   //
   //
   //


   if (CloseOnFriday && TimeDayOfWeek(TimeCurrent())==5)
   {
     if (TimeHour(TimeCurrent()) > FridayCloseHour ||
        (TimeHour(TimeCurrent())== FridayCloseHour && TimeMinute(TimeCurrent())>= FridayCloseMinute))
     {
       for(int i=OrdersTotal()-1; i>=0; i--)
  	    { 
     	   dummyResult = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()     != s_symbol)    continue;
            if(OrderMagicNumber()!= MagicNumber)       continue;

            if(OrderType()==OP_BUY)  { dummyResult = OrderClose(OrderTicket(),OrderLots(),MarketInfo(s_symbol,MODE_ASK),0,CLR_NONE); continue; }
            if(OrderType()==OP_SELL) { dummyResult = OrderClose(OrderTicket(),OrderLots(),MarketInfo(s_symbol,MODE_BID),0,CLR_NONE); continue; }
       }
       return(0);
     }
   }
   
   //
   //
   //
   //
   //

      if (StopLossPips<=0)
           bool forceCloseOnTrendChange = True;
      else      forceCloseOnTrendChange = CloseOnTrendChange; 
           bool stopedTrading           = false;
           int  trendDirection          = findTrend();

                        manageOpenedOrders(trendDirection,forceCloseOnTrendChange,stopedTrading);

      if (stopedTrading) return(0);

   //
   //
   //
   //
   //

         double totalProfit  = 0;
         int    openedBuys   = 0;
         int    openedSells  = 0;
         int    openedOrders = countOpenedOrders(openedBuys,openedSells,totalProfit);
         
         //
         //
         //
         //
         //

         if (CloseWhenProfit>0 &&  totalProfit >= CloseWhenProfit)
         {
            if (StopWhenClosedAllTrades) PostMessage();
                  CloseAll(); openedOrders = countOpenedOrders(openedBuys,openedSells,totalProfit);
         }
         if (CloseWhenLoss > 0 && totalProfit <= -CloseWhenLoss)
         {
            if (StopWhenClosedAllTrades) PostMessage();
                  CloseAll(); openedOrders = countOpenedOrders(openedBuys,openedSells,totalProfit);
         }
         if (FindMessage()) return(0);
      
         //
         //
         //
         //
         //
      
         bool canEnterNewTrade = true;

            if (AllowOnlyOneActiveTrade) canEnterNewTrade = (openedOrders==0);
            else                         canEnterNewTrade = (countOpenedOnACurrentBar()==0);

   //
   //
   //    time fiter checking
   //
   //
      
         if (canEnterNewTrade)
         {
            string     st1 = normalizeTime(Trade_startFrom);
            string     et1 = normalizeTime(Trade_endAt);
            datetime   ts1  = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+st1); datetime ts2 = ts1;
            datetime   te1  = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+et1); datetime te2 = te1;
            if (te1<ts1) { ts1 -= 24*60*60; te2 += 24*60*60; }
                    canEnterNewTrade = ((TimeCurrent()>=ts1 && TimeCurrent()<=te1) || (TimeCurrent()>=ts2 && TimeCurrent()<=te2));
         }

   //
   //
   //
   //
   //
   
   if (canEnterNewTrade && trendDirection != __trendNeutral)
   {
      if (!AllowMultipleTradesOnBar) if (countClosedOrders()>0) return(0);
      
      //
      //
      //
      //
      //

      if (!UseVoltyTrailingStop)
            double tradeLots = getLots(StopLossPips);
      else         tradeLots = getLots(Volty_initialStopLoss);
      if(AccountFreeMargin()<tradeLots*MarketInfo(s_symbol,MODE_MARGINREQUIRED))
         { showTwoStateMessage("money","Not enough money to trade "+DoubleToStr(tradeLots,2),false); return(0); }
      else showTwoStateMessage("money","Continuing to trade",true);
      
      //
      //
      //
      //
      //
      
      Spread = MarketInfo(s_symbol,MODE_SPREAD)/pipMultiplier;
      if (Spread>WorstSpread) WorstSpread=Spread;
      if (SpreadProtection && Spread>NormalSpread+PipTolerance) DontContinue=1; else DontContinue=0;
      
      //
      //
      //
      //
      //
      
      if (trendDirection==__trendUp   && openedSells==0 && DontContinue==0) Buy(tradeLots);
      if (trendDirection==__trendDown && openedBuys ==0 && DontContinue==0) Sell(tradeLots);
   }  
   return(0);      
}

//----------------------------------------------------------------------------------------
//                                 
//----------------------------------------------------------------------------------------
//
//
//
//    lots and range calculation
//
//
//

double getLots(double range)
{
   RefreshRates();
   double step   = MarketInfo(s_symbol,MODE_LOTSTEP);
   double minLot = MarketInfo(s_symbol,MODE_MINLOT);
   double maxLot = MarketInfo(s_symbol,MODE_MAXLOT);
   double lots   = BaseLot;
   if (UseAutomaticMM)
   {
      if (Risk>0)
      {
         lots = AccountFreeMargin()*(Risk/100.0)/(range*MarketInfo(s_symbol,MODE_TICKVALUE)/pPoint);
      }
   }      
return(MathMax(MathMin(lots,maxLot),minLot));   
}

//
//
//
//
//

int findTrend()
{
   RefreshRates();
   
   //
   //
   //
   //
   //
   
   double ichi1    = iCustom(s_symbol,ichTf,"Kumo_Breakout_Histo",Tenkan,Kijun,Senkou,0,ichibar);
   double ichi2    = iCustom(s_symbol,ichTf,"Kumo_Breakout_Histo",Tenkan,Kijun,Senkou,1,ichibar);
   double nrtrNow  = iCustom(s_symbol,0,"NRTR_ATR_STOP",ATR,Coefficient,3,nrtrbar);
   double nrtrPre  = iCustom(s_symbol,0,"NRTR_ATR_STOP",ATR,Coefficient,3,nrtrbar+1);
   
   double rsinow   = iRSI(s_symbol,0,PeriodRSI,PRICE_CLOSE,rsibar);
   double rsipre   = iRSI(s_symbol,0,PeriodRSI,PRICE_CLOSE,rsibar+1);
   double rsipre2  = iRSI(s_symbol,0,PeriodRSI,PRICE_CLOSE,rsibar+2);
   
   /*     
   double rsinow   = iCustom(s_symbol,0,"rsi",PeriodRSI,RsiPrice,0,rsibar);
   double rsipre   = iCustom(s_symbol,0,"rsi",PeriodRSI,RsiPrice,0,rsibar+1);
   double rsipre2  = iCustom(s_symbol,0,"rsi",PeriodRSI,RsiPrice,0,rsibar+2);
   */
   
   double sarupnow = iCustom(s_symbol,0,"Parabolic_SAR_2",AccStep,AccLimit,PriceHigh,PriceLow,true,0,sarbar);
   double saruppre = iCustom(s_symbol,0,"Parabolic_SAR_2",AccStep,AccLimit,PriceHigh,PriceLow,true,0,sarbar+1);
   double sardnnow = iCustom(s_symbol,0,"Parabolic_SAR_2",AccStep,AccLimit,PriceHigh,PriceLow,true,1,sarbar);
   double sardnpre = iCustom(s_symbol,0,"Parabolic_SAR_2",AccStep,AccLimit,PriceHigh,PriceLow,true,1,sarbar+1);
   
   //
   //
   //
   //
   //
   
   if (UseNrtr)
   {
     bool posNrtr = (nrtrNow>0 && nrtrPre<0); // Cross
     bool negNrtr = (nrtrNow<0 && nrtrPre>0);
   }
   else      
   {
         posNrtr = true;
         negNrtr = true;
   }
   
   
   if (UseRsi)
   {
     bool rsislopingUp = (rsinow < levelOb && rsinow > levelOs && rsinow > rsipre);
     bool rsislopingDn = (rsinow < levelOb && rsinow > levelOs && rsinow < rsipre);
   }
   else      
   {
         rsislopingUp = true;
         rsislopingDn = true;
   }
   
   if (UsePsar)
   {
     bool bullsar = (sarupnow != EMPTY_VALUE && sardnpre != EMPTY_VALUE && saruppre == EMPTY_VALUE && sardnnow == EMPTY_VALUE);
     bool bearsar = (sardnnow != EMPTY_VALUE && saruppre != EMPTY_VALUE && sardnpre == EMPTY_VALUE && sarupnow == EMPTY_VALUE);
   }
   else      
   {
         bullsar = true;
         bearsar = true;
   }
   
   //
   //
   //
   //
   //

   if (ichi1==1 && ichi2==EMPTY_VALUE && posNrtr && rsislopingUp && bullsar) return(__trendUp);
   if (ichi2==1 && ichi1==EMPTY_VALUE && negNrtr && rsislopingDn && bearsar) return(__trendDown);
                                                                             return(__trendNeutral);
}

//----------------------------------------------------------------------------------------
//       orders counters
//----------------------------------------------------------------------------------------
//
//
//
//
//

int countOpenedOrders(int& openedBuys,int& openedSells,double& totalProfit)
{
   int openedOrders = 0;   
       openedBuys   = 0;
       openedSells  = 0;
       totalProfit  = 0;
   
   //
   //
   //
   //
   //
      
   for(int i=0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break;
   
      //
      //
      //
      //
      //
      
      if(AllSymbolsForProfitAndLoss)
      {
         if(OrderMagicNumber() == MagicNumber)
         if(OrderType() == OP_BUY || OrderType() == OP_SELL) totalProfit  += (OrderProfit()+OrderSwap()); 
      }
      if(OrderSymbol() != s_symbol) continue;
      if(NoHedge)
      {
         if(OrderType() == OP_BUY)  openedBuys++; 
         if(OrderType() == OP_SELL) openedSells++;
      }
      if(OrderMagicNumber() != MagicNumber) continue;
                  
      //
      //
      //
      //
      //
                  
      if(OrderType() == OP_BUY || OrderType() == OP_SELL) { openedOrders++; if (!AllSymbolsForProfitAndLoss) totalProfit  += (OrderProfit()+OrderSwap()); }
   }      
   return(openedOrders);
}

//
//
//
//
//

int countClosedOrders()
{
   int      closedAtBar = 0;    
   int      barShift    = iBarShift(s_symbol,0,Time[0]);
   
   for(int i = OrdersHistoryTotal()-1; i >= 0 ; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == false) break;
      if(OrderMagicNumber() != MagicNumber)                continue;
      if(OrderSymbol()      != s_symbol)                   continue;
      if(iBarShift(s_symbol,0,OrderOpenTime())!= barShift) continue; 
         closedAtBar++;
         break;
   } 
   return(closedAtBar); 
}  

//
//
//
//
//

int countOpenedOnACurrentBar()
{
   int      openedAtBar = 0;    
   datetime startTime   = Time[0];
   datetime endTime     = Time[0]+Period()*60;
   
   for(int i=0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break;
      if(OrderMagicNumber() != MagicNumber)                     continue;
      if(OrderSymbol()      != s_symbol)                        continue;
      if(OrderOpenTime()<startTime || OrderOpenTime()>=endTime) continue; 
         openedAtBar++;
         break;
   } 
   return(openedAtBar); 
}  

//----------------------------------------------------------------------------------------
//       opened orders management 
//----------------------------------------------------------------------------------------
//
//
//
//
//

void manageOpenedOrders(int currentDirection,bool doCloseOnTrendChange, bool stoped)
{
   double TakeProfit = TakeProfitPips*pPoint*pipMultiplier;
   double StopLoss   = StopLossPips  *pPoint*pipMultiplier;
   double newStop;
   double curStop;
   double maxStop;
   
   //
   //
   //
   //
   //
   
   for(int i=OrdersTotal()-1; i>=0 ; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break;
      
      //
      //
      //    check if stop when profit was signaled
      //    do not trade untill the sell stop order expires or is deleted
      //
      //

      if(OrderMagicNumber() == IEAMessagesIDMagic && OrderType()==OP_BUYLIMIT && StopWhenClosedAllTrades)
      {
         if (StringSubstr(OrderComment(),0,IEAMessagesIDLength)==IEAMessagesID)
         {
            int pos = StringFind(OrderComment(),IEAMessagesIDExSep);
            if (pos>-1)
            {
               datetime expiring = StrToDouble(StringSubstr(OrderComment(),pos+4,0));
                     if(expiring <= TimeCurrent())
                     {
                        dummyResult = OrderDelete(OrderTicket());
                        return;
                     }                        
            }
            CloseAll(); stoped=true; return;
         }            
      }

      //
      //
      //
      //
      //
      
      if(OrderMagicNumber() != MagicNumber) continue;
      if(OrderSymbol()      != s_symbol)    continue;

      //
      //
      //
      //
      //

      int err = 0;      
      if(OrderType() == OP_BUY)
      {
         int ticketB = OrderTicket();
         if (doCloseOnTrendChange) { if (currentDirection==__trendDown) { CloseOrder(0,ticketB); continue; }}
         if (EcnBroker && StopLoss>0)   { if (OrderStopLoss()==0)   { RefreshRates(); setStopLoss(ticketB  ,OrderOpenPrice()-StopLoss);}}
         if (EcnBroker && TakeProfit>0) { if (OrderTakeProfit()==0) { RefreshRates(); setTakeProfit(ticketB,OrderOpenPrice()+TakeProfit);}}
         
         //
         //
         //
         //
         //
         
         for(int c=0; c < NumberOfTries; c++)
         { 
            RefreshRates();
               if (!UseVoltyTrailingStop)
                     double trailingStopBuy = MarketInfo(s_symbol,MODE_BID)-lTrailingStop*pPoint*pipMultiplier;
               else         trailingStopBuy = volbuyValue(s_symbol);
            
               //
               //
               //
               //
               //
               
               curStop = NormalizeDouble(OrderStopLoss(),digit);
               newStop = NormalizeDouble(trailingStopBuy,digit);
               maxStop = NormalizeDouble(MarketInfo(s_symbol,MODE_BID)-MarketInfo(s_symbol,MODE_STOPLEVEL)*pPoint,digit);
               if (TrailOnlyWhenInProfit)
                  bool canTrailBuy = (MarketInfo(s_symbol,MODE_BID)-OrderOpenPrice()) > lTrailingStop*pPoint*pipMultiplier;
               else    canTrailBuy = true;                  
               if (canTrailBuy && newStop > curStop && newStop <= maxStop)
               {
                  ResetLastError();
                  dummyResult = OrderModify(OrderTicket(),OrderOpenPrice(),newStop,OrderTakeProfit(),0);
                  err = GetLastError(); checkError("stop loss modified",err);
               }
        			switch (err)
 	       	   {
        			   case ERR_SERVER_BUSY:
		            case ERR_NO_CONNECTION:
		            case ERR_INVALID_PRICE:
		            case ERR_OFF_QUOTES:
		            case ERR_BROKER_BUSY:
		            case ERR_TRADE_CONTEXT_BUSY:
			                 Sleep(PAUSE_BEFORE_RETRY);
			                 continue;

		            case ERR_PRICE_CHANGED:
		            case ERR_REQUOTE:
				              continue;

		            default:
			                 c=NumberOfTries;
			                 continue;
               }
         }
      }
      
      //
      //
      //
      //
      //
      
      if(OrderType() == OP_SELL)
      {
         int ticketS = OrderTicket();
         if (doCloseOnTrendChange) { if (currentDirection==__trendUp) { CloseOrder(0,ticketS); continue; }}
         if (EcnBroker && StopLoss>0)   { if (OrderStopLoss()==0)   { RefreshRates(); setStopLoss(ticketS  ,OrderOpenPrice()+StopLoss);}}
         if (EcnBroker && TakeProfit>0) { if (OrderTakeProfit()==0) { RefreshRates(); setTakeProfit(ticketS,OrderOpenPrice()-TakeProfit);}}

         //
         //
         //
         //
         //
         
         for(c=0; c < NumberOfTries; c++)
         { 
            RefreshRates();
               if (!UseVoltyTrailingStop)
                     double trailingStopSell = MarketInfo(s_symbol,MODE_BID)+sTrailingStop*pPoint*pipMultiplier;
               else         trailingStopSell = volsellValue(s_symbol);
               
               //
               //
               //
               //
               //
               
               curStop = NormalizeDouble(OrderStopLoss(),digit);
               newStop = NormalizeDouble(trailingStopSell,digit);
               maxStop = NormalizeDouble(MarketInfo(s_symbol,MODE_ASK)+MarketInfo(s_symbol,MODE_STOPLEVEL)*pPoint,digit);
               if (TrailOnlyWhenInProfit)
                  bool canTrailSell = (OrderOpenPrice()-MarketInfo(s_symbol,MODE_ASK)) > lTrailingStop*pPoint*pipMultiplier;
               else    canTrailSell = true;                  
               if (canTrailSell && curStop > 0 && newStop < curStop && newStop > maxStop)
               {
                  ResetLastError();
                  dummyResult = OrderModify(OrderTicket(),OrderOpenPrice(),newStop,OrderTakeProfit(),0);
                  err = GetLastError(); checkError("stop loss modified",err);
               }                        
        			switch (err)
  	       	   {
        			   case ERR_SERVER_BUSY:
		            case ERR_NO_CONNECTION:
		            case ERR_INVALID_PRICE:
		            case ERR_OFF_QUOTES:
		            case ERR_BROKER_BUSY:
		            case ERR_TRADE_CONTEXT_BUSY:
   		                 Sleep(PAUSE_BEFORE_RETRY);
	  	                    continue;

		            case ERR_PRICE_CHANGED:
		            case ERR_REQUOTE:
   			              continue;

		            default:
			                 c=NumberOfTries;
			                 continue;
               }
         }                  
      }
   }
}

//----------------------------------------------------------------------------------------
//       orders management
//----------------------------------------------------------------------------------------
//       buy and sell orders
//----------------------------------------------------------------------------------------
//
//
//
//
//

void setStopLoss(int ticket,double stopLoss)
{
   if (ticket != -1)
   {
      for(int c=0; c < NumberOfTries; c++)
      {
         double minStop = 0;
         bool   canGo   = false;
         if (OrderType()==OP_BUY)
               { minStop = MarketInfo(s_symbol,MODE_BID)-MarketInfo(s_symbol,MODE_STOPLEVEL)*pPoint; canGo = stopLoss<=minStop; }
         else  { minStop = MarketInfo(s_symbol,MODE_ASK)+MarketInfo(s_symbol,MODE_STOPLEVEL)*pPoint; canGo = stopLoss>=minStop; }
         if (canGo)
         {
            ResetLastError();
            dummyResult = OrderModify(ticket,OrderOpenPrice(),stopLoss,OrderTakeProfit(),0);
               int     err = GetLastError(); checkError("stop loss applied",err);
               switch (err)
	    	      {
                  case ERR_SERVER_BUSY:
                  case ERR_NO_CONNECTION:
                  case ERR_INVALID_PRICE:
                  case ERR_OFF_QUOTES:
                  case ERR_BROKER_BUSY:
                  case ERR_TRADE_CONTEXT_BUSY:
      			        Sleep(PAUSE_BEFORE_RETRY);
   	  		           continue;

                  case ERR_PRICE_CHANGED:
	    		      case ERR_REQUOTE:
	     			        continue;

                  default:
	                   c = NumberOfTries;
	                    continue;
             }
         }            
      }
      dummyResult = OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);      
   }   
}

//
//
//
//
//

void setTakeProfit(int ticket,double takeProfit)
{
   if (ticket != -1)
   {
      for(int c=0; c < NumberOfTries; c++)
      {
         ResetLastError();
         dummyResult = OrderModify(ticket,OrderOpenPrice(),OrderStopLoss(),takeProfit,0);
            int     err = GetLastError(); checkError("take profit applied",err);
            switch (err)
   	  	   {
               case ERR_SERVER_BUSY:
               case ERR_NO_CONNECTION:
               case ERR_INVALID_PRICE:
               case ERR_OFF_QUOTES:
               case ERR_BROKER_BUSY:
               case ERR_TRADE_CONTEXT_BUSY:
	  		           Sleep(PAUSE_BEFORE_RETRY);
   			        continue;

               case ERR_PRICE_CHANGED:
	  		      case ERR_REQUOTE:
   				     continue;

               default:
	                 c=NumberOfTries;
	                continue;
            }
      }
      dummyResult = OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);      
   }   
}

//
//
//
//
//

void Buy(double Lots)
{ 
   double TakeProfit = TakeProfitPips*pPoint*pipMultiplier;
   double StopLoss   = StopLossPips  *pPoint*pipMultiplier;
   if (UseVoltyTrailingStop)
          StopLoss   = Volty_initialStopLoss*pPoint*pipMultiplier;
   
   //
   //
   //
   //
   //
   
   if (IsTesting() || CheckTradeAllowed())
   for(int c=0; c < NumberOfTries; c++)
   { 
      RefreshRates();
      double sl=0;
      double tp=0;
         if (!EcnBroker)
         {
            if (StopLoss > 0)   sl = MarketInfo(s_symbol,MODE_ASK)-StopLoss;
            if (TakeProfit > 0) tp = MarketInfo(s_symbol,MODE_ASK)+TakeProfit;
         }            
         int ticket = OrderSend(s_symbol,OP_BUY,Lots,MarketInfo(s_symbol,MODE_ASK),AllowedSlippage*pipMultiplier,sl,tp,"IchiNrtr-buy",MagicNumber,0,Blue);
         
         //
         //
         //
         //
         //
         
         int     err = GetLastError(); checkError("buy order opened",err);
  			switch (err)
         {
            case ERR_NO_ERROR:
                 if (EcnBroker && StopLoss>0)   setStopLoss(ticket,MarketInfo(s_symbol,MODE_ASK)-StopLoss);
                 if (EcnBroker && TakeProfit>0) setTakeProfit(ticket,MarketInfo(s_symbol,MODE_ASK)+TakeProfit);
                     c=NumberOfTries;
                 continue;
			                 
			   case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY:
                 Sleep(PAUSE_BEFORE_RETRY);
                 continue;

            case ERR_PRICE_CHANGED:
            case ERR_REQUOTE:
	              continue;

            default:
                 c=NumberOfTries;
                 continue;
         }
   } 	    
}

//
//
//
//
//

void Sell(double Lots)
{        
   double TakeProfit = TakeProfitPips*pPoint*pipMultiplier;
   double StopLoss   = StopLossPips  *pPoint*pipMultiplier;
   if (UseVoltyTrailingStop)
          StopLoss   = Volty_initialStopLoss*pPoint*pipMultiplier;
      
   //
   //
   //
   //
   //
   
   if (IsTesting() || CheckTradeAllowed())
   for(int c=0;c < NumberOfTries; c++)
   { 
      RefreshRates();
      double sl=0;
      double tp=0;
         if (!EcnBroker)
         {
            if (StopLoss > 0)   sl = MarketInfo(s_symbol,MODE_BID)+StopLoss;
            if (TakeProfit > 0) tp = MarketInfo(s_symbol,MODE_BID)-TakeProfit;
         }
         int ticket = OrderSend(s_symbol,OP_SELL,Lots,MarketInfo(s_symbol,MODE_BID),AllowedSlippage*pipMultiplier,sl,tp,"IchiNrtr-sell",MagicNumber,0,Red);
         
         //
         //
         //
         //
         //
         
         int     err = GetLastError(); checkError("sell order opened",err);
  			switch (err)
         {
            case ERR_NO_ERROR:
                 if (EcnBroker && StopLoss>0)   setStopLoss(ticket,MarketInfo(s_symbol,MODE_BID)+StopLoss);
                 if (EcnBroker && TakeProfit>0) setTakeProfit(ticket,MarketInfo(s_symbol,MODE_BID)-TakeProfit);
                     c=NumberOfTries;
                 continue;
			                 
			   case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY:
                 Sleep(PAUSE_BEFORE_RETRY);
                 continue;

            case ERR_PRICE_CHANGED:
            case ERR_REQUOTE:
	              continue;

            default:
                 c = NumberOfTries;
                 continue;
         }
   }
}

//----------------------------------------------------------------------------------------
//       orders closing and closing all (take profit mode)
//----------------------------------------------------------------------------------------
//
//
//
//
//

void CloseAll()
{
   for (int i=OrdersTotal()-1; i>=0; i--)
   { 
      dummyResult = OrderSelect(i, SELECT_BY_POS,MODE_TRADES);
      if (OrderMagicNumber()!=MagicNumber) continue;
      if (!AllSymbolsForProfitAndLoss)
      if (OrderSymbol() != s_symbol)       continue;

      //
      //
      //
      //
      //

      if (OrderType()==OP_BUY || OrderType()==OP_SELL)
      {
         for(int c=0 ; c<3; c++)
         {
            RefreshRates();
               if (OrderType()==OP_BUY)
                     double cp = MarketInfo(s_symbol,MODE_BID);  
               else         cp = MarketInfo(s_symbol,MODE_ASK);
               
            //
            //
            //
            //
            //
                          
            ResetLastError();                           
            dummyResult = OrderClose(OrderTicket(),OrderLots(),cp,0,CLR_NONE);
            int     err=GetLastError(); checkError(s_symbol+" order closed",err);
     			switch (err)
            {
   			   case ERR_SERVER_BUSY:
               case ERR_NO_CONNECTION:
               case ERR_INVALID_PRICE:
               case ERR_OFF_QUOTES:
               case ERR_BROKER_BUSY:
               case ERR_TRADE_CONTEXT_BUSY:
                    Sleep(PAUSE_BEFORE_RETRY);
                    continue;

               case ERR_PRICE_CHANGED:
               case ERR_REQUOTE:
	                continue;

               default:
                    c=NumberOfTries;
                    continue;
            }                 
         }
      }
   }
}

//
//
//
//
//

void CloseOrder(double lotsToClose=0,int ticket=-1)
{
   double minLot = NormalizeDouble(MarketInfo(s_symbol,MODE_MINLOT),2);
   string message;

   //
   //
   //
   //
   //
      
   if (IsTesting() || CheckTradeAllowed())
   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      dummyResult = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if (OrderMagicNumber()!=MagicNumber) continue;
      if (OrderSymbol() != s_symbol)       continue;
      if (ticket!=-1)
         if (OrderTicket()!=ticket) continue;
         
      //
      //
      //
      //
      //
         
      if (OrderType()==OP_BUY || OrderType()==OP_SELL)
      {
         if (OrderType()==OP_BUY)
               { string operation = "buy"; color theColor  = Blue;}  
         else  {        operation = "sell";      theColor  = Red; }
            
         //
         //
         //
         //
         //

         if (lotsToClose==0) lotsToClose = OrderLots();
         if (lotsToClose!=OrderLots())
         {
            lotsToClose = MathMax(minLot,lotsToClose);
               if (OrderLots() < 2.0*minLot)
                  lotsToClose = OrderLots();
         }               
            
         if (lotsToClose!=OrderLots())
                  message="partialy closed "+operation+" - closed "+DoubleToStr(lotsToClose,2)+" lots";
         else     message=operation+" order closed";
            
         //
         //
         //
         //
         //
            
         for(int c=0 ; c < NumberOfTries; c++)
         {
            RefreshRates();
            if (OrderType()==OP_BUY)
                  double cp = MarketInfo(s_symbol,MODE_BID);  
            else         cp = MarketInfo(s_symbol,MODE_ASK);
               
            //
            //
            //
            //
            //
               
            ResetLastError();               
            dummyResult = OrderClose(OrderTicket(),lotsToClose,cp,AllowedSlippage*pipMultiplier,theColor);
            int err=GetLastError();  checkError(message,err);
     			switch (err)
            {
    			   case ERR_SERVER_BUSY:
               case ERR_NO_CONNECTION:
               case ERR_INVALID_PRICE:
               case ERR_OFF_QUOTES:
               case ERR_BROKER_BUSY:
               case ERR_TRADE_CONTEXT_BUSY:
                    Sleep(PAUSE_BEFORE_RETRY);
                    continue;

               case ERR_PRICE_CHANGED:
               case ERR_REQUOTE:
    	              continue;

               default:
                    c=NumberOfTries;
                    continue;
            }
         }
      }            
   }  
}

//----------------------------------------------------------------------------------------
//       miscellaneus functions           
//----------------------------------------------------------------------------------------
//
//
//
//
//

string normalizeTime(string time)
{
   int sepAt  = StringFind(time,":",0);
   int hour   = StrToInteger(StringSubstr(time,0,sepAt));
   int minute = StrToInteger(StringSubstr(time,sepAt+1,0));
   
   //
   //
   //
   //
   //
   
   hour   = MathMax(MathMin(hour  ,24),0);
   minute = MathMax(MathMin(minute,59),0);
   string answer="";
      while(true)
      {
         if (hour==0) { answer="00";     break; }
         if (hour<10) { answer="0"+hour; break; }
                        answer=    hour; break; 
      }                        
      while(true)
      {
         if (minute==0) { answer=answer+":00";       break; }
         if (minute<10) { answer=answer+":0"+minute; break; }
                          answer=answer+":" +minute; break; 
      }
   return(" "+answer); 
}

//
//
//
//
//

double volbuyValue(string symbol)
{
   double volbuy = iCustom(symbol,vol_timeFrame,"volty_channel_stop_on_jurik-for_ea",0,Price,Length,Phase,Double,AtrLength,Kv,MoneyRisk,0,0,vol_barToUse);
   return(volbuy);
}

double volsellValue(string symbol)
{
   double volsell = iCustom(symbol,vol_timeFrame,"volty_channel_stop_on_jurik-for_ea",0,Price,Length,Phase,Double,AtrLength,Kv,MoneyRisk,0,1,vol_barToUse);
   return(volsell);
}

//----------------------------------------------------------------------------------------
//       terminal status handling
//----------------------------------------------------------------------------------------
//
//
//
//
//

bool CheckTradeAllowed() { return(IsTradeAllowed() && !IsStopped() && IsExpertEnabled() && !IsTradeContextBusy()); }
bool CheckTerminalStatus()
{
   bool status=false;
   
   //
   //
   //
   //
   //
   
   while(true)
   {
         if (!IsConnected())
             { showTwoStateMessage("connected","No connection to server",False); break; }
         else  showTwoStateMessage("connected","Reconected to server",true);
         if ( IsStopped())
             { showTwoStateMessage("stopped","EA stopped",False); break; }  
         else  showTwoStateMessage("stopped","EA started again",true);
         if (!IsTradeAllowed())
             { showTwoStateMessage("allowed","Trading not allowed",false); break; }
         else  showTwoStateMessage("allowed","Trading allowed again",true);
         if (!IsExpertEnabled() && !IsTesting())
            { showTwoStateMessage("disabled","EA''s are disabled",false); break; }
         else showTwoStateMessage("disabled","EA''s are enabled again",true);
         if ( IsTradeContextBusy())
            { showTwoStateMessage("busy","Trade contest busy",false); break; }
         else showTwoStateMessage("busy","Trade contest ready again",true);

      //
      //
      //
      //
      //
      
      status=true;
      break;
   }
   if (SpreadProtection)
   {
      if (DontContinue==1)
            showTwoStateMessage("spreads","Spreads widen",false);
      else  showTwoStateMessage("spreads","Spreads normal again",true);
   }            
   return(status);
}

//----------------------------------------------------------------------------------------
//       inter EA messages handling
//----------------------------------------------------------------------------------------
//
//
//
//
//
//

bool FindMessage()
{
   bool found=false;
   for (int i=OrdersTotal()-1; i>=0; i--)
   {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      if (OrderMagicNumber() == IEAMessagesIDMagic)
      if (OrderComment()     == IEAMessagesID)
      {
        found=true; break;
      }
   }
   return(found);
}

//
//
//
//
//

void PostMessage()
{
   string   message    = IEAMessagesID;
   int      timeToAdd  = 660;
   double   lot        = MarketInfo(s_symbol,MODE_MINLOT);
   datetime expiration = Time[0]+24*3600;
            expiration = StrToTime(TimeToStr(expiration,TIME_DATE)+" 00:00");
   
   //
   //
   //
   //
   //
   
   if (!FindMessage())
   {
     for(int c=0; c<NumberOfTries; c++)
      {
         expiration = MathMax(expiration,TimeCurrent()+timeToAdd);
         
         //
         //
         //
         //
         //
         
         ResetLastError();
         dummyResult = OrderSend(s_symbol,OP_BUYLIMIT,lot,pPoint,0,0,0,message,IEAMessagesIDMagic,expiration,CLR_NONE);
         int err = GetLastError();
      	switch (err)
 	      {
 	         case ERR_TRADE_EXPIRATION_DENIED:
 	               if (expiration !=0)
 	               {
 	                  message    = IEAMessagesID+IEAMessagesIDExSep+expiration;
                     expiration = 0; 	                   
 	               }
 	               continue;
 	         
            case ERR_INVALID_TRADE_PARAMETERS:
                  timeToAdd += 300;
                  continue;

            case ERR_SERVER_BUSY:
		      case ERR_NO_CONNECTION:
		      case ERR_INVALID_PRICE:
		      case ERR_OFF_QUOTES:
		      case ERR_BROKER_BUSY:
		      case ERR_TRADE_CONTEXT_BUSY:
			          Sleep(PAUSE_BEFORE_RETRY);
			          continue;

            case ERR_PRICE_CHANGED:
            case ERR_REQUOTE:
		              continue;

            default:
	                 c=NumberOfTries;
	                 continue;
         }
      }
   }             
}

//----------------------------------------------------------------------------------------
//       messages handling
//----------------------------------------------------------------------------------------
//
//
//
//
//
//

bool   msg_errState[];
string msg_errNames[];
string msg_messageText[20];
color  msg_messageColor[20];
int    msg_lastMessage=0;

//
//
//
//
//

void checkError(string what,int err)
{
   showMessage(what);
   if(err!=ERR_NO_ERROR && err!=ERR_NO_RESULT)
         showMessage("error occured :"+ErrorDescription(err),Red);

}

//
//
//
//
//

void showTwoStateMessage(string name, string message, bool state)
{
   for(int i=ArraySize(msg_errNames)-1; i>=0; i--) if (msg_errNames[i]==name) break;
   if (i==-1)
      {
         int size = ArraySize(msg_errNames)+1;
         i = size-1;
            ArrayResize(msg_errNames,size); msg_errNames[i] = name;
            ArrayResize(msg_errState,size); msg_errState[i] = true;
      }

   //
   //
   //
   //
   //

   if (msg_errState[i]!= state)
   {   
      msg_errState[i] = state;
      if (state==false)
            showMessage(message,Red);
      else  showMessage(message,Green);
   }      
}

//
//
//
//
//

void showMessage(string text, color theColor=Gray)
{
   if(!showMessages) { Print(text); return; }
   
   //
   //
   //
   //
   //
   
   if(msg_lastMessage>19)
   {
      for(int i=0; i<19; i++)
      {
         msg_messageText[i] =msg_messageText[i+1];
         msg_messageColor[i]=msg_messageColor[i+1];
      }
      msg_lastMessage = 19;
   }

   //
   //
   //    set message que text and color
   //
   //
   
      msg_messageText[msg_lastMessage]  = text+" - "+TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS);
      msg_messageColor[msg_lastMessage] = theColor;
   
   //
   //
   //
   //
   //
      
   for(i=0; i<=msg_lastMessage; i++)
   {
      string name = "msg_que"+i;
      if (ObjectFind(name) == -1)
      {
         ObjectCreate(name,OBJ_LABEL,0,0,0);
            ObjectSet(name,OBJPROP_CORNER,3);
            ObjectSet(name,OBJPROP_XDISTANCE,5);
            ObjectSet(name,OBJPROP_YDISTANCE,5+14*i);
      }
      ObjectSetText(name,msg_messageText[i],9,"Arial",msg_messageColor[i]);
   }
   msg_lastMessage++;
   WindowRedraw();
}

//
//
//
//
//

//|---------Trailing Stop based on VoltyChannel

void MoveStopsToVolty(int iMN)
  {
   int icnt,itotal;
   double Close_1=Close[1]; // first bar
   double volbuy_trail = iCustom(strSymbol,vol_timeFrame,"volty_channel_stop_on_jurik-for_ea",0,Price,Length,Phase,Double,AtrLength,Kv,MoneyRisk,0,0,vol_barToUse);
   double volsell_trail = iCustom(strSymbol,vol_timeFrame,"volty_channel_stop_on_jurik-for_ea",0,Price,Length,Phase,Double,AtrLength,Kv,MoneyRisk,0,1,vol_barToUse);
  
   itotal=OrdersTotal();

   for(icnt=0;icnt<itotal;icnt++)
     {                              
      dummyResult=OrderSelect(icnt,SELECT_BY_POS,MODE_TRADES);
      if(OrderType()==OP_SELL && OrderSymbol()==strSymbol && OrderMagicNumber()==iMN)// check for opened position, symbol & MagicNumber
        {
         if((volbuy_trail>Close_1) && (volbuy_trail!=OrderStopLoss())) dummyResult=OrderModify(OrderTicket(),OrderOpenPrice(),volbuy_trail,OrderTakeProfit(),0,Orange);
        }
      if(OrderType()==OP_BUY && OrderSymbol()==strSymbol && OrderMagicNumber()==iMN)
        {
         if((volsell_trail<Close_1) && (volsell_trail!=OrderStopLoss())) dummyResult=OrderModify(OrderTicket(),OrderOpenPrice(),volsell_trail,OrderTakeProfit(),0,Orange);
        }
     }  
  }

//
//
//
//
//
//

int GetMagic() 
{

   if (StringFind(s_symbol, "CADJPY") >= 0) return(9933921);
   if (StringFind(s_symbol, "CADCHF") >= 0) return(9933922);
   
   if (StringFind(s_symbol, "XAUUSD") >= 0) return(9933931);
   if (StringFind(s_symbol, "XAGUSD") >= 0) return(9933932);
   
   if (StringFind(s_symbol, "NZDJPY") >= 0) return(9933941);
   if (StringFind(s_symbol, "NZDUSD") >= 0) return(9933942);
   
   if (StringFind(s_symbol, "CHFJPY") >= 0) return(9934144);
   
   if (StringFind(s_symbol, "EURAUD") >= 0) return(9934211);
   if (StringFind(s_symbol, "EURCAD") >= 0) return(9934962);
   if (StringFind(s_symbol, "EURUSD") >= 0) return(9934963);
   if (StringFind(s_symbol, "EURGBP") >= 0) return(9934964);
   if (StringFind(s_symbol, "EURCHF") >= 0) return(9934965);
   if (StringFind(s_symbol, "EURNZD") >= 0) return(9934966);
   if (StringFind(s_symbol, "EURJPY") >= 0) return(9934967);
   
   if (StringFind(s_symbol, "GBPUSD") >= 0) return(9934971);
   if (StringFind(s_symbol, "GBPCHF") >= 0) return(9934972);
   if (StringFind(s_symbol, "GBPJPY") >= 0) return(9934973);
   if (StringFind(s_symbol, "GBPNZD") >= 0) return(9934974);
   if (StringFind(s_symbol, "GBPDKK") >= 0) return(9934975);
   
   if (StringFind(s_symbol, "USDCHF") >= 0) return(9934981);
   if (StringFind(s_symbol, "USDJPY") >= 0) return(9934982);
   if (StringFind(s_symbol, "USDCAD") >= 0) return(9934983);
   if (StringFind(s_symbol, "USDDKK") >= 0) return(9934984);

   if (StringFind(s_symbol, "AUDUSD") >= 0) return(9934991);
   if (StringFind(s_symbol, "AUDNZD") >= 0) return(9934992);
   if (StringFind(s_symbol, "AUDCAD") >= 0) return(9934993);
   if (StringFind(s_symbol, "AUDCHF") >= 0) return(9934994);
   if (StringFind(s_symbol, "AUDJPY") >= 0) return(9934995);
   
return(ManualMagic);
}