/*
   Generated by EX4-TO-MQ4 decompiler V4.0.224.1 []
   Website: http://purebeam.biz
   E-mail : purebeam@gmail.com
*/
#property copyright "00"
#property link      "http://www.mql4.com/"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Black

extern int nBar = 0;
extern bool bLeftOrigin = FALSE;
extern double priceStep = 0.0;
extern bool bVolumeDiffusion = TRUE;
extern int volumeTimeFrame = 0;
extern bool bColorize = TRUE;
extern bool bShowScale = TRUE;
extern int nScale = 256;
extern bool bBuiltinColorize = FALSE;
extern bool bNegativeColor = FALSE;
extern bool bHSVInterp = TRUE;
extern color colBandMax = Orange;
extern color colBandMin = Black;
extern double bandMaxLength = 1.0;
extern double bandHeightRatio = 1.0;
extern int maxBand = 500;
extern double point = 0.0;
string gs_160;
double gda_168[];

int init() {
   gs_160 = "PriceBand";
   IndicatorShortName(gs_160);
   if (volumeTimeFrame == 0) volumeTimeFrame = Period();
   if (point == 0.0) {
      if (Point == 0.0 || Symbol() == "GOLD") point = 0.1;
      else point = Point;
   }
   if (priceStep == 0.0) {
      switch (Period()) {
      case PERIOD_M1:
      case PERIOD_M5:
      case PERIOD_M15:
      case PERIOD_M30:
         priceStep = point;
         break;
      case PERIOD_H1:
      case PERIOD_H4:
         priceStep = 2.0 * point;
         break;
      case PERIOD_D1:
         priceStep = 4.0 * point;
         break;
      case PERIOD_W1:
      default:
         priceStep = 8.0 * point;
      }
   }
   ArrayResize(gda_168, maxBand);
   if (bNegativeColor) {
      colBandMax ^= 16777215;
      colBandMin ^= 16777215;
   }
   Print("Point= ", Point, ", point= ", point, ", priceStep= ", priceStep);
   return (0);
}

string getBandName(int ai_0) {
   return (gs_160 + " Band" + ai_0);
}

string getScaleSepName() {
   return (gs_160 + " ScaleSep");
}

string getScaleUnitName(int ai_0) {
   return (gs_160 + " ScaleUnit" + ai_0);
}

void objInit(bool ai_0) {
   string ls_8;
   for (int li_4 = 0; li_4 < maxBand; li_4++) {
      ls_8 = getBandName(li_4);
      if (ai_0) ObjectCreate(ls_8, OBJ_RECTANGLE, 0, 0, 0);
      else ObjectDelete(ls_8);
   }
   if (bShowScale) {
      ls_8 = getScaleSepName();
      if (ai_0) {
         ObjectCreate(ls_8, OBJ_RECTANGLE, 0, 0, 0);
         ObjectSet(ls_8, OBJPROP_BACK, FALSE);
      } else ObjectDelete(ls_8);
      for (li_4 = 0; li_4 < nScale; li_4++) {
         ls_8 = getScaleUnitName(li_4);
         if (ai_0) ObjectCreate(ls_8, OBJ_RECTANGLE, 0, 0, 0);
         else ObjectDelete(ls_8);
      }
   }
}

void deinit() {
   objInit(0);
}

int getR(int ai_0) {
   return (ai_0 >> 0 & 255);
}

int getG(int ai_0) {
   return (ai_0 >> 8 & 255);
}

int getB(int ai_0) {
   return (ai_0 >> 16 & 255);
}

void getRgb(int ai_0, int &ai_4, int &ai_8, int &ai_12) {
   ai_4 = getR(ai_0);
   ai_8 = getG(ai_0);
   ai_12 = getB(ai_0);
}

int clip255(double ad_0) {
   return (MathMin(MathMax(MathRound(ad_0), 0), 255));
}

double clip1(double ad_0) {
   return (MathMin(MathMax(ad_0, 0.0), 1.0));
}

int rgbToColor(double ad_0, double ad_8, double ad_16) {
   return (clip255(ad_16) << 16 | clip255(ad_8) << 8 | clip255(ad_0));
}

