extern int bb_period;
extern double bb_deviation,
  atr1, atr2;
extern double mult_sl, mult_trsl;
extern int start_time, end_time;
extern double lotsize = 3;
extern int magic = 0;

/*
  Enter new trade (lotsize 3) when you have a crossing of the upper or lower band.
  Exit one lot when you get atr1 * Atr50()
  Exit second lot when you get atr2 * Atr50()
  Always trail the third lot
  Trailing stop is mult_trsl * average extreme of the last 3 bars
 */

int start()
{
  if(is_open(magic) == true)
    {
      maintenance();
      return(0);
    }
  else //If there is no open trade
    {
      if(in_time() == true)
	{
	  //	  Print("Lot 1 is not open");
	  if(new_bar() == true)
	    enter_new_trade(bb_entry());
	}
    }
  //Will have to put in a call to Close_orders here if/when out of time.
}

bool in_time()
{
  if(Hour() == start_time && Hour() <= end_time)  //Friday before 0500.
    return(true);
  else
    return(false);
}


void maintenance()
{
  exit();
  trail_stop();
    
}

void exit()
{
  switch(OrderType())
    {
    case OP_BUY:
      {
	if(OrderLots() > 2)
	  {
	    if(Bid - OrderOpenPrice() > atr1 * Atr50())
	      OrderClose(OrderTicket(), 1, Bid, 3, Blue);
	    return(1);
	  }
	if(OrderLots() > 1)
	  {
	    if(Bid - OrderOpenPrice() > atr2 * Atr50())
	      OrderClose(OrderTicket(), 1, Bid, 3, Blue);
	    return(1);
	  }
      } break;
    case OP_SELL:
      {
	if(OrderLots() > 2)
	  {
	    if(OrderOpenPrice() - Ask > atr1 * Atr50())
	      OrderClose(OrderTicket(), 1, Ask, 3, Red);
	    return(1);
	  }
	if(OrderLots() > 1)
	  {
	    if(OrderOpenPrice() - Ask > atr2 * Atr50())
	      OrderClose(OrderTicket(), 1, Ask, 3, Red);
	    return(1);
	  }
      } break;

      return(0);
    }
}
	  
	  

double Atr50()
{ //This function gives SMA 50 of 1-hour atr14
  double foo = 0;

  for(int i = 0; i < 50; i++)
    {
      foo += iATR(NULL, PERIOD_M30, 14, i);
    }

  return(foo / 50);
}


bool new_bar()
{
  static datetime lastbar = 0;
  datetime currbar = Time[0];
  if(lastbar != currbar)  //Will always be true for the first run.
    {
      lastbar = currbar;
      return(true);
    }
  else
    return(false);
}

void enter_new_trade(int sig)   //To determine when to enter a new trade.
{
  switch(sig)
    {
    case -1:
      return(0);

    case 1:  //If we get a buy signal
      {

	OrderSend(Symbol(), OP_BUY, lotsize, Ask, 3, NormalizeDouble(Bid - (mult_sl * (Bid - stoploss(OP_BUY))), Digits),
		  0, "Buy at market", magic, 0, Blue);
	return(0);
      }

    case 0:  //If we get a sell signal 
      {
	OrderSend(Symbol(), OP_SELL, lotsize, Bid, 3, NormalizeDouble(Ask + (mult_sl * (stoploss(OP_SELL) - Ask)), Digits),
		  0, "Sell at market", magic, 0, Red);
	return(0);
      }
    }
}

double stoploss(int OP)
{ // This function will return the stoploss depending on the type of order and calculates the SL on the average
  // of the extrema of the last 3 bars.  This is like the Bill Poulos stop strategy (shown by pappa).

  switch(OP)
    {
    case OP_BUY:
      {
	return((Low[1] + Low[2] + Low[3])/3);
      }

    case OP_SELL:
      {
	return((High[1] + High[2] + High[3])/3);
      }
    }
}

int bb_entry()
{ // This function should give an entry order depending on whether the last bar closed outside the standard deviation
  // windows.

  // If the last open is less than the upper band, and the last close > upper band, buy
  if(Open[1] < band(OP_BUY)&&
     Close[1] > band(OP_BUY))
    {
      Print("Sending buy signal");
      return(1);
    }

  else if(Open[1] > band(OP_SELL) &&
	  Close[1] < band(OP_SELL))
    {
      Print("Sending sell signal");
      return(0);
    }
  else 
    return(-1);
}

double band(int sig)
{ // This should return the upper and lower band of the Bollinger, as a multiple of the standard deviation.
  switch(sig)
    {
    case OP_BUY:
      {
	return(iMA(NULL, 0, bb_period, 0, MODE_SMA, PRICE_CLOSE, 1) + bb_deviation
	       * (iBands(NULL, 0, bb_period, 1, 0, PRICE_CLOSE, MODE_UPPER, 1) 
		  - iMA(NULL, 0, bb_period, 0, MODE_SMA, PRICE_CLOSE, 1)));
      }
    case OP_SELL:
      {
	return(	iMA(NULL, 0, bb_period, 0, MODE_SMA, PRICE_CLOSE, 1) - bb_deviation 
		* (iMA(NULL, 0, bb_period, 0, MODE_SMA, PRICE_CLOSE, 1) 
		   - iBands(NULL, 0, bb_period, 1, 0, PRICE_CLOSE, MODE_LOWER, 1)));
      }
    }
}

bool is_open(int mgc)
{
  for(int trade = 0; trade < OrdersTotal(); trade++)
    {
      OrderSelect(trade, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == mgc)
	{
	  return(true);
	}  //End magic check.
    }  //End for loop.
  return(false);
}

double trail_stop()
{  //This function will adjust the trailing stops as required.
   //This function must be called only after the order has been selected.

  double TrSL = OrderStopLoss();
   
  switch(OrderType())
    {
    case OP_BUY:
      { 
	if(stoploss(OP_BUY) > TrSL)
	  {
	    OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid - (mult_trsl * (Bid - stoploss(OP_BUY)))
									 , Digits),
			OrderTakeProfit(), 0, Red);
	    Print("Modified buy stop-loss");
	    TrSL = stoploss(OP_BUY);
	  }

      }break;
      
    case OP_SELL:
      {  
	if(stoploss(OP_SELL) < TrSL)
	  {
	    OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask + (mult_trsl * (stoploss(OP_SELL) - Ask))
									 , Digits),
			OrderTakeProfit(), 0, Red);
	    Print("Modified sell stop-loss");
	    TrSL = stoploss(OP_SELL);
	  }

      }break;
    }
  //  Print("The new order parameters are: Stoploss = ", TrSL);
  return(TrSL);
}
