//+------------------------------------------------------------------+
//|                                                 forexProfits.mq4 |
//|                                   Copyright © 2007, Greg Spinner |
//|                                      mailto:greg@globeplus.co.uk |
//+------------------------------------------------------------------+
// This indicator is a partial implementation of the ideas in Jeff Wilde's Forex Profits book.
/*
The indicator checks for a "setup bar" and then reads back through the MACD histogram bars
to confirm the current trend. If a long or short signal is indicated, entry point is calculated 
as 2 pips (plus spread) above/below the high/low of the setup bar.  The take profit is 
calculated by looking for the next "big" number that is greater than the minimum specified in 
the parameters (minProfit). Stop loss is either the "stopLossDistance" or, if slBasedOnpt=true, 
potential profit / 1.5. If the price doesn't go 2 pips above the setup bar high within 5 bars, 
the signal is removed.

This indicator comes with no guarantees and any trades placed based on its signals are entirely at the users own risk.

Any errors or suggestions for improvements can be sent to the email address shown above.

*/
#property copyright "Copyright © 2007, Greg Spinner"
#property link      "mailto:greg@globeplus.co.uk"

#property indicator_chart_window

#property indicator_buffers 5
#property indicator_color1 Black
#property indicator_color2 Green
#property indicator_color3 Red
#property indicator_color4 DarkViolet
#property indicator_color5 Maroon

//---- input parameters
extern double dmaFilter=0;    // if set, will only indicate trades if high/low is above specified DMA 
extern int FastMAPeriod = 12; // parameters for MACD
extern int SlowMAPeriod = 26; // parameters for MACD
extern int SignalMAPeriod = 9;// parameters for MACD
extern string alertsOn="y";   // alerts to be displayed when new signal found?
extern int debugStartBar=0;   // debug messages will be displayed between this bar....  
extern int debugEndBar=0;     // ....and this bar. 
extern bool slBasedOnpt=true; // base stop loss on calculated take profit?
extern int stopLossDist=10;   // if previous parameter is false, always sets stop loss this number of pips away from high/low of setup bar
extern int minProfit=25;      // take profit is calculated as the next "big" number but will always be at least this number of pips away 
extern int latestBar=1;       // only indicates signals on this bar or earlier
//---- buffers
double stopLoss_Buffer[];
double enterBuyTrade_Buffer[];
double enterSellTrade_Buffer[];
double takeProfit_Buffer[];
double closeTrade_Buffer[];
//---- variables
datetime currentBarTime;
bool newBar;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IndicatorDigits(Digits + 1);
//----
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexBuffer(0,stopLoss_Buffer);
   SetIndexArrow(0,214);
   SetIndexLabel(0,"Stop loss");
//----
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexBuffer(1,enterBuyTrade_Buffer);
   SetIndexArrow(1,233);
   SetIndexLabel(1,"Enter buy stop trade");
//----
   SetIndexStyle(2,DRAW_ARROW);
   SetIndexBuffer(2,enterSellTrade_Buffer);
   SetIndexArrow(2,234);
   SetIndexLabel(2,"Enter sell stop trade");
//----
   SetIndexStyle(3,DRAW_ARROW);
   SetIndexBuffer(3,takeProfit_Buffer);
   SetIndexArrow(3,174);
   SetIndexLabel(3,"Take profit");
//----
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexBuffer(4,closeTrade_Buffer);
   SetIndexArrow(4,231);
   SetIndexLabel(4,"Trade closed");
   
   Comment("\nforexProfits ",Period(),", MACD = ",FastMAPeriod,",",SlowMAPeriod,",",SignalMAPeriod, "\nAlerts switch = ",alertsOn,", DMA Filter = ",dmaFilter);   
   
   return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   //----
   Comment("");
   return(0);
  }