void colorToHsv(int ai_0, double &ad_4, double &ad_12, double &ad_20) {
   int li_28 = getR(ai_0);
   int li_32 = getG(ai_0);
   int li_36 = getB(ai_0);
   int li_40 = MathMax(MathMax(li_28, li_32), li_36);
   int li_44 = MathMin(MathMin(li_28, li_32), li_36);
   double ld_48 = li_40 - li_44;
   if (ld_48 <= 0.0) ad_4 = 0;
   else {
      if (li_40 == li_28) ad_4 = 60.0 * (li_32 - li_36) / ld_48;
      else {
         if (li_40 == li_32) ad_4 = 60.0 * (li_36 - li_28) / ld_48 + 120.0;
         else ad_4 = 60.0 * (li_28 - li_32) / ld_48 + 240.0;
      }
   }
   ad_12 = ld_48 / 255.0;
   ad_20 = li_40 / 255.0;
}

int hsvToColor(double ad_0, double ad_8, double ad_16) {
   double ld_60;
   double ld_68;
   double ld_76;
   if (ad_0 < 0.0) ad_0 += 360.0 * MathCeil((-ad_0) / 360.0);
   int li_24 = MathFloor(ad_0 / 60.0);
   li_24 %= 6;
   double ld_28 = ad_0 / 60.0 - li_24;
   double ld_36 = 255.0 * (ad_16 * (1.0 - ad_8));
   double ld_44 = 255.0 * (ad_16 * (1.0 - ld_28 * ad_8));
   double ld_52 = 255.0 * (ad_16 * (1.0 - (1.0 - ld_28) * ad_8));
   ad_16 = 255.0 * ad_16;
   switch (li_24) {
   case 0:
      ld_60 = ad_16;
      ld_68 = ld_52;
      ld_76 = ld_36;
      break;
   case 1:
      ld_60 = ld_44;
      ld_68 = ad_16;
      ld_76 = ld_36;
      break;
   case 2:
      ld_60 = ld_36;
      ld_68 = ad_16;
      ld_76 = ld_52;
      break;
   case 3:
      ld_60 = ld_36;
      ld_68 = ld_44;
      ld_76 = ad_16;
      break;
   case 4:
      ld_60 = ld_52;
      ld_68 = ld_36;
      ld_76 = ad_16;
      break;
   case 5:
      ld_60 = ad_16;
      ld_68 = ld_36;
      ld_76 = ld_44;
   }
   return (rgbToColor(ld_60, ld_68, ld_76));
}

int getBandColor(double ad_0) {
   double ld_8;
   double ld_16;
   double ld_24;
   double ld_32;
   double ld_40;
   double ld_48;
   double ld_56;
   double ld_64;
   double ld_72;
   double ld_80;
   double ld_88;
   double ld_96;
   int li_104;
   int li_108;
   int li_112;
   int li_116;
   int li_120;
   int li_124;
   double ld_128;
   if (!bColorize) return (colBandMax);
   ad_0 = clip1(ad_0);
   ad_0 = MathRound(ad_0 * (nScale - 1)) / (nScale - 1);
   if (!bBuiltinColorize) {
      if (bHSVInterp) {
         colorToHsv(colBandMin, ld_32, ld_40, ld_48);
         colorToHsv(colBandMax, ld_56, ld_64, ld_72);
         ld_80 = (ld_56 - ld_32) * ad_0 + ld_32;
         ld_88 = (ld_64 - ld_40) * ad_0 + ld_40;
         ld_96 = (ld_72 - ld_48) * ad_0 + ld_48;
         return (hsvToColor(ld_80, ld_88, ld_96));
      }
      getRgb(colBandMin, li_104, li_108, li_112);
      getRgb(colBandMax, li_116, li_120, li_124);
      ld_8 = (li_116 - li_104) * ad_0 + li_104;
      ld_16 = (li_120 - li_108) * ad_0 + li_108;
      ld_24 = (li_124 - li_112) * ad_0 + li_112;
      return (rgbToColor(ld_8, ld_16, ld_24));
   }
   if (ad_0 <= 0.25) {
      ld_128 = ad_0 / 0.25;
      ld_8 = 239.0 * ld_128 + 16.0;
      ld_16 = 64.0 * ld_128 + 4.0;
      ld_24 = 0;
   } else {
      if (ad_0 <= 0.5) {
         ld_128 = (ad_0 - 0.25) / 0.25;
         ld_8 = 255 - 255.0 * ld_128;
         ld_16 = 64;
         ld_24 = 255.0 * ld_128;
      } else {
         if (ad_0 <= 0.75) {
            ld_128 = (ad_0 - 0.5) / 0.25;
            ld_8 = 0;
            ld_16 = 191.0 * ld_128 + 64.0;
            ld_24 = 255;
         } else {
            ld_128 = (ad_0 - 0.75) / 0.25;
            ld_8 = 255.0 * ld_128;
            ld_16 = 255;
            ld_24 = 255;
         }
      }
   }
   if (bNegativeColor) {
      ld_8 = 255 - ld_8;
      ld_16 = 255 - ld_16;
      ld_24 = 255 - ld_24;
   }
   return (rgbToColor(ld_8, ld_16, ld_24));
}

