// ----------------------------------------------------------------------------
// Since I've started coding a few indicators/experts
// I was asked about donations:
//
// Yes, you may donate to me via
// paypal@webtemp.org
//
// (although I don't really care)
// It's just for motivation. ;-) Do it if you find the stuff useful.
// ----------------------------------------------------------------------------

#property copyright "mail@webtemp.org"
#property link      ""

#property indicator_chart_window

extern int    MaxBars   = 500;        // Bar count to be processed (to save CPU time)
extern double MinFactor = 2;           // Minimum multiple of ATR a breakout candle must have to cause a line
extern double   MomoProportion = 2;         // The upper (if Long bias) / lower (if short bias) limit of MZ according to the momo candle
extern color MZLongBiasColor = DarkGreen;
extern color MZShortBiasColor = Maroon;


int MaxLines = 2000;
double L[2000], S[2000];
datetime LT[2000], ST[2000];
double LH[2000], SH[2000];
int Trend;

int init() {
  for(int i = 0; i < MaxLines; i++) {
    L[i] = 0;
    S[i] = 0;
  }
  Trend = 0;
  return(0);
}

int deinit() {
  for(int j = 0; j < MaxLines; j++) {
    string n = "ZL"+j;
    string na = "ZLa"+j;
    ObjectDelete(n);
    ObjectDelete(na);
    n = "ZS"+j;
    na = "ZSa"+j;
    ObjectDelete(n);
    ObjectDelete(na);
  }
  for(j = 0; j < Trend; j++) {
    n = "ZT"+j;
    na = "ZTa"+j;
    ObjectDelete(n);
    ObjectDelete(na);
  }
  init();
  return(0);
}

string GetTimeDiffNice(int t) {
  t = Time[0] - t;
  if (t < 120) return(t+" seconds ago");
  t /= 60;
  if (t < 120) return(t+" minutes ago");
  t /= 60;
  if (t < 48) return(t+" hours ago");
  t /= 24;
  return(t+" days ago");
}

