//+------------------------------------------------------------------+
//|                             levelstop reverse Ea//satheesh       |
//|              Copyright 2014, MetaQuotes Software Corp.           |
//|                                                                  |
//+------------------------------------------------------------------+
#property version   "1.00"
#property strict
extern bool UseATRMode = true;
extern int NonATRStopPips = 40;
extern int ATRPeriod = 9;
extern double ATRMultiplier = 3.0;
extern int ATRSmoothing = 0;
extern color UpArrowColor = DodgerBlue;
extern color DnArrowColor = OrangeRed;
extern int ArrowDistance = 0;
static int prevTrend = 0;
//---- buffers
double TrStopLevel[];
extern bool SendLongTrades  = TRUE; 
extern bool SendShortTrades = TRUE;
extern int MinBarsBetweenTradesOfSameType = 0;
extern bool DumbTradeRules = true;
extern int    Magic = 123456;
extern double Lots      = 0.05;

/*
 extern bool UseMM = false;// Money management
 extern double LotsPer10000 = 1.0;//Amount of lots per every 10,000 of free margin
*/
//
extern string rah="Use risk based lotsize, instead of fixed lots?";
extern string rah1="   if no SL is specified, the script calculates with 30pips";
extern bool   UseLotsPerRiskCalculation=TRUE;
extern double RiskPercentage=2.5;
 bool   DoFreeMarginCheck          = FALSE;//should check if there is enough free margin to open the trade
 bool   DoFreeMarginForSlAlsoCheck = FALSE;//checks if there is also enough free margin for a (potentially) SL-hit
//
extern double StopLoss     = 20.0;
extern double TakeProfit   = 50.0;
extern double TrailingStop = 25.0;
extern int Slippage     = 3;
int slippagepips;

//int MaPeriod1    = 14;
//int MaPeriod2    = 200;
//extern int SignalCandle = 0;

//The minimum difference between MAs for Cross to count
//double  MinDiff          = 0.10;
extern string mdtsmhi0="-1.0 = disable:";
//extern double MaxDiffToSlowMa =-1.0;//10.0;//fxdaytrader
extern bool   PrintToJournal  = FALSE;
extern string   tthisep="----------------------------------------------------------------";
extern string	trh				= "----Trading hours----";
extern string	tr1				= "tradingHours is a comma delimited list";
extern string   tr1a            = "of start and stop times.";
extern string	tr2				= "Prefix start with '+', stop with '-'";
extern string   tr2a            = "Use 24H format.";//, local time.";
extern string	tr3				= "Example: '+07.00,-10.30,+14.15,-16.00'";
extern string	tr3a			    = "Do not leave spaces";
extern string	tr4				= "Blank input means 8.00 to 16.00";
extern string	tradingHours = "+06.00,-16.00";
extern string	tr5 = "true:LocalTime, false:ServerTime";
extern bool    UseLocalTime = FALSE;//true:TimeLocal(), false:TimeCurrent()
int TradingHourTime;
//close stuff:
extern string tr6 = "you should set the trading hours accordingly to avoid opening trades after that hour!";
extern bool EnableClosingOnEndOfMonth = FALSE;
extern int  EndOfMonthClosingHour     = 22;
extern int  EndOfMonthClosingMinute   = 55;
extern bool EnableClosingOnEndOfWeek  = TRUE;//FALSE;
extern string tr7 = "(0 means Sunday,1,2,3,4,5,6) of the specified date";
extern int  EndOfWeekDay              = 5;//(0 means Sunday,1,2,3,4,5,6) of the specified date
extern int  EndOfWeekClosingHour      = 22;//you should set the trading hours accordingly to avoid opening trades after that hour!
extern int  EndOfWeekClosingMinute    = 55;
extern bool EnableDailyClosingAtTime  = FALSE;
extern int  DailyClosingHour          = 22;
extern int  DailyClosingMinute        = 55;
////////////////////////////////////////////////////////////////////////////////////////

double pips2dbl;
//int LastBars = 0;

//---- variables
double ATRBuffer[];
double SmoothBuffer[];
string ShortName;
int ArrowObjects = 0;
int ArrowNumber;
int PrevArrows = 0;
datetime LastArrowTime = 0;
bool LastArrowSignal = 0;
datetime LastAlertBar = 0;
datetime CurrentBarTime = 0;
#define VTS_OBJECT_PREFIX "vtsbh2483-"
string ObjName;
#define SIGNAL_NONE 0
#define SIGNAL_BUY 1  
#define SIGNAL_SELL  2
////////////////////////////////////////////////////////////////////////////////////////
// trading hours variables
int 	          tradeHours[];
string          tradingHoursDisplay;//tradingHours is reduced to "" on initTradingHours, so this variable saves it for screen display.
bool            TradeTimeOk;
bool ForceTradeClosure=false;
////////////////////////////////////////////////////////////////////////////////////////
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
initTradingHours();//Sets up the trading hours array
   BrokerDigitAdjust(Symbol());
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }

