diff --git a/Algorithm/QCAlgorithm.Indicators.cs b/Algorithm/QCAlgorithm.Indicators.cs index 319460cd9236..da2faf1c059a 100644 --- a/Algorithm/QCAlgorithm.Indicators.cs +++ b/Algorithm/QCAlgorithm.Indicators.cs @@ -1292,9 +1292,9 @@ public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resoluti /// Optional function to select a value from the BaseData. Defaults to casting the input to a TradeBar. /// The Mesa Adaptive Moving Average (MAMA) indicator for the requested symbol with the specified limits. [DocumentationAttribute(Indicators)] - public MesaAdaptiveMovingAverage MAMA(Symbol symbol, decimal fastLimit = 0.5m, decimal slowLimit = 0.05m, Resolution? resolution = null, Func selector = null) + public MesaAdaptiveMovingAverage MAMA(Symbol symbol, decimal fastLimit = 0.5m, decimal slowLimit = 0.05m, Resolution? resolution = null, Func selector = null) { - var name = CreateIndicatorName(symbol, $"MAMA", resolution); + var name = CreateIndicatorName(symbol, $"MAMA({fastLimit},{slowLimit})", resolution); var mesaAdaptiveMovingAverage = new MesaAdaptiveMovingAverage(name, fastLimit, slowLimit); InitializeIndicator(mesaAdaptiveMovingAverage, resolution, selector, symbol); return mesaAdaptiveMovingAverage; diff --git a/Indicators/MesaAdaptiveMovingAverage.cs b/Indicators/MesaAdaptiveMovingAverage.cs index 57f85baea271..dd3cee308545 100644 --- a/Indicators/MesaAdaptiveMovingAverage.cs +++ b/Indicators/MesaAdaptiveMovingAverage.cs @@ -52,10 +52,10 @@ public class MesaAdaptiveMovingAverage : BarIndicator, IIndicatorWarmUpPeriodPro /// Variables holding previous calculation values for use in subsequent iterations. /// private decimal _prevPeriod; - private decimal _prevI2; - private decimal _prevQ2; - private decimal _prevRe; - private decimal _prevIm; + private decimal _prevInPhase2; + private decimal _prevQuadrature2; + private decimal _prevReal; + private decimal _prevImaginary; private decimal _prevSmoothPeriod; private decimal _prevPhase; private decimal _prevMama; @@ -82,10 +82,10 @@ public MesaAdaptiveMovingAverage(string name, decimal fastLimit = 0.5m, decimal _inPhaseHistory = new RollingWindow(6); _quadratureHistory = new RollingWindow(6); _prevPeriod = 0m; - _prevI2 = 0m; - _prevQ2 = 0m; - _prevRe = 0m; - _prevIm = 0m; + _prevInPhase2 = 0m; + _prevQuadrature2 = 0m; + _prevReal = 0m; + _prevImaginary = 0m; _prevSmoothPeriod = 0m; _prevPhase = 0m; _prevMama = 0m; @@ -147,10 +147,8 @@ protected override decimal ComputeNextValue(IBaseDataBar input) private (decimal, decimal) ComputeMamaAndFama() { - // Small Coefficient - const decimal sC = 0.0962m; - // Large Coefficient - const decimal lC = 0.5769m; + const decimal smallCoefficient = 0.0962m; + const decimal largeCoefficient = 0.5769m; var adjustedPeriod = 0.075m * _prevPeriod + 0.54m; @@ -158,24 +156,24 @@ protected override decimal ComputeNextValue(IBaseDataBar input) var smooth = (4 * _priceHistory[0] + 3 * _priceHistory[1] + 2 * _priceHistory[2] + _priceHistory[3]) / 10; // Detrend the smoothed price to remove market noise, applying coefficients and adjusted period. - var detrender = (sC * smooth + lC * _smoothHistory[1] - lC * _smoothHistory[3] - sC * _smoothHistory[5]) * adjustedPeriod; + var detrender = (smallCoefficient * smooth + largeCoefficient * _smoothHistory[1] - largeCoefficient * _smoothHistory[3] - smallCoefficient * _smoothHistory[5]) * adjustedPeriod; // Compute the InPhase (I1) and Quadrature (Q1) components for the adaptive moving average. - var q1 = (sC * detrender + lC * _detrendHistory[1] - lC * _detrendHistory[3] - sC * _detrendHistory[5]) * adjustedPeriod; - var i1 = _detrendHistory[2]; + var quadrature1 = (smallCoefficient * detrender + largeCoefficient * _detrendHistory[1] - largeCoefficient * _detrendHistory[3] - smallCoefficient * _detrendHistory[5]) * adjustedPeriod; + var inPhase1 = _detrendHistory[2]; // Advance the phase of I1 and Q1 by 90 degrees - var ji = (sC * i1 + lC * _inPhaseHistory[1] - lC * _inPhaseHistory[3] - sC * _inPhaseHistory[5]) * adjustedPeriod; - var jq = (sC * q1 + lC * _quadratureHistory[1] - lC * _quadratureHistory[3] - sC * _quadratureHistory[5]) * adjustedPeriod; - var i2 = i1 - jq; - var q2 = q1 + ji; + var adjustedInPhase = (smallCoefficient * inPhase1 + largeCoefficient * _inPhaseHistory[1] - largeCoefficient * _inPhaseHistory[3] - smallCoefficient * _inPhaseHistory[5]) * adjustedPeriod; + var adjustedQuadrature = (smallCoefficient * quadrature1 + largeCoefficient * _quadratureHistory[1] - largeCoefficient * _quadratureHistory[3] - smallCoefficient * _quadratureHistory[5]) * adjustedPeriod; + var inPhase2 = inPhase1 - adjustedQuadrature; + var quadrature2 = quadrature1 + adjustedInPhase; // Smooth the I2 and Q2 components before applying the discriminator - i2 = 0.2m * i2 + 0.8m * _prevI2; - q2 = 0.2m * q2 + 0.8m * _prevQ2; + inPhase2 = 0.2m * inPhase2 + 0.8m * _prevInPhase2; + quadrature2 = 0.2m * quadrature2 + 0.8m * _prevQuadrature2; // Get alpha - var alpha = ComputeAlpha(i1, q1, i2, q2); + var alpha = ComputeAlpha(inPhase1, quadrature1, inPhase2, quadrature2); // Calculate the MAMA and FAMA var mama = alpha * _priceHistory[0] + (1m - alpha) * _prevMama; @@ -184,24 +182,24 @@ protected override decimal ComputeNextValue(IBaseDataBar input) // Update rolling history _smoothHistory.Add(smooth); _detrendHistory.Add(detrender); - _inPhaseHistory.Add(i1); - _quadratureHistory.Add(q1); + _inPhaseHistory.Add(inPhase1); + _quadratureHistory.Add(quadrature1); return (mama, fama); } - private decimal ComputeAlpha(decimal i1, decimal q1, decimal i2, decimal q2) + private decimal ComputeAlpha(decimal inPhase1, decimal quadrature1, decimal inPhase2, decimal quadrature2) { - var re = i2 * _prevI2 + q2 * _prevQ2; - var im = i2 * _prevQ2 - q2 * _prevI2; - re = 0.2m * re + 0.8m * _prevRe; - im = 0.2m * im + 0.8m * _prevIm; + var real = inPhase2 * _prevInPhase2 + quadrature2 * _prevQuadrature2; + var imaginary = inPhase2 * _prevQuadrature2 - quadrature2 * _prevInPhase2; + real = 0.2m * real + 0.8m * _prevReal; + imaginary = 0.2m * imaginary + 0.8m * _prevImaginary; // Calculate the period var period = 0m; - if (im != 0 && re != 0) + if (imaginary != 0 && real != 0) { - var angleInDegrees = (decimal)Math.Atan((double)(im / re)) * _rad2Deg; + var angleInDegrees = (decimal)Math.Atan((double)(imaginary / real)) * _rad2Deg; period = (angleInDegrees > 0) ? 360m / angleInDegrees : 0m; } @@ -229,9 +227,9 @@ private decimal ComputeAlpha(decimal i1, decimal q1, decimal i2, decimal q2) // Calculate the phase var phase = 0m; - if (i1 != 0) + if (inPhase1 != 0) { - phase = (decimal)Math.Atan((double)(q1 / i1)) * _rad2Deg; + phase = (decimal)Math.Atan((double)(quadrature1 / inPhase1)) * _rad2Deg; } // Calculate the delta phase @@ -249,10 +247,10 @@ private decimal ComputeAlpha(decimal i1, decimal q1, decimal i2, decimal q2) } // Update previous values - _prevI2 = i2; - _prevQ2 = q2; - _prevRe = re; - _prevIm = im; + _prevInPhase2 = inPhase2; + _prevQuadrature2 = quadrature2; + _prevReal = real; + _prevImaginary = imaginary; _prevPeriod = period; _prevSmoothPeriod = smoothPeriod; _prevPhase = phase; @@ -271,10 +269,10 @@ public override void Reset() _inPhaseHistory.Reset(); _quadratureHistory.Reset(); _prevPeriod = 0m; - _prevI2 = 0m; - _prevQ2 = 0m; - _prevRe = 0m; - _prevIm = 0m; + _prevInPhase2 = 0m; + _prevQuadrature2 = 0m; + _prevReal = 0m; + _prevImaginary = 0m; _prevSmoothPeriod = 0m; _prevPhase = 0m; _prevMama = 0m;