//+------------------------------------------------------------------+
//| Uses cloned BBs drawn by Indicator.               Back Bands.mq4 |
//| Last edit: October 14, 2014                                      |
//| The -3 Back shifted BB "snags" price outliers at levels that can |
//| set-up apparent S/R.                                             |
//+------------------------------------------------------------------+
#property copyright "© 2014 apipshort"
#property link "http://www.forexfactory.com/showthread.php?t=494596"
#property indicator_chart_window
#property strict

#property version "1.0"
#property description "This Indicator is a replacement for Greedy Bands."
#property description "Please consult the thread *Gramps' Greedy Indicator* at the above link."
#property description "Without explanations and documentation found there, things will not make sense"
#property description "This is a DEMO and exploratory version only. Do not take it for granted that results"
#property description "will be correct or meaningful and please accept apologies for warts and bugs."

#property indicator_buffers 7
#property indicator_color1 clrGray
#property indicator_color2 clrGray
#property indicator_color3 clrGray
#property indicator_color4 clrDeepSkyBlue
#property indicator_color5 clrDeepSkyBlue
#property indicator_color6 clrNONE
#property indicator_color7 clrNONE

extern string         m = "     First Two Options are On/Off Switches"; // ==>    Back Bands
extern bool    activate = true;     // Activate Indicator.
extern bool     keepAll = false;    // Save/Accumulate All Drawn Lines.
extern int        limit = 0;        // Number of Bars Used. All Possible = 0
extern string        m1 = "     Default Simple MA Period = 25"; // ==>    Set SMA Period for Desired BB System!
extern int    smaPeriod = 25;       // Bands SMA Period
extern double    bandSD = 2.0;      // Bands at Standard Deviation
extern color     clrSMA = clrGray;        // Color SMA
extern color      clrBB = clrGray;        // Color Normal BB
extern color    clrBack = clrDeepSkyBlue; // Color Back BB ( -3 )
extern color    clrFore = clrNONE;        // Color Fore BB ( +3 )
extern int       widthB = 1;        // Line Thickness of the BBs
extern string        m2 = "     Manage Lines"; // ==>
extern bool     showRay = false;    // Show Lines as Rays
extern bool      backgr = false;    // Lines in Background
extern color  clrLineHi = clrRed;       // Color High Lines
extern color  clrLineLo = clrLimeGreen; // Color Low Lines
extern int       widthL = 1;        // Lines Width
extern string        m3 = "     Select a New Pair"; // ==>
extern bool     newPair = false;    // Allow Chart Reset to New Pair
extern string      pair = "USDJPY"; // Set a New Pair
extern string        m4 = "     More Options"; // ==>
extern bool     comment = true;     // Show a Comment Line
extern bool   writeFile = false;    // Write Data from Selected TFs to File

//buffers sma and BBs
double sma[];
double hiBB[],    loBB[];  // shift = 0
double hiBack[], loBack[]; // shift = -3: the signal BB
double hiFore[], loFore[]; // shift = +3: cosmetic fore shifted

string pref="poi_";
string fileName, thisTF ,tag, tStamp;
int handle;       // file handle
int hitHi, hitLo; // high/low hit counters
int tfID, set_ID; // TF#, record ID
double Z, zHigh, zLow, SD; // z-scores and SD on bar
double barHi, barLo, PoI;  // Point of Interest
datetime barTime; // detect new bar event
bool writeDone = true;