//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
int start()
{
   //Comment(commentstring);
   /*
   if (FastMA == SlowMA)
   {
      if (PrintToJournal) Print("MA periods should differ.");
      return;
   }
   */
   

   TradeManager(Symbol(),Magic);

   //Wait for the new Bar in a chart.
	//if (LastBars == Bars) return;
	//else LastBars = Bars;

   //if ((Bars < SlowMA) || (IsTradeAllowed() == false)) return;
  // if (Bars < SlowMA) return(0);
   
   Checkcross();
   return(0);
   }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
int Checkcross()
  {
{
  
if ( ATRSmoothing <= 0 ) {
        ATRSmoothing = 1;
    }
    
   int ictr;
    int counted_bars = IndicatorCounted();
    
    // Check for errors
    if ( counted_bars < 0 ) {
        return( -1 );
    }

    // Last bar will be recounted
    if ( counted_bars > 0 ) {
        counted_bars--;
    }
    
    int limit = Bars - counted_bars;
    ictr = limit - 1;
    
    if ( UseATRMode && Bars < ATRPeriod ) {
        return( 0 );
    }
    
    // Make sure buffers are sized correctly
    int buff_size = ArraySize( TrStopLevel );
    if ( ArraySize( ATRBuffer ) != buff_size ) {
        ArraySetAsSeries( ATRBuffer, false );
        ArrayResize( ATRBuffer, buff_size );
        ArraySetAsSeries( ATRBuffer, true );

        ArraySetAsSeries( SmoothBuffer, false );
        ArrayResize( SmoothBuffer, buff_size );
        ArraySetAsSeries( SmoothBuffer, true );
    }
    
    int xctr;
    
    if ( UseATRMode ) {
        // First calculate the ATR
        for ( xctr = 0; xctr < limit; xctr++ ) {
            ATRBuffer[xctr] = iATR( NULL, 0, ATRPeriod, xctr );
        }
            
        // Smooth the ATR
        for ( xctr = 0; xctr < limit; xctr++ ) {
            SmoothBuffer[xctr] = Wilders( ATRBuffer, ATRSmoothing, xctr );
        }
    }
    
    
    for ( xctr = ictr; xctr >= 0; xctr-- ) {
         // Calculate the stop amount
        double DeltaStop = NonATRStopPips * Point;
        
        // Calculate our stop value based on ATR if required
        if ( UseATRMode ) {
            DeltaStop = NormalizeDouble( SmoothBuffer[xctr] * ATRMultiplier, 4 );
        }
        
        // Figure out where the current bar's stop level should be
        double NewStopLevel;
        double PrevStop = TrStopLevel[xctr + 1];
        bool Up = false;
        bool Dn = false;
        
        if ( Close[xctr] == PrevStop ) {
            NewStopLevel = PrevStop;
        }
        else {
            if ( Close[xctr + 1] <= PrevStop && Close[xctr] < PrevStop ) {
                NewStopLevel = MathMin( PrevStop, ( Close[xctr] + DeltaStop ) );
            }
            else {
                if ( Close[xctr + 1] >= PrevStop && Close[xctr] > PrevStop ) {
                    NewStopLevel = MathMax( PrevStop, ( Close[xctr] - DeltaStop ) );
                }
                else {
                    if ( Close[xctr] > PrevStop ) {
                        NewStopLevel = Close[xctr] - DeltaStop;
                        Up = true;
                    }
                    else {
                        NewStopLevel = Close[xctr] + DeltaStop;
                        Dn = true;
                    }
                }
            }
        }
        
        
        TrStopLevel[xctr] = NewStopLevel;
        
        // Can't do the arrows until the bar closes
        if ( xctr > 0 ) {
            if ( Up ) { 
                if ( Time[xctr] > LastArrowTime ) {
                    double UpSignal = TrStopLevel[xctr] - ( ArrowDistance * Point );
                    ObjName = GetNextObjectName();
                    ObjectCreate( ObjName, OBJ_ARROW, 0, Time[xctr], UpSignal );
                    ObjectSet( ObjName, OBJPROP_COLOR, UpArrowColor );
                    ObjectSet( ObjName, OBJPROP_ARROWCODE, 233 );
                    ArrowObjects++;
                    LastArrowTime = Time[xctr];
                    LastArrowSignal = true;
                }
            }
            
            if ( Dn ) {
                if ( Time[xctr] > LastArrowTime ) {
                    double DnSignal = TrStopLevel[xctr] + ( 2 * Point ) + ( ArrowDistance * Point );
                    ObjName = GetNextObjectName();
                    ObjectCreate( ObjName, OBJ_ARROW, 0, Time[xctr], DnSignal );
                    ObjectSet( ObjName, OBJPROP_COLOR, DnArrowColor );
                    ObjectSet( ObjName, OBJPROP_ARROWCODE, 234 );
                    ArrowObjects++;
                    LastArrowTime = Time[xctr];
                    LastArrowSignal = false;
                }
            }
        }
        int i;
   int totalOrders;
   int ticket;
   double tempOrder;
        int order = SIGNAL_NONE;
   if (Up)
   {
      order = SIGNAL_BUY;
   } else if (Dn)
   {
      order = SIGNAL_SELL;
   }
   else
   {
      order = SIGNAL_NONE;
   }
   
   if (DumbTradeRules)
   {
      // Check current positions to see if they need to be closed
      // due to the stop flopping over.
      totalOrders=OrdersTotal();
      for (i=0;i<totalOrders;i++)
      {
         OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
         if (OrderSymbol() == Symbol())
         {
            // If the stop has flopped to the other side of the trade then close it.
            if (OrderType() == OP_BUY && order == SIGNAL_SELL)
            {
               Print("closing long position");
               OrderClose (OrderTicket(),Lots,Bid,3);
            }
            
            if (OrderType() == OP_SELL && order == SIGNAL_BUY)
            {
               Print("closing short position");
               OrderClose (OrderTicket(),Lots,Ask,3);
            }
         } // end if symbol
      } // end for i
      
      // If there aren't any open positions, then open one in the right direction.
      totalOrders=OrdersTotal();
      if (totalOrders == 0)
      {
         // If the current signal is buy, then go long
         if (order == SIGNAL_BUY)
         {
         double SL = 0, TP = 0;
	RefreshRates();
   double bid = MarketInfo(Symbol(),MODE_BID);
   double ask = MarketInfo(Symbol(),MODE_ASK);
   if (StopLoss   > 0.0000) SL = bid - (StopLoss * pips2dbl);
   if (TakeProfit > 0.0000) TP = bid + (TakeProfit * pips2dbl);
            Print ("Creating buy order");
            ticket=OrderSend2Stage(Symbol(),OP_BUY,Lots,Ask,Slippage, SL, TP,"initial buy",Magic,0,Green);
            if(ticket>0)
            {
               if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               {
                  Print("BUY order opened : ",OrderOpenPrice());
               }
            }
            else
            {
               Print("Error opening BUY order : ",GetLastError()); 
            }
         }
         // If the current signal is sell, then go short
         else if (order == SIGNAL_SELL)
         {
         double SL = 0, TP = 0;//satheesh
	RefreshRates();         //satheesh
   double bid = MarketInfo(Symbol(),MODE_BID);//satheesh
   double ask = MarketInfo(Symbol(),MODE_ASK);//satheesh
   if (StopLoss   > 0.0000) SL = ask + (StopLoss * pips2dbl);//satheesh
   if (TakeProfit > 0.0000) TP = ask - (TakeProfit * pips2dbl);//satheesh
            Print ("Creating sell order");
            ticket=OrderSend2Stage(Symbol(),OP_SELL,Lots,Bid,Slippage, SL, TP,"initial sell",Magic,0,Red);
            if(ticket>0)
            {
               if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               {
                  Print("SELL order opened : ",OrderOpenPrice());
               }
            }
            else
            {
               Print("Error opening SELL order : ",GetLastError()); 
            }
         }
      } // end else totalorders > 0
   } // End if dumb trade rules
   else
   {
   } // End else dumb trade rules
  }
  return( 0 );
  }}
 
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Wilders Calculation                                              |
//+------------------------------------------------------------------+
double Wilders( double& indBuffer[], int Periods, int shift ) {
    double retval = 0.0;
    retval = iMAOnArray( indBuffer, 0, ( Periods * 2 ) - 1, 0, MODE_EMA, shift );
    return( retval );
}
//+------------------------------------------------------------------+
//| Gets the next object index so they can be deleted later          |
//+------------------------------------------------------------------+
string GetNextObjectName() {
    int rand_val = MathRand() + 1;
    ArrowNumber++;
    //string retval = VTS_OBJECT_PREFIX + rand_val;
    string retval = VTS_OBJECT_PREFIX + ArrowNumber;
    return( retval );
}
 //+------------------------------------------------------------------+
