protected override void OnCalculate() { DoubleBottom_DS.Set(0); SetSuccessFromEcho = false; double LowestLowFromEchoBars; double LowestLowFromEchoBarsIndex; DateTime LowestLowFromEchoBarsDate; //Get the lowest Price/Index from our Echo-Period if (ProcessingBarIndex >= (Bars.Count - 1) || History == true) { LowestLowFromEchoBars = LowestLowPrice(this.Candles)[0]; LowestLowFromEchoBarsIndex = LowestLowIndex(this.Candles)[0]; LowestLowFromEchoBarsDate = Bars[(int)LowestLowFromEchoBarsIndex].Time; } else { return; //Just the Last Bar plus the Echo-Bars } //check if datafeed is providing appropriate data if (Bars[BarsAgo + (int)LowestLowFromEchoBarsIndex] == null) { return; } //Calculate the minimum distance from current low to the next low DateTime MinBarsAgoDateTime = Bars[BarsAgo + (int)LowestLowFromEchoBarsIndex].Time; //Calculate Tolerance double tolerance = LowestLowFromEchoBars * (TolerancePercentage / 100); double tolerance_min = LowestLowFromEchoBars - tolerance; double tolerance_max = LowestLowFromEchoBars + tolerance; double SMA_tol = SMA(200)[0] * (TolerancePercentage / 100); double SMA_tol_min = SMA(200)[0] - SMA_tol; double SMA_tol_max = SMA(200)[0] + SMA_tol; if (VerboseMode) { Print("Instrument {3} Bar {0}, Tol+{1}, Tol-{2}", Bars[0].Time.ToString(), Math.Round(tolerance_max, 2), Math.Round(tolerance_min, 2), Bars.Instrument); } //Check, when the chart was the last time below our current low. That period becomes irrelevant for us and gets ignored IEnumerable <IBar> belowLow = Bars.Where(y => y.Low <= tolerance_min) .Where(x => x.Time < LowestLowFromEchoBarsDate) .OrderByDescending(x => x.Time); //if there is no other Low and the chart is coming all the way from a higher price, than just leave this indicator if (!belowLow.Any()) { return; } DateTime IgnoreFromHereOn = belowLow.FirstOrDefault().Time; //Draw ToleranceArea for the respected timeperiod if (DrawTolerance) { //AddChartRectangle("ToleranceRectangle", true, Bars.GetBarsAgo(IgnoreFromHereOn), tolerance_max, 0, tolerance_min, Color.Yellow, Color.Yellow, 50); AddChartRectangle("ToleranceRectangle", true, IgnoreFromHereOn.AddDays(-1), tolerance_max, Bars[0].Time.AddDays(1), tolerance_min, Color.Yellow, Color.Yellow, 50); } //Check, if the time period between the highes Echo-Candle and the MinBarsAgo has any higher price. then we are not at a current high, we are just in strange time situations if (LowestLowPrice(this.Candles + BarsAgo)[0] < LowestLowFromEchoBars) { return; } //find previous bottom //Select all data and find lows. IEnumerable <IBar> lastBottoms = Bars.Where(x => x.Time <= MinBarsAgoDateTime && //older than x Bars, so we have a arch in between the two low points x.Time >= IgnoreFromHereOn) //but younger than the timeperiod when the chart was below our low .Where(y => y.Low <= tolerance_max && // Low <= current Low + Tolerance y.Low >= tolerance_min // Low >= current Low + Tolerance ) .OrderBy(x => x.Low) ; int LowestLowBarsBefore = 5; foreach (IBar bar in lastBottoms) { double LowestLow = LowestLowPrice(Bars.GetBarsAgo(bar.Time))[0]; //calculate the lowest low between current bar and potential bottom double LowestLowBefore = LowestLowPrice(Bars.GetBarsAgo(bar.Time) + LowestLowBarsBefore)[0]; //calculate the lowest low before the potential bottom. this is to make sure that there is no lower price leading up to the bottom //now check, if the current bar is on the same price level as the potential bottom. just to make sure, there is no lower price in that period. if (LowestLow <= (tolerance_max) && //check if that lowest low is inside tolerance levels LowestLow >= (tolerance_min) && LowestLowBefore <= (tolerance_max) && //check if the lowest low Before is inside tolerance levels LowestLowBefore >= (tolerance_min) && (LowestLow == LowestLowBefore || //LowestLow has to be either current bar or the current bottom from loop LowestLow == LowestLowFromEchoBars) ) { //Drawings //Red Connection Line of the Bottoms string strdoubleBottomConnecter = "DoubleBottomConnecter_" + Bars[0].Time.ToString() + "_" + bar.Time.ToString(); AddChartLine(strdoubleBottomConnecter, Bars.GetBarsAgo(bar.Time), bar.Low, (int)LowestLowFromEchoBarsIndex, LowestLowFromEchoBars, Color.LawnGreen); //High and Breakthrough double BreakThrough = HighestHighPrice(Bars.GetBarsAgo(bar.Time))[0]; double BreakThroughAgo = HighestHighIndex(Bars.GetBarsAgo(bar.Time))[0]; string strBreakThrough = strdoubleBottomConnecter + "BreakThrough"; string strBreakThroughVert = strdoubleBottomConnecter + "BreakThroughVert"; AddChartLine(strBreakThrough, (int)BreakThroughAgo, BreakThrough, 0, BreakThrough, Color.Aquamarine, DashStyle.Solid, 2); AddChartLine(strBreakThroughVert, (int)BreakThroughAgo, bar.Low, (int)BreakThroughAgo, BreakThrough, Color.Aquamarine, DashStyle.Solid, 2); if (Filter_SMA200) { if (bar.Low < SMA_tol_min || bar.Low > SMA_tol_max) { continue; //check for SMA200 filter and check if the current low is within the SMA-tolerances } } //Mark current low DoubleBottom_DS.Set((int)LowestLowFromEchoBarsIndex, 1); //Mark previous low(s) DoubleBottom_DS.Set(Bars.GetBarsAgo(bar.Time), 0.5); SetSuccessFromEcho = true; if (VerboseMode) { Print("DoubleBottom Low: {0}, Time: {1}, LowestLow: {2}, LowestLowBefore: {3}, BreakThrough: {4}", bar.Low, bar.Time.ToString(), LowestLow, LowestLowBefore, BreakThrough); } //set Stop and Target for Strategy _stop = LowestLow * 0.99; _target = BreakThrough * 0.99; } } if (SetSuccessFromEcho) { DoubleBottom_DS.Set(1); Print("Indikator Kaufsignal: " + LowestLowFromEchoBarsDate.ToString()); } else { DoubleBottom_DS.Set(0); } }
protected override void OnCalculate() { DoubleTop_DS.Set(0); double HighestHighFromEchoBars; double HighestHighFromEchoBarsIndex; DateTime HighestHighFromEchoBarsDate; //Get the highest Price/Index from our Echo-Period if (ProcessingBarIndex >= (Bars.Count - 1)) { HighestHighFromEchoBars = HighestHighPrice(this.Candles)[0]; HighestHighFromEchoBarsIndex = HighestHighIndex(this.Candles)[0]; HighestHighFromEchoBarsDate = Bars[(int)HighestHighFromEchoBarsIndex].Time; } else { return; //Just the Last Bar plus the Echo-Bars } //check if datafeed is providing appropriate data if (Bars[BarsAgo + (int)HighestHighFromEchoBarsIndex] == null) { return; } //Calculate the minimum distance from current low to the next low DateTime MinBarsAgoDateTime = Bars[BarsAgo + (int)HighestHighFromEchoBarsIndex].Time; //Calculate Tolerance double tolerance = HighestHighFromEchoBars * (TolerancePercentage / 100); double tolerance_min = HighestHighFromEchoBars - tolerance; double tolerance_max = HighestHighFromEchoBars + tolerance; Print(Bars.Instrument + " Bar {0}, Tol+{1}, Tol-{2}", Bars[0].Time.ToString(), Math.Round(tolerance_max, 2), Math.Round(tolerance_min, 2)); //Check, when the chart was the last time above our current high. That period becomes irrelevant for us and gets ignored IEnumerable <IBar> aboveHigh = Bars.Where(y => y.High >= tolerance_max) .Where(x => x.Time < HighestHighFromEchoBarsDate) .OrderByDescending(x => x.Time); DateTime IgnoreFromHereOn = DateTime.MinValue.AddDays(1); //if there is no other High and the chart is coming all the way from a lower price, than just leave this indicator //if (!aboveHigh.Any()) //{ // return; //} if (aboveHigh.GetEnumerator().MoveNext()) { IgnoreFromHereOn = aboveHigh.FirstOrDefault().Time; } //Draw ToleranceArea for the respected timeperiod if (DrawTolerance) { //AddChartRectangle("ToleranceRectangle", true, Bars.GetBarsAgo(IgnoreFromHereOn), tolerance_max, 0, tolerance_min, Color.Yellow, Color.Yellow, 50); AddChartRectangle("ToleranceRectangle", true, IgnoreFromHereOn.AddDays(-1), tolerance_max, Bars[0].Time.AddDays(1), tolerance_min, Color.Yellow, Color.Yellow, 50); } //Check, if the time period between the highes Echo-Candle and the MinBarsAgo has any higher price. then we are not at a current high, we are just in strange time situations if (HighestHighPrice(this.Candles + BarsAgo)[0] > HighestHighFromEchoBars) { return; } //find previous highs //Select all data and find highs. IEnumerable <IBar> lastTops = Bars.Where(x => x.Time <= MinBarsAgoDateTime && //older than x Bars, so we have a arch in between the two low points x.Time >= IgnoreFromHereOn) //but younger than the timeperiod when the chart was below our low .Where(y => y.High <= tolerance_max && // Low <= current Low + Tolerance y.High >= tolerance_min // Low >= current Low + Tolerance ) .OrderBy(x => x.High) ; int HighestHighBarsBefore = 5; foreach (IBar bar in lastTops) { double HighestHigh = HighestHighPrice(Bars.GetBarsAgo(bar.Time))[0]; //calculate the HighestHigh between current bar and potential bottom double HighestHighBefore = HighestHighPrice(Bars.GetBarsAgo(bar.Time) + HighestHighBarsBefore)[0]; //calculate the HighestHigh before the potential top. this is to make sure that there is no higher price leading up to the top //now check, if the current bar is on the same price level as the potential top. just to make sure, there is no higher price in that period. if (HighestHigh <= (tolerance_max) && //check if that HighestHigh is inside tolerance levels HighestHigh >= (tolerance_min) && HighestHighBefore <= (tolerance_max) && //check if the HighestHighBefore is inside tolerance levels HighestHighBefore >= (tolerance_min) && (HighestHigh == HighestHighBefore || //HighestHigh has to be either current bar or the current bottom from loop HighestHigh == HighestHighFromEchoBars) ) { Print("DoubleTop High: {0}, Time: {1}, HighestHigh: {2}, HighestHighBefore: {3}", bar.High, bar.Time.ToString(), HighestHigh, HighestHighBefore); //Drawings //Red Connection Line of the Bottoms string strdoubleTopConnecter = "DoubleTopConnecter_" + Bars[0].Time.ToString() + "_" + bar.Time.ToString(); AddChartLine(strdoubleTopConnecter, Bars.GetBarsAgo(bar.Time), bar.High, (int)HighestHighFromEchoBarsIndex, HighestHighFromEchoBars, Color.Red); //High and Breakthrough double BreakThrough = LowestLowPrice(Bars.GetBarsAgo(bar.Time))[0]; double BreakThroughAgo = LowestLowIndex(Bars.GetBarsAgo(bar.Time))[0]; string strBreakThrough = strdoubleTopConnecter + "BreakThrough"; string strBreakThroughVert = strdoubleTopConnecter + "BreakThroughVert"; AddChartLine(strBreakThrough, (int)BreakThroughAgo, BreakThrough, 0, BreakThrough, Color.Aquamarine, DashStyle.Solid, 2); AddChartLine(strBreakThroughVert, (int)BreakThroughAgo, bar.High, (int)BreakThroughAgo, BreakThrough, Color.Aquamarine, DashStyle.Solid, 2); //Mark current High DoubleTop_DS.Set((int)HighestHighFromEchoBarsIndex, 1); //Mark previous High(s) DoubleTop_DS.Set(Bars.GetBarsAgo(bar.Time), 0.5); SetSuccessFromEcho = true; } } if (SetSuccessFromEcho) { DoubleTop_DS.Set(1); } else { DoubleTop_DS.Set(0); } }