Files
QuanTAlib/lib/momentum/Apo.cs
T

60 lines
2.3 KiB
C#
Raw Normal View History

2024-10-27 21:59:46 -07:00
using System.Runtime.CompilerServices;
namespace QuanTAlib;
/// <summary>
/// APO: Absolute Price Oscillator
2024-11-04 18:08:33 -08:00
/// A momentum indicator that measures the difference between two moving averages
/// of different periods. Similar to PPO but shows absolute difference instead of percentage.
2024-10-27 21:59:46 -07:00
/// </summary>
public sealed class Apo : AbstractBase
{
2024-11-04 18:08:33 -08:00
private readonly AbstractBase _fastMa, _slowMa;
2024-10-27 21:59:46 -07:00
2024-11-04 18:08:33 -08:00
/// <param name="fastPeriod">The period for the faster moving average.</param>
/// <param name="slowPeriod">The period for the slower moving average.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown when fastPeriod or slowPeriod is less than 1, or when fastPeriod is greater than or equal to slowPeriod.
/// </exception>
2024-10-27 21:59:46 -07:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-11-04 18:08:33 -08:00
public Apo(int fastPeriod = 12, int slowPeriod = 26)
2024-10-27 21:59:46 -07:00
{
2024-11-04 18:08:33 -08:00
ArgumentOutOfRangeException.ThrowIfLessThan(fastPeriod, 1);
ArgumentOutOfRangeException.ThrowIfLessThan(slowPeriod, 1);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(fastPeriod, slowPeriod);
2024-10-27 21:59:46 -07:00
2024-11-04 18:08:33 -08:00
_fastMa = new Ema(fastPeriod);
_slowMa = new Ema(slowPeriod);
2024-10-27 21:59:46 -07:00
WarmupPeriod = slowPeriod;
Name = $"APO({fastPeriod},{slowPeriod})";
}
/// <param name="source">The data source object that publishes updates.</param>
2024-11-04 18:08:33 -08:00
/// <param name="fastPeriod">The period for the faster moving average.</param>
/// <param name="slowPeriod">The period for the slower moving average.</param>
2024-10-27 21:59:46 -07:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Apo(object source, int fastPeriod, int slowPeriod) : this(fastPeriod, slowPeriod)
{
var pubEvent = source.GetType().GetEvent("Pub");
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override void ManageState(bool isNew)
{
if (isNew)
2024-11-04 18:08:33 -08:00
{
2024-10-27 21:59:46 -07:00
_index++;
2024-11-04 18:08:33 -08:00
_lastValidValue = Input.Value;
}
2024-10-27 21:59:46 -07:00
}
2024-11-04 18:08:33 -08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-10-27 21:59:46 -07:00
protected override double Calculation()
{
ManageState(Input.IsNew);
2024-11-04 18:08:33 -08:00
_fastMa.Calc(Input);
_slowMa.Calc(Input);
return _fastMa.Value - _slowMa.Value;
2024-10-27 21:59:46 -07:00
}
}