//| Delete all the arrow objects                                     |
//+------------------------------------------------------------------+
void DeleteAllArrowObjects() {
    int delcnt = 0;
    
    for ( int ictr = 1; ictr <= ArrowNumber; ictr++ ) {
         ObjName = VTS_OBJECT_PREFIX + ( ictr + 1 );
        if ( ObjectDelete( ObjName ) ) {
            delcnt++;
        }
    }
    Print( "Objects deleted: ", delcnt );
    return;
} 

void DoTrailing()
{
   bool result;
   int total = OrdersTotal();
   for (int pos = 0; pos < total; pos++)
   {
      if (OrderSelect(pos, SELECT_BY_POS) == false) continue;
      if ((OrderMagicNumber() == Magic) && (OrderSymbol() == Symbol()))
      {
         if (OrderType() == OP_BUY)
         {
            RefreshRates();
            if (Bid - OrderOpenPrice() >= TrailingStop * pips2dbl) //If profit is greater or equal to the desired Trailing Stop value
            {
               if (OrderStopLoss() < (Bid - TrailingStop * pips2dbl)) //If the current stop-loss is below the desired trailing stop level
                  result=OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * pips2dbl, OrderTakeProfit(), 0);
            }
         }
         else if (OrderType() == OP_SELL)
         {
            RefreshRates();
            if (OrderOpenPrice() - Ask >= TrailingStop * pips2dbl) //If profit is greater or equal to the desired Trailing Stop value
            {
	              if ((OrderStopLoss() > (Ask + TrailingStop * pips2dbl)) || (OrderStopLoss() == 0)) //If the current stop-loss is below the desired trailing stop level
                  result=OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailingStop * pips2dbl, OrderTakeProfit(), 0);
            }
         }
      }
   }   
}

