I am struggling with this indicator.
During live markets, it seems to get phantom, random, inaccurate signals. The data window I have open is capturing the correct data, and when I refresh the chart, the indicator is behaving exactly as it should. I just can't trust it during live markets, or I am continually refreshing the chart manually. Would anyone be able to take a quick look and tell me what I have potentially done wrong?
The indicator should be comparing the current bar with the previous bar. If NQ makes a higher high and the ES makes an equal or lower high, it should print a signal on top of the NQ price bar. If both NQ and ES make higher highs, there is no signal.
Thank you for any and all input.
Here is the indicator.
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
using NinjaTrader.Data;
namespace NinjaTrader.NinjaScript.Indicators
{
public class AssetHighComparisonIndicator : Indicator
{
private const double TOLERANCE = 0.0001; // Tolerance for price comparisons
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Compares highs of two assets and signals divergence";
Name = "Asset High Comparison Indicator";
Calculate = Calculate.OnBarClose;
IsOverlay = true;
DisplayInDataBox = true;
DrawOnPricePanel = true;
DrawHorizontalGridLines = true;
DrawVerticalGridLines = true;
PaintPriceMarkers = true;
ScaleJustification = ScaleJustification.Right;
Asset2 = string.Empty;
SignalOffset = 5;
PositiveSignalColor = Brushes.Green;
NegativeSignalColor = Brushes.Red;
LookbackPeriod = 1;
TimeFrame = 5;
}
else if (State == State.Configure)
{
AddDataSeries(Asset2, new BarsPeriod { BarsPeriodType = BarsPeriodType.Minute, Value = TimeFrame });
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < LookbackPeriod || CurrentBars[1] < LookbackPeriod || BarsInProgress != 0)
return;
if (Calculate != Calculate.OnBarClose || CurrentBar < 1)
return;
double asset1CurrentHigh = High[0];
double asset1PreviousHigh = High[1];
double asset2CurrentHigh = Highs[1][0];
double asset2PreviousHigh = Highs[1][1];
bool asset1HigherHigh = asset1CurrentHigh > asset1PreviousHigh + TOLERANCE;
bool asset2HigherHigh = asset2CurrentHigh > asset2PreviousHigh + TOLERANCE;
Print($"Bar: {CurrentBar}, Time: {Time[0]}");
Print($"Asset1 Current: {asset1CurrentHigh}, Previous: {asset1PreviousHigh}, Higher: {asset1HigherHigh}");
Print($"Asset2 Current: {asset2CurrentHigh}, Previous: {asset2PreviousHigh}, Higher: {asset2HigherHigh}");
Print($"Condition Check: (asset1HigherHigh && !asset2HigherHigh) = {asset1HigherHigh && !asset2HigherHigh}");
Print($"Condition Check: (!asset1HigherHigh && asset2HigherHigh) = {!asset1HigherHigh && asset2HigherHigh}");
if (asset1HigherHigh && !asset2HigherHigh)
{
double signalPrice = asset1CurrentHigh + SignalOffset * TickSize;
Draw.Diamond(this, $"PositiveSignal{CurrentBar}", false, 0, signalPrice, PositiveSignalColor);
Print($"Drawing Positive Signal at bar {CurrentBar}");
}
else if (!asset1HigherHigh && asset2HigherHigh)
{
double signalPrice = asset1CurrentHigh + SignalOffset * TickSize;
Draw.Diamond(this, $"NegativeSignal{CurrentBar}", false, 0, signalPrice, NegativeSignalColor);
Print($"Drawing Negative Signal at bar {CurrentBar}");
}
else
{
Print($"No signal drawn at bar {CurrentBar}");
}
Print("--------------------");
}
[NinjaScriptProperty]
[Display(Name="Asset 2", Description="Symbol for the comparison asset", Order=1, GroupName="Parameters")]
public string Asset2 { get; set; }
[NinjaScriptProperty]
[Range(0, 20)]
[Display(Name="Signal Offset", Description="Distance from high in ticks", Order=2, GroupName="Parameters")]
public int SignalOffset { get; set; }
[NinjaScriptProperty]
[Range(1, 10)]
[Display(Name="Lookback Period", Description="Number of bars to look back for comparison", Order=3, GroupName="Parameters")]
public int LookbackPeriod { get; set; }
[NinjaScriptProperty]
[Range(1, 60)]
[Display(Name="Time Frame", Description="Time frame in minutes for both assets", Order=4, GroupName="Parameters")]
public int TimeFrame { get; set; }
[NinjaScriptProperty]
[XmlIgnore]
[Display(Name="Positive Signal Color", Description="Color for signals when Asset 1 outperforms", Order=5, GroupName="Parameters")]
public Brush PositiveSignalColor { get; set; }
[Browsable(false)]
public string PositiveSignalColorSerializable
{
get { return Serialize.BrushToString(PositiveSignalColor); }
set { PositiveSignalColor = Serialize.StringToBrush(value); }
}
[NinjaScriptProperty]
[XmlIgnore]
[Display(Name="Negative Signal Color", Description="Color for signals when Asset 2 outperforms", Order=6, GroupName="Parameters")]
public Brush NegativeSignalColor { get; set; }
[Browsable(false)]
public string NegativeSignalColorSerializable
{
get { return Serialize.BrushToString(NegativeSignalColor); }
set { NegativeSignalColor = Serialize.StringToBrush(value); }
}
}
}

Comment