using System.Drawing; using TradingPlatform.BusinessLayer; namespace QuanTAlib; public class AoIndicator : Indicator, IWatchlistIndicator { [InputParameter("Fast Period", sortIndex: 1, 1, 1000, 1, 0)] public int FastPeriod { get; set; } = 5; [InputParameter("Slow Period", sortIndex: 2, 1, 1000, 1, 0)] public int SlowPeriod { get; set; } = 34; [InputParameter("Show cold values", sortIndex: 21)] public bool ShowColdValues { get; set; } = true; private Ao? _ao; protected LineSeries? UpSeries; protected LineSeries? DownSeries; public int MinHistoryDepths => SlowPeriod; int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; public override string ShortName => $"AO {FastPeriod}:{SlowPeriod}"; public override string SourceCodeLink => "https://github.com/mihakralj/QuanTAlib/blob/main/lib/momentum/ao/Ao.Quantower.cs"; public AoIndicator() { OnBackGround = true; SeparateWindow = true; Name = "AO - Awesome Oscillator"; Description = "Momentum indicator measuring market momentum"; UpSeries = new(name: "AO Up", color: Color.Green, width: 2, style: LineStyle.Solid); DownSeries = new(name: "AO Down", color: Color.Red, width: 2, style: LineStyle.Solid); AddLineSeries(UpSeries); AddLineSeries(DownSeries); } protected override void OnInit() { _ao = new Ao(FastPeriod, SlowPeriod); base.OnInit(); } protected override void OnUpdate(UpdateArgs args) { bool isNew = args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar; TBar bar = this.GetInputBar(args); TValue result = _ao!.Update(bar, isNew); if (!_ao.IsHot && !ShowColdValues) { return; } // Determine color based on momentum // Green if rising, Red if falling // We need previous value to compare. // Since OnUpdate is called multiple times for the same bar (ticks), // we need to be careful about "previous value". // Ideally, we compare with the value of the *previous bar*. // But AO coloring is usually: Current > Previous Bar's AO => Green. // Or Current > Previous Value (intra-bar)? // Standard is: "Green bar if the bar is higher than the previous bar. Red bar if the bar is lower than the previous bar." // "Previous bar" usually means the AO value of the previous period. // We can get the previous value from the indicator history if we stored it, // or just use _ao.Last (which is current) and we need the previous one. // But _ao doesn't expose history directly unless we use TSeries. // However, Quantower stores history in the Series. // Get previous value from series double prevAo = double.NaN; if (Count > 1) { // Try to get from UpSeries prevAo = UpSeries!.GetValue(1); if (double.IsNaN(prevAo)) { prevAo = DownSeries!.GetValue(1); } } // If first bar, just pick a color (e.g. Green) or NaN if (double.IsNaN(prevAo) || result.Value > prevAo) { UpSeries!.SetValue(result.Value); DownSeries!.SetValue(double.NaN); } else { UpSeries!.SetValue(double.NaN); DownSeries!.SetValue(result.Value); } } }