/*
double LotsOptimized()
{
   if (!UseMM) return(Lots);
   double vol = NormalizeDouble((AccountFreeMargin() / 10000) * LotsPer10000, 2);//double vol = NormalizeDouble((AccountFreeMargin() / 10000) * LotsPer10000, 1);
   if (vol <= 0) return(0.1);
   return(vol);
}
*/
//+------------------------------------------------------------------+

void BrokerDigitAdjust(string symbol) {
 int Multiplier = 1;
 int digits=MarketInfo(symbol,MODE_DIGITS);
 if (digits==3 || digits==5) Multiplier = 10;
 if (digits==6) Multiplier = 100;   
 if (digits==7) Multiplier = 1000;
 pips2dbl = Multiplier*MarketInfo(symbol,MODE_POINT);
 Slippage=slippagepips*Multiplier;
}

bool OrderSend2Stage(string symbol,int type,double lots,double price,int slippage,double sl,double tp,string ocomment,int magic,datetime expiry,color col) {
 TradeTimeOk = CheckTradingTimes();
 if (!TradeTimeOk) return(0);
 if (!SendLongTrades  && type==OP_BUY) return(0);
 if (!SendShortTrades && type==OP_SELL) return(0);
 bool result=true;
 int ticket;RefreshRates();
 //lots = NormalizeLots(symbol,lots);
 lots = CalcLotsAndCheckMargin(symbol,type,lots,RiskPercentage,price,sl);
  if (!OCTimeLastOrderSameTypeOk(symbol,type,magic)) return(0);
  while (IsTradeContextBusy()) Sleep(100);
  ticket=OrderSend(symbol,type,lots,price,slippage,0,0,ocomment,magic,expiry,col);
  while (IsTradeContextBusy()) Sleep(100);
   if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
    //Print(" *** ERROR -> COULD NOT SELECT ORDERTICKET "+OrderTicket()+" *** ");
    return(false);
   }
   //Print("**** send ORDER at "+DoubleToStr(price,Digits)+", SL("+DoubleToStr(StopLoss,2)+")="+DoubleToStr(sl,Digits)+", TP("+DoubleToStr(TakeProfit,2)+"="+DoubleToStr(tp,Digits));
    if (sl!=0.00000 && tp!=0.00000) result = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizePrice(OrderSymbol(),sl),NormalizePrice(OrderSymbol(),tp),OrderExpiration(),CLR_NONE);
    if (sl!=0.00000 && tp==0.00000) result = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizePrice(OrderSymbol(),sl),OrderTakeProfit(),OrderExpiration(),CLR_NONE);
    if (sl==0.00000 && tp!=0.00000) result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),NormalizePrice(OrderSymbol(),tp),OrderExpiration(),CLR_NONE);
  
 return(result);
}

