I’m looking for a way to evaluate an Alert, one condition at a time, for a given time and instrument value (not the current bar value, but a range of values)
Under NinjaTrader.NinjaScript.DrawingTools.Polygon I’m seeing the function:
No, I would not use Polygon.IsAlertConditionTrue() as a general-purpose evaluator for an arbitrary time/price range.
That method is part of the drawing-tool alert contract. The built-in Polygon implementation only exposes CrossInside and CrossOutside. It converts each ChartAlertValue from time/value coordinates into chart pixels, checks whether that point is inside the polygon, and then uses the supplied values to detect a crossing. So the array is there for the alert engine’s transition test, not as a general historical range-query API.
For your case I would separate the two jobs:
Build an ordered set of samples for the instrument and time range you want to evaluate.
Run a pure predicate against each sample, for example IsInsidePolygon(time, price).
Compare consecutive results if you need a cross rather than a simple inside/outside result.
Trigger Alert() only when the state changes in the direction you care about.
If you are building your own DrawingTool, then overriding GetValidAlertConditions() and IsAlertConditionTrue() is the right integration point. If this is an indicator, strategy or AddOn, calling Polygon’s override directly is the wrong layer because it depends on ChartControl, ChartScale, panel coordinates and the alert engine’s expected value history.
If you share whether the range is a set of historical bars, tick data, or chart mouse coordinates, the clean implementation differs slightly.
If the inputs are chart mouse coordinates, stay in chart-pixel space for the hit test.
Convert the mouse point and every polygon anchor into the same panel coordinates. Then run the point-in-polygon test on those X/Y values. Do not convert the mouse price back into a historical series first.
The important checks are:
use the polygon’s own ChartPanel and ChartScale;
account for the panel’s X/Y offsets;
reject the test while anchors or scale are unavailable;
decide explicitly whether a point on an edge counts as inside;
recompute after zoom, scroll or scale changes.
I would keep this as a small pure function such as IsInsidePolygon(Point mouse, IReadOnlyList vertices) and keep ChartControl/ChartScale conversion outside it. That makes edge, vertex, inside and outside cases easy to test.
Four useful cases are: center point inside, point outside, point exactly on an edge, and the same data point after a chart zoom. The last case proves the coordinate conversion is refreshed instead of using stale pixels.
If you are evaluating chart mouse coordinates, I would convert the mouse point into chart-domain values first and then keep the actual condition test independent from the rendering layer.
For the X coordinate, ChartControl.GetTimeByX(x) can give you the corresponding chart time.
For the Y coordinate, ChartScale.GetValueByY(y) gives you the value/price represented by that pixel position.
Conceptually:
mouse X/Y
→ DateTime + price/value
→ pure IsInsidePolygon(time, value) test
→ compare previous/current state if you need CrossInside or CrossOutside.
That separation also makes the logic much easier to test because the polygon test no longer depends directly on the Alert engine.
One thing to watch is coordinate space. If your mouse event is giving WPF coordinates while the calculation expects device pixels, use the matching ChartScale conversion method and make sure you are using the scale for the panel that actually contains the drawing object.
I would avoid calling Polygon.IsAlertConditionTrue() directly unless you are implementing the DrawingTool alert contract itself.