//+------------------------------------------------------------------+
int init()
   {
   //if found label "00z_SMA" read SMA Period from there
   int getSMA=StrToInteger(ObjectDescription("00z_SMA"));
   if(getSMA > 2) smaPeriod = getSMA;

   if(newPair && (Symbol() != pair)) ChartSetSymbolPeriod(0, pair, Period());

   int maxBars = Bars - smaPeriod -1; ;
   if(limit==0 || limit > maxBars) limit = maxBars;

   GetPeriod(Period());
   bandSD=MathAbs(bandSD);
   if(!keepAll) {ClearLines(); Clear(pref, 0);}

   string text=StringConcatenate(Symbol(), "  ", IntegerToString(smaPeriod)," SMA  ", DoubleToStr(bandSD,1)," SD");
   Label("tf", 350, 25, 0, thisTF, 14, "Arial", clrLineHi);
   Label("sma", 400, 25, 0, text, 14, "Arial", clrLineHi);

   string name=StringConcatenate("Back Bands ", smaPeriod, " SMA");
   IndicatorShortName(name);

   SetIndexBuffer(0,sma);
   SetIndexStyle(0,DRAW_SECTION,STYLE_SOLID,widthB,clrSMA);
   SetIndexLabel(0,name);

   SetIndexBuffer(1,hiBB);
   SetIndexStyle(1,DRAW_SECTION,STYLE_SOLID,widthB,clrBB);
   SetIndexLabel(1,"Upper BB");

   SetIndexBuffer(2,loBB);
   SetIndexStyle(2,DRAW_SECTION,STYLE_SOLID,widthB,clrBB);
   SetIndexLabel(2,"Lower BB");

   SetIndexBuffer(3,hiBack);
   SetIndexStyle(3,DRAW_SECTION,STYLE_SOLID,widthB,clrBack);
   SetIndexShift(3,-3);
   SetIndexLabel(3,"Upper -3 Back Band");

   SetIndexBuffer(4,loBack);
   SetIndexStyle(4,DRAW_SECTION,STYLE_SOLID,widthB,clrBack);
   SetIndexShift(4,-3);
   SetIndexLabel(4,"Lower -3 Back Band");

   SetIndexBuffer(5,hiFore);
   SetIndexStyle(5,DRAW_SECTION,STYLE_SOLID,widthB,clrFore);
   SetIndexShift(5,3);
   SetIndexLabel(5,NULL);

   SetIndexBuffer(6,loFore);
   SetIndexStyle(6,DRAW_SECTION,STYLE_SOLID,widthB,clrFore);
   SetIndexShift(6,3);
   SetIndexLabel(6,NULL);

   // Write header. File will be closed after writing of data for one TF.
   // File is re-opened and Data appended for the next selected TFs.
   // Be sure to start with a new or empty file for each fresh collection of TF sets.

   if(writeFile)
      {
      set_ID=0;
      fileName=StringConcatenate("Back Bands\\", Symbol(), "_sma", smaPeriod, "_",
                                 TimeToString(TimeCurrent(), TIME_DATE), ".txt");

      handle=FileOpen(fileName, FILE_CSV|FILE_READ|FILE_WRITE, '\t');
      FileWrite(handle, "Set_ID", "Date", "TF#", "TF", "Close",
                "SMA", "Pi Line", "Tag", "SD",
                "Z-Score", "Bar High", "Z-High",
                "Bar Low", "Z-Low", "Bar#", "SMA Per", fileName);

      FileSeek(handle,0,SEEK_END);
      writeDone = false;
      } // end if(writeFile)

   return(0);
  } // end int init()

//+------------------------------------------------------------------+
void WriteToFile(int i)
   {
   set_ID++;
   SD = iStdDev(NULL, 0, smaPeriod, 0, MODE_SMA,PRICE_CLOSE, i);
   Z = GetZ(0, i);
   zHigh = GetZHi(0, i);
   zLow  = GetZLo(0, i);

   FileWrite(handle, set_ID, tStamp, tfID, thisTF, DoubleToStr(Close[i],Digits),
             DoubleToStr(sma[i],Digits), DoubleToStr(PoI,Digits), tag, DoubleToStr(SD,Digits),
             DoubleToStr(Z,4), DoubleToStr(barHi,Digits), DoubleToStr(zHigh,4),
             DoubleToStr(barLo,Digits), DoubleToStr(zLow,4), i, smaPeriod);
   return;
   } // end void WriteToFile()

//+------------------------------------------------------------------+
int deinit()
   {
   Clear("tf", 0);
   Clear(pref, 0);
   if(!keepAll) ClearLines();
   if(comment) Comment("");

   return(0);
   } // end int deinit()

