
#property copyright "www.TrendLineIndicator.com"
#property link      "www.TrendLineIndicator.com"

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_color3 Red

extern int Bars.Back = 500;
int gi_80 = 15;
double gd_84 = 0.8;
extern bool Show.Trendlines = TRUE;
bool gi_96 = TRUE;
bool gi_100 = TRUE;
bool gi_104 = FALSE;
int gi_108 = 30;
int gi_112 = 70;
double gd_116 = 1.0;
double gd_124 = 0.02;
extern bool Sound.Alert = TRUE;
extern bool Email.Alert = TRUE;
double g_ibuf_140[];
double g_ibuf_144[];
double g_ibuf_148[];

int init() {
   deleteAllObjects();
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0, 233);
   SetIndexBuffer(0, g_ibuf_140);
   SetIndexEmptyValue(0, 0.0);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1, 234);
   SetIndexBuffer(1, g_ibuf_144);
   SetIndexEmptyValue(1, 0.0);
   SetIndexStyle(2, DRAW_LINE);
   SetIndexBuffer(2, g_ibuf_148);
   SetIndexEmptyValue(2, 0.0);
   return (0);
}

int deinit() {
   deleteAllObjects();
   return (0);
}

int start() {
   int lia_16[30];
   int lia_20[30];
   int li_36;
   int li_40;
   string l_name_44;
   bool li_52;
   int l_count_60;
   int li_64;
   double ld_68;
   string l_name_84;
   deleteAllObjects();
   if (Low[0] == High[0] && Low[0] == Close[0] && Low[0] == Open[0]) GlobalVariableDel("al");
   double l_iatr_0 = iATR(Symbol(), 0, 50, 1);
   int l_count_8 = 0;
   int l_count_12 = 0;
   for (int l_index_24 = 0; l_index_24 < Bars; l_index_24++) {
      g_ibuf_140[l_index_24] = 0.0;
      g_ibuf_144[l_index_24] = 0.0;
      g_ibuf_148[l_index_24] = 0.0;
   }
   for (l_index_24 = 5; l_index_24 < Bars.Back; l_index_24++) {
      g_ibuf_140[l_index_24] = 0.0;
      g_ibuf_144[l_index_24] = 0.0;
      g_ibuf_148[l_index_24] = 0.0;
      if (Low[l_index_24] < Low[l_index_24 - 1] && Low[l_index_24] < Low[l_index_24 - 2] && Low[l_index_24] < Low[l_index_24 + 1] && Low[l_index_24] < Low[l_index_24 + 2] &&
         Low[l_index_24] < Low[l_index_24 + 3] && Low[l_index_24] < Low[l_index_24 - 3] && Low[l_index_24] < Low[l_index_24 + 4] && Low[l_index_24] < Low[l_index_24 - 4] &&
         Low[l_index_24] < Low[l_index_24 + 5] && Low[l_index_24] < Low[l_index_24 - 5] && High[iHighest(Symbol(), 0, MODE_HIGH, 3, l_index_24 + 1)] - Low[l_index_24] > gd_116 * l_iatr_0 && High[iHighest(Symbol(), 0, MODE_HIGH, 3, l_index_24 - 3)] - Low[l_index_24] > gd_116 * l_iatr_0) {
         l_count_8++;
         lia_16[l_count_8 - 1] = l_index_24;
      }
      if (High[l_index_24] > High[l_index_24 - 1] && High[l_index_24] > High[l_index_24 - 2] && High[l_index_24] > High[l_index_24 + 1] && High[l_index_24] > High[l_index_24 +
         2] && High[l_index_24] > High[l_index_24 + 3] && High[l_index_24] > High[l_index_24 - 3] && High[l_index_24] > High[l_index_24 + 4] && High[l_index_24] > High[l_index_24 - 4] &&
         High[l_index_24] > High[l_index_24 + 5] && High[l_index_24] > High[l_index_24 - 5] && High[l_index_24] - Low[iLowest(Symbol(), 0, MODE_LOW, 3, l_index_24 + 1)] > gd_116 * l_iatr_0 && High[l_index_24] - Low[iLowest(Symbol(), 0, MODE_LOW, 3, l_index_24 - 3)] > gd_116 * l_iatr_0) {
         l_count_12++;
         lia_20[l_count_12 - 1] = l_index_24;
      }
   }
   for (int l_index_28 = 0; l_index_28 < l_count_8; l_index_28++) {
      for (int li_32 = l_index_28 + 1; li_32 < l_count_8; li_32++) {
         if (MathAbs(lia_16[l_index_28] - lia_16[li_32]) >= gi_80) {
            if (isObjectAtLevel(Low[lia_16[l_index_28]], Low[lia_16[li_32]]) == 0) {
               li_36 = MathMax(lia_16[l_index_28], lia_16[li_32]);
               li_40 = MathMin(lia_16[l_index_28], lia_16[li_32]);
               if (gi_96 && Low[li_40] < Low[li_36]) continue;
               l_name_44 = "TBSI_SUP_" + ObjectsTotal();
               ObjectCreate(l_name_44, OBJ_TREND, 0, Time[li_36], Low[li_36], Time[li_40], Low[li_40]);
               ObjectSet(l_name_44, OBJPROP_RAY, TRUE);
               ObjectSet(l_name_44, OBJPROP_COLOR, Green);
               ObjectSet(l_name_44, OBJPROP_STYLE, STYLE_DOT);
               li_52 = FALSE;
               for (int li_56 = li_36; li_56 > li_40; li_56--) {
                  if (Low[li_56] + gd_84 * l_iatr_0 < ObjectGetValueByShift(l_name_44, li_56) || Close[li_56] < ObjectGetValueByShift(l_name_44, li_56)) {
                     li_52 = TRUE;
                     break;
                  }
               }
               if (li_52) ObjectDelete(l_name_44);
               else {
                  l_count_60 = 0;
                  li_64 = -1;
                  for (li_56 = li_40 - 7; li_56 > -1; li_56--) {
                     if (Low[li_56] + gd_84 * l_iatr_0 < ObjectGetValueByShift(l_name_44, li_56) || Close[li_56] < ObjectGetValueByShift(l_name_44, li_56)) break;
                     if (Low[li_56 + 1] - l_iatr_0 * gd_124 < ObjectGetValueByShift(l_name_44, li_56 + 1) && High[li_56] > High[li_56 + 1] && g_ibuf_140[li_56 + 1] == 0.0 && !gi_104 ||
                        boll(li_56) < gi_108 && !gi_100 || SMA20Up(li_56) != -1) {
                        g_ibuf_148[li_56] = Low[iLowest(Symbol(), 0, MODE_LOW, 4, li_56)] - 1.0 * Point;
                        g_ibuf_148[li_56 - 1] = g_ibuf_148[li_56];
                        g_ibuf_140[li_56] = Low[li_56] - l_iatr_0 / 2.0;
                        li_64 = li_56;
                        l_count_60++;
                     }
                  }
                  if (l_count_60 == 0) ObjectDelete(l_name_44);
                  else {
                     ObjectSet(l_name_44, OBJPROP_RAY, FALSE);
                     if (li_64 != -1) {
                        ld_68 = 100000.0 * (ObjectGet(l_name_44, OBJPROP_PRICE2) - ObjectGet(l_name_44, OBJPROP_PRICE1)) / (ObjectGet(l_name_44, OBJPROP_TIME2) - ObjectGet(l_name_44, OBJPROP_TIME1));
                        ObjectSet(l_name_44, OBJPROP_TIME2, Time[li_64]);
                        ObjectSet(l_name_44, OBJPROP_PRICE2, ObjectGet(l_name_44, OBJPROP_PRICE1) + ld_68 * (Time[li_64] - ObjectGet(l_name_44, OBJPROP_TIME1)) / 100000.0);
                     }
                  }
               }
            }
         }
      }
   }
   for (int l_index_76 = 0; l_index_76 < l_count_12; l_index_76++) {
      for (int li_80 = l_index_76 + 1; li_80 < l_count_12; li_80++) {
         if (MathAbs(lia_20[l_index_76] - lia_20[li_80]) >= gi_80) {
            if (isObjectAtLevel(High[lia_20[l_index_76]], High[lia_20[li_80]]) == 0) {
               li_36 = MathMax(lia_20[l_index_76], lia_20[li_80]);
               li_40 = MathMin(lia_20[l_index_76], lia_20[li_80]);
               if (gi_96 && High[li_40] > High[li_36]) continue;
               l_name_84 = "TBSI_RES_" + ObjectsTotal();
               ObjectCreate(l_name_84, OBJ_TREND, 0, Time[li_36], High[li_36], Time[li_40], High[li_40]);
               ObjectSet(l_name_84, OBJPROP_RAY, TRUE);
               ObjectSet(l_name_84, OBJPROP_COLOR, Red);
               ObjectSet(l_name_84, OBJPROP_STYLE, STYLE_DOT);
               li_52 = FALSE;
               for (li_56 = li_36; li_56 > li_40; li_56--) {
                  if (High[li_56] - gd_84 * l_iatr_0 > ObjectGetValueByShift(l_name_84, li_56) || Close[li_56] > ObjectGetValueByShift(l_name_84, li_56)) {
                     li_52 = TRUE;
                     break;
                  }
               }
               if (li_52) ObjectDelete(l_name_84);
               else {
                  l_count_60 = 0;
                  li_64 = -1;
                  for (li_56 = li_40 - 7; li_56 > -1; li_56--) {
                     if (High[li_56] - gd_84 * l_iatr_0 > ObjectGetValueByShift(l_name_84, li_56) || Close[li_56] > ObjectGetValueByShift(l_name_84, li_56)) break;
                     if (High[li_56 + 1] + l_iatr_0 * gd_124 > ObjectGetValueByShift(l_name_84, li_56 + 1) && Low[li_56] < Low[li_56 + 1] && g_ibuf_144[li_56 + 1] == 0.0 && !gi_104 || boll(li_56) > gi_112 &&
                        !gi_100 || SMA20Up(li_56) != 1) {
                        g_ibuf_148[li_56] = High[iHighest(Symbol(), 0, MODE_HIGH, 4, li_56)] + 1.0 * Point;
                        g_ibuf_148[li_56 - 1] = g_ibuf_148[li_56];
                        g_ibuf_144[li_56] = High[li_56] + l_iatr_0 / 2.0;
                        li_64 = li_56;
                        l_count_60++;
                     }
                  }
                  if (l_count_60 == 0) ObjectDelete(l_name_84);
                  else {
                     ObjectSet(l_name_84, OBJPROP_RAY, FALSE);
                     if (li_64 != -1) {
                        ld_68 = 100000.0 * (ObjectGet(l_name_84, OBJPROP_PRICE2) - ObjectGet(l_name_84, OBJPROP_PRICE1)) / (ObjectGet(l_name_84, OBJPROP_TIME2) - ObjectGet(l_name_84, OBJPROP_TIME1));
                        ObjectSet(l_name_84, OBJPROP_TIME2, Time[li_64]);
                        ObjectSet(l_name_84, OBJPROP_PRICE2, ObjectGet(l_name_84, OBJPROP_PRICE1) + ld_68 * (Time[li_64] - ObjectGet(l_name_84, OBJPROP_TIME1)) / 100000.0);
                     }
                  }
               }
            }
         }
      }
   }
   string ls_92 = "";
   if (g_ibuf_140[0] != 0.0 && !GlobalVariableCheck("al")) {
      ls_92 = "Long Trade at " + Symbol() + ", Stop Loss at " + g_ibuf_148[0];
      if (Sound.Alert) Alert(ls_92);
      if (Email.Alert) SendMail("TrendLineX Alert - Long", ls_92);
      GlobalVariableSet("al", 1);
   }
   if (g_ibuf_144[0] != 0.0 && !GlobalVariableCheck("al")) {
      ls_92 = "Short Trade at " + Symbol() + ", Stop Loss at " + g_ibuf_148[0];
      if (Sound.Alert) Alert(ls_92);
      if (Email.Alert) SendMail("TrendLineX Alert - Short", ls_92);
      GlobalVariableSet("al", 1);
   }
   if (!Show.Trendlines) deleteAllObjects();
   return (0);
}

