//+------------------------------------------------------------------+
//|                                     smPA_PriceRetracement_v1.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010.08.08, SwingMan"
#property link      ""

#property indicator_chart_window

//---- input parameters
//+------------------------------------------------------------------+
extern bool Use_OpenClose = false;
extern int Max_RetracementBars = 10;
extern string ____Trend = "";
extern int Period_Avg = 13;
extern int Shift =0;
extern int Mode = MODE_EMA;
extern int Length_AvgSlope = 1;
extern int Length_Over = 2;
extern int Applied_Price = PRICE_MEDIAN;
extern string ____RetraceLines = "";
//extern bool Draw_AllLines = true;
extern int Line_Width = 1;
extern color LongRetrace_Color = MediumTurquoise;
extern color ShortRetrace_Color = Magenta;
extern int maxBars = 1500;
extern string ____Info = "";
extern string __ModeAverages  = "0=SMA,1=EMA,2=SSMA,3=LWMA";
extern string __AppliedPrices = "0=C,2=H,3=L,4=med,5=typ,6=weig";
//+------------------------------------------------------------------+



//---- variables
double oneTick;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   //---- name for DataWindow and indicator subwindow label
   string short_name="SwingMan PriceRetracement_v1";
   IndicatorShortName(short_name);
   SetIndexLabel(0,short_name);
   Comment(short_name);
   
   
   oneTick = 1/(MathPow(10,Digits));
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   Comment("");
   ObjectsDeleteAll(0,OBJ_RECTANGLE);
   ObjectsDeleteAll(0,OBJ_TREND);
   return(0);
}

//####################################################################
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int limit, j, hilo;
   datetime time1, time2, timeBar;
   double price1, price2;
   bool bControlLine;
   color dColor;
   
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;

   //---- main loop
   for(int i=0; i<limit; i++)
   {      
      if (i < maxBars) 
      {
         // trend
         double avg0= iMA(Symbol(),Period(), Period_Avg,Shift,Mode,Applied_Price,i);
         double avg1= iMA(Symbol(),Period(), Period_Avg,Shift,Mode,Applied_Price,i+Length_AvgSlope);
         bControlLine = false;
         
         // LONG trend
         if (avg0>avg1)
         {
            dColor=LongRetrace_Color;
            if (Use_OpenClose)
               bControlLine = IsRetraceLong_OpenClose(i, time1, price1, time2, price2, timeBar);
            else 
               bControlLine = IsRetraceLong_HighLow(i, time1, price1, time2, price2, timeBar);
         }
         else
         // SHORT trend
         if (avg0<avg1)
         {
            dColor=ShortRetrace_Color;
            if (Use_OpenClose)
               bControlLine = IsRetraceShort_OpenClose(i, time1, price1, time2, price2, timeBar);
            else 
               bControlLine = IsRetraceShort_HighLow(i, time1, price1, time2, price2, timeBar);
         }

         if (bControlLine) 
            Draw_PriceControlLine(time1, price1, time2, price2, timeBar, dColor);
      }   
   } //<- for i   
//----
   return(0);
}
//+------------------------------------------------------------------+
//####################################################################

//___________________________________________________________________
double HighOC(int iBar)
{
   double maxValue=MathMax(Open[iBar], Close[iBar]);
   return(maxValue);
}

//___________________________________________________________________
double LowOC(int iBar)
{
   double minValue=MathMin(Open[iBar], Close[iBar]);
   return(minValue);
}

                        //***************************************
                        //    RETRACE IN LONG TREND             *
                        //***************************************                        
//___________________________________________________________________
bool IsRetraceLong_OpenClose(int iBar, datetime& time1, double& price1, datetime& time2, double& price2, datetime& timeBar)
{
int nIntervals, j,k, iBar1;
double maxValue1, maxValue2;
bool bMatchShape;
  
   time2    =Time[iBar];   
   maxValue2=HighOC(iBar);
   price2 = maxValue2;
   timeBar = time2;
   
   j=Max_RetracementBars;

   // loop for bars
   for (j=Max_RetracementBars-1; j>=3; j--) 
   {
      nIntervals = j;
      time1    = Time[iBar+j];
      maxValue1=HighOC(iBar+j);      
      price1  = maxValue1;
      iBar1   = iBar+j;
      double slopeStep=(maxValue2-maxValue1)/nIntervals;
      
      if (slopeStep<0)
      {
         bMatchShape = true;         
         for (k=j-1; k>=1; k--)
         {
            double limitValue=maxValue1+(j-k)*slopeStep;
            if (HighOC(iBar+k)>limitValue)     
            {
               bMatchShape = false;
               break;
            }   
         }
         // retrace is available
         if (bMatchShape)
         {
            time1  = Time[iBar1+Length_Over];
            price1 = price1 - slopeStep*Length_Over;
            //--
            if (iBar>Length_Over-1)
            {
               time2  = Time[iBar-Length_Over];
               price2 = price2 + slopeStep*Length_Over;
            }   
            return(true);
         }   
      }
   }
   return(false);
}//IsRetraceLong_OpenClose
                        
