//+------------------------------------------------------------------+
//|                                           Candle Color EA.mq4    |
//|                                           Copyright © 2013, Zool |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, Zool"
#define  NL    "\n"
#define  up "Up"
#define  down "Down"
#define  none "None"

extern string com1="-- The nuber of same color candles needed to open a trade --";
extern int CandleCount=1;
extern string com3="-- Filters --";
extern bool UseDistanceFiltering=false;
extern int MinDistancePips=10;
extern string com4="-- If lotsize=0 then trade volume will be calculated based on the risk value --";
extern double LotSize=0;
extern string com5="-- Risk and SL based lot sizing % --";
extern double TradeRisk=1;
extern string com6="-- ATR use for SL calculation --";
extern bool UseATRSL=true;
extern int ATRPeriods=20;
extern int ATRtimeframe=0;
extern double ATRMultiplier=2;
extern string com7="-- If ATR SL is false, then this is the fixed SL value --";
extern int StopLossPips=50;
extern string com8="-------------";
extern int MagicNumber=12345;
extern int      DisplayGapSize=30;
extern int      Takeprofit=30;

datetime lastcheck;
string Gap, ScreenMessage;

//double CurrentATR;
double UnitSizing;
double ActualSL;
int digitmultiplier;

string         TradeDirection;

int init()
  {
   manageupperstatus("Candle Color Trader - CR 2013");
   if (Digits==5 || Digits==3) digitmultiplier=10; else digitmultiplier=1;
   return(0);
   Gap="";

   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }
  }

int deinit()
  {
  return(0);
  }

int start()
  {
  if(lastcheck<iTime(NULL,0,0))
   {
      lastcheck=iTime(NULL,0,0);
      CalculateValues();
      LookForClose();
      if (IsTradingAllowed()) LookForTrades();
   }
   DisplayUserFeedback();
   return(0);
  }

void LookForClose()
   {
   double prevopen=Open[1];
   double prevclose=Close[1];
   if ((CountLongPositions()>0) && (prevopen>prevclose)) CloseLongPositions();
   if ((CountShortPositions()>0) && (prevopen<prevclose)) CloseShortPositions();
   }
   
   
bool TooClose()
   {
   int totalorders=OrdersTotal();
   int orderscroll;
   bool result=false;
   for(orderscroll=0;orderscroll<totalorders;orderscroll++)
      {
      OrderSelect(orderscroll,SELECT_BY_POS,MODE_TRADES);
      if( (OrderSymbol()==Symbol()) && (OrderMagicNumber()==MagicNumber) )
         {
         if ( MathAbs(OrderOpenPrice()-Bid)<(MinDistancePips*Point*digitmultiplier) ) result=true;
         }
      }
   return(result);   
   }

bool IsTradingAllowed()
   {
   bool IsItTooClose=false;
   bool result=true;
   if (UseDistanceFiltering) IsItTooClose=TooClose();
   if (IsItTooClose) {result=false;} 
   return(result);
   }

bool DirectionSignal()
{
   int cc;
   TradeDirection = up;
   for (cc = 1; cc <= CandleCount; cc++)
   {
         if (Close[cc] < Open[cc] )
         {
            TradeDirection = none; break;
         }
   }
   if (TradeDirection == up) return(true);
   TradeDirection = down;
   for (cc = 1; cc <= CandleCount; cc++)
   {
         if (Close[cc] > Open[cc] )
         {
            TradeDirection = none; break;
         }
   } 
   if (TradeDirection == down) return(true);
   TradeDirection = none;
   return(false);
}

void CalculateValues()
   {
      string symb = Symbol();
      double MinLot = MarketInfo(symb,MODE_MINLOT);
      double CurrentATR=iATR(Symbol(),ATRtimeframe,ATRPeriods,1)*ATRMultiplier;
      if (UseATRSL) ActualSL=CurrentATR; else ActualSL=StopLossPips*Point*digitmultiplier;
      UnitSizing=((AccountBalance()*(TradeRisk/100))/(ActualSL/Point)/MarketInfo(Symbol(),MODE_TICKVALUE));
      if (LotSize>0) UnitSizing=LotSize;
      if (UnitSizing < MinLot) UnitSizing = MinLot;
      UnitSizing=NormalizeDouble(UnitSizing,2);
   }

void LookForTrades()
   {
   if(DirectionSignal() && (TradeDirection == up))
      {
      CloseShortPositions();
      OpenLongPositions();
      }
   
   if(DirectionSignal() && (TradeDirection == down))
      {
      CloseLongPositions();
      OpenShortPositions();
      }
   }

void manageupperstatus(string addstatus)
   {
   ObjectDelete("Upper_Status");
   if(addstatus!="")
      {
      ObjectCreate("Upper_Status", OBJ_LABEL, 0, 0, 0);
      ObjectSet("Upper_Status", OBJPROP_CORNER,1);
      ObjectSet("Upper_Status", OBJPROP_XDISTANCE, 2);
      ObjectSet("Upper_Status", OBJPROP_YDISTANCE, 13);
      ObjectSetText("Upper_Status", addstatus, 9, "Verdana", White);
      }
   }

void OpenLongPositions()
   {
   int ticket;
double CurrentATR;
   ticket=OrderSend(Symbol(),OP_BUY,UnitSizing,Ask,0,0,0,NULL,MagicNumber,0,Blue);
   OrderSelect(ticket, SELECT_BY_TICKET);
   OrderModify(OrderTicket(), OrderOpenPrice(), LongStopLoss(Ask, CurrentATR),Takeprofit*Point*digitmultiplier, 0, CLR_NONE);
   }

