mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-18 18:48:05 +00:00
Documentation
This commit is contained in:
+57
-6
@@ -2,10 +2,11 @@ namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// EMA: Exponential Moving Average
|
||||
/// EMA needs very short history buffer and calculates the EMA value using just the
|
||||
/// previous EMA value. The weight of the new datapoint (alpha) is alpha = 2 / (period + 1)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// EMA needs very short history buffer and calculates the EMA value using just the
|
||||
/// previous EMA value. The weight of the new datapoint (alpha) is alpha = 2 / (period + 1)
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Uses no buffer, relying only on the previous EMA value.
|
||||
/// - The weight of new data points is calculated as alpha = 2 / (period + 1).
|
||||
@@ -19,19 +20,52 @@ namespace QuanTAlib;
|
||||
/// - https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
|
||||
/// - https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
|
||||
/// </remarks>
|
||||
|
||||
public class Ema : AbstractBase
|
||||
{
|
||||
// inherited _index
|
||||
// inherited _value
|
||||
|
||||
/// <summary>
|
||||
/// The period for the EMA calculation.
|
||||
/// </summary>
|
||||
private readonly int _period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer for SMA calculation.
|
||||
/// </summary>
|
||||
private CircularBuffer _sma;
|
||||
|
||||
/// <summary>
|
||||
/// The last calculated EMA value.
|
||||
/// </summary>
|
||||
private double _lastEma, _p_lastEma;
|
||||
|
||||
/// <summary>
|
||||
/// Compensator for early EMA values.
|
||||
/// </summary>
|
||||
private double _e, _p_e;
|
||||
|
||||
/// <summary>
|
||||
/// The smoothing factor for EMA calculation.
|
||||
/// </summary>
|
||||
private readonly double _k;
|
||||
|
||||
/// <summary>
|
||||
/// Flags to track initialization status.
|
||||
/// </summary>
|
||||
private bool _isInit, _p_isInit;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to determine whether to use SMA for initial values.
|
||||
/// </summary>
|
||||
private readonly bool _useSma;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period for EMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
public Ema(int period, bool useSma = true)
|
||||
{
|
||||
if (period < 1)
|
||||
@@ -47,6 +81,10 @@ public class Ema : AbstractBase
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified alpha value.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The smoothing factor for EMA calculation.</param>
|
||||
public Ema(double alpha)
|
||||
{
|
||||
_k = alpha;
|
||||
@@ -57,13 +95,21 @@ public class Ema : AbstractBase
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object for event subscription.</param>
|
||||
/// <param name="period">The period for EMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
public Ema(object source, int period, bool useSma = true) : this(period, useSma)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
//inhereted public void Sub(object source, in ValueEventArgs args)
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Ema instance.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
@@ -74,6 +120,10 @@ public class Ema : AbstractBase
|
||||
_sma = new(_period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Ema instance.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the input is new.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
@@ -92,8 +142,9 @@ public class Ema : AbstractBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core EMA calculation
|
||||
/// Performs the EMA calculation.
|
||||
/// </summary>
|
||||
/// <returns>The calculated EMA value.</returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
double result, _ema;
|
||||
@@ -118,7 +169,7 @@ public class Ema : AbstractBase
|
||||
_ema = _k * (Input.Value - _lastEma) + _lastEma;
|
||||
|
||||
// _useSma decides if we use compensator or not
|
||||
result = (_useSma || _e == 0) ? _ema : _ema / (1 - _e);
|
||||
result = (_useSma || _e <= double.Epsilon) ? _ema : _ema / (1 - _e);
|
||||
}
|
||||
_lastEma = _ema;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
Reference in New Issue
Block a user