#property copyright "Don Isbell"
#property link      "disbellj@gmail.com"

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Magenta
#property indicator_color2 Aqua
#property indicator_width1 2
#property indicator_width2 2

extern bool Show_Trendlines_For_Next_Trend = True;
extern color UpTrendLine_Color = Green;
extern color DownTrendLine_Color = Orange;
extern bool Show_UpTrend_Lows = True;
extern bool Show_DownTrend_Highs = True;
extern bool Use_Close_vs_This_High_or_Low = False;
extern double NoMM_Lots = 0.1;
//---- Don's Money Management input parameters
extern string DonsMM = "Dons Money Management for Number of Lots";
extern bool  UseDonsMM = True;
extern double RISK_PERCENT = 2.0;

double TickSize,TickValue,Pip,PipValue;
int LotsRoundTo,RoundTo;
double Semafor_0,Semafor_1,Semafor_2,Semafor_3,Semafor_4,Semafor_5;
bool TopSemafor1,TopSemafor2,TopSemafor3,BottomSemafor1,BottomSemafor2,BottomSemafor3;
double LastTopSemafor1value,LastTopSemafor2value,LastTopSemafor3value,LastBottomSemafor1value,LastBottomSemafor2value,LastBottomSemafor3value,Spread,StopLossLevel,StopLoss;
datetime LastTopSemafor1time,LastTopSemafor2time,LastTopSemafor3time,LastBottomSemafor1time,LastBottomSemafor2time,LastBottomSemafor3time;
double myLots;