void OpenShortPositions()
   {
   int ticket;
   double CurrentATR;
   ticket=OrderSend(Symbol(),OP_SELL,UnitSizing,Bid,0,0,0,NULL,MagicNumber,0,Red);
   OrderSelect(ticket, SELECT_BY_TICKET);
   OrderModify(OrderTicket(), OrderOpenPrice(), ShortStopLoss(Bid,CurrentATR), Takeprofit*Point*digitmultiplier, 0, CLR_NONE);
   }
   
double LongStopLoss(double StartPrice, double CurrentATR)
   {
   double result;
   if ( (!UseATRSL) && (StopLossPips==0)) return(0);
   result=StartPrice-ActualSL;
   result=NormalizeDouble(result,Digits);
   return(result);
   }
   
double ShortStopLoss( double StartPrice,double CurrentATR)
   {
   double result;
   if ( (!UseATRSL) && (StopLossPips==0)) return(0);
   result=StartPrice+ActualSL;
   result=NormalizeDouble(result,Digits);
   return(result);
   }
   
void CloseLongPositions()
   {
   int totalorders=OrdersTotal();
   int orderscroll;
   for(orderscroll=0;orderscroll<totalorders;orderscroll++)
      {
      OrderSelect(orderscroll,SELECT_BY_POS,MODE_TRADES);
      if((OrderSymbol()==Symbol())&&(OrderMagicNumber()==MagicNumber)&&((OrderType()==OP_BUY)))
         {
         OrderClose(OrderTicket(),OrderLots(),Bid,0,Blue);
         }
      }
   }
   
int CountLongPositions()
   {
   int totalorders=OrdersTotal();
   int orderscroll;
   int result=0;
   for(orderscroll=0;orderscroll<totalorders;orderscroll++)
      {
      OrderSelect(orderscroll,SELECT_BY_POS,MODE_TRADES);
      if((OrderSymbol()==Symbol())&&(OrderMagicNumber()==MagicNumber)&&((OrderType()==OP_BUY)))
         {
         result++;
         }
      }
   return(result);
   }
 
void CloseShortPositions()
   {
   int totalorders=OrdersTotal();
   int orderscroll;
   for(orderscroll=0;orderscroll<totalorders;orderscroll++)
      {
      OrderSelect(orderscroll,SELECT_BY_POS,MODE_TRADES);
      if((OrderSymbol()==Symbol())&&(OrderMagicNumber()==MagicNumber)&&((OrderType()==OP_SELL)))
         {
         OrderClose(OrderTicket(),OrderLots(),Ask,0,Blue);
         }
      }
   }   

int CountShortPositions()
   {
   int totalorders=OrdersTotal();
   int orderscroll;
   int result=0;
   for(orderscroll=0;orderscroll<totalorders;orderscroll++)
      {
      OrderSelect(orderscroll,SELECT_BY_POS,MODE_TRADES);
      if((OrderSymbol()==Symbol())&&(OrderMagicNumber()==MagicNumber)&&((OrderType()==OP_SELL)))
         {
         result++;
         }
      }
   return(result);
   }

void DisplayUserFeedback()
{  
double CurrentATR;
   ScreenMessage = "";
   SM(NL);
   SM("Candle Color Trading EA" + NL);
   //SM("local  time: "+TimeToStr(TimeLocal() + TIME_DATE|TIME_MINUTES|TIME_SECONDS) + NL );
   //SM("server time: "+TimeToStr(TimeCurrent() + TIME_DATE|TIME_MINUTES|TIME_SECONDS) + NL );
   SM("+---------+ general information and settings:" + NL);    
   SM("Current ATR with multiplier: " + DoubleToStr(CurrentATR/Point/digitmultiplier,0) + " (multiplier: " + DoubleToStr(ATRMultiplier,2) + ")" + NL );
   SM("Current stop loss: " + DoubleToStr(ActualSL/Point/digitmultiplier,0) + NL);
   SM("Current lot size: " + DoubleToStr(UnitSizing,2) + NL);
   SM("Magic number: " + MagicNumber + NL);
   string OpenOrderTypes = "";
   int OpenTrades=CountLongPositions()+CountShortPositions();
   if (CountLongPositions()>0)              OpenOrderTypes = StringConcatenate(OpenOrderTypes," Buy");
   if (CountShortPositions()>0)             OpenOrderTypes = StringConcatenate(OpenOrderTypes," Sell");
   SM(Gap + NL);
   SM("open trades: " + OpenTrades + " | types: "+OpenOrderTypes+ NL);
   SM(NL);
   double spread = (Ask - Bid); 
   double LongSwap = MarketInfo(Symbol(),MODE_SWAPLONG);  
   double ShortSwap = MarketInfo(Symbol(),MODE_SWAPSHORT);  
   SM("Spread = " + DoubleToStr(spread, 1) + " | LongSwap " + DoubleToStr(LongSwap, 2) + ": ShortSwap " + DoubleToStr(ShortSwap, 2) + NL);
   SM(NL);
   SM("+---------------------------------------------------------------+" + NL);
   Comment(ScreenMessage);
}

void SM(string message)
{
   ScreenMessage = StringConcatenate(ScreenMessage,Gap,message);
}