/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters MAMethod maMethod = (MAMethod)IndParam.ListParam[1].Index; int iPeriod1 = (int)IndParam.NumParam[0].Value; int iPeriod2 = (int)IndParam.NumParam[1].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Calculation int iFirstBar = iPeriod1 + iPeriod2 + 2; double[] adIndicator1 = new double[Bars]; double[] adIndicator2 = new double[Bars]; double[] adOscllator = new double[Bars]; // --------------------------------------------------------- Average_True_Range ATR1 = new Average_True_Range(slotType); ATR1.IndParam.ListParam[1].Index = IndParam.ListParam[1].Index; ATR1.IndParam.NumParam[0].Value = IndParam.NumParam[0].Value; ATR1.IndParam.CheckParam[0].Checked = IndParam.CheckParam[0].Checked; ATR1.Calculate(slotType); Average_True_Range ATR2 = new Average_True_Range(slotType); ATR2.IndParam.ListParam[1].Index = IndParam.ListParam[1].Index; ATR2.IndParam.NumParam[0].Value = IndParam.NumParam[1].Value; ATR2.IndParam.CheckParam[0].Checked = IndParam.CheckParam[0].Checked; ATR2.Calculate(slotType); adIndicator1 = ATR1.Component[0].Value; adIndicator2 = ATR2.Component[0].Value; // ---------------------------------------------------------- for (int iBar = iFirstBar; iBar < Bars; iBar++) { adOscllator[iBar] = adIndicator1[iBar] - adIndicator2[iBar]; } // Saving the components Component = new IndicatorComp[3]; Component[0] = new IndicatorComp(); Component[0].CompName = "Histogram"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Histogram; Component[0].FirstBar = iFirstBar; Component[0].Value = adOscllator; Component[1] = new IndicatorComp(); Component[1].ChartType = IndChartType.NoChart; Component[1].FirstBar = iFirstBar; Component[1].Value = new double[Bars]; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[1].DataType = IndComponentType.AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[1].DataType = IndComponentType.ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType.ForceCloseShort; Component[2].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; switch (IndParam.ListParam[0].Text) { case "The Oscillator rises": indLogic = IndicatorLogic.The_indicator_rises; break; case "The Oscillator falls": indLogic = IndicatorLogic.The_indicator_falls; break; case "The Oscillator is higher than the zero line": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; break; case "The Oscillator is lower than the zero line": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; break; case "The Oscillator crosses the zero line upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; break; case "The Oscillator crosses the zero line downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; break; case "The Oscillator changes its direction upward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_upward; break; case "The Oscillator changes its direction downward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_downward; break; default: break; } NoDirectionOscillatorLogic(iFirstBar, iPrvs, adOscllator, 0, ref Component[1], indLogic); Component[2].Value = Component[1].Value; return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters int iBollPrd = (int)IndParam.NumParam[0].Value; double dBollMult = IndParam.NumParam[1].Value; int iKeltPrd = (int)IndParam.NumParam[2].Value; double dKeltMult = IndParam.NumParam[3].Value; double dLevel = IndParam.NumParam[4].Value * Point; double dFireLine = IndParam.NumParam[5].Value * Point; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Calculation int iFirstBar = Math.Max(iBollPrd * 2, iKeltPrd) + 1; double[] adRegr = new double[Bars]; double[] adAtr = new double[Bars]; double[] adMA_Boll = new double[Bars]; double[] adStd = new double[Bars]; double[] adFire = new double[Bars]; adMA_Boll = MovingAverage(iBollPrd, 0, MAMethod.Exponential, Close); // Get ATR and StandardDeviation values -- used in original MT4 indicator Average_True_Range Atr = new Average_True_Range(SlotTypes.OpenFilter); Atr.IndParam.NumParam[0].Value = iKeltPrd; Atr.Calculate(SlotTypes.OpenFilter); adAtr = Atr.Component[0].Value; Standard_Deviation StdDev = new Standard_Deviation(SlotTypes.OpenFilter); StdDev.IndParam.NumParam[0].Value = iBollPrd; StdDev.Calculate(SlotTypes.OpenFilter); adStd = StdDev.Component[0].Value; // fill Linear Regression values, not built in indicator // ported from MQ 4 code // these values remains constant, get outside for loop for performance double SumBars = 0; double SumSqrBars = 0; SumBars = iBollPrd * (iBollPrd - 1) * 0.5; SumSqrBars = (iBollPrd - 1) * iBollPrd * (2 * iBollPrd - 1) / 6; double Num2 = SumBars * SumBars - iBollPrd * SumSqrBars; for (int iBar = iFirstBar; iBar < Bars; iBar++) { double SumY = 0; double Sum1 = 0; double Sum2 = 0; double Slope = 0; for (int x = 0; x < iBollPrd; x++) { double HH = double.MinValue; double LL = double.MaxValue; for (int y = x; y < x + iBollPrd; y++) { HH = Math.Max(HH, High[iBar - y]); LL = Math.Min(LL, Low[iBar - y]); } double dSumsBegin = (Close[iBar - x] - ((HH + LL) / 2 + adMA_Boll[iBar - x]) / 2); Sum1 += x * dSumsBegin; SumY += dSumsBegin; } Sum2 = SumBars * SumY; double Num1 = iBollPrd * Sum1 - Sum2; if (Num2 != 0.0) { Slope = Num1 / Num2; } else { Slope = 0; } double Intercept = (SumY - Slope * SumBars) / iBollPrd; adRegr[iBar] = Intercept + Slope * (iBollPrd - 1); double diff = adAtr[iBar] * dKeltMult; double std = adStd[iBar]; double bbs = (dBollMult * std) / diff; if (bbs < 1) { adFire[iBar] = -dFireLine; } else { adFire[iBar] = dFireLine; } } // Saving the components Component = new IndicatorComp[4]; Component[0] = new IndicatorComp(); Component[0].CompName = "BB Squeeze"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Histogram; Component[0].FirstBar = iFirstBar; Component[0].Value = adRegr; Component[1] = new IndicatorComp(); Component[1].CompName = "Fire"; Component[1].DataType = IndComponentType.IndicatorValue; Component[1].ChartType = IndChartType.Line; Component[1].ChartColor = Color.Blue; Component[1].FirstBar = iFirstBar; Component[1].Value = adFire; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; Component[3] = new IndicatorComp(); Component[3].ChartType = IndChartType.NoChart; Component[3].FirstBar = iFirstBar; Component[3].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[2].DataType = IndComponentType.AllowOpenLong; Component[2].CompName = "Is long entry allowed"; Component[3].DataType = IndComponentType.AllowOpenShort; Component[3].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[2].DataType = IndComponentType.ForceCloseLong; Component[2].CompName = "Close out long position"; Component[3].DataType = IndComponentType.ForceCloseShort; Component[3].CompName = "Close out short position"; } if (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter) { // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; // placeholder components for storing long / short values IndicatorComp icBBLong = new IndicatorComp(); IndicatorComp icBBShort = new IndicatorComp(); IndicatorComp icFire = new IndicatorComp(); switch (IndParam.ListParam[0].Text) { case "The BB Squeeze is higher than the level line and Fire is on": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_is_higher_than_the_level_line); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_higher_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze is higher than the level line and Fire is off": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_is_higher_than_the_level_line); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_lower_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze is lower than the level line and Fire is on": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_is_lower_than_the_level_line); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_higher_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze is lower than the level line and Fire is off": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_is_lower_than_the_level_line); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_lower_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze is higher than the level line": OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref Component[2], ref Component[3], IndicatorLogic.The_indicator_is_higher_than_the_level_line); if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze is lower than the level line": OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref Component[2], ref Component[3], IndicatorLogic.The_indicator_is_lower_than_the_level_line); if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze rises and Fire is on": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_rises); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_higher_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze rises and Fire is off": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_rises); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_lower_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze falls and Fire is on": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_falls); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_higher_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze falls and Fire is off": icBBLong.Value = new double[Bars]; icBBShort.Value = new double[Bars]; icFire.Value = new double[Bars]; OscillatorLogic(iFirstBar, iPrvs, adRegr, dLevel, -dLevel, ref icBBLong, ref icBBShort, IndicatorLogic.The_indicator_falls); NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref icFire, IndicatorLogic.The_indicator_is_lower_than_the_level_line); for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[2].Value[iBar] = (icBBLong.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; Component[3].Value[iBar] = (icBBShort.Value[iBar] == 1 && icFire.Value[iBar] == 1) ? 1.0 : 0.0; } if (dLevel != 0) { SpecialValues = new double[2] { dLevel, -dLevel }; } break; case "The BB Squeeze rises": OscillatorLogic(iFirstBar, iPrvs, adRegr, 0, 0, ref Component[2], ref Component[3], IndicatorLogic.The_indicator_rises); break; case "The BB Squeeze falls": OscillatorLogic(iFirstBar, iPrvs, adRegr, 0, 0, ref Component[2], ref Component[3], IndicatorLogic.The_indicator_falls); break; case "Fire is on": NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref Component[2], IndicatorLogic.The_indicator_is_higher_than_the_level_line); Component[3].Value = Component[2].Value; break; case "Fire is off": NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref Component[2], IndicatorLogic.The_indicator_is_lower_than_the_level_line); Component[3].Value = Component[2].Value; break; case "Fire changes from on to off": NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref Component[2], IndicatorLogic.The_indicator_crosses_the_level_line_downward); Component[3].Value = Component[2].Value; break; case "Fire changes from off to on": NoDirectionOscillatorLogic(iFirstBar, iPrvs, adFire, 0, ref Component[2], IndicatorLogic.The_indicator_crosses_the_level_line_upward); Component[3].Value = Component[2].Value; break; case "Draw only, no Entry or Exit signals": Component[2].DataType = IndComponentType.NotDefined; Component[2].CompName = "Visual Only"; Component[3].DataType = IndComponentType.NotDefined; Component[3].CompName = "Visual Only"; break; default: break; } OscillatorLogic(iFirstBar, iPrvs, adRegr, 0, 0, ref Component[2], ref Component[3], indLogic); } return; }