void addVolume(double ad_0, double ad_8, double ad_16, double ad_24) {
   int li_48;
   int li_32 = MathRound(ad_0 / point);
   int li_36 = MathRound(ad_8 / point);
   int li_40 = 1;
   if (li_32 > li_36) li_40 = -1;
   for (int li_44 = li_32; li_44 != li_36; li_44 += li_40) {
      li_48 = MathRound((li_44 * point - ad_24) / priceStep);
      if (li_48 >= 0 && li_48 < maxBand) gda_168[li_48] += ad_16;
   }
}

int start() {
   int li_12;
   int li_16;
   double ld_60;
   double ld_68;
   double ld_76;
   double ld_84;
   double ld_92;
   int li_100;
   double ld_104;
   string ls_120;
   int li_128;
   int li_132;
   double ld_136;
   double ld_144;
   double ld_152;
   double ld_160;
   int li_0 = WindowFirstVisibleBar();
   int li_4 = MathMin(WindowBarsPerChart() + 1, li_0 + 1);
   int li_8 = li_4;
   if (nBar > 0) {
      if (!bLeftOrigin) li_0 = li_0 - li_4 + nBar;
      li_8 = MathMin(li_4, nBar);
      if (nBar >= li_4) bandMaxLength = 1.0;
      li_4 = nBar;
   }
   if (volumeTimeFrame == Period()) {
      li_12 = li_0;
      li_16 = li_4;
   } else {
      li_12 = iBarShift(NULL, volumeTimeFrame, Time[li_0]);
      li_16 = MathCeil(li_4 * Period() / volumeTimeFrame);
      if (li_12 - li_16 + 1 < 0) li_16 = li_12 + 1;
   }
   double ld_20 = Low[iLowest(NULL, 0, MODE_LOW, li_4, li_0 - li_4 + 1)] - point / 10.0;
   double ld_28 = High[iHighest(NULL, 0, MODE_HIGH, li_4, li_0 - li_4 + 1)] + point / 10.0;
   double ld_36 = ld_28 - ld_20;
   int li_44 = MathMin(MathCeil(ld_36 / priceStep), maxBand);
   ArrayInitialize(gda_168, 0);
   int li_48 = 0;
   for (int li_52 = li_12; li_48 < li_16; li_52--) {
      ld_60 = iOpen(NULL, volumeTimeFrame, li_52);
      ld_68 = iHigh(NULL, volumeTimeFrame, li_52);
      ld_76 = iLow(NULL, volumeTimeFrame, li_52);
      ld_84 = iClose(NULL, volumeTimeFrame, li_52);
      ld_92 = iVolume(NULL, volumeTimeFrame, li_52);
      if (!bVolumeDiffusion) addVolume(ld_84, ld_84 + point, ld_92, ld_20);
      else {
         if (ld_60 <= ld_84) {
            li_100 = MathRound((ld_60 + 2.0 * ld_68 - 2.0 * ld_76 - ld_84 + 1.0) / point);
            ld_104 = ld_92 / li_100;
            addVolume(ld_60, ld_76, ld_104, ld_20);
            addVolume(ld_76, ld_68, ld_104, ld_20);
            addVolume(ld_68, ld_84, ld_104, ld_20);
            addVolume(ld_84, ld_84 - point, ld_104, ld_20);
         } else {
            li_100 = MathRound((ld_84 + 2.0 * ld_68 - 2.0 * ld_76 - ld_60 + 1.0) / point);
            ld_104 = ld_92 / li_100;
            addVolume(ld_60, ld_68, ld_104, ld_20);
            addVolume(ld_68, ld_76, ld_104, ld_20);
            addVolume(ld_76, ld_84, ld_104, ld_20);
            addVolume(ld_84, ld_84 + point, ld_104, ld_20);
         }
      }
      li_48++;
   }
   double ld_112 = gda_168[ArrayMaximum(gda_168)];
   if (ld_112 > 0.0) {
      ld_112 = 1.0 / ld_112;
      for (int li_56 = 0; li_56 < maxBand; li_56++) gda_168[li_56] = gda_168[li_56] * ld_112;
   }
   objInit(1);
   for (li_56 = 0; li_56 < maxBand; li_56++) {
      ls_120 = getBandName(li_56);
      ld_144 = ld_20 + (li_56 - 0.5 + (1 - bandHeightRatio) / 2.0) * priceStep;
      ld_152 = ld_144 + priceStep * bandHeightRatio;
      ld_160 = gda_168[li_56];
      ld_136 = (li_8 - 1) * bandMaxLength;
      if (bLeftOrigin) {
         li_128 = li_0;
         li_132 = MathRound(MathMax(li_128 - ld_160 * ld_136, 0));
      } else {
         li_128 = MathRound(MathMax(li_0 - li_4 + 1, 0));
         li_132 = MathRound(MathMax(li_128 + ld_160 * ld_136, 0));
      }
      ObjectMove(ls_120, 0, Time[li_128], ld_144);
      ObjectMove(ls_120, 1, Time[li_132], ld_152);
      ObjectSet(ls_120, OBJPROP_COLOR, getBandColor(ld_160));
   }
   if (bShowScale) {
      ld_136 = 1.0 / nScale * (li_8 - 1) * bandMaxLength;
      if (bLeftOrigin) {
         li_128 = li_0;
         li_132 = MathRound(MathMax(li_128 - nScale * ld_136, 0));
      } else {
         li_128 = MathRound(MathMax(li_0 - li_4 + 1, 0));
         li_132 = MathRound(MathMax(li_128 + nScale * ld_136, 0));
      }
      ls_120 = getScaleSepName();
      ObjectMove(ls_120, 0, Time[li_128], ld_20);
      ObjectMove(ls_120, 1, Time[li_132], ld_20);
      ObjectSet(ls_120, OBJPROP_COLOR, C'0xE0,0xE0,0xE0');
      for (int li_168 = 0; li_168 < nScale; li_168++) {
         ls_120 = getScaleUnitName(li_168);
         if (bLeftOrigin) {
            li_128 = MathRound(MathMax(li_0 - li_168 * ld_136, 0));
            li_132 = MathRound(MathMax(li_0 - (li_168 + 1) * ld_136, 0));
         } else {
            li_128 = MathRound(MathMax(li_0 - li_4 + 1 + li_168 * ld_136, 0));
            li_132 = MathRound(MathMax(li_0 - li_4 + 1 + (li_168 + 1) * ld_136, 0));
         }
         ld_152 = ld_20;
         ld_144 = ld_20 - MathMax(0.05 * (WindowPriceMax() - WindowPriceMin()), 2.0 * priceStep);
         ld_160 = 1.0 * li_168 / (nScale - 1);
         ObjectMove(ls_120, 0, Time[li_128], ld_144);
         ObjectMove(ls_120, 1, Time[li_132], ld_152);
         ObjectSet(ls_120, OBJPROP_COLOR, getBandColor(ld_160));
      }
   }
   ObjectsRedraw();
   return (0);
}
