It's definitely not optimized well, and I would ask for some advices on that.
Yesterday it worked without any crash. Today my chart loaded missing part of the bars - I had to reload all historical data, after doing that it crashed the program. Then I had to try to open NT8 4 times until it sucessfuly loaded. Other 3 times it crashed during opening. There was once a time when I had to open NT8 in saf mode and remove this indicator completely.
The idea of this indicator is - it projects Text symbol "-" above or below bar based on the distance between the close of the bar and Ray Line that is the closest to this bar (it represents support or resistance). It recognizes when the Ray starts.
It works great, I love it, but sometimes it crashes whole program...
***EDIT: Now it crashed after I tried to add Bar Counter indicator to the chart... There was even no Ray on the chart at the moment of crash. No levels projected, plain chart. Tried again after that and no problem this time.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
namespace NinjaTrader.NinjaScript.Indicators
{
public class AAASR : Indicator
{
private SimpleFont symbolFont;
private DateTime lastRayUpdateTime = DateTime.MinValue;
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name = "Max Bars Back", Order = 1)]
public int MaxBarsBack { get; set; } = 102;
[NinjaScriptProperty]
[Display(Name = "Require Ray Lines", Order = 2)]
public bool RequireRayLines { get; set; }
[NinjaScriptProperty]
[Display(Name = "Use Extremes (Low/High)", Order = 3)]
public bool UseExtremes { get; set; }
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = "Support/Resistance Levels with Ray Lines";
Name = "AAASR";
Calculate = Calculate.OnBarClose;
IsOverlay = true;
DisplayInDataBox = true;
DrawOnPricePanel = true;
PaintPriceMarkers = true;
ScaleJustification = ScaleJustification.Right;
IsSuspendedWhileInactive = true;
UseExtremes = false;
}
else if (State == State.Configure)
{
symbolFont = new SimpleFont("Arial", 8) { Bold = false };
}
else if (State == State.Historical)
{
ClearOutputWindow();
}
}
protected override void OnBarUpdate()
{
try
{
if (CurrentBar < 1) return;
// Only process recent bars to improve performance
if (CurrentBar < Count - Math.Min(256, MaxBarsBack)) return;
DateTime barTime = Time[0];
double referencePriceUp = UseExtremes ? Low[0] : Close[0]; // Use low for projection Up
double referencePriceDown = UseExtremes ? High[0] : Close[0]; // Use High for projection down
// Check if any Ray lines have been moved
bool raysChanged = CheckForRayLineChanges();
// Find relevant Ray lines for this specific bar
double refLow = FindRelevantRayBelow(referencePriceUp, barTime, out bool hasRayBelow);
double refHigh = FindRelevantRayAbove(referencePriceDown, barTime, out bool hasRayAbove);
if (RequireRayLines)
{
// Only draw UP levels if there's a Ray below the reference price
DrawUpLevels(referencePriceUp, refLow, hasRayBelow);
// Only draw DOWN levels if there's a Ray above the reference price
DrawDownLevels(referencePriceDown, refHigh, hasRayAbove);
}
else
{
// When not requiring Ray lines, use previous bar's high/low as reference
if (refLow <= 0) refLow = Low[0];
if (refHigh <= 0) refHigh = High[0];
DrawUpLevels(referencePriceUp, refLow, true);
DrawDownLevels(referencePriceDown, refHigh, true);
}
if (raysChanged)
{
lastRayUpdateTime = DateTime.Now;
}
}
catch (Exception ex)
{
Log("Error in OnBarUpdate: " + ex.Message, LogLevel.Error);
}
}
[ATTACH=JSON]{"data-align":"none","data-size":"full","data-attachmentid":1340284}[/ATTACH]
private double FindRelevantRayBelow(double price, DateTime barTime, out bool found)
{
found = false;
double nearest = 0;
foreach (var obj in DrawObjects)
{
if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true &&
ray.StartAnchor.Price == ray.EndAnchor.Price)
{
double rayPrice = ray.StartAnchor.Price;
DateTime rayTime = ray.StartAnchor.Time;
if (rayPrice < price && rayPrice > nearest && rayTime <= barTime)
{
nearest = rayPrice;
found = true;
}
}
}
return nearest;
}
private double FindRelevantRayAbove(double price, DateTime barTime, out bool found)
{
found = false;
double nearest = double.MaxValue;
foreach (var obj in DrawObjects)
{
if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true &&
ray.StartAnchor.Price == ray.EndAnchor.Price)
{
double rayPrice = ray.StartAnchor.Price;
DateTime rayTime = ray.StartAnchor.Time;
if (rayPrice > price && rayPrice < nearest && rayTime <= barTime)
{
nearest = rayPrice;
found = true;
}
}
}
return found ? nearest : 0;
}
private void DrawUpLevels(double referencePrice, double refLow, bool shouldDraw)
{
try
{
double oneRup = referencePrice + (referencePrice - refLow);
double twoRup = referencePrice + 2 * (referencePrice - refLow);
Brush up1RBrush = shouldDraw ? Brushes.Lime : Brushes.Transparent;
Brush up2RBrush = shouldDraw ? Brushes.White : Brushes.Transparent;
Draw.Text(this, "UP_1R" + CurrentBar, false, "—", 0, oneRup, 0, up1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
Draw.Text(this, "UP_2R" + CurrentBar, false, "—", 0, twoRup, 0, up2RBrush, symbolFont, TextAlignment.Center, null, null, 0);
}
catch (Exception ex)
{
Log("Error in DrawUpLevels: " + ex.Message, LogLevel.Error);
}
}
private void DrawDownLevels(double referencePrice, double refHigh, bool shouldDraw)
{
try
{
double oneRdown = referencePrice - (refHigh - referencePrice);
double twoRdown = referencePrice - 2 * (refHigh - referencePrice);
Brush down1RBrush = shouldDraw ? Brushes.Red : Brushes.Transparent;
Brush down2RBrush = shouldDraw ? Brushes.White : Brushes.Transparent;
Draw.Text(this, "DOWN_1R" + CurrentBar, false, "—", 0, oneRdown, 0, down1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
Draw.Text(this, "DOWN_2R" + CurrentBar, false, "—", 0, twoRdown, 0, down2RBrush, symbolFont, TextAlignment.Center, null, null, 0);
}
catch (Exception ex)
{
Log("Error in DrawDownLevels: " + ex.Message, LogLevel.Error);
}
}
private bool CheckForRayLineChanges()
{
foreach (var obj in DrawObjects)
{
if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true)
{
if (ray.StartAnchor.Time > lastRayUpdateTime ||
ray.EndAnchor.Time > lastRayUpdateTime)
{
return true;
}
}
}
return false;
}
private void ClearOutputWindow()
{
foreach (var drawObject in DrawObjects.ToList())
{
if (drawObject is DrawingTools.Text text &&
(text.Tag.StartsWith("UP_") || text.Tag.StartsWith("DOWN_")))
{
RemoveDrawObject(text.Tag);
}
}
}
}
}

. There was definitely no crashes.
Comment