//+------------------------------------------------------------------+
//| Alert method                                                     |
//+------------------------------------------------------------------+
void showAlert(string message,double price,string message2,double price2,string message3,double price3,int currentBar,int startBar,int endBar)
{
   showDebug("Show Alert current bar is "+currentBar,currentBar);
   if (alertsOn != "y") return;
   startBar = 0;
   endBar = 1;
   //Print ("newBar = ", newBar);
   
   if (!newBar) return;

   if (currentBar >= startBar && currentBar <= endBar)
   {          
      Alert(WindowExpertName(),": ",TimeToStr(Time[currentBar]), " ", Symbol(),Period(),message,price, message2, price2, message3, price3);
   }      
}
//+------------------------------------------------------------------+
//| Debug method                                                     |
//+------------------------------------------------------------------+
void showDebug(string message,int currentBar)
{
   if (debugStartBar == 0 && debugEndBar == 0) {return;}
   if (currentBar >= debugStartBar && currentBar <= debugEndBar)
   {          
      Print(WindowExpertName(),": ",Symbol(),Period()," ",TimeToStr(Time[currentBar])," Bar:",currentBar," ",message);
   }      
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   newBar=false;
   //Print ("currentBarTime = ",currentBarTime," Time[1] = ",Time[1]);
   if (currentBarTime != Time[1])
   {
      newBar = true;
      currentBarTime = Time[1];
   }
   int limit, k;
   int counted_bars = IndicatorCounted();
   //---- check for possible errors
   if(counted_bars < 0) 
       return(-1);
   //---- last counted bar will be recounted
   if(counted_bars > 0) 
       counted_bars--;
   limit = Bars - counted_bars;
   if (counted_bars<1)
   {
      while (k<Bars)
      {
         stopLoss_Buffer[k]= 0.0;
         enterBuyTrade_Buffer[k]= 0.0;
         enterSellTrade_Buffer[k]= 0.0;
         closeTrade_Buffer[k]= 0.0;
         takeProfit_Buffer[k]= 0.0;
         k++;
      }
   }
//----

   int symbolDigits = MarketInfo(Symbol(),MODE_DIGITS);
   int spread = MarketInfo(Symbol(),MODE_SPREAD);
   int multiplier = MathPow(10,symbolDigits);
   double pips2 = 2.0/multiplier;
   double pips50 = 50.0/multiplier;
   double stopLossPips = stopLossDist*1.0/multiplier;
   double spreadPips = spread*1.0/multiplier;
   double minProfitPips = minProfit*1.0/multiplier;
   double profitTarget;
   showDebug("Limit = "+limit,0);
   for(int i = limit; i >= latestBar; i--)
   {
      bool setupSell = false, setupBuy = false;
      double shadowSize, bodySize, entryPoint, bodyPerc, stopLoss;

      showDebug("Open = "+Open[i]+", Close = "+Close[i]+", High = "+High[i]+", Low = "+Low[i],i);                  
      if (Open[i] < Close[i])    //"green" bar
      {
         if (Close[i] == High[i] || Low[i] == Open [i]) {continue;}
         shadowSize = (Open[i] - Low[i]) + (High[i] - Close[i]);
      }
      else  // "red" bar
      {
         if (Close[i] == Low[i] || High[i] == Open [i]) {continue;}
         shadowSize = (Close[i] - Low[i]) + (High[i] - Open[i]);
      }
      if (shadowSize <= 0) {continue;}
      bodySize = MathAbs(Close[i] - Open[i]);
            
      if (High[i] > High[i+1] && Low[i] > Low[i+1])   //"long" setup bar
      {
         bodyPerc = bodySize / shadowSize * 100;
         showDebug("Long: Shadow = "+shadowSize+", Body = "+bodySize+", Bodyperc = "+bodyPerc,i);
         if (bodyPerc > 50) {continue;}
         setupBuy = true;
         entryPoint = High[i] + pips2 + spreadPips;
         stopLoss = Low[i] - stopLossPips;
      }
      if (High[i] < High[i+1] && Low[i] < Low[i+1])   //"short" setup bar
      {
         bodyPerc = bodySize / shadowSize * 100;
         showDebug("Short: Shadow = "+shadowSize+", Body = "+bodySize+", Bodyperc = "+bodyPerc,i);
         if (bodyPerc > 50) {continue;}
         setupSell = true;
         entryPoint = Low[i] - pips2 - spreadPips;
         stopLoss = High[i] + stopLossPips;
      }
      if (!setupBuy && !setupSell) {continue;}
      // set up bar found, now try and determine the trend
      
      bool MACDSell = false, MACDBuy = false;
      int trendUp = 0, trendDown = 0;
      showDebug("Bars = "+Bars,i);
      for (int j = i; j <= Bars; j++)
      {
         double MACDLineCurrent     = iMACD(NULL, 0, FastMAPeriod, SlowMAPeriod, SignalMAPeriod, PRICE_CLOSE, MODE_MAIN,j);
         double SignalLineCurrent   = iMACD(NULL, 0, FastMAPeriod, SlowMAPeriod, SignalMAPeriod, PRICE_CLOSE, MODE_SIGNAL,j);
         double MACDHist = MACDLineCurrent - SignalLineCurrent;
         if (MACDHist > 0) {trendUp++;}
         if (MACDHist < 0) {trendDown++;}
         showDebug("MACDHist = "+MACDHist+", trendUp = "+trendUp+", trendDown = "+trendDown,i);
         if (trendUp >= 5) 
         {
            MACDBuy = true;
            break;
         }
         if (trendDown >= 5) 
         {
            MACDSell = true;
            break;
         }
      }
      
      /*int symbolDigits = MarketInfo(Symbol(),MODE_DIGITS);
      crossoverHiLo = NormalizeDouble(crossoverHiLo,symbolDigits);
      stopLoss = NormalizeDouble(stopLoss,symbolDigits);*/
         
      double current_dmaFilterValue = 0;
      if(dmaFilter > 0)
      {
         current_dmaFilterValue=iMA(NULL,0,dmaFilter,0,MODE_SMA,PRICE_CLOSE,i);
      }      
      showDebug("setupBuy = "+setupBuy+", setupSell = "+setupSell+", MACDBuy = "+MACDBuy+", MACDSell = "+MACDSell,i);

      bool tradeTriggered=false;      
      if (setupBuy && MACDBuy)
      {
         //if (dmaFilter > 0 && Low[i] <= current_dmaFilterValue) {continue;}
         if (i>5)
         {
            for (int l=i; l>i-5; l--)
            {
               if (l==0) {break;}
               if (High[l] >= entryPoint) {tradeTriggered = true; break;}
            }
            if (!tradeTriggered) {continue;}
         }
         profitTarget = NormalizeDouble(entryPoint,symbolDigits - 2);
         showDebug("profitTarget = "+profitTarget+", ep = "+(entryPoint),i);
         if (profitTarget < entryPoint)
         {
            profitTarget = profitTarget + pips50;
         }
         if ((profitTarget - entryPoint) < minProfitPips)
         {
            profitTarget = profitTarget + pips50;
         }
         if (slBasedOnpt)
         {
            stopLoss = entryPoint - ((profitTarget - entryPoint)/1.5);
         }
         showDebug("profitTarget = "+profitTarget,i);
         profitTarget = profitTarget - pips2;
         enterBuyTrade_Buffer[i] = entryPoint;
         stopLoss_Buffer[i] = stopLoss;
         takeProfit_Buffer[i] = profitTarget;
         showAlert(": buy stop trade identified. Entry point: ",entryPoint,", stop loss: ", stopLoss,"",0.0,i,0,0);
      }      
      if (setupSell && MACDSell)
      {
         //if (dmaFilter > 0 && Low[i] <= current_dmaFilterValue) {continue;}
         if (i>5)
         {
            for (l=i; l>i-5; l--)
            {
               //showDebug("l = "+l+", Low = "+Low[l]+", entryPoint = "+entryPoint,i);
               if (l==0) {break;}
               if (Low[l] <= entryPoint) {tradeTriggered = true; break;}
            }
            if (!tradeTriggered) {continue;}
         }
         profitTarget = NormalizeDouble(entryPoint,symbolDigits - 2);
         //showDebug("profitTarget = "+profitTarget+", ep = "+(entryPoint),i);
         if (profitTarget > entryPoint)
         {
            profitTarget = profitTarget - pips50;
         }
         if ((entryPoint - profitTarget) < minProfitPips)
         {
            profitTarget = profitTarget - pips50;
         }
         if (slBasedOnpt)
         {
            stopLoss = entryPoint + ((entryPoint - profitTarget)/1.5);
         }
         //showDebug("profitTarget = "+profitTarget,i);
         profitTarget = profitTarget + pips2;
         enterSellTrade_Buffer[i] = entryPoint;
         stopLoss_Buffer[i] = stopLoss;
         takeProfit_Buffer[i] = profitTarget;
         showAlert(": sell stop trade identified. Entry point: ",entryPoint,", stop loss: ", stopLoss,"",0.0,i,0,0);
      }      
   }
//----
   return(0);
}
//+------------------------------------------------------------------+