Skip to main content

Indicator Development

Indicators are C# classes in the HyperionX.Custom.Indicators namespace. They inherit from Indicator and use HyperionX chart/data APIs.

Minimal Indicator​

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using System.Xml.Serialization;
using HyperionX.Chart.Classes;
using HyperionX.Chart.Enums;
using HyperionX.Core.Attributes;
using HyperionX.Core.DataCalc;
using HyperionX.Core.Enums;

namespace HyperionX.Custom.Indicators;

public class MyMovingAverage : Indicator
{
private Plot _plot;

[HyperionXProperty]
[Display(Name = "Period", GroupName = "Parameters", Order = 1)]
public int Period { get; set; }

[Browsable(false)]
[XmlIgnore]
public Series<double> Average { get; set; }

public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
Name = "My Moving Average";
Version = "1.0";
Period = 14;

_plot = new Plot(Colors.DeepSkyBlue, "Average", 2, PlotLineType.Solid, PlotChartType.Linear);
AddPanePlot(_plot);
}
else if (State == State.Configured)
{
Average = new Series<double>();
AddSeries(Average);
_plot.DataSource = Average;
}
}

public override void OnBarUpdate()
{
if (CurrentBar < Period)
return;

double sum = 0;
for (int i = 0; i < Period; i++)
sum += Input[i];

Average[0] = sum / Period;
}
}

Plots​

A Plot defines how a series is rendered.

_plot = new Plot(
Colors.DeepSkyBlue,
"Average",
2,
PlotLineType.Solid,
PlotChartType.Linear);

Supported line types currently include:

  • PlotLineType.Solid
  • PlotLineType.Dashed

Supported chart types currently include:

  • PlotChartType.Linear
  • PlotChartType.Bars

Use _plot.DataSource = YourSeries; in State.Configured after creating and registering the series.

Series​

Use Series<double> for indicator output.

[Browsable(false)]
[XmlIgnore]
public Series<double> Signal { get; set; }

Signal = new Series<double>();
AddSeries(Signal);
Signal[0] = Close[0] - Close[1];

Always register custom series with AddSeries(...) before writing values.

Registered numeric outputs are also available through IndicatorBase.OutputSeries in registration order. Keep named public series properties when a strategy or generated helper should consume a specific output clearly.

Optional Consumer Interfaces​

Indicators can opt into two additional read-only integrations.

InterfaceConsumerContract
IIndicatorAnalysisProviderLocal AI/chart analysis APIReturn recent structured IndicatorAnalysisEvent records.
IResearchFeatureProviderResearch dataset builderReturn named numeric ResearchIndicatorFeature values for a requested absolute bar index.

These interfaces supplement normal output series; they do not replace them. Keep returned data deterministic, bounded, and read-only. A provider should return an empty collection when it has no valid data rather than throw into the caller.

IIndicatorAnalysisProvider is in HyperionX.Core.Interfaces; IResearchFeatureProvider and ResearchIndicatorFeature are in HyperionX.Core.ResearchLab.

public IEnumerable<ResearchIndicatorFeature> GetResearchFeatures(int barIndex)
{
if (Average == null || barIndex < 0 || barIndex >= Average.Count)
yield break;

yield return new ResearchIndicatorFeature
{
Name = "my_average",
Value = Average.IsValidPoint(barIndex)
? Average.GetValueAt(barIndex)
: 0
};
}

Built-In Indicators From Scripts​

Generated indicator helper methods are available from the Indicator base class and from strategies. For example, the built-in SMA helper is generated from the SMA class:

private SMA _sma;

public override void OnStateChanged()
{
if (State == State.Configured)
_sma = SMA(14);
}

public override void OnBarUpdate()
{
double average = _sma[0];
}

Only call helpers that exist in your local Code Lab build. If a custom indicator class does not compile, its generated helper will not be available.

Drawing On The Chart​

Use the HyperionX Draw API.

Draw.LineHorizontal(this, "last-close", Close[0], Brushes.DeepSkyBlue, 1, DashStyles.Dash);

Draw.FixedText(
this,
"status",
$"Close: {Close[0]:0.####}",
ChartHudAnchor.TopRight,
textBrush: Brushes.White,
backgroundBrush: Brushes.Black,
borderBrush: Brushes.DeepSkyBlue,
fontSize: 12);

Use Draw.FixedText(...) or Draw.HudText(...) for fixed panel text. Do not use Draw.TextFixed(...).

Custom Overlay Renderers​

For advanced drawing, implement IChartOverlayRenderer and draw through IChartRenderContext instead of reaching directly into WPF chart internals.

The render context exposes:

  • Visible bar indexes
  • Price and pixel coordinate transforms
  • Price range and chart dimensions
  • Draw methods for lines, rectangles, circles, and text

This is the correct direction for advanced tools such as timers, labels, volume profile overlays, and order-flow overlays.

Stability Rules​

  • Guard early bars with if (CurrentBar < requiredBars) return;.
  • Do not assume Input, indicators, or external series have enough bars.
  • Keep secrets out of parameters.
  • Do not mutate UI objects from background threads.
  • Let one indicator fail without taking down the chart.