//+------------------------------------------------------------------+
//|                                                    EverTrend.mq4 |
//|                                                Steven G. Germain |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Steven G. Germain"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue 
#property indicator_color2 Red 


//---- input parameters
extern int       TrendLinePeriod=900;
extern int       CycleSize=50;
extern bool      ShowTrendLines=TRUE;
extern bool      ShowTrendLineRays=TRUE;
extern bool      ShowTrendLinesWithInvalidPoints=TRUE;
extern bool      ShowSRLines=TRUE;
extern bool      ShowSRLinesWithInvalidPoints=TRUE;
extern bool      ShowSRArrows=TRUE;

//extern bool      ShowTrendStrength=TRUE;
//extern bool      ShowTrendLineAngle=TRUE;
//extern bool      ShowMajorTrendLines=TRUE;
//extern bool      ShowMinorTrendLines=TRUE;



//---- variables
double     SRLow=9999;
datetime   SRLowDateTime;
int        SRLowBar;

double     SRHigh=0;
datetime   SRHighDateTime;
int        SRHighBar;

string     SRMode="HIGH";

string     LineName[10000];
string     LineType[10000];
bool       LineValid[10000];

int        LineCount=0;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   SRLowDateTime=Time[1];
   SRHighDateTime=Time[1];
   
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{

   ClearVariables();
         
   return(0);
}



//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int    counted_bars=IndicatorCounted();

   ClearVariables();
 
   GetSRPoints();

   if (ShowTrendLines==true)
      DrawTrendLines();

   return(0);
}
//+------------------------------------------------------------------+
int GetSRPoints()
{
   int i;

   for (i=TrendLinePeriod;i>=1;i--)
   {
      // Lower Lows
      if (Low[i] <= SRLow){
         SRLow = Low[i];
         SRLowDateTime = Time[i];
         SRLowBar = i;
      }

      // Higher Highs
      if (High[i] >= SRHigh){
         SRHigh = High[i];
         SRHighDateTime = Time[i];
         SRHighBar = i;
      }

      // Draw the Support Line if the price has moved upwards
      if (i <= SRLowBar - CycleSize && SRMode=="LOW")
      {
         DrawHLine("S", SRLowDateTime, SRLow, STYLE_SOLID, Crimson);

         SRMode="HIGH";
         SRHigh = 0;
         SRHighDateTime = Time[i];
         SRHighBar = 0;
         
         i = SRLowBar - 1;
      } 

      // Draw the Resistance Line if the price has moved downward
      if (i <= SRHighBar - CycleSize && SRMode=="HIGH")
      {
         DrawHLine("R", SRHighDateTime, SRHigh, STYLE_SOLID, MediumSeaGreen);

         SRMode="LOW";
         SRLow = 9999;
         SRLowDateTime = Time[i];
         SRLowBar = 0;

         i = SRHighBar - 1;
      } 
   } return(0);
}



int DrawTrendLines()
{
   string Point1="NULL", Point2="NULL";
   int    LineIdx;
   string FinalLineName;

   // Draw the Support Trend Line
   for(LineIdx=1;LineIdx<=LineCount-2;LineIdx++)
   {
      if ((LineValid[LineIdx]==FALSE && ShowTrendLinesWithInvalidPoints==TRUE) || LineValid[LineIdx]==TRUE)
      {
      
         if (LineType[LineIdx]=="S")
         {
            if (Point1 == "NULL")
            {
               Point1=LineName[LineIdx];
            }else{
               Point2=LineName[LineIdx];
               FinalLineName=DrawTrendLine("TLS", Point1, Point2, STYLE_SOLID, Blue);
               Point1 = Point2;
            }
         }
      }
   }
   ObjectSet(FinalLineName,OBJPROP_RAY,TRUE);

   Point1="NULL";
   Point2="NULL";
 
   // Draw the Resistance Trend Line
   for(LineIdx=1;LineIdx<=LineCount-2;LineIdx++)
   {
      if ((LineValid[LineIdx]==FALSE && ShowTrendLinesWithInvalidPoints==TRUE) || LineValid[LineIdx]==TRUE)
      {
      
         if (LineType[LineIdx]=="R")
         {
            if (Point1 == "NULL")
            {
               Point1=LineName[LineIdx];
            }else{
               Point2=LineName[LineIdx];
               FinalLineName=DrawTrendLine("TLR", Point1, Point2, STYLE_SOLID, Blue);
               Point1 = Point2;
            }
         }
      }
   }
   ObjectSet(FinalLineName,OBJPROP_RAY,TRUE);return(0);

}


