From 596045f74d4a6c09157674d5bde6b15dff21a871 Mon Sep 17 00:00:00 2001 From: moshferatu Date: Tue, 23 Jul 2024 09:01:50 -0700 Subject: [PATCH] Add the ability to use closing prices when detecting pivots instead of highs / lows --- indicators/PivotPoints.cs | 58 +++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/indicators/PivotPoints.cs b/indicators/PivotPoints.cs index 1e9aaec..95312ae 100644 --- a/indicators/PivotPoints.cs +++ b/indicators/PivotPoints.cs @@ -47,6 +47,7 @@ namespace NinjaTrader.NinjaScript.Indicators RollingWindow = 10; PivotHighStroke = new Stroke(Brushes.LimeGreen, 3); PivotLowStroke = new Stroke(Brushes.Red, 3); + UseClosePrice = false; // For use during backtesting in order to limit the number of pivots processed. MaxPivots = 0; @@ -89,26 +90,26 @@ namespace NinjaTrader.NinjaScript.Indicators { if (i == centerBarIndex) continue; // The center bar is the potential pivot, skip it. - if (High[centerBarIndex] < High[i]) isPivotHigh = false; - if (Low[centerBarIndex] > Low[i]) isPivotLow = false; + if (GetHigh(centerBarIndex) < GetHigh(i)) isPivotHigh = false; + if (GetLow(centerBarIndex) > GetLow(i)) isPivotLow = false; } // Check if there's any pivot high without an end bar index and at the same price level as the current potential pivot high. - bool existsConflictingPivotHigh = pivots.Any(p => p.IsPivotHigh && p.EndBarIndex == 0 && p.Level == High[centerBarIndex]); + bool existsConflictingPivotHigh = pivots.Any(p => p.IsPivotHigh && p.EndBarIndex == 0 && p.Level == GetHigh(centerBarIndex)); // Check if there's any pivot low without an end bar index and at the same price level as the current potential pivot low. - bool existsConflictingPivotLow = pivots.Any(p => p.IsPivotLow && p.EndBarIndex == 0 && p.Level == Low[centerBarIndex]); + bool existsConflictingPivotLow = pivots.Any(p => p.IsPivotLow && p.EndBarIndex == 0 && p.Level == GetLow(centerBarIndex)); if (isPivotHigh && !existsConflictingPivotHigh) { - PivotPoint pivot = new PivotPoint { IsPivotHigh = true, Level = High[centerBarIndex], StartBarIndex = CurrentBar - centerBarIndex }; + PivotPoint pivot = new PivotPoint { IsPivotHigh = true, Level = GetHigh(centerBarIndex), StartBarIndex = CurrentBar - centerBarIndex }; pivots.Add(pivot); Pivot[0] = pivot; } if (isPivotLow && !existsConflictingPivotLow) { - PivotPoint pivot = new PivotPoint { IsPivotLow = true, Level = Low[centerBarIndex], StartBarIndex = CurrentBar - centerBarIndex }; + PivotPoint pivot = new PivotPoint { IsPivotLow = true, Level = GetLow(centerBarIndex), StartBarIndex = CurrentBar - centerBarIndex }; pivots.Add(pivot); Pivot[0] = pivot; } @@ -117,6 +118,16 @@ namespace NinjaTrader.NinjaScript.Indicators pivots.RemoveAt(0); } + private double GetHigh(int barsAgo) + { + return UseClosePrice ? Close[barsAgo] : High[barsAgo]; + } + + private double GetLow(int barsAgo) + { + return UseClosePrice ? Close[barsAgo] : Low[barsAgo]; + } + protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { base.OnRender(chartControl, chartScale); @@ -153,10 +164,15 @@ namespace NinjaTrader.NinjaScript.Indicators public int RollingWindow { get; set; } - [Display(Name = "Pivot High Stroke", Order = 2, GroupName = "Pivot")] + [NinjaScriptProperty] + [Display(Name = "Use Close Price", Order = 2, GroupName = "Pivot")] + public bool UseClosePrice + { get; set; } + + [Display(Name = "Pivot High Stroke", Order = 3, GroupName = "Pivot")] public Stroke PivotHighStroke { get; set; } - [Display(Name = "Pivot Low Stroke", Order = 3, GroupName = "Pivot")] + [Display(Name = "Pivot Low Stroke", Order = 4, GroupName = "Pivot")] public Stroke PivotLowStroke { get; set; } [Browsable(false)] @@ -171,18 +187,18 @@ namespace NinjaTrader.NinjaScript.Indicators public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private PivotPoints[] cachePivotPoints; - public PivotPoints PivotPoints(int rollingWindow) + public PivotPoints PivotPoints(int rollingWindow, bool useClosePrice) { - return PivotPoints(Input, rollingWindow); + return PivotPoints(Input, rollingWindow, useClosePrice); } - public PivotPoints PivotPoints(ISeries input, int rollingWindow) + public PivotPoints PivotPoints(ISeries input, int rollingWindow, bool useClosePrice) { if (cachePivotPoints != null) for (int idx = 0; idx < cachePivotPoints.Length; idx++) - if (cachePivotPoints[idx] != null && cachePivotPoints[idx].RollingWindow == rollingWindow && cachePivotPoints[idx].EqualsInput(input)) + if (cachePivotPoints[idx] != null && cachePivotPoints[idx].RollingWindow == rollingWindow && cachePivotPoints[idx].UseClosePrice == useClosePrice && cachePivotPoints[idx].EqualsInput(input)) return cachePivotPoints[idx]; - return CacheIndicator(new PivotPoints(){ RollingWindow = rollingWindow }, input, ref cachePivotPoints); + return CacheIndicator(new PivotPoints(){ RollingWindow = rollingWindow, UseClosePrice = useClosePrice }, input, ref cachePivotPoints); } } } @@ -191,14 +207,14 @@ namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { - public Indicators.PivotPoints PivotPoints(int rollingWindow) + public Indicators.PivotPoints PivotPoints(int rollingWindow, bool useClosePrice) { - return indicator.PivotPoints(Input, rollingWindow); + return indicator.PivotPoints(Input, rollingWindow, useClosePrice); } - public Indicators.PivotPoints PivotPoints(ISeries input , int rollingWindow) + public Indicators.PivotPoints PivotPoints(ISeries input , int rollingWindow, bool useClosePrice) { - return indicator.PivotPoints(input, rollingWindow); + return indicator.PivotPoints(input, rollingWindow, useClosePrice); } } } @@ -207,14 +223,14 @@ namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { - public Indicators.PivotPoints PivotPoints(int rollingWindow) + public Indicators.PivotPoints PivotPoints(int rollingWindow, bool useClosePrice) { - return indicator.PivotPoints(Input, rollingWindow); + return indicator.PivotPoints(Input, rollingWindow, useClosePrice); } - public Indicators.PivotPoints PivotPoints(ISeries input , int rollingWindow) + public Indicators.PivotPoints PivotPoints(ISeries input , int rollingWindow, bool useClosePrice) { - return indicator.PivotPoints(input, rollingWindow); + return indicator.PivotPoints(input, rollingWindow, useClosePrice); } } }