int start() {
  static datetime latest = 0;
  int changed = Bars - IndicatorCounted();
  if (changed < 2) return(0);
  
  for(int i = MathMin(changed-1, MaxBars); i > 0; i--) {
    if (latest >= Time[i]) continue;
    latest = Time[i];

    for(int j = 0; j < MaxLines; j++) {
      if ((L[j] > 0) && (Low[i] <= L[j])) {
        string n = "ZT"+Trend;
        ObjectDelete(n);
        ObjectCreate(n, OBJ_TREND, 0, LT[j], L[j], Time[i-1]-Period()*60, L[j]);
        ObjectSet(n, OBJPROP_COLOR, SeaGreen);
        ObjectSet(n, OBJPROP_RAY, false);
        ObjectSet(n, OBJPROP_BACK, true);
        string na = "ZTa"+Trend;
        ObjectDelete(na);
        ObjectCreate(na, OBJ_TREND, 0, LT[j], L[j], Time[i-1]-Period()*60, L[j]);
        ObjectSet(na, OBJPROP_COLOR, SeaGreen);
        ObjectSet(na, OBJPROP_RAY, false);
        ObjectSet(na, OBJPROP_BACK, true);
        L[j] = 0;
        Trend++;
      }
      if ((S[j] > 0) && (High[i] >= S[j])) {
        n = "ZT"+Trend;
        ObjectDelete(n);
        ObjectCreate(n, OBJ_TREND, 0, ST[j], S[j], Time[i-1]-Period()*60, S[j]);
        ObjectSet(n, OBJPROP_COLOR, Purple);
        ObjectSet(n, OBJPROP_RAY, false);
        ObjectSet(n, OBJPROP_BACK, true);
        na = "ZTa"+Trend;
        ObjectDelete(na);
        ObjectCreate(na, OBJ_TREND, 0, ST[j], S[j], Time[i-1]-Period()*60, S[j]);
        ObjectSet(na, OBJPROP_COLOR, Purple);
        ObjectSet(na, OBJPROP_RAY, false);
        ObjectSet(na, OBJPROP_BACK, true);
        S[j] = 0;
        Trend++;
      }
    }

    double r = MathAbs(Close[i] - Open[i]) - MathAbs(Close[i+1] - Open[i+1]);
    double k = MathAbs(Close[i+1] - Close[i+2]) * MinFactor;
    if ((Close[i] > Close[i+1] && Open[i] < Open[i+1])) {double m = Open[i] - Close[i+1];}
    else
    m = MathAbs(Open[i] - Close[i+1]);
    if ((Close[i] < Open[i] && Close[i+1] < Open[i+1]) || (Close[i] > Open[i] && Close[i+1] > Open[i+1])) {double h = MathAbs(Close[i] - Close[i+1]) / MomoProportion;}
    else
    h = (MathAbs(Close[i] - Open[i]) / MomoProportion) - MathAbs(Close[i+1] - Open[i+1]) + m;

    if (Close[i] - Close[i+1] > 0 && High[i] - High[i+1] > 0 && Close[i] - High[i+1] > 0 && r > 0 && Close[i] - Close[i+1] > k) {
      for(j = 0; j < MaxLines; j++) {
        if (L[j] == High[i+1]) break;
        if (L[j] != 0) continue;
        if (Open[i+1] < Close[i+1]) {L[j] = Close[i+1];} else {L[j] = Open[i+1];}
        LT[j] = Time[i+1];
        LH[j] = L[j] + h;
        break;
      }
    }

    if (Close[i] - Close[i+1] < 0 && Low[i] - Low[i+1] < 0 && Close[i] - Low[i+1] < 0 && r > 0 && Close[i] - Close[i+1] < r) {
      for(j = 0; j < MaxLines; j++) {
        if (S[j] == Low[i+1]) break;
        if (S[j] != 0) continue;
        if (Open[i+1] < Close[i+1]) {S[j] = Open[i+1];} else {S[j] = Close[i+1];}
        ST[j] = Time[i+1];
        SH[j] = S[j] - h;
        break;
      }
    }
  }
  
  for(j = 0; j < MaxLines; j++) {
    n = "ZL"+j;
    na = "ZLa"+j;
    if (L[j] == 0) {
      ObjectDelete(n);
      ObjectDelete(na);
      continue;
    } 
    ObjectCreate(n, OBJ_RECTANGLE, 0, 0, 0);
    ObjectSet(n, OBJPROP_COLOR, MZLongBiasColor);
    ObjectSet(n, OBJPROP_TIME1, LT[j]);
    ObjectSet(n, OBJPROP_PRICE1, L[j]);
    ObjectSet(n, OBJPROP_TIME2, Time[0]);
    ObjectSet(n, OBJPROP_PRICE2, LH[j]);
    
    ObjectCreate(na, OBJ_FIBO, 0, 0, 0);
    ObjectSet(na, OBJPROP_FIBOLEVELS, 1);
    ObjectSet(na, OBJPROP_LEVELCOLOR, MZLongBiasColor);
    ObjectSet(na, OBJPROP_TIME1, LT[j]);
    ObjectSet(na, OBJPROP_PRICE1, L[j]);
    ObjectSet(na, OBJPROP_TIME2, Time[0]);
    ObjectSet(na, OBJPROP_PRICE2, L[j]);
    ObjectSet(na, OBJPROP_BACK, true);
    ObjectSetFiboDescription(na, 0, GetTimeDiffNice(LT[j])+" "+DoubleToStr(L[j], Digits));
    }

  for(j = 0; j < MaxLines; j++) {
    n = "ZS"+j;
    na = "ZSa"+j;
    if (S[j] == 0) {
      ObjectDelete(n);
      ObjectDelete(na);
      
      continue;
    } 
    ObjectCreate(n, OBJ_RECTANGLE, 0, 0, 0);
    ObjectSet(n, OBJPROP_COLOR, MZShortBiasColor);
    ObjectSet(n, OBJPROP_TIME1, ST[j]);
    ObjectSet(n, OBJPROP_PRICE1, S[j]);
    ObjectSet(n, OBJPROP_TIME2, Time[0]);
    ObjectSet(n, OBJPROP_PRICE2, SH[j]);
    
    ObjectCreate(na, OBJ_FIBO, 0, 0, 0);
    ObjectSet(na, OBJPROP_FIBOLEVELS, 1);
    ObjectSet(na, OBJPROP_LEVELCOLOR, MZShortBiasColor);
    ObjectSet(na, OBJPROP_TIME1, ST[j]);
    ObjectSet(na, OBJPROP_PRICE1, S[j]);
    ObjectSet(na, OBJPROP_TIME2, Time[0]);
    ObjectSet(na, OBJPROP_PRICE2, S[j]);
    ObjectSet(na, OBJPROP_BACK, true);
    ObjectSetFiboDescription(na, 0, GetTimeDiffNice(ST[j])+" "+DoubleToStr(S[j], Digits));
  }

  return(0);
}