bool OCTimeLastOrderSameTypeOk(string symbol,int type,int magicnumber) {
 if (MinBarsBetweenTradesOfSameType==0) return(true);
 //History
 for (int cnt=OrdersHistoryTotal()-1; cnt>=0; cnt--) {
  if (!OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY)) continue;
  if (OrderSymbol()!=symbol) continue;
  if (OrderMagicNumber()!=magicnumber) continue;
  if (OrderType()!=type) continue;
   {//start loop
     if (TimeCurrent() - OrderCloseTime() < (MinBarsBetweenTradesOfSameType * Period() * 60)) return(false);
   }//end loop
 }//for (int cnt=OrdersHistoryTotal()-1; cnt>=0; cnt--) {
 
 //Open Trades:
 for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
  if (!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
  if (OrderSymbol()!=symbol) continue;
  if (OrderMagicNumber()!=magicnumber) continue;
  if (OrderType()!=type) continue;
   {//start loop
     if (OrderOpenTime()>=iTime(OrderSymbol(),0,0)) return(false);
     if (TimeCurrent() - OrderOpenTime() < (MinBarsBetweenTradesOfSameType * Period() * 60)) return(false);
   }//end loop
 }//for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
return(true);
}

//Lot size must be adjusted to be a multiple of lotstep, which may not be a power of ten on some brokers
double NormalizeLots(string symbol, double lots) {
  if (MathAbs(lots)<MarketInfo(symbol,MODE_MINLOT)) return(MarketInfo(symbol,MODE_MINLOT));
  if (MathAbs(lots)>MarketInfo(symbol,MODE_MAXLOT)) return(MarketInfo(symbol,MODE_MAXLOT));
  double ls = MarketInfo(symbol,MODE_LOTSTEP); 
  lots=MathRound(lots/ls)*ls;
  return(MathMin(MarketInfo(symbol,MODE_MAXLOT),MathMax(MarketInfo(symbol,MODE_MINLOT),lots))); 
}//double NormalizeLots(string symbol, double lots) {


//Open price for pending order must be adjusted to be a multiple of ticksize, not point, and on metals they are not the same.
//see also http://forum.mql4.com/45425#564188
double NormalizePrice(string symbol, double price) {
 if (price==0.00000000) return(0.0);
 double ts = MarketInfo(symbol,MODE_TICKSIZE);
return(MathRound(price/ts)*ts );
}


void TradeManager(string symbol,int magicnumber) {
 if (ForceTradeClosure) CloseAllTrades(symbol,magicnumber);
 if (EnableDailyClosingAtTime) CheckForDailyClosingHour();
 if (EnableClosingOnEndOfWeek) CheckForEndOfWeekClosingHour();
 if (EnableClosingOnEndOfMonth) CheckForLastEndMonthClosingHour();

 for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
  if (!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
  if (OrderSymbol()!=symbol) continue;
  if (OrderMagicNumber()!=magicnumber) continue;
   {
    if (TrailingStop > 0.00) DoTrailing();
   }
  }//for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
}


//////////////////////////////////////////////////////////////////

bool CheckTradingTimes() 
{
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	// Trade 24 hours if no input is given
	if ( ArraySize( tradeHours ) == 0 ) return ( true );

	// Get local time in minutes from midnight
    if (UseLocalTime) TradingHourTime = TimeLocal();
     else if (!UseLocalTime) TradingHourTime = TimeCurrent();
    int time = TimeHour(TradingHourTime) * 60 + TimeMinute(TradingHourTime);
   
	// Don't you love this?
	int i = 0;
	while ( time >= tradeHours[i] ) 
	{	
		if ( i == ArraySize( tradeHours ) ) break;
		i++;		
	}
	if ( i % 2 == 1 ) return ( true );
	return ( false );

}//End bool CheckTradingTimes() 