//---- buffers
double DowntrendHighs[];
double UptrendLows[]; 

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//----
   SetIndexBuffer(0,DowntrendHighs);
   SetIndexLabel(0,""+NULL+" Downtrend Highs");
   SetIndexStyle(0,DRAW_LINE);

   SetIndexBuffer(1,UptrendLows);
   SetIndexLabel(1,""+NULL+" Uptrend Lows");
   SetIndexStyle(1,DRAW_LINE);
   
   TickSize = MarketInfo(Symbol(),MODE_TICKSIZE);
   TickValue = MarketInfo(Symbol(),MODE_TICKVALUE);
   
   //Figure out what a pip and its value is on this broker
      if(TickSize == 0.01 || TickSize == 0.0001) {
      Pip = TickSize;
      PipValue = TickValue;
      } else if(TickSize == 0.001 || TickSize == 0.00001) {
      Pip = TickSize*10;
      PipValue = TickValue*10;
      } 
   
   if(MarketInfo(Symbol(),MODE_LOTSIZE) == 100000) {
   LotsRoundTo = 2;
   } else if(MarketInfo(Symbol(),MODE_LOTSIZE) == 10000) {
   LotsRoundTo = 1;
   } else if(MarketInfo(Symbol(),MODE_LOTSIZE) == 1000) {
   LotsRoundTo = 0;
   }
   
   if(Point == 0.01) RoundTo = 2;
   else if(Point == 0.001) RoundTo = 3;
   else if(Point == 0.0001) RoundTo = 4;
   else if(Point == 0.00001) RoundTo = 5;
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   ObjectsDeleteAll();
   Comment("");
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int limit;
   int counted_bars=IndicatorCounted();
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- the last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- main loop
   for(int i=limit; i>=0; i--) {
      Semafor_0 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,0,i);
      Semafor_1 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,1,i);
      Semafor_2 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,2,i);
      Semafor_3 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,3,i);
      Semafor_4 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,4,i);
      Semafor_5 = iCustom(NULL,0,"3_Level_ZZ_Semafor",5,13,34,"1,3","8,5","13,8",140,141,142,5,i);
   
      TopSemafor1 = (Semafor_0 == 0 && Semafor_1 != 0 && Semafor_2 == 0 && Semafor_3 == 0 && Semafor_4 == 0 && Semafor_5 == 0);
      TopSemafor2 = (Semafor_0 == 0 && Semafor_1 != 0 && Semafor_2 == 0 && Semafor_3 != 0 && Semafor_4 == 0 && Semafor_5 == 0);
      TopSemafor3 = (Semafor_0 == 0 && Semafor_1 != 0 && Semafor_2 == 0 && Semafor_3 != 0 && Semafor_4 == 0 && Semafor_5 != 0);
      BottomSemafor1 = (Semafor_0 != 0 && Semafor_1 == 0 && Semafor_2 == 0 && Semafor_3 == 0 && Semafor_4 == 0 && Semafor_5 == 0);
      BottomSemafor2 = (Semafor_0 != 0 && Semafor_1 == 0 && Semafor_2 != 0 && Semafor_3 == 0 && Semafor_4 == 0 && Semafor_5 == 0);
      BottomSemafor3 = (Semafor_0 != 0 && Semafor_1 == 0 && Semafor_2 != 0 && Semafor_3 == 0 && Semafor_4 != 0 && Semafor_5 == 0);

      if(TopSemafor1 == True) {
         LastTopSemafor1value = NormalizeDouble(Semafor_1,RoundTo);
         LastTopSemafor1time = Time[i];
      }
      if(TopSemafor2 == True) {
         LastTopSemafor2value = NormalizeDouble(Semafor_3,RoundTo);
         LastTopSemafor2time = Time[i];
      }     
      if(TopSemafor3 == True) {
         LastTopSemafor3value = NormalizeDouble(Semafor_5,RoundTo);
         LastTopSemafor3time = Time[i];
      }
      if(BottomSemafor1 == True) {
         LastBottomSemafor1value = NormalizeDouble(Semafor_0,RoundTo);
         LastBottomSemafor1time = Time[i];
      }
      if(BottomSemafor2 == True) {
         LastBottomSemafor2value = NormalizeDouble(Semafor_2,RoundTo);
         LastBottomSemafor2time = Time[i];
      }
      if(BottomSemafor3 == True) {
         LastBottomSemafor3value = NormalizeDouble(Semafor_4,RoundTo);
         LastBottomSemafor3time = Time[i];
      }
   }

      if(LastBottomSemafor3time > LastTopSemafor3time) {// && High[1] < High[0]) {
         for(int j = iBarShift(NULL,0,LastBottomSemafor3time,false); j>=0; j--) {
            if(Show_Trendlines_For_Next_Trend == True) {
               if(Low[j+3] > Low[j+2] && Low[j+2] < Low[j+1]) {
                  string UpTrendline = "UpTrend Support "+TimeToStr(Time[j+2]);
                  ObjectCreate(UpTrendline,OBJ_TREND,0,LastBottomSemafor3time,LastBottomSemafor3value,Time[j+2],Low[j+2]);
                  ObjectSet(UpTrendline,OBJPROP_COLOR,UpTrendLine_Color);
               }
            }
            if(Show_UpTrend_Lows == True) {
               if(Use_Close_vs_This_High_or_Low == True) {
                  if(Low[j] >= Low[j+1] || Close[j] >= Low[j+1]) { //if this bar's low is higher than or equal to last bar's low, we are in an uptrend
                     UptrendLows[j] = Low[j];
                     DowntrendHighs[j] = EMPTY_VALUE;
                  }
               } else if(Use_Close_vs_This_High_or_Low == False) {
                  if(Low[j] >= Low[j+1]) { //if this bar's low is higher than or equal to last bar's low, we are in an uptrend
                     UptrendLows[j+1] = Low[j+1];
                     UptrendLows[j] = Low[j];
                     //DowntrendHighs[j] = EMPTY_VALUE;
                  }
               }
            }
         }
         for(j = iBarShift(NULL,0,LastTopSemafor3time,false); j>=iBarShift(NULL,0,LastBottomSemafor3time,false); j--) {
            if(Show_Trendlines_For_Next_Trend == True) {
               if(High[j+3] < High[j+2] && High[j+2] > High[j+1]) {
                  string DownTrendline = "DownTrend Resistance "+TimeToStr(Time[j+2]);
                  ObjectCreate(DownTrendline,OBJ_TREND,0,LastTopSemafor3time,LastTopSemafor3value,Time[j+2],High[j+2]);
                  ObjectSet(DownTrendline,OBJPROP_COLOR,DownTrendLine_Color);
               }
            }
            if(Show_DownTrend_Highs == True) {
               if(Use_Close_vs_This_High_or_Low == True) {
                  if(High[j] <= High[j+1] || Close[j] <= High[j+1]) { //if this bar's high is lower than or equal to last bar's high, we are in a downtrend
                     DowntrendHighs[j] = High[j];
                     UptrendLows[j] = EMPTY_VALUE;
                  }
               } else if(Use_Close_vs_This_High_or_Low == False) {
                  if(High[j] <= High[j+1]) { //if this bar's high is lower than or equal to last bar's high, we are in a downtrend
                     DowntrendHighs[j+1] = High[j+1];
                     DowntrendHighs[j] = High[j];
                     //UptrendLows[j] = EMPTY_VALUE;
                  }
               }
            }
         }
      } else if(LastTopSemafor3time > LastBottomSemafor3time) {// && Low[1] > Low[0]) {
         for(j = iBarShift(NULL,0,LastTopSemafor3time,false); j>=0; j--) {
            if(Show_Trendlines_For_Next_Trend == True) {
               if(High[j+3] < High[j+2] && High[j+2] > High[j+1]) {
                  DownTrendline = "DownTrend Resistance "+TimeToStr(Time[j+2]);
                  ObjectCreate(DownTrendline,OBJ_TREND,0,LastTopSemafor3time,LastTopSemafor3value,Time[j+2],High[j+2]);
                  ObjectSet(DownTrendline,OBJPROP_COLOR,DownTrendLine_Color);
               }
            }
            if(Show_DownTrend_Highs == True) {
               if(Use_Close_vs_This_High_or_Low == True) {
                  if(High[j] <= High[j+1] || Close[j] <= High[j+1]) { //if this bar's high is lower than or equal to last bar's high, we are in a downtrend
                     DowntrendHighs[j] = High[j];
                     UptrendLows[j] = EMPTY_VALUE;
                  }
               } else if(Use_Close_vs_This_High_or_Low == False) {
                  if(High[j] <= High[j+1] || High[j] <= High[j+1]) { //if this bar's high is lower than or equal to last bar's high, we are in a downtrend
                     DowntrendHighs[j] = High[j];
                     UptrendLows[j] = EMPTY_VALUE;
                  }
               }
            } 
         }
         for(j = iBarShift(NULL,0,LastBottomSemafor3time,false); j>=iBarShift(NULL,0,LastTopSemafor3time,false); j--) {
            if(Show_Trendlines_For_Next_Trend == True) {
               if(Low[j+3] > Low[j+2] && Low[j+2] < Low[j+1]) {
                  UpTrendline = "UpTrend Support "+TimeToStr(Time[j+2]);
                  ObjectCreate(UpTrendline,OBJ_TREND,0,LastBottomSemafor3time,LastBottomSemafor3value,Time[j+2],Low[j+2]);
                  ObjectSet(UpTrendline,OBJPROP_COLOR,UpTrendLine_Color);
               }
            }
            if(Show_UpTrend_Lows == True) {
               if(Use_Close_vs_This_High_or_Low == True) {
                  if(Low[j] >= Low[j+1] || Close[j] >= Low[j+1]) { //if this bar's low is higher than or equal to last bar's low, we are in an uptrend
                  UptrendLows[j] = Low[j];
                  DowntrendHighs[j] = EMPTY_VALUE;
                  }
               } else if(Use_Close_vs_This_High_or_Low == False) {
                  if(Low[j] >= Low[j+1] || Low[j] >= Low[j+1]) { //if this bar's low is higher than or equal to last bar's low, we are in an uptrend
                  UptrendLows[j] = Low[j];
                  DowntrendHighs[j] = EMPTY_VALUE;
                  }
               }
            } 
         }
      }
      
      //Figure out what a spread is on this broker
         if(TickSize == 0.01 || TickSize == 0.0001) {
            Spread = MarketInfo(Symbol(),MODE_SPREAD);
         } else if(TickSize == 0.001 || TickSize == 0.00001) {
            Spread = MarketInfo(Symbol(),MODE_SPREAD)/10;
         }

      if(LastBottomSemafor3time > LastTopSemafor3time) {//uptrend, so only buy
         for(int k = iBarShift(NULL,0,LastBottomSemafor3time,false)-1; k>=0; k--) {
            if(LastBottomSemafor1time > LastBottomSemafor2time && LastBottomSemafor1time > LastBottomSemafor3time && High[k+1] < High[k]) {
               StopLoss = ((Ask-LastBottomSemafor1value)/Pip)+1;
               StopLossLevel = LastBottomSemafor1value-(1*Pip);
            } else if(LastBottomSemafor2time > LastBottomSemafor1time && LastBottomSemafor2time > LastBottomSemafor3time && High[k+1] < High[k]) {
               StopLoss = ((Ask-LastBottomSemafor2value)/Pip)+1;
               StopLossLevel = LastBottomSemafor2value-(1*Pip);
            } else if(LastBottomSemafor3time > LastBottomSemafor1time && LastBottomSemafor3time > LastBottomSemafor2time && High[k+1] < High[k]) {
               StopLoss = ((Ask-LastBottomSemafor2value)/Pip)+1;
               StopLossLevel = LastBottomSemafor2value-(1*Pip);
            }
         }
      } else if(LastTopSemafor3time > LastBottomSemafor3time) {//downtrend so only sell
         for(k = iBarShift(NULL,0,LastTopSemafor3time,false)-1; k>=0; k--) {
            if(LastTopSemafor1time > LastTopSemafor2time && LastTopSemafor1time > LastTopSemafor3time && Low[k+1] > Low[k]) {
               StopLoss = ((LastTopSemafor1value-Bid)/Pip)+Spread+1;
               StopLossLevel = LastTopSemafor1value+(Spread*Pip)+(1*Pip);
            } else if(LastTopSemafor2time > LastTopSemafor1time && LastTopSemafor2time > LastTopSemafor3time && Low[k+1] > Low[k]) {
               StopLoss = ((LastTopSemafor2value-Bid)/Pip)+Spread+1;
               StopLossLevel = LastTopSemafor2value+(Spread*Pip)+(1*Pip);
            } else if(LastTopSemafor3time > LastTopSemafor1time && LastTopSemafor3time > LastTopSemafor2time && Low[k+1] > Low[k]) {
               StopLoss = ((LastTopSemafor2value-Bid)/Pip)+Spread+1;
               StopLossLevel = LastTopSemafor2value+(Spread*Pip)+(1*Pip);
            }
         }
      }
      /*
      if(ObjectFind(Period()+" StopLoss Level") == -1 && StopLossLevel != 0) {
         ObjectCreate(Period()+" StopLoss Level",OBJ_HLINE,0,0,StopLossLevel);
      } else {
         ObjectSet(Period()+" StopLoss Level",OBJPROP_PRICE1,StopLossLevel);
         ObjectSet(Period()+" StopLoss Level",OBJPROP_WIDTH,2);
      }
      */
      //----------------------- ADJUST LOTS IF USING MONEY MANAGEMENT
      if(StopLoss != 0 && StopLossLevel != 0) {
         if (UseDonsMM == False) {
            myLots = NoMM_Lots ;
         } else if (UseDonsMM == True) {
            myLots = NormalizeDouble( (AccountBalance()*(RISK_PERCENT*0.01)) / (StopLoss*PipValue) ,LotsRoundTo) ;
         }
      }  
      /*
      Comment(
      "Server name = " + AccountServer() + "\n" +     
      "Server Time = " + TimeToStr(TimeCurrent()) + "\n" +
      "---------------------------------------" + "\n" +
      "Pair Symbol = " + Symbol() + "\n" +
      "Spread = " + DoubleToStr(Spread,2) + " pips" + "\n" +
      "---------------------------------------" + "\n" +
      "Account Balance = " + AccountCurrency() + " " + DoubleToStr(AccountBalance(),2) + "\n" +
      "Risk Percent = " + DoubleToStr(RISK_PERCENT,2) + " %" + "\n" +
      "StopLoss = " +DoubleToStr(StopLoss,2) + "\n" +
      "StopLoss Level = " + DoubleToStr(StopLossLevel,RoundTo) + "\n" +
      "Number of Lots to Trade = " + DoubleToStr(myLots,LotsRoundTo) + "\n" +
      "Tick Value = " + AccountCurrency() + " " + DoubleToStr(TickValue,2) + "\n" +
      "Pip Value = " + AccountCurrency() + " " + DoubleToStr(PipValue,2) + "\n" +
      "Real Pip Value = " + AccountCurrency() + " " + DoubleToStr(PipValue*myLots,2) + "\n" +
      "---------------------------------------" + "\n" +
      "CHECK MATH:" + "\n" +
      "Wanting to Risk: Account Balance x (Risk Percent x 0.01) = " + AccountCurrency() + " " + DoubleToStr(AccountBalance()*(RISK_PERCENT*0.01),2) + "\n" +
      "Actually Risked: Stop Loss x Pip Value x Number of Lots = " + AccountCurrency() + " " + DoubleToStr(StopLoss*PipValue*myLots,2) + "\n" +
      "As Percentage of Account = " + DoubleToStr(((StopLoss*PipValue*myLots)/AccountBalance())*100,2) + " %" + "\n" +
      "---------------------------------------" + "\n" +
      "LastTopSemafor3value = " + DoubleToStr(LastTopSemafor3value,RoundTo) + "\n" +
      "LastTopSemafor3time = " + TimeToStr(LastTopSemafor3time) + "\n" +
      "LastBottomSemafor3value = " + DoubleToStr(LastBottomSemafor3value,RoundTo) + "\n" +
      "LastBottomSemafor3time = " + TimeToStr(LastBottomSemafor3time)
      );
      */
//----
   return(0);
  }