//+------------------------------------------------------------------+
int start()
   {
   Label("server_time", 700, 25, 0,
         TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), 14, "Arial", clrLineHi);

   PlotBB();
   if(!activate) return(0);
   if(barTime != iTime(NULL,0,0))
      {
      hitHi = 0; hitLo = 0;
      Clear(pref, 0);
      string line = StringConcatenate(tfID, "_");
      Clear(line, 0);
      DrawPiLines();
      barTime = iTime(NULL,0,0);
      } // end if(barTime

   if(comment)
      {
      double count = hitHi + hitLo;
      string percHits = DoubleToString((count / limit) * 100, 2);
      Comment("\n", thisTF, "  ", smaPeriod," SMA  Bands SD ",bandSD, "  Total Bars ",Bars, "  Bars Tested ",limit, "\n",
      "Bars Hit ",(int)count, "  High Lines ",hitHi, "  Low Lines ",hitLo, "  Hits = ",percHits," %", "\n", "\n"
      "Activated= ",activate, "  Save Lines= ",keepAll, "  Write File= ",writeFile);
      } // end if(comment)

   return(0);
   } // end int start()

//+------------------------------------------------------------------+
void PlotBB()
   {
   int i,Counted_bars;
   Counted_bars=IndicatorCounted();
   i=Bars-Counted_bars-1;
   if (i>limit-1)i=limit-1;

   while(i >= 0)
      {
      sma[i]=iMA(NULL, 0, smaPeriod, 0, MODE_SMA,PRICE_CLOSE, i);
      hiBB[i] = iBands(NULL, 0, smaPeriod, bandSD, 0, PRICE_CLOSE,MODE_UPPER, i);
      loBB[i] = iBands(NULL, 0, smaPeriod, bandSD, 0, PRICE_CLOSE,MODE_LOWER, i);

      hiBack[i] = hiFore[i] = hiBB[i];
      loBack[i] = loFore[i] = loBB[i];

      i--;
      } // end while(i >= 0)

   return;
   } // end void PlotBB()

//+------------------------------------------------------------------+
void DrawPiLines()
   {
   if(tfID == 8) {showRay = true; widthL = 1;}
   int i = limit; string obj;
   while(i >= 4)
      {
      int k = i; if(i <= 10) k=10;
      barHi = High[i];
      barLo =  Low[i];

      if(barHi > hiBB[i-3] && hiBB[i-3] > hiBB[i])
         {
         tStamp = TimeToString(Time[i], TIME_DATE|TIME_MINUTES);
         obj=StringConcatenate(pref, tfID, "_",IntegerToString(i), "_barHi_", thisTF);
         TrendLine(obj, i, i-3, barHi, barHi, clrLineHi, 2, 0, false, false);
         PoI=hiBB[i-3];
         obj=StringConcatenate(tfID, "_", IntegerToString(i), "_high_", thisTF, " ", tStamp);
         TrendLine(obj, i, k-10, PoI, PoI, clrLineHi, 0, widthL, showRay, backgr);
         tag="high";
         if(writeFile && !writeDone) WriteToFile(i);
         hitHi++;
         }

      if(barLo < loBB[i-3] && loBB[i-3] < loBB[i])
         {
         tStamp = TimeToString(Time[i], TIME_DATE|TIME_MINUTES);
         obj=StringConcatenate(pref, tfID, "_", IntegerToString(i), "_barLo_", thisTF);
         TrendLine(obj, i, i-3, barLo, barLo, clrLineLo, 2, 0, false, false);
         PoI=loBB[i-3];
         obj=StringConcatenate(tfID, "_", IntegerToString(i), "_low_", thisTF, " ", tStamp);
         TrendLine(obj, i, k-10, PoI, PoI, clrLineLo, 0, widthL, showRay, backgr);
         tag="low";
         if(writeFile && !writeDone) WriteToFile(i);
         hitLo++;
         }

      i--;
      } // end while(i >= 4)

   if(writeFile) {FileClose(handle); writeDone = true;}
   return;
   } // end void DrawPiLines(

//+---------------------------SUPPORT--------------------------------+