//+------------------------------------------------------------------+
//| Initialize Trading Hours Array                                   |
//+------------------------------------------------------------------+
bool initTradingHours() 
{
   // Called from init()
   
   tradingHoursDisplay = tradingHours;//For display
   if (tradingHoursDisplay=="") tradingHoursDisplay = "24 hours trading";
   
	// Assume 24 trading if no input found
	if ( tradingHours == "" )	
	{
		ArrayResize( tradeHours, 0 );
		return ( true );
	}

	int i;

	// Add 00:00 start time if first element is stop time
	if ( StringSubstr( tradingHours, 0, 1 ) == "-" ) 
	{
		tradingHours = StringConcatenate( "+0,", tradingHours );   
	}
	
	// Add delimiter
	if ( StringSubstr( tradingHours, StringLen( tradingHours ) - 1) != "," ) 
	{
		tradingHours = StringConcatenate( tradingHours, "," );   
	}
	
	string lastPrefix = "-";
	i = StringFind( tradingHours, "," );
	
	while (i != -1) {

		// Resize array
		int size = ArraySize( tradeHours );
		ArrayResize( tradeHours, size + 1 );

		// Get part to process
		string part = StringSubstr( tradingHours, 0, i );

		// Check start or stop prefix
		string prefix = StringSubstr ( part, 0, 1 );
		if ( prefix != "+" && prefix != "-" ) 
		{
			Print("ERROR IN TRADINGHOURS INPUT (NO START OR CLOSE FOUND), ASSUME 24HOUR TRADING.");
			ArrayResize ( tradeHours, 0 );
			return ( true );
		}

		if ( ( prefix == "+" && lastPrefix == "+" ) || ( prefix == "-" && lastPrefix == "-" ) )	
		{
			Print("ERROR IN TRADINGHOURS INPUT (START OR CLOSE IN WRONG ORDER), ASSUME 24HOUR TRADING.");
			ArrayResize ( tradeHours, 0 );
			return ( true );
		}
		
		lastPrefix = prefix;

		// Convert to time in minutes
		part = StringSubstr( part, 1 );
		double time = StrToDouble( part );
		int hour = MathFloor( time );
		int minutes = MathRound( ( time - hour ) * 100 );

		// Add to array
		tradeHours[size] = 60 * hour + minutes;

		// Trim input string
		tradingHours = StringSubstr( tradingHours, i + 1 );
		i = StringFind( tradingHours, "," );
	}

	return ( true );
}//End bool initTradingHours() 
//end trading hours
////////////////////////////////////////////////////////////////

void CheckForDailyClosingHour() {
   static int OldDailyClosingBarTime=0;
   
   if (UseLocalTime) TradingHourTime = TimeLocal();
    else if (!UseLocalTime) TradingHourTime = TimeCurrent();
   
   if (EnableDailyClosingAtTime) {
    if (TimeHour(TradingHourTime) >= DailyClosingHour && TimeMinute(TradingHourTime) >= DailyClosingMinute) if (OldDailyClosingBarTime != iTime(NULL,PERIOD_D1,0)) {
     OldDailyClosingBarTime = iTime(NULL,PERIOD_D1,0);
     ForceTradeClosure=true;
    }//if (OldDailyClosingBarTime != iTime(NULL,PERIOD_D1, 0)) {
   }//if (EnableDailyClosingAtTime) {
}

void CheckForEndOfWeekClosingHour() {
   static int OldEndOfWeekClosingBarTime=0;
   
   if (UseLocalTime) TradingHourTime = TimeLocal();
    else if (!UseLocalTime) TradingHourTime = TimeCurrent();

   if (EnableClosingOnEndOfWeek && TimeDayOfWeek(TradingHourTime)==EndOfWeekDay) if (TimeHour(TradingHourTime) >= EndOfWeekClosingHour && TimeMinute(TradingHourTime) >= EndOfWeekClosingMinute)
    if (OldEndOfWeekClosingBarTime != iTime(NULL,PERIOD_W1,0)) {
     OldEndOfWeekClosingBarTime = iTime(NULL,PERIOD_W1,0);
     ForceTradeClosure=true;
   }
}

//function (IsLeapYear, DaysOfMonth) by WHRoeder, http://forum.mql4.com/51054#691229
void CheckForLastEndMonthClosingHour() {
 if (UseLocalTime) TradingHourTime = TimeLocal();
  else if (!UseLocalTime) TradingHourTime = TimeCurrent();
  if (EnableClosingOnEndOfMonth && TimeDay(TradingHourTime)==GetLastDayOfMonth()) if (TimeHour(TradingHourTime) >= EndOfMonthClosingHour && TimeMinute(TradingHourTime) >= EndOfMonthClosingMinute) ForceTradeClosure=true;
}

int GetLastDayOfMonth() {
 if (UseLocalTime) TradingHourTime = TimeLocal();
  else if (!UseLocalTime) TradingHourTime = TimeCurrent();
 return(DaysOfMonth(TradingHourTime));
}

bool IsLeapYear(int year) {
 return(year%4==0 && year%100!=0 && year%400==0);
}

