diff --git a/Tests/test_updates_oscillators.cs b/Tests/test_updates_oscillators.cs index 297f0ebd..ae2574a5 100644 --- a/Tests/test_updates_oscillators.cs +++ b/Tests/test_updates_oscillators.cs @@ -61,4 +61,36 @@ public class OscillatorsUpdateTests Assert.Equal(initialValue, finalValue, precision); } + + [Fact] + public void Ao_Update() + { + var indicator = new Ao(); + TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Ac_Update() + { + var indicator = new Ac(); + TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } } diff --git a/lib/oscillators/Ac.cs b/lib/oscillators/Ac.cs new file mode 100644 index 00000000..f298d560 --- /dev/null +++ b/lib/oscillators/Ac.cs @@ -0,0 +1,71 @@ +using System.Runtime.CompilerServices; +namespace QuanTAlib; + +/// +/// AC: Acceleration/Deceleration Oscillator +/// A momentum indicator that measures the acceleration and deceleration of the current driving force. +/// It is derived from the Awesome Oscillator (AO) and helps identify potential trend reversals. +/// +/// +/// The AC calculation process: +/// 1. Calculate the Awesome Oscillator (AO) +/// 2. Calculate a 5-period simple moving average of the AO +/// 3. Subtract the 5-period SMA from the current AO value +/// +/// Key characteristics: +/// - Oscillates above and below zero +/// - Measures the acceleration/deceleration of market driving force +/// - Positive values indicate increasing momentum +/// - Negative values indicate decreasing momentum +/// - Can be used to identify potential trend reversals +/// +/// Formula: +/// AC = AO - SMA(AO, 5) +/// +/// Sources: +/// Bill Williams - "Trading Chaos" (1995) +/// https://www.investopedia.com/terms/a/ac.asp +/// + +[SkipLocalsInit] +public sealed class Ac : AbstractBase +{ + private readonly Ao _ao; + private readonly Sma _sma5; + + /// The data source object that publishes updates. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Ac(object source) : this() + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new BarSignal(Sub)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Ac() + { + _ao = new Ao(); + _sma5 = new Sma(5); + WarmupPeriod = 39; // AO requires 34 periods + 5 for AC's SMA + Name = "AC"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void ManageState(bool isNew) + { + if (isNew) + { + _index++; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override double Calculation() + { + ManageState(BarInput.IsNew); + var ao = _ao.Calc(BarInput, BarInput.IsNew); + _sma5.Calc(ao, BarInput.IsNew); + + return ao - _sma5.Value; + } +} diff --git a/lib/oscillators/Ao.cs b/lib/oscillators/Ao.cs new file mode 100644 index 00000000..97c39ea0 --- /dev/null +++ b/lib/oscillators/Ao.cs @@ -0,0 +1,71 @@ +using System.Runtime.CompilerServices; +namespace QuanTAlib; + +/// +/// AO: Awesome Oscillator +/// A momentum indicator that reflects the precise changes in the market driving force. +/// It is used to affirm trends or to anticipate possible reversals. +/// +/// +/// The AO calculation process: +/// 1. Calculates the 5-period simple moving average of the HL2 (High+Low)/2 values. +/// 2. Calculates the 34-period simple moving average of the HL2 (High+Low)/2 values. +/// 3. Subtracts the 34-period SMA from the 5-period SMA. +/// +/// Key characteristics: +/// - Oscillates above and below zero +/// - Positive values indicate bullish momentum +/// - Negative values indicate bearish momentum +/// - Crosses above zero suggest buying opportunities +/// - Crosses below zero suggest selling opportunities +/// +/// Formula: +/// AO = SMA(HL2, 5) - SMA(HL2, 34) +/// +/// Sources: +/// Bill Williams - "Trading Chaos" (1995) +/// https://www.investopedia.com/terms/a/awesomeoscillator.asp +/// + +[SkipLocalsInit] +public sealed class Ao : AbstractBase +{ + private readonly Sma _sma5; + private readonly Sma _sma34; + + /// The data source object that publishes updates. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Ao(object source) : this() + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new BarSignal(Sub)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Ao() + { + _sma5 = new Sma(5); + _sma34 = new Sma(34); + WarmupPeriod = 34; + Name = "AO"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void ManageState(bool isNew) + { + if (isNew) + { + _index++; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override double Calculation() + { + ManageState(BarInput.IsNew); + _sma5.Calc(BarInput.HL2, BarInput.IsNew); + _sma34.Calc(BarInput.HL2, BarInput.IsNew); + + return _sma5.Value - _sma34.Value; + } +} diff --git a/lib/oscillators/_list.md b/lib/oscillators/_list.md index 618c07b3..b779856e 100644 --- a/lib/oscillators/_list.md +++ b/lib/oscillators/_list.md @@ -1,7 +1,7 @@ # Oscillators indicators -AC - Acceleration Oscillator -AO - Awesome Oscillator +✔️ AC - Acceleration Oscillator +✔️ AO - Awesome Oscillator AROON - Aroon oscillator BOP - Balance of Power CCI - Commodity Channel Index