The Ultimate Oscillator in NinjaScript keeps buying pressure and true range in
Series<double> and sums them over three windows. See
the explainer.
What you’ll need
- NinjaTrader 8
- New → NinjaScript Editor → Indicators → New Indicator, name it
AlgoGenUO
The source
#region Using declarations
using System;
using System.Windows.Media;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Indicators;
#endregion
namespace NinjaTrader.NinjaScript.Indicators
{
public class AlgoGenUO : Indicator
{
private Series<double> bp, tr;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "AlgoGen Ultimate Oscillator";
Description = "Ultimate Oscillator (7/14/28)";
S1 = 7; S2 = 14; S3 = 28;
IsOverlay = false;
AddPlot(new Stroke(Brushes.DodgerBlue, 2), PlotStyle.Line, "UO");
AddLine(Brushes.Gray, 70, "Overbought");
AddLine(Brushes.Gray, 30, "Oversold");
}
else if (State == State.DataLoaded)
{
bp = new Series<double>(this);
tr = new Series<double>(this);
}
}
private double Sum(Series<double> s, int period)
{
double sum = 0;
for (int i = 0; i < period; i++) sum += s[i];
return sum;
}
protected override void OnBarUpdate()
{
if (CurrentBar == 0) { bp[0] = 0; tr[0] = High[0] - Low[0]; return; }
double trueLow = Math.Min(Low[0], Close[1]);
bp[0] = Close[0] - trueLow;
tr[0] = Math.Max(High[0], Close[1]) - trueLow;
if (CurrentBar < S3) return;
double a1 = Sum(bp, S1) / Sum(tr, S1);
double a2 = Sum(bp, S2) / Sum(tr, S2);
double a3 = Sum(bp, S3) / Sum(tr, S3);
Value[0] = 100.0 * (4 * a1 + 2 * a2 + a3) / 7.0;
}
#region Properties
[NinjaScriptProperty][System.ComponentModel.DataAnnotations.Range(1, int.MaxValue)]
[System.ComponentModel.Display(Name = "S1", GroupName = "Parameters", Order = 0)]
public int S1 { get; set; }
[NinjaScriptProperty][System.ComponentModel.DataAnnotations.Range(1, int.MaxValue)]
[System.ComponentModel.Display(Name = "S2", GroupName = "Parameters", Order = 1)]
public int S2 { get; set; }
[NinjaScriptProperty][System.ComponentModel.DataAnnotations.Range(1, int.MaxValue)]
[System.ComponentModel.Display(Name = "S3", GroupName = "Parameters", Order = 2)]
public int S3 { get; set; }
#endregion
}
}
Compile & apply
- Press F5 to compile.
- Add AlgoGen Ultimate Oscillator to a chart; it draws in its own panel between 0 and 100 with the 30/70 lines, matching the output chart.
Gotchas
bp/tras Series. Storing buying pressure and true range asSeries<double>lets the window sums look back and survive reloads.- True low/high from
Close[1]. The prior close in the min/max gives the true range, matching ATR. - Sum, then divide.
Sum(bp)/Sum(tr)per window; the 4/2/1 weighting blends the three.
That’s the five-language set: Python, MQL5, Pine Script, EasyLanguage, and this one. Now test a UO rule in AlgoGen.
This post is educational, not financial advice. Indicators describe the past; they don’t predict the future. Backtest anything before you risk real money on it.
Sources and further reading
- NinjaScript system indicator methods (NinjaTrader)
