//https://www.tradingview.com/script/admGhVz7-3-Line-Strike-TTF/
#property copyright "Bugscoder Studio"
#property link      "https://www.bugscoder.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 2
#property indicator_type1   DRAW_ARROW
#property indicator_width1  1
#property indicator_color1  clrDarkSeaGreen
#property indicator_type2   DRAW_ARROW
#property indicator_width2  1
#property indicator_color2  clrTomato

input bool showBear3LS = true; //Show Bearish 3 Line Strike
input bool showBull3LS = true; //Show Bullish 3 Line Strike
input double  BullSignalGap = 50;
input double  BearSignalGap = 50;

extern bool   alertsOn            = true;
extern bool   alertsOnCurrent     = false;
extern bool   alertsMessage       = true;
extern bool   alertsNotification  = true;//false;
extern bool   alertsSound         = true;
extern bool   alertsEmail         = false;


double up[], dn[];
string obj_prefix = "3LS_";

int OnInit() {
   IndicatorDigits(Digits);
   SetIndexLabel(0, "up");
   SetIndexBuffer(0, up);
   SetIndexArrow(0, 233);
   SetIndexLabel(1, "dn");
   SetIndexBuffer(1, dn);
   SetIndexArrow(1, 234);

   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[],
                const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) {

   int startPos = rates_total-prev_calculated-4;
   if (startPos <= 1) { startPos = 1; }
   
   for(int pos=startPos; pos>=0; pos--) {
      up[pos]  = is3LSBull(pos) ?  Low[pos]-BullSignalGap*_Point : EMPTY_VALUE;
      dn[pos]  = is3LSBear(pos) ? High[pos]+BearSignalGap*_Point : EMPTY_VALUE;
   }

   if ( alertsOn ) manageAlerts();
   

   return(rates_total);
}

void OnDeinit(const int reason) {
   ObjectsDeleteAll(0, obj_prefix);
}

int price_diff(double price1, double price2, string _pair = "", bool abs = true) {
   if (_pair == "") { _pair = Symbol(); }
   double _point = MarketInfo(_pair, MODE_POINT);
   
   double p = price1-price2;
   if (abs == true) { p = MathAbs(p); }
   p = NormalizeDouble(p/_point, 0);
   string s = DoubleToStr(p, 0);
   int diff = (int) StringToInteger(s);
   
   return diff;
}

int getCandleColorIndex(int pos) {
   return (Close[pos] > Open[pos]) ? 1 : (Close[pos] < Open[pos]) ? -1 : 0;
}

bool isEngulfing(int pos, bool checkBearish) {
   bool ret = false;
   int sizePrevCandle = price_diff(Close[pos+1], Open[pos+1]);
   int sizeCurrentCandle = price_diff(Close[pos], Open[pos]);
   bool isCurrentLagerThanPrevious = sizeCurrentCandle > sizePrevCandle ? true : false;
   
   if (checkBearish == true) {
      bool isGreenToRed = getCandleColorIndex(pos) < 0 && getCandleColorIndex(pos+1) > 0 ? true : false;
      ret = isCurrentLagerThanPrevious == true && isGreenToRed == true ? true : false;
   }
   else {
      bool isRedToGreen = getCandleColorIndex(pos) > 0 && getCandleColorIndex(pos+1) < 0 ? true : false;
      ret = isCurrentLagerThanPrevious == true && isRedToGreen == true ? true : false;
   }
   
   return ret;
}

bool isBearishEngulfuing(int pos) {
   return isEngulfing(pos, true);
}

bool isBullishEngulfuing(int pos) {
   return isEngulfing(pos, false);
}

bool is3LSBear(int pos) {
   bool ret = false;
   
   bool is3LineSetup = ((getCandleColorIndex(pos+1) > 0) && (getCandleColorIndex(pos+2) > 0) && (getCandleColorIndex(pos+3) > 0)) ? true : false;
   ret = (is3LineSetup == true && isBearishEngulfuing(pos)) ? true : false;
   
   return ret;
}

bool is3LSBull(int pos) {
   bool ret = false;
   
   bool is3LineSetup = ((getCandleColorIndex(pos+1) < 0) && (getCandleColorIndex(pos+2) < 0) && (getCandleColorIndex(pos+3) < 0)) ? true : false;
   ret = (is3LineSetup == true && isBullishEngulfuing(pos)) ? true : false;
   
   return ret;
}

void manageAlerts()
{
   int whichBar = 0;
   if (alertsOn)
   {
      if (alertsOnCurrent)
          whichBar = 0;
      else     
           whichBar = 1; 
         if (up[whichBar]  != EMPTY_VALUE) doAlert(whichBar,"3LS Up Signal");
         if (dn[whichBar] != EMPTY_VALUE) doAlert(whichBar,"3LS Down Signal");
   }
}

void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

       message =  StringConcatenate(Symbol(),", ",timeFrameToString(_Period)," 3LS ",doWhat," @ ",TimeToStr(TimeLocal(),TIME_SECONDS));
          if (alertsMessage)      Alert(message);
          if (alertsEmail)        SendMail(StringConcatenate(Symbol()," 3LS "),message);
          if (alertsNotification) SendNotification(message);
          if (alertsSound)        PlaySound("alert2.wav");
   }

}


string sTfTable[] = {"M1","M5","M10","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,10,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
