mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 13:58:04 +00:00
Macd
This commit is contained in:
@@ -58,6 +58,7 @@ public class EventingTests
|
|||||||
("Trima", new Trima(p), new Trima(input, p)),
|
("Trima", new Trima(p), new Trima(input, p)),
|
||||||
("Vidya", new Vidya(p), new Vidya(input, p)),
|
("Vidya", new Vidya(p), new Vidya(input, p)),
|
||||||
("Apo", new Apo(12, 26), new Apo(input, 12, 26)),
|
("Apo", new Apo(12, 26), new Apo(input, 12, 26)),
|
||||||
|
("Macd", new Macd(12, 26, 9), new Macd(input, 12, 26, 9)),
|
||||||
("Rsi", new Rsi(p), new Rsi(input, p)),
|
("Rsi", new Rsi(p), new Rsi(input, p)),
|
||||||
("Rsx", new Rsx(p), new Rsx(input, p)),
|
("Rsx", new Rsx(p), new Rsx(input, p)),
|
||||||
("Cmo", new Cmo(p), new Cmo(input, p)),
|
("Cmo", new Cmo(p), new Cmo(input, p)),
|
||||||
|
|||||||
@@ -120,6 +120,21 @@ public class MomentumUpdateTests
|
|||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Macd_Update()
|
||||||
|
{
|
||||||
|
var indicator = new Macd(fastPeriod: 12, slowPeriod: 26, signalPeriod: 9);
|
||||||
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
|
{
|
||||||
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices
|
||||||
|
}
|
||||||
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Pmo_Update()
|
public void Pmo_Update()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
- Total: 116 of 175 indicators implemented (66%)
|
- Total: 116 of 175 indicators implemented (66%)
|
||||||
|
|
||||||
|
|
||||||
|BASIC TRANSFORMS|Class Name|
|
|**BASIC TRANSFORMS**|**Class Name**|
|
||||||
|---|:--:|
|
|---|:--:|
|
||||||
|OC2 - Midpoint price|`.OC2`|
|
|OC2 - Midpoint price|`.OC2`|
|
||||||
|HL2 - Median Price|`.HL2`|
|
|HL2 - Median Price|`.HL2`|
|
||||||
@@ -22,8 +22,9 @@
|
|||||||
|OHL3 - Mean Price|`.OHL3`|
|
|OHL3 - Mean Price|`.OHL3`|
|
||||||
|OHLC4 - Average Price|`.OHLC4`|
|
|OHLC4 - Average Price|`.OHLC4`|
|
||||||
|HLCC4 - Weighted Price|`.HLCC4`|
|
|HLCC4 - Weighted Price|`.HLCC4`|
|
||||||
<br>
|
|
||||||
|**AVERAGES & TRENDS**|**Class Name**|
|
|**AVERAGES & TRENDS**|**Class Name**|
|
||||||
|
|--|:--:|
|
||||||
|AFIRMA - Adaptive FIR Moving Average|`Afirma`|
|
|AFIRMA - Adaptive FIR Moving Average|`Afirma`|
|
||||||
|ALMA - Arnaud Legoux Moving Average|`Alma`|
|
|ALMA - Arnaud Legoux Moving Average|`Alma`|
|
||||||
|DEMA - Double Exponential Moving Average|`Dema`|
|
|DEMA - Double Exponential Moving Average|`Dema`|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
namespace QuanTAlib;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MACD: Moving Average Convergence Divergence
|
||||||
|
/// A trend-following momentum indicator that shows the relationship between two moving
|
||||||
|
/// averages of an asset's price. MACD is calculated by subtracting the longer-period
|
||||||
|
/// EMA from the shorter-period EMA. The result is then used to calculate a signal line
|
||||||
|
/// (EMA of MACD) and histogram (MACD - Signal).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The MACD calculation process:
|
||||||
|
/// 1. Calculate the fast EMA (default 12 periods)
|
||||||
|
/// 2. Calculate the slow EMA (default 26 periods)
|
||||||
|
/// 3. MACD Line = Fast EMA - Slow EMA
|
||||||
|
/// 4. Signal Line = EMA of MACD Line (default 9 periods)
|
||||||
|
/// 5. MACD Histogram = MACD Line - Signal Line
|
||||||
|
///
|
||||||
|
/// Key characteristics:
|
||||||
|
/// - Centerline crossovers signal trend changes
|
||||||
|
/// - Signal line crossovers indicate trading opportunities
|
||||||
|
/// - Histogram shows momentum of price movement
|
||||||
|
/// - Divergences can signal potential reversals
|
||||||
|
///
|
||||||
|
/// Formula:
|
||||||
|
/// MACD Line = EMA(fast) - EMA(slow)
|
||||||
|
/// Signal Line = EMA(MACD Line, signal)
|
||||||
|
/// Histogram = MACD Line - Signal Line
|
||||||
|
///
|
||||||
|
/// Sources:
|
||||||
|
/// https://www.investopedia.com/terms/m/macd.asp
|
||||||
|
/// https://school.stockcharts.com/doku.php?id=technical_indicators:macd
|
||||||
|
/// </remarks>
|
||||||
|
|
||||||
|
[SkipLocalsInit]
|
||||||
|
public sealed class Macd : AbstractBase
|
||||||
|
{
|
||||||
|
private readonly Ema _fastEma;
|
||||||
|
private readonly Ema _slowEma;
|
||||||
|
private readonly Ema _signalEma;
|
||||||
|
private const int DefaultFastPeriod = 12;
|
||||||
|
private const int DefaultSlowPeriod = 26;
|
||||||
|
private const int DefaultSignalPeriod = 9;
|
||||||
|
private double _macdLine;
|
||||||
|
private double _signalLine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the MACD line value (Fast EMA - Slow EMA)
|
||||||
|
/// </summary>
|
||||||
|
public double MacdLine => _macdLine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Signal line value (EMA of MACD line)
|
||||||
|
/// </summary>
|
||||||
|
public double SignalLine => _signalLine;
|
||||||
|
|
||||||
|
/// <param name="fastPeriod">The number of periods for the fast EMA (default 12).</param>
|
||||||
|
/// <param name="slowPeriod">The number of periods for the slow EMA (default 26).</param>
|
||||||
|
/// <param name="signalPeriod">The number of periods for the signal line EMA (default 9).</param>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when any period is less than 1.</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Macd(int fastPeriod = DefaultFastPeriod, int slowPeriod = DefaultSlowPeriod, int signalPeriod = DefaultSignalPeriod)
|
||||||
|
{
|
||||||
|
if (fastPeriod < 1)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(fastPeriod));
|
||||||
|
if (slowPeriod < 1)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(slowPeriod));
|
||||||
|
if (signalPeriod < 1)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(signalPeriod));
|
||||||
|
if (fastPeriod >= slowPeriod)
|
||||||
|
throw new ArgumentException("Fast period must be less than slow period");
|
||||||
|
|
||||||
|
_fastEma = new(fastPeriod);
|
||||||
|
_slowEma = new(slowPeriod);
|
||||||
|
_signalEma = new(signalPeriod);
|
||||||
|
WarmupPeriod = slowPeriod + signalPeriod;
|
||||||
|
Name = $"MACD({fastPeriod},{slowPeriod},{signalPeriod})";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="source">The data source object that publishes updates.</param>
|
||||||
|
/// <param name="fastPeriod">The number of periods for the fast EMA.</param>
|
||||||
|
/// <param name="slowPeriod">The number of periods for the slow EMA.</param>
|
||||||
|
/// <param name="signalPeriod">The number of periods for the signal line EMA.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Macd(object source, int fastPeriod, int slowPeriod, int signalPeriod) : this(fastPeriod, slowPeriod, signalPeriod)
|
||||||
|
{
|
||||||
|
var pubEvent = source.GetType().GetEvent("Pub");
|
||||||
|
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
protected override void ManageState(bool isNew)
|
||||||
|
{
|
||||||
|
if (isNew)
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
protected override double Calculation()
|
||||||
|
{
|
||||||
|
ManageState(Input.IsNew);
|
||||||
|
|
||||||
|
// Calculate MACD line
|
||||||
|
double fastEma = _fastEma.Calc(Input.Value, Input.IsNew);
|
||||||
|
double slowEma = _slowEma.Calc(Input.Value, Input.IsNew);
|
||||||
|
_macdLine = fastEma - slowEma;
|
||||||
|
|
||||||
|
// Calculate Signal line
|
||||||
|
_signalLine = _signalEma.Calc(_macdLine, Input.IsNew);
|
||||||
|
|
||||||
|
// Return histogram
|
||||||
|
return _macdLine - _signalLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user