//___________________________________________________________________
bool IsRetraceLong_HighLow(int iBar, datetime& time1, double& price1, datetime& time2, double& price2, datetime& timeBar)
{
int nIntervals, j,k, iBar1;
double maxValue1, maxValue2;
bool bMatchShape;
  
   time2    =Time[iBar];   
   maxValue2=High[iBar];
   price2  = maxValue2;
   timeBar = time2;
   
   j=Max_RetracementBars;

   // loop for bars
   for (j=Max_RetracementBars-1; j>=3; j--) 
   {
      nIntervals = j;
      time1    = Time[iBar+j];
      maxValue1= High[iBar+j];      
      price1  = maxValue1;
      iBar1   = iBar+j;
      double slopeStep=(maxValue2-maxValue1)/nIntervals;
      
      if (slopeStep<0)
      {
         bMatchShape = true;         
         for (k=j-1; k>=1; k--)
         {
            double limitValue=maxValue1+(j-k)*slopeStep;
            if (High[iBar+k]>limitValue)
            {
               bMatchShape = false;
               break;
            }   
         }
         // retrace is available
         if (bMatchShape)
         {
            time1  = Time[iBar1+Length_Over];
            price1 = price1 - slopeStep*Length_Over;
            //--
            if (iBar>Length_Over-1)
            {
               time2  = Time[iBar-Length_Over];
               price2 = price2 + slopeStep*Length_Over;
            }   
            return(true);
         }   
      }
   }
   return(false);
}//IsRetraceLong_HighLow

                        //***************************************
                        //    RETRACE IN SHORT TREND            *
                        //***************************************                        
//___________________________________________________________________
bool IsRetraceShort_OpenClose(int iBar, datetime& time1, double& price1, datetime& time2, double& price2, datetime& timeBar)
{
int nIntervals, j,k, iBar1;
double minValue1, minValue2;
bool bMatchShape;
  
   time2=Time[iBar];   
   minValue2=LowOC(iBar);
   price2  = minValue2;
   timeBar = time2;
   
   j=Max_RetracementBars;

   // loop for bars
   for (j=Max_RetracementBars-1; j>=3; j--) 
   {
      nIntervals = j;
      time1    = Time[iBar+j];
      minValue1=LowOC(iBar+j);      
      price1  = minValue1;
      iBar1   = iBar+j;
      double slopeStep=(minValue2-minValue1)/nIntervals;
      
      if (slopeStep>0)
      {
         bMatchShape = true;         
         for (k=j-1; k>=1; k--)
         {
            double limitValue=minValue1+(j-k)*slopeStep;
            if (LowOC(iBar+k)<limitValue) 
            {    
               bMatchShape = false;
               break;
            }   
         }
         // retrace is available
         if (bMatchShape)
         {
            time1  = Time[iBar1+Length_Over];
            price1 = price1 - slopeStep*Length_Over;
            //--
            if (iBar>Length_Over-1)
            {
               time2  = Time[iBar-Length_Over];
               price2 = price2 + slopeStep*Length_Over;
            }   
            return(true);
         }   
      }
   }
   return(false);
}//IsRetraceShort_OpenClose
                        
//___________________________________________________________________
bool IsRetraceShort_HighLow(int iBar, datetime& time1, double& price1, datetime& time2, double& price2, datetime& timeBar)
{
int nIntervals, j,k, iBar1;
double minValue1, minValue2;
bool bMatchShape;
  
   time2    =Time[iBar];   
   minValue2=Low[iBar];
   price2  = minValue2;
   timeBar = time2;
   
   j=Max_RetracementBars;

   // loop for bars
   for (j=Max_RetracementBars-1; j>=3; j--) 
   {
      nIntervals = j;
      time1    = Time[iBar+j];
      minValue1= Low[iBar+j];      
      price1  = minValue1;
      iBar1   = iBar+j;
      double slopeStep=(minValue2-minValue1)/nIntervals;
      
      if (slopeStep>0)
      {
         bMatchShape = true;         
         for (k=j-1; k>=1; k--)
         {
            double limitValue=minValue1+(j-k)*slopeStep;
            if (Low[iBar+k]<limitValue)     
            {
               bMatchShape = false;
               break;
            }   
         }
         // retrace is available
         if (bMatchShape)
         {
            time1  = Time[iBar1+Length_Over];
            price1 = price1 - slopeStep*Length_Over;
            //--
            if (iBar>Length_Over-1)
            {
               time2  = Time[iBar-Length_Over];
               price2 = price2 + slopeStep*Length_Over;
            }   
            return(true);
         }   
      }
   }
   return(false);
}//IsRetraceShort_HighLow


//###################################################################
//___________________________________________________________________
void Draw_PriceControlLine(datetime time1, double price1, datetime time2, double price2, datetime timeBar, color dColor)
{
string objName;
   objName = "RLine_"+
             TimeToStr(timeBar,TIME_DATE|TIME_MINUTES);//+"_"+

   if (ObjectFind(objName) == -1) 
   {      
      ObjectCreate(objName, OBJ_TREND,0,time1,price1,time2,price2);
      ObjectSet(objName, OBJPROP_WIDTH,Line_Width); 
      ObjectSet(objName, OBJPROP_COLOR,dColor);
      ObjectSet(objName, OBJPROP_BACK,true);
      ObjectSet(objName, OBJPROP_RAY,false);
   }
   return;
   
   /*if (Draw_AllLines)
      objName = "RLine_"+
                  //TimeToStr(time1,TIME_DATE|TIME_MINUTES);//+"_"+
                  TimeToStr(time2,TIME_DATE|TIME_MINUTES);//+"_"+
                  //DoubleToStr(price1,Digits)+"_"+
                  //DoubleToStr(price2,Digits);
   else
      objName = "RLine_"+
                  TimeToStr(time1,TIME_DATE|TIME_MINUTES);//+"_"+
                  //TimeToStr(time2,TIME_DATE|TIME_MINUTES);//+"_"+
                  //DoubleToStr(price1,Digits)+"_"+
                  //DoubleToStr(price2,Digits);*/
}

