
// EA written by TheBrigadier on ForexFactory
// Based on system designed by supercat1977

#property copyright "EA by TheBrigdier, Tiger Trend Trading by supercat1977."
#property link      "http://www.forexfactory.com/showthread.php?t=365794"

extern string Seperator1 = "************EMA Settings************";
extern int ShortEMA = 3;
extern int LongEMA = 5;
extern int FastShortEMA = 3;
extern int FastLongEMA = 5;
extern int PeriodShort = PERIOD_M15;
extern int PeriodLong = PERIOD_D1;
extern int Type = MODE_EMA;
extern string Seperator2 = "************Lot Management************";
extern double Lots = 0.01;
extern int Slippage = 3;
extern double MinimumMargin = 0.65;
extern string Seperator3 = "************Stop Loss************";
extern double StopLossType = 0;
extern double Padding = 150;
extern double StopLossPeriod = PERIOD_D1;
extern double MaxStopLoss = 5000;
extern double HardStopLoss = 200;
extern string Seperator4 = "*************Partial Trades*****************";
extern bool CloseHalfAtBreakEven = false;
extern string Seperator5 = "Only place trades outside of a range";
extern int RangeUp = 0;
extern int RangeDown = 0;


string symbol;
bool is_a_trade_open;
int daily_bars;
int five_bars;
bool daily_trend_down;
bool daily_trend_up;
int BarOfLastTrade;
double range_value;
int PARTIAL_CLOSE_MARKER;

/* Initialize  */
int init()
  {
      symbol = Symbol();
      BarOfLastTrade = 0;
      daily_trend_down = false;
      daily_trend_up = false;
      determine_initial_daily_trend();
      PARTIAL_CLOSE_MARKER = 9900;
  }

/* Unused  */
int deinit(){return(0);}

/* Let's do this  */
int start()
  {
   bool did_trend_just_change = false;
   bool old_trend_up = daily_trend_up;
   
   /* Get the daily trend direction */
   daily_trend_direction(); 
   if (old_trend_up != daily_trend_up)
   {
      did_trend_just_change = true;
   }   
   
   if (CloseHalfAtBreakEven)
   partial_close_from_signal();
   
   /* Close any open trades upon receiving a signal */
   close_trades_from_signal();

   /* Trade only once per bar  */
   if(BarOfLastTrade + 1 < iBars(Symbol(), PeriodShort))
   {
     int ticket = -1;
     if (daily_trend_up && ma_buy_signal() && enough_margin() && passed_range(true, did_trend_just_change))
     {
         double buy_sl = get_buy_stop_loss();
         if (CloseHalfAtBreakEven)
         {
            OrderSend(Symbol(), OP_BUY, get_lot_size()/2, Ask, Slippage, buy_sl, 0, "buy", 1, 0, Green);
            OrderSend(Symbol(), OP_BUY, get_lot_size()/2, Ask, Slippage, buy_sl, Ask + PARTIAL_CLOSE_MARKER*Point, "buy", 1, 0, Green);
         }
         else
            ticket = OrderSend(Symbol(), OP_BUY, get_lot_size(), Ask, Slippage, buy_sl, 0, "buy", 1, 0, Green);
            
         if (ticket != -1)   
             BarOfLastTrade = iBars(Symbol(), 0);
         range_value = Ask;
     }
     if (daily_trend_down && ma_sell_signal() && enough_margin() && passed_range(false, did_trend_just_change))
     {
        double sell_sl = get_sell_stop_loss();
        if (CloseHalfAtBreakEven)
        {
            OrderSend(Symbol(), OP_SELL, get_lot_size()/2, Bid, Slippage, sell_sl, 0, "sell", 1, 0, Red);
            OrderSend(Symbol(), OP_SELL, get_lot_size()/2, Bid, Slippage, sell_sl, Bid - PARTIAL_CLOSE_MARKER*Point, "sell", 1, 0, Red);
        }
        else
            ticket = OrderSend(Symbol(), OP_SELL, get_lot_size(), Bid, Slippage, sell_sl, 0, "sell", 1, 0, Red);   
        
        if (ticket != -1)   
            BarOfLastTrade = iBars(Symbol(), PeriodShort);
        range_value = Bid;
     } 
   }   

   return(0);
}

/* Close open trades when we catch the appropriate signal  */
void close_trades_from_signal()
{
   for (int i = 0; i < OrdersTotal(); i++)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if (OrderType() == OP_SELL  && OrderSymbol() == Symbol() && daily_trend_up)
            OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Blue);
         
         else if (OrderType() == OP_BUY  && OrderSymbol() == Symbol() && daily_trend_down)
            OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Blue);
      }      
   }
} 
 
/* Close half the trades at the violation of a daily high or low  */
void partial_close_from_signal()
{
   for (int i = 0; i < OrdersTotal(); i++)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         Print(MathAbs(OrderOpenPrice() - OrderTakeProfit()), "     ", PARTIAL_CLOSE_MARKER*Point, "  ", MathAbs(OrderOpenPrice() - OrderTakeProfit()) - PARTIAL_CLOSE_MARKER*Point < 0.01);
         if (OrderType() == OP_SELL  && OrderSymbol() == Symbol() && (MathAbs(OrderOpenPrice() - OrderTakeProfit() - PARTIAL_CLOSE_MARKER*Point) < 0.01) && Ask > iHigh(Symbol(), PeriodLong, 1))
            OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Green);
         else if (OrderType() == OP_BUY  && OrderSymbol() == Symbol() && (MathAbs(OrderTakeProfit() - OrderOpenPrice() - PARTIAL_CLOSE_MARKER*Point) < 0.01) && Bid < iLow(Symbol(), PeriodLong, 1))
            OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Green);
      }  
   }    
    
} 
 