string DrawTrendLine(string TrendLineType, string Point1, string Point2, int Style, color Color)
{
   LineCount+=1;
   LineName[LineCount]=TrendLineType + "_" + DoubleToStr(LineCount,0);
   LineType[LineCount]=TrendLineType;
   LineValid[LineCount]=TRUE;

   ObjectDelete(LineName[LineCount]);

   ObjectCreate(LineName[LineCount],OBJ_TREND,0,0,0,0,0);
   ObjectSet(LineName[LineCount],OBJPROP_TIME1,ObjectGet(Point1, OBJPROP_TIME1)); //
   ObjectSet(LineName[LineCount],OBJPROP_PRICE1,ObjectGet(Point1, OBJPROP_PRICE1)); // HORIZONTAL LOW LINE
   ObjectSet(LineName[LineCount],OBJPROP_TIME2,ObjectGet(Point2, OBJPROP_TIME1)); //
   ObjectSet(LineName[LineCount],OBJPROP_PRICE2,ObjectGet(Point2, OBJPROP_PRICE1)); // HORIZONTAL LOW LINE
   ObjectSet(LineName[LineCount],OBJPROP_WIDTH,2);   
   ObjectSet(LineName[LineCount],OBJPROP_STYLE,Style);
   ObjectSet(LineName[LineCount],OBJPROP_COLOR,Color);
   ObjectSet(LineName[LineCount],OBJPROP_BACK,TRUE);
   ObjectSet(LineName[LineCount],OBJPROP_RAY,ShowTrendLineRays);
   
   return (LineName[LineCount]);
   
}



int DrawHLine(string SRLineType, datetime DayTime, double Price, int Style, color Color)
{
   LineCount+=1;
   LineName[LineCount]="LINE_" + SRLineType + "_" + DoubleToStr(LineCount,0);
   LineType[LineCount]=SRLineType;
   LineValid[LineCount]=TRUE;

   ObjectDelete(LineName[LineCount]);

   ObjectCreate(LineName[LineCount],OBJ_TREND,0,0,0,0,0);
   ObjectSet(LineName[LineCount],OBJPROP_TIME1,DayTime); //
   ObjectSet(LineName[LineCount],OBJPROP_PRICE1,Price); // HORIZONTAL LOW LINE
   ObjectSet(LineName[LineCount],OBJPROP_TIME2,Time[0]); //
   ObjectSet(LineName[LineCount],OBJPROP_PRICE2,Price); // HORIZONTAL LOW LINE
   ObjectSet(LineName[LineCount],OBJPROP_STYLE,Style);
   ObjectSet(LineName[LineCount],OBJPROP_WIDTH,2);   
   ObjectSet(LineName[LineCount],OBJPROP_COLOR,Color);
   ObjectSet(LineName[LineCount],OBJPROP_BACK,TRUE);

   // Create the lines but hide them
   if (ShowSRLines==false)
      ObjectSet(LineName[LineCount],OBJPROP_TIME2,DayTime);



   LineCount+=1;
   LineType[LineCount]="ARROW";
   LineValid[LineCount]=FALSE;
   LineName[LineCount] = "ARROW_" + SRLineType + "_" + DoubleToStr(LineCount,0);

   ObjectDelete(LineName[LineCount]);

  /* ObjectCreate(LineName[LineCount],OBJ_ARROW,0,DayTime,Price,0,0);
   ObjectSet(LineName[LineCount],OBJPROP_BACK,False);
   ObjectSet(LineName[LineCount],OBJPROP_COLOR,Color);*/

   if (ShowSRArrows==true)
   {
      if (SRLineType=="S")
      {
       //  ObjectSet(LineName[LineCount],OBJPROP_ARROWCODE,233);//SYMBOL_ARROWUP);
      }
        
      if (SRLineType=="R")
      {
       //  ObjectSet(LineName[LineCount],OBJPROP_ARROWCODE,234);//SYMBOL_ARROWDOWN);
         //ObjectSet(LineName[LineCount],OBJPROP_PRICE1,Price+(10*Point));
      }
   }else
   {
      ObjectSet(LineName[LineCount],OBJPROP_PRICE1,0); 
   }      

return(0);
}


//+------------------------------------------------------------------+
//| Clear the variables and arrays used to create the trend lines    |
//+------------------------------------------------------------------+
int ClearVariables()
{
   for(int i=1;i<=LineCount;i++)
   {
      /*
      ObjectDelete("TLS_" + DoubleToStr(LineCount,0));
      ObjectDelete("TLR_" + DoubleToStr(LineCount,0));
      ObjectDelete("ARROW_S_" + DoubleToStr(LineCount,0));
      ObjectDelete("ARROW_R_" + DoubleToStr(LineCount,0));
      ObjectDelete("LINE_S_" + DoubleToStr(LineCount,0));
      ObjectDelete("LINE_R_" + DoubleToStr(LineCount,0));
      */

      if (StringLen(LineName[i]) > 0)
         ObjectDelete(LineName[i]);

      LineName[i]=NULL;
      LineType[i]=NULL;
      LineValid[i]=NULL;
   }

return(0);

}