int DaysOfMonth(datetime when) {
 // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
 static int dpm[] ={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  };
 int iDpm = TimeMonth(when) - 1;
 if (iDpm != 1)  return(dpm[iDpm]);
 return(dpm[iDpm] + IsLeapYear(TimeYear(when)));
}
bool CloseAllTrades(string symbol,int magicnumber) {
 bool result;
 ForceTradeClosure=false;
 //Print("CloseAllTrades(): closing all open orders ...");
 for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
  if (!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
  if (OrderSymbol()!=symbol) continue;
  if (OrderMagicNumber()!=magicnumber) continue;
   {  
     //Print("CloseAllTrades(): Closing all open orders ...");
     while (IsTradeContextBusy()) Sleep(100);
     RefreshRates();

     if (OrderType()==OP_BUY)  result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),99999,CLR_NONE);
     if (OrderType()==OP_SELL) result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),99999,CLR_NONE);
     if (OrderType()>OP_SELL && OrderType()<=OP_SELLSTOP) result = OrderDelete(OrderTicket());//delete pending orders      
     if (!result) ForceTradeClosure=true;
   }
  }//for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
  return(0);
}//End void CloseAllTrades()
//end trading hours
////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//risk/lots calculation stuff:
double CalcLotsAndCheckMargin(string symbol,int type,double lots,double RiskPercentage,double price,double SLprice) {
  
 if (MathAbs(RiskPercentage)>0.000 && UseLotsPerRiskCalculation) lots = CalculateLotSize(symbol,RiskPercentage,lots,price,SLprice);//if using risk-based calculation
 if (DoFreeMarginCheck) lots = FreeMarginCheck(symbol,type,lots,price,SLprice);//do we have enough free margin?
  else if (!DoFreeMarginCheck) lots = NormalizeLots(symbol,lots);
 return(lots);
}

double CalculateLotSize(string symbol,double RiskPercent,double lots,double BidAskPrice,double SLprice) {
   
      
  
  //mod. - if there is no SLprice specified, the script would work with 50 pips (you can change that, search for the 30 in the code some lines below) ...
  if (SLprice==0) SLprice = BidAskPrice+(30*pips2dbl);
    
   lots = NormalizeLots(symbol,lots);
   if (RiskPercent==0.0) return(lots); 
   if (BidAskPrice == 0.00000 || SLprice == 0.00000) return(lots);
   
   double FreeMargin = AccountFreeMargin();
    //double TickValue = MarketInfo(symbol,MODE_TICKVALUE) ;   
   double TickValue = MarketInfo(symbol,MODE_TICKVALUE) * MarketInfo(symbol,MODE_POINT) / MarketInfo(symbol,MODE_TICKSIZE);

   double LotStep = MarketInfo(symbol,MODE_LOTSTEP);
   double SLPts = MathAbs(BidAskPrice - SLprice);
   
   SLPts/= MarketInfo(symbol,MODE_POINT);//No idea why *= factor does not work here, but it doesn't
   
   double Exposure = SLPts * TickValue; // Exposure based on 1 full lot

   double AllowedExposure = (FreeMargin * RiskPercent) / 100;
   
   //int TotalSteps = ((AllowedExposure / Exposure) / LotStep);
   double TotalSteps = ((AllowedExposure / Exposure) / LotStep); 
   double LotSize = TotalSteps * LotStep;
   
   return(NormalizeLots(symbol,LotSize));
}//double CalculateLotSize(string symbol,double RiskPercent,double lots,double BidAskPrice,double SLprice) {

///////////////////////////////////////////////////////////////////////////////
//start freemargincheck
/*
  Usage: before the OrderSend-Command you may set your already calculated lotsize = FreeMarginCheck(string symbol,int ordertype,double lots,double BidAskPrice,double SLprice)
  if there is no SLprice specified, the script would work with 50 pips (you can change that, search for the 30 in the code some lines below) ...
*/

