#property strict #property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 3 #property indicator_type1 DRAW_HISTOGRAM #property indicator_color1 clrDarkGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 3 #property indicator_type2 DRAW_HISTOGRAM #property indicator_color2 clrDarkRed #property indicator_style2 STYLE_SOLID #property indicator_width2 3 #property indicator_type3 DRAW_LINE #property indicator_color3 clrBlue #property indicator_style3 STYLE_SOLID #property indicator_width3 1 double bbTrends[]; int min; bool lineAbove; bool lineBelow; // Buffers double bbHistoUp[]; double bbHistoLow[]; double maLine[]; // Custom functions // Linear regression double linreg(int p, double& arr[]) { double SumY = 0; double Sum1 = 0; double Slope = 0; double c; for (int x = 0; x < p; x++) { c = arr[ArraySize(arr) - 1 - x]; SumY += c; Sum1 += x * c; } double SumBars = p * (p - 1) * 0.5; double SumSqrBars = (p - 1) * p * (2 * p - 1) / 6; double Sum2 = SumBars * SumY; double Num1 = p * Sum1 - Sum2; double Num2 = SumBars * SumBars - p * SumSqrBars; if (Num2 != 0) Slope = Num1 / Num2; else Slope = 0; double Intercept = (SumY - Slope * SumBars) / p; double linregval = Intercept + Slope * (p - 1); return (linregval); } // Hull moving average double Hma(int length, double& arr[]) { double wmaArr[]; double wma1; double wma2; for (int i = 0; i < length; i++) { wma1 = Wma(length / 2, arr, length - 1 - i) * 2; wma2 = Wma(length, arr, length - 1 - i); ArrayResize(wmaArr, ArraySize(wmaArr) + 1); wmaArr[i] = wma1 - wma2; } double hma = Wma(int(MathSqrt(length)), wmaArr, 0); return (hma); } // Wheighted moving average double Wma(int length, double& arr[], int shift) { double sum = 0; double norm = 0; double weight; for (int i = 0; i < length; i++) { weight = (length - i) * length; norm += weight; sum += (arr[ArraySize(arr) - 1 - i - shift] * weight); } double wma = sum / norm; return (wma); } // inputs input int shortLengthInput = 10; // Short BB Length input int longLengthInput = 50; // Long BB Length input double shortDevMultInput = 1.0; // Short Std Dev input double longDevMultInput = 2.0; // Long St dDev enum Type { type1 = 1, // SMA type2 = 2, // EMA type3 = 3, // LSMA type4 = 4, // HMA type5 = 5, // WMA }; input Type maTypeInput = type1; // Moving Average Type input int maLengthInput = 14; // Moving Average Length enum Strat { strat1 = 1, // Dot Only strat2 = 2, // Dot and Line }; input Strat strat = strat1; // Strategy input ENUM_OBJECT objSell = OBJ_ARROW_DOWN; // sell signal shape input ENUM_OBJECT objBuy = OBJ_ARROW_UP; // buy signal shape input int sellSigSize = 2; // sell signal size input int buySigSize = 2; // buy signal size input color sellSigClr = clrOrangeRed; // sell signal color input color buySigClr = clrLimeGreen; // buy signal color int OnInit() { IndicatorBuffers(2); SetIndexBuffer(0, bbHistoUp); SetIndexBuffer(1, bbHistoLow); SetIndexBuffer(2, maLine); return (INIT_SUCCEEDED); } void OnDeinit(const int reason) { ObjectsDeleteAll(0); ObjectsDeleteAll(1); } 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[]) { ArraySetAsSeries(bbHistoUp, false); ArraySetAsSeries(bbHistoLow, false); ArraySetAsSeries(maLine, false); ArraySetAsSeries(time, false); ArraySetAsSeries(close, false); ArraySetAsSeries(high, false); ArraySetAsSeries(open, false); ArraySetAsSeries(low, false); int limit = prev_calculated; if (prev_calculated == 0) { if (shortLengthInput > longLengthInput) { limit = shortLengthInput; } else { limit = longLengthInput; } ArrayResize(bbTrends, limit); ArrayFill(bbTrends, 0, ArraySize(bbTrends), 0); } for (int i = limit; i < rates_total - 1; i++) { int shift = iBarShift(_Symbol, 0, time[i]); double shortMiddle = iBands(_Symbol, 0, shortLengthInput, shortDevMultInput, 0, PRICE_CLOSE, 0, shift); double shortUpper = iBands(_Symbol, 0, shortLengthInput, shortDevMultInput, 0, PRICE_CLOSE, 1, shift); double shortLower = iBands(_Symbol, 0, shortLengthInput, shortDevMultInput, 0, PRICE_CLOSE, 2, shift); double longMiddle = iBands(_Symbol, 0, longLengthInput, longDevMultInput, 0, PRICE_CLOSE, 0, shift); double longUpper = iBands(_Symbol, 0, longLengthInput, longDevMultInput, 0, PRICE_CLOSE, 1, shift); double longLower = iBands(_Symbol, 0, longLengthInput, longDevMultInput, 0, PRICE_CLOSE, 2, shift); double bbTrend = (MathAbs(shortLower - longLower) - MathAbs(shortUpper - longUpper)) / shortMiddle * 100; ArrayResize(bbTrends, ArraySize(bbTrends) + 1); bbTrends[i] = bbTrend; if (bbTrend > 0) { bbHistoLow[i] = EMPTY_VALUE; bbHistoUp[i] = bbTrend; } else if (bbTrend < 0) { bbHistoUp[i] = EMPTY_VALUE; bbHistoLow[i] = bbTrend; } else { bbHistoLow[i] = EMPTY_VALUE; bbHistoUp[i] = EMPTY_VALUE; } double ma; switch (maTypeInput) { case 1: ma = iMAOnArray(bbTrends, 0, maLengthInput, 0, MODE_SMA, 0); break; case 2: ma = iMAOnArray(bbTrends, 0, maLengthInput, 0, MODE_EMA, 0); break; case 3: ma = linreg(maLengthInput, bbTrends); break; case 4: ma = Hma(maLengthInput, bbTrends); break; case 5: ma = Wma(maLengthInput, bbTrends, 0); break; default: break; } maLine[i] = ma; if (strat == 2) { if (maLine[i] > 0) { lineAbove = true; lineBelow = false; } else if (maLine[i] < 0) { lineAbove = false; lineBelow = true; } } else { lineAbove = true; lineBelow = true; } if (lineAbove) { if (bbTrends[i - 1] < maLine[i - 1] && bbTrends[i] > maLine[i]) { string objNb = time[i] + "b"; // Histogram draw ObjectCreate(objNb, objBuy, 1, time[i], maLine[i]); ObjectSetInteger(0, objNb, OBJPROP_ANCHOR, ANCHOR_UPPER); ObjectSetInteger(0, objNb, OBJPROP_WIDTH, buySigSize); ObjectSetInteger(0, objNb, OBJPROP_COLOR, buySigClr); string objNbM = time[i] + "bM"; // main chart draw ObjectCreate(objNbM, objBuy, 0, time[i], low[i]); ObjectSetInteger(0, objNbM, OBJPROP_ANCHOR, ANCHOR_UPPER); ObjectSetInteger(0, objNbM, OBJPROP_WIDTH, buySigSize); ObjectSetInteger(0, objNbM, OBJPROP_COLOR, buySigClr); } } if (lineBelow) { if (bbTrends[i - 1] > maLine[i - 1] && bbTrends[i] < maLine[i]) { string objNs = time[i] + "s"; ObjectCreate(objNs, objSell, 1, time[i], maLine[i]); ObjectSetInteger(0, objNs, OBJPROP_ANCHOR, ANCHOR_BOTTOM); ObjectSetInteger(0, objNs, OBJPROP_WIDTH, sellSigSize); ObjectSetInteger(0, objNs, OBJPROP_COLOR, sellSigClr); string objNsM = time[i] + "sM"; ObjectCreate(objNsM, objSell, 0, time[i], high[i]); ObjectSetInteger(0, objNsM, OBJPROP_ANCHOR, ANCHOR_BOTTOM); ObjectSetInteger(0, objNsM, OBJPROP_WIDTH, sellSigSize); ObjectSetInteger(0, objNsM, OBJPROP_COLOR, sellSigClr); } } } return (rates_total - 1); }