int SMA20Up(int ai_0) {
   double lda_4[3];
   for (int l_index_8 = 0; l_index_8 < 3; l_index_8++) lda_4[l_index_8] = iMA(Symbol(), 0, 20, 0, MODE_SMA, PRICE_CLOSE, ai_0 + l_index_8);
   if (lda_4[0] > lda_4[1] && lda_4[1] > lda_4[2]) return (1);
   if (lda_4[0] < lda_4[1] && lda_4[1] < lda_4[2]) return (-1);
   return (0);
}

int boll(int a_shift_0) {
   return (100.0 * ((Close[a_shift_0] - iBands(Symbol(), 0, 20, 2, 0, PRICE_CLOSE, MODE_LOWER, a_shift_0)) / (iBands(Symbol(), 0, 20, 2, 0, PRICE_CLOSE, MODE_UPPER, a_shift_0) - iBands(Symbol(), 0, 20, 2, 0, PRICE_CLOSE, MODE_LOWER, a_shift_0))));
}

void deleteAllObjects() {
   for (int li_0 = 0; li_0 < ObjectsTotal(); li_0++) {
      if (StringFind(ObjectName(li_0), "TBSI") != -1) {
         ObjectDelete(ObjectName(li_0));
         li_0--;
      }
   }
}

bool isObjectAtLevel(double ad_0, double ad_8) {
   double l_iatr_16 = iATR(Symbol(), 0, 50, 1);
   for (int li_24 = 0; li_24 < ObjectsTotal(); li_24++) {
      if (ObjectType(ObjectName(li_24)) == 2 && StringFind(ObjectName(li_24), "TBSI") != -1) {
         if ((MathAbs(ObjectGet(ObjectName(li_24), OBJPROP_PRICE1) - ad_0) < l_iatr_16 / 2.0 && MathAbs(ObjectGet(ObjectName(li_24), OBJPROP_PRICE2) - ad_8) < l_iatr_16 / 2.0) ||
            (MathAbs(ObjectGet(ObjectName(li_24), OBJPROP_PRICE1) - ad_8) < l_iatr_16 / 2.0 && MathAbs(ObjectGet(ObjectName(li_24), OBJPROP_PRICE2) - ad_0) < l_iatr_16 / 2.0)) return (TRUE);
      }
   }
   return (FALSE);
}