double FreeMarginCheck(string symbol,int ordertype,double lots,double BidAskPrice,double SLprice) { 
  lots = NormalizeLots(symbol,lots);
  if (CheckAccountFreeMargin(symbol,ordertype,lots)) return(lots);//everything ok
 
  //adjust:
  Print("... not enough money, will try to decrease lotsize of "+DoubleToStr(lots,MarketInfo(symbol,MODE_DIGITS))+" (max. lots: "+DoubleToStr(MarketInfo(symbol,MODE_MAXLOT),MarketInfo(symbol,MODE_DIGITS))+" | min. lots: "+DoubleToStr(MarketInfo(symbol,MODE_MINLOT),MarketInfo(symbol,MODE_DIGITS))+") ...");
  if (SLprice==0.0) {
    //x-digit broker adjust
     int Multiplier = 1;
     double digits=MarketInfo(symbol,MODE_DIGITS);
     if (digits==3 || digits==5) Multiplier = 10;
     if (digits==6) Multiplier = 100;   
     if (digits==7) Multiplier = 1000;
     double pips2dbl = Multiplier*MarketInfo(symbol,MODE_POINT); 
    //end x-digit broker adjust
   Print("... no SL specified, will count with 30 pips instead ...");
   SLprice = BidAskPrice+(30*pips2dbl);
  }//if (SLprice==0.0) {
  
  double ls=MarketInfo(symbol,MODE_LOTSTEP);
  while (!CheckAccountFreeMargin(symbol,ordertype,lots))
   {
    //lots = lots - ls;
    lots = NormalizeLots(symbol,lots - ls);
   }//while (!CheckAccountFreeMargin(symbol,ordertype,lots))
  
  if (DoFreeMarginForSlAlsoCheck) {
   Print("... lotsize adjusted to "+DoubleToStr(lots,MarketInfo(symbol,MODE_DIGITS))+", checking for enough free margin for SL now ...");
   lots = NormalizeLots(symbol,CheckMarginAndNormalizeLotSize(symbol,lots,BidAskPrice,SLprice,AccountFreeMargin())); 
  }
  Print("... done - lotsize finally adjusted to "+DoubleToStr(lots,MarketInfo(symbol,MODE_DIGITS))+" ...");
  
 return(lots);//everything ok now, hopefully ... ;)
}//double FreeMarginCheck(string symbol,int ordertype,double lots) { 

bool CheckAccountFreeMargin(string symbol,int ordertype,double lots) {
 if (ordertype==OP_BUYSTOP || ordertype==OP_BUYLIMIT) ordertype=OP_BUY;
 if (ordertype==OP_SELLSTOP || ordertype==OP_SELLLIMIT) ordertype=OP_SELL;
  if ( ((AccountStopoutMode()==1) && (AccountFreeMarginCheck(symbol,ordertype,lots) > AccountStopoutLevel()))
  || ( (AccountStopoutMode()==0)  && (((AccountFreeMarginCheck(symbol,ordertype,lots)/AccountEquity())*100) > AccountStopoutLevel()))) return(true);//everything seems to be ok
   else return(false);
}//bool CheckAccountFreeMargin(string symbol,int ordertype,double lots) {

double CheckMarginAndNormalizeLotSize(string symbol,double lots,double BidAskPrice,double SLprice,double accBalance) {
//----
 lots = NormalizeLots(symbol,lots);
 
 double SLpips =(MathAbs(BidAskPrice - SLprice))/ MarketInfo(symbol,MODE_POINT);
   
 double ls = MarketInfo(symbol,MODE_LOTSTEP);
 double MarginRequired = MarketInfo(symbol,MODE_MARGINREQUIRED);
 //double accBalance = AccountFreeMargin();
 // fix tickvalue for extremely rare occasion when a change in ticksize leads to a change in tickvalue, source: http://forum.mql4.com/29781
 double tickValueReliable = MarketInfo(symbol,MODE_TICKVALUE) * MarketInfo(symbol,MODE_POINT) / MarketInfo(symbol,MODE_TICKSIZE);
  //Print("checkMarginAndNormalizeLotSize() - checking free margin (currency="+AccountCurrency()+"): free margin required for "+DoubleToStr(lots,3)+" lots: "+DoubleToStr(lots * MarginRequired,2)+" | for SL: "+DoubleToStr(lots * SLpips * PointValuePerLot(symbol),2)+" = total: "+DoubleToStr(lots * MarginRequired+lots * SLpips * PointValuePerLot(symbol),2)+" | current free margin: "+DoubleToStr(AccountFreeMargin(),2)+"");
  if (accBalance < lots * SLpips * tickValueReliable + lots * MarginRequired)
  //old: if (accBalance < lots * SLpips * PointValuePerLot(symbol) + lots * MarginRequired) // do we have enough money for that trade?
  { // if not, try to decrease lots:  
    if (lots>MarketInfo(symbol,MODE_MAXLOT)) lots=MarketInfo(symbol,MODE_MAXLOT);//saves time ...
   while (accBalance < (lots * SLpips * tickValueReliable) + (lots * MarginRequired))
    {
     lots = lots - ls;
     lots = NormalizeLots(symbol,lots);
    }
  }
//----
 //if (lots <= 0.0) lots = -1;
 if (lots <= 0.0) lots = MarketInfo(symbol,MODE_MINLOT);//return the minimum if everything other fails ...
 return(lots);
}//double CheckMarginAndNormalizeLotSize(string symbol,double lots,double BidAskPrice,double SLprice,double accBalance) {

//end freemargincheck
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          