//+------------------------------------------------------------------+
//|                                        Adjustable Moving Average |
//|                             Copyright © 2009-2012, EarnForex.com |
//|                                        http://www.earnforex.com/ |
//+------------------------------------------------------------------+
//////////////////////////////////////////////////////////////////////
// !!! YOU MUST COMPILE THIS EA WITH THE BUILD 509 COMPILER, download the metaeditor for build 509 at http://www.forexfactory.com/showthread.php?t=470340 !!!
//////////////////////////////////////////////////////////////////////
#property copyright "Copyright © 2009-2012, EarnForex // mod. fxdaytrader, http://ForexBaron.net"
#property link      "http://www.earnforex.com"

extern bool SendLongTrades  = TRUE; //fxdaytrader
extern bool SendShortTrades = TRUE;//fxdaytrader
extern int MinBarsBetweenTradesOfSameType = 0;//1;//fxdaytrader

extern int    Magic = 123456;
extern double Lots      = 0.1;
/*
 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 = 18.0;
extern int Slippage     = 3;
int slippagepips;//fxdaytrader

extern int MaPeriod1    = 5;//60;
extern int MaPeriod2    = 13;//240;
extern int MA_Method    = MODE_EMA;
extern int SignalCandle = 0;

//The minimum difference between MAs for Cross to count
extern double MinDiff          = 1.0;
extern string mdtsmhi0="-1.0 = disable:";
extern double MaxDiffToSlowMa = -1.0;//10.0;//fxdaytrader
extern bool   PrintToJournal  = FALSE;//fxdaytrader

double pips2dbl;//fxdaytrader
int LastBars = 0;

int PrevCross = 0;//0 - undefined, 1 - bullish cross (fast MA above slow MA), -1 - bearish cross (fast MA below slow MA)

int SlowMA,FastMA;
string commentstring;

//
extern string   tthisep="----------------------------------------------------------------";
//CheckTradingTimes. Baluda has provided all the code for this. Mny thanks Paul; you are a star.
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 24 hour trading.";
extern string	tradingHours = "+01.00,-22.50";//"+08.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;
////////////////////////////////////////////////////////////////////////////////////////
// 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;
////////////////////////////////////////////////////////////////////////////////////////

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int init()
{
   string domainname=CharToStr(104)+CharToStr(116)+CharToStr(116)+CharToStr(112)+CharToStr(58)+CharToStr(47)+CharToStr(47)+CharToStr(70)+CharToStr(111)+CharToStr(114)+CharToStr(101)+CharToStr(120)+CharToStr(66)+CharToStr(97)+CharToStr(114)+CharToStr(111)+CharToStr(110)+CharToStr(46)+CharToStr(110)+CharToStr(101)+CharToStr(116);
   commentstring = "\n"+"Adjustable_MA EA mod. v1.10, © 2009-2012, EarnForex // mod. Marc (fxdaytrader) ******* "+domainname+"\n";
   initTradingHours();//Sets up the trading hours array
   BrokerDigitAdjust(Symbol());//fxdaytrader
   FastMA = MathMin(MaPeriod1, MaPeriod2);
   SlowMA = MathMax(MaPeriod1, MaPeriod2);
   
   if (FastMA == SlowMA)
   {
      SlowMA++;
      if (PrintToJournal) Print("MA periods should differ, added +1 to SlowMA");
      return;
   }
   
 return(0);
}

int deinit() {
 Comment("");
}

//+------------------------------------------------------------------+
//| 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();
}

//+------------------------------------------------------------------+
//| Check for cross and open/close the positions respectively        |
//+------------------------------------------------------------------+
void CheckCross()
{
   double fastma = iMA(NULL, 0, FastMA, 0, MA_Method, PRICE_CLOSE, SignalCandle);
   double slowma = iMA(NULL, 0, SlowMA, 0, MA_Method, PRICE_CLOSE, SignalCandle);
   double difftoslowma = MathAbs(slowma-MarketInfo(Symbol(),MODE_BID));
   if (MaxDiffToSlowMa>-1.0 && difftoslowma>MaxDiffToSlowMa*pips2dbl) {
   if (PrintToJournal) Print(" *** PRICE- SLOW MA DIFF not ok (max. diff="+DoubleToStr(MaxDiffToSlowMa,2)+" pips, current diff = "+DoubleToStr(difftoslowma/pips2dbl,2)+" pips)");
    return(0);//fxdaytrader
   }
   
   if (PrevCross == 0) //Was undefined
   {
      if ((fastma - slowma) >= MinDiff * pips2dbl) PrevCross = 1; //Bullish state
      else if ((slowma - fastma) >= MinDiff * pips2dbl) PrevCross = -1; //Bearish state
      //return;
   }
   else if (PrevCross == 1) //Was bullish
   {
      if ((slowma - fastma) >= MinDiff * pips2dbl) //Became bearish
      {
         ClosePrev();
         fSell();
         PrevCross = -1;
      }
   }
   else if (PrevCross == -1) //Was bearish
   {
      if ((fastma - slowma) >= MinDiff * pips2dbl) //Became bullish
      {
         ClosePrev();
         fBuy();
         PrevCross = 1;
      }
   }
}

//+------------------------------------------------------------------+
//| Close previous position                                          |
//+------------------------------------------------------------------+
void ClosePrev()
{
   int total = OrdersTotal();
   bool result;
   for (int i = 0; i < total; i++)
   {
      if (OrderSelect(i, SELECT_BY_POS) == false) continue;
      if ((OrderSymbol() == Symbol()) && (OrderMagicNumber() == Magic))
      {
         if (OrderType() == OP_BUY)
         {
            RefreshRates();
            while (IsTradeContextBusy()) Sleep(100);
            result=OrderClose(OrderTicket(), OrderLots(), Bid, 99999, CLR_NONE);
         }
         else if (OrderType() == OP_SELL)
         {
            RefreshRates();
            while (IsTradeContextBusy()) Sleep(100);
            result=OrderClose(OrderTicket(), OrderLots(), Ask, 99999, CLR_NONE);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Sell                                                             |
//+------------------------------------------------------------------+
int fSell()
{
	double SL = 0, TP = 0;
	RefreshRates();
   double bid = MarketInfo(Symbol(),MODE_BID);
   double ask = MarketInfo(Symbol(),MODE_ASK);
   if (StopLoss   > 0.0000) SL = ask + (StopLoss * pips2dbl);
   if (TakeProfit > 0.0000) TP = ask - (TakeProfit * pips2dbl);
    //Print("**** SELL at "+DoubleToStr(bid,Digits)+", SL("+DoubleToStr(StopLoss,2)+")="+DoubleToStr(SL,Digits)+", TP("+DoubleToStr(TakeProfit,2)+"="+DoubleToStr(TP,Digits));
   int result = OrderSend2Stage(Symbol(), OP_SELL, Lots, bid, Slippage, SL, TP, "Adjustable MA: "+Symbol()+" SELL", Magic,0,CLR_NONE);
	return(0);
}

//+------------------------------------------------------------------+
//| Buy                                                              |
//+------------------------------------------------------------------+
int fBuy()
{
	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("**** BUY at "+DoubleToStr(ask,Digits)+", SL("+DoubleToStr(StopLoss,2)+")="+DoubleToStr(SL,Digits)+", TP("+DoubleToStr(TakeProfit,2)+"="+DoubleToStr(TP,Digits));
	int result = OrderSend2Stage(Symbol(), OP_BUY, Lots, ask, Slippage, SL, TP, "Adjustable MA: "+Symbol()+" BUY", Magic,0,CLR_NONE);
   return(0);
}

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);
}
*/
//+------------------------------------------------------------------+
//fxdaytrader:
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 (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
//see also the original function by WHRoeder, http://forum.mql4.com/45425#564188, fxdaytrader
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))); //check if lots >= min. lots && <= max. lots, fxdaytrader
}//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--) {
}


//////////////////////////////////////////////////////////////////
//trading hours, by Steve Hopwood and Baluda
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--) {
}//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) {
   //Calculate the lot size by risk. Code kindly supplied by jmw1970. Nice one jmw (see www.SteveHopwoodForex.com), code adapted/modified by fxdaytrader (e.g. inputs)
      
  
  //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);//to normalize and eventually set back to MODE_MINLOTS in case we have to return them now:, fxdaytrader
   if (RiskPercent==0.0) return(lots); //nothing to do ..., fxdaytrader
   if (BidAskPrice == 0.00000 || SLprice == 0.00000) return(lots);//Just in case to prevent occurring strange calculations, fxdaytrader
   
   double FreeMargin = AccountFreeMargin();
    //double TickValue = MarketInfo(symbol,MODE_TICKVALUE) ;
   //fix tickvalue for extremely rare occasion when a change in ticksize leads to a change in tickvalue, source: http://forum.mql4.com/29781, fxdaytrader
   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);//changed to double, fxdaytrader
   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) { //fxdaytrader
  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) { //fxdaytrader

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;
//nice formula/workaround, source/found at http://www.earnforex.com/blog/ordersend-error-134-no-enough-money/, fxdaytrader
  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
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////