void TrendLine(string obj, int t1, int t2, double p1, double p2,
               color clr, int styl, int wide, bool ray, bool back)
   {
       if(!ObjectCreate(0,obj,OBJ_TREND,0,0,0,0,0))    {}
   if(!ObjectSetInteger(0,obj,OBJPROP_TIME1, Time[t1])){}
   if(!ObjectSetInteger(0,obj,OBJPROP_TIME2, Time[t2])){}
    if(!ObjectSetDouble(0,obj,OBJPROP_PRICE1, p1)) {}
    if(!ObjectSetDouble(0,obj,OBJPROP_PRICE2, p2)) {}
   if(!ObjectSetInteger(0,obj,OBJPROP_COLOR, clr)) {}
   if(!ObjectSetInteger(0,obj,OBJPROP_STYLE, styl)){}
   if(!ObjectSetInteger(0,obj,OBJPROP_WIDTH, wide)){}
   if(!ObjectSetInteger(0,obj,OBJPROP_RAY,   ray)) {}
   if(!ObjectSetInteger(0,obj,OBJPROP_BACK,  back)){}

   return;
   }// end void TrendLine(

//+------------------------------------------------------------------+
void Label(string obj, int x, int y, int corner, string text,
           int t_size, string t_font, color t_clr)
   {
       if(!ObjectCreate(0,obj,OBJ_LABEL,0,0,0))       {}
   if(!ObjectSetInteger(0,obj,OBJPROP_XDISTANCE, x))  {}
   if(!ObjectSetInteger(0,obj,OBJPROP_YDISTANCE, y))  {}
   if(!ObjectSetInteger(0,obj,OBJPROP_CORNER, corner)){}
   if(!ObjectSetText(obj,text, t_size, t_font, t_clr)){}

   return;
   }// end void Label(

//+------------------------------------------------------------------+
void Clear(string findMe, int startFrom)
   {
   string name;
   int obj_total=ObjectsTotal();
   for(int i=obj_total-1; i>=0; i--)
      {
      name=ObjectName(i);
      if(StringFind(name,findMe)==startFrom) ObjectDelete(name);
      }
   return;
   } // end void Clear(

//+------------------------------------------------------------------+
void ClearLines()
   {
   for(int i=0; i<=8; i++)
      {
      string line=StringConcatenate(IntegerToString(i), "_");
      Clear(line, 0);
      }
   return;
   } // end void ClearLines(

//+------------------------------------------------------------------+
double GetZ(int period, int bar)
   { // Bar z-score
   return((iClose(NULL, period, bar) -
          iMA(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar))/
          iStdDev(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar));
   } // end double GetZ(int period, int bar)

//+------------------------------------------------------------------+
double GetZHi(int period, int bar)
   { // Bar High z-score
   return((iHigh(NULL, period, bar) -
          iMA(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar))/
          iStdDev(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar));
   } // end double GetZHi(int period, int bar)

//+------------------------------------------------------------------+
double GetZLo(int period, int bar)
   { // Bar Low z-score
   return((iLow(NULL, period, bar) -
          iMA(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar))/
          iStdDev(NULL, period, smaPeriod, 0,MODE_SMA,PRICE_CLOSE, bar));
   } // end double GetZLo(int period, int bar)

//+------------------------------------------------------------------+
void GetPeriod(int period)
   {
   switch(period)
      {
      case PERIOD_MN1: tfID = 8; thisTF = "MN";  return;
      case PERIOD_W1:  tfID = 7; thisTF = "W1";  return;
      case PERIOD_D1:  tfID = 6; thisTF = "D1";  return;
      case PERIOD_H4:  tfID = 5; thisTF = "H4";  return;
      case PERIOD_H1:  tfID = 4; thisTF = "H1";  return;
      case PERIOD_M30: tfID = 3; thisTF = "M30"; return;
      case PERIOD_M15: tfID = 2; thisTF = "M15"; return;
      case PERIOD_M5:  tfID = 1; thisTF = "M5";  return;
      case PERIOD_M1:  tfID = 0; thisTF = "M1";  return;
      default:	return;
      }
   } // end string GetPeriod( int period )

//+-----------------------------EOP----------------------------------+