/* Did a buy signal occur on the previous candle? */
/* If so return true, else return false  */
bool ma_buy_signal()
{        
      double ma_short =    iMA(symbol, PeriodShort, FastShortEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_short_pr = iMA(symbol, PeriodShort, FastShortEMA, 0, Type, PRICE_CLOSE, 2);
      double ma_long =     iMA(symbol, PeriodShort, FastLongEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_long_pr =  iMA(symbol, PeriodShort, FastLongEMA, 0, Type, PRICE_CLOSE, 2);
      
      if (ma_short_pr < ma_long_pr && ma_short > ma_long) 
         return (true);
      else 
         return (false);
}   

/* Did a sell signal occur on the previous candle? */
/* If so return true, else return false  */
bool ma_sell_signal()
{        
      double ma_short =    iMA(symbol, PeriodShort, FastShortEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_short_pr = iMA(symbol, PeriodShort, FastShortEMA, 0, Type, PRICE_CLOSE, 2);
      double ma_long =     iMA(symbol, PeriodShort, FastLongEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_long_pr =  iMA(symbol, PeriodShort, FastLongEMA, 0, Type, PRICE_CLOSE, 2);
      
      if (ma_short_pr > ma_long_pr && ma_short < ma_long) 
         return (true);
      else 
         return (false);
}

/* Did a buy signal occur on the previous candle? */
/* If so return true, else return false  */
void daily_trend_direction()
{        
      double ma_short =    iMA(symbol, PeriodLong, ShortEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_short_pr = iMA(symbol, PeriodLong, ShortEMA, 0, Type, PRICE_CLOSE, 2);
      double ma_long =     iMA(symbol, PeriodLong, LongEMA, 0, Type, PRICE_CLOSE, 1);
      double ma_long_pr =  iMA(symbol, PeriodLong, LongEMA, 0, Type, PRICE_CLOSE, 2);
      
      if (ma_short_pr < ma_long_pr && ma_short > ma_long) 
      {
         daily_trend_up = true;
         daily_trend_down = false;
      }
      else if (ma_short_pr > ma_long_pr && ma_short < ma_long)
      {
         daily_trend_up = false;
         daily_trend_down = true;
      }   
}   

void determine_initial_daily_trend()
{
      double ma_short =    iMA(symbol, PeriodLong, ShortEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
      double ma_long =     iMA(symbol, PeriodLong, LongEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
      
      if (ma_short < ma_long)
      {
         daily_trend_up = false;
         daily_trend_down = true;
      }
      else
      {
         daily_trend_up = true;
         daily_trend_down = false;
      }
}               

double get_sell_stop_loss()
{
   if (StopLossType == 0) /* hard stop loss  */
      return (Ask + HardStopLoss*Point);
   else if (StopLossType == 1) /* stop loss at the high of the current candle  */
      return (iHigh(Symbol(), StopLossPeriod, 0) + Padding*Point);
   else
      return (previous_high_stop_loss()); /* stop loss at the high of the previous candle  */
}

double previous_high_stop_loss()
{
   double prev_daily_high = iHigh(Symbol(), StopLossPeriod, 1); 
   if (prev_daily_high > Ask && prev_daily_high + Padding*Point - Ask < MaxStopLoss*Point)
      return (prev_daily_high + Padding*Point);
   else
      return (Ask + HardStopLoss*Point);   
}

double get_buy_stop_loss()
{
   if (StopLossType == 0)
      return (Bid - HardStopLoss*Point); /* hard stop loss  */
   else if (StopLossType == 1)
      return (iLow(Symbol(), StopLossPeriod, 0) - Padding*Point); /* stop loss at the low of the current candle  */
   else
      return (previous_low_stop_loss()); /* stop loss at the low of the previous candle  */
}
      
double previous_low_stop_loss()
{
   double prev_daily_low = iLow(Symbol(), StopLossPeriod, 1);
   if (prev_daily_low < Bid && Bid - prev_daily_low - Padding*Point < MaxStopLoss*Point)
      return (prev_daily_low - Padding*Point);
   else
      return (Bid - HardStopLoss*Point);   
}

double get_lot_size()
{
       return (Lots);
}

bool passed_range(bool buy, bool trend_change)
{
   if (trend_change) 
      return (true);
   if (buy && (Ask > range_value + RangeUp*Point || Ask < range_value - RangeDown*Point))
      return (true);
   else if (!buy && (Bid > range_value + RangeUp*Point || Bid < range_value - RangeDown*Point))
      return (true);
   else
      return (false);
}

/* Does the account have more free margin then the specified percent?  */
bool enough_margin()
{
   return (AccountFreeMargin() > AccountBalance()*MinimumMargin);
}

double spread()
{
   return (Ask - Bid);
}    