diff --git a/Source/Indicators/KAMA_Series.cs b/Source/Indicators/KAMA_Series.cs
index c9360ae5..eda39bc4 100644
--- a/Source/Indicators/KAMA_Series.cs
+++ b/Source/Indicators/KAMA_Series.cs
@@ -1,63 +1,67 @@
-namespace QuanTAlib;
-using System;
-
-/*
-KAMA: Kaufman's Adaptive Moving Average
- Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
- Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
- it was not until the popular book titled "Trading Systems and Methods" that it was made widely
- available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
- Moving Average, considers market volatility apart from price fluctuations.
-
- KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
-
-Sources:
- https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
- https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
- https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
-
-Remark:
- If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
- Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
- slightly different results for the first 50 bars - and then converges with the other one.
-
- */
-
-public class KAMA_Series : Single_TSeries_Indicator
-{
- private static double _scFast, _scSlow;
- private readonly System.Collections.Generic.List _buffer = new();
- private double _lastkama = double.NaN;
- private double _lastlastkama;
-
- public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
- _scFast = 2.0 / (fast+1);
- _scSlow = 2.0 / (slow+1);
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- public override void Add((System.DateTime t, double v) TValue, bool update) {
- if (update) {
- _buffer[_buffer.Count - 1] = TValue.v;
- this._lastkama = this._lastlastkama;
- }
- else {
- _buffer.Add(TValue.v);
- }
- if (_buffer.Count>_p+1) { _buffer.RemoveAt(0); }
- double _kama = TValue.v;
- double _change = Math.Abs( _buffer[_buffer.Count-1] - _buffer[(_buffer.Count>_p+1)?1:0]);
- double _sumpv = 0;
- for (int i = 1; i < _buffer.Count; i++) {
- _sumpv += Math.Abs(_buffer[(_buffer.Count>0)?i:0]- _buffer[i-1]);
- }
- double _er = (_sumpv==0)?0:_change/_sumpv;
- double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
- if (_buffer.Count==1) { _lastkama = _buffer[0]; }
-
- _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
- _lastlastkama = _lastkama;
- _lastkama = _kama;
- var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama);
- base.Add(result, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+KAMA: Kaufman's Adaptive Moving Average
+ Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
+ Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
+ it was not until the popular book titled "Trading Systems and Methods" that it was made widely
+ available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
+ Moving Average, considers market volatility apart from price fluctuations.
+
+ KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
+
+Sources:
+ https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
+ https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
+ https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
+
+Remark:
+ If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
+ Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
+ slightly different results for the first 50 bars - and then converges with the other one.
+
+ */
+
+public class KAMA_Series : Single_TSeries_Indicator
+{
+ private static double _scFast, _scSlow;
+ private readonly System.Collections.Generic.List _buffer = new();
+ private double _lastkama = double.NaN;
+ private double _lastlastkama;
+
+ public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
+ _scFast = 2.0 / (fast+1);
+ _scSlow = 2.0 / (slow+1);
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ if (update){
+ _buffer[_buffer.Count - 1] = TValue.v;
+ this._lastkama = this._lastlastkama;
+ } else {
+ _buffer.Add(TValue.v);
+ }
+ if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
+ double _kama = TValue.v;
+ if (this.Count < this._p) {
+ for (int i = 0; i < this._buffer.Count; i++) { _kama += this._buffer[i]; }
+ _kama /= this._buffer.Count;
+ } else {
+ double _change = Math.Abs(_buffer[_buffer.Count - 1] - _buffer[(_buffer.Count > _p + 1) ? 1 : 0]);
+ double _sumpv = 0;
+ for (int i = 1; i < _buffer.Count; i++)
+ {
+ _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]);
+ }
+ double _er = (_sumpv == 0) ? 0 : _change / _sumpv;
+ double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
+ _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
+ }
+ _lastlastkama = _lastkama;
+ _lastkama = _kama;
+ var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama);
+ base.Add(result, update);
+ }
}
\ No newline at end of file
diff --git a/Tests/MovingAvg/KAMA_Test.cs b/Tests/MovingAvg/KAMA_Test.cs
new file mode 100644
index 00000000..69e771c6
--- /dev/null
+++ b/Tests/MovingAvg/KAMA_Test.cs
@@ -0,0 +1,33 @@
+using Xunit;
+using System;
+using QuanTAlib;
+
+namespace MovingAvg;
+public class KAMA_Test
+{
+ [Fact]
+ public void Add_Test()
+ {
+ TSeries a = new() { 0, 1, 2, 3, 4, 5 };
+ KAMA_Series c = new(a, 3);
+ Assert.Equal(6, c.Count);
+ a.Add(5);
+ Assert.Equal(a.Count, c.Count);
+ a.Add(0, update: true);
+ Assert.Equal(a.Count, c.Count);
+ }
+
+ [Fact]
+ public void Edge_Test()
+ {
+ TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
+ KAMA_Series c = new(a, 3);
+ Assert.Equal(a.Count, c.Count);
+ a.Add(double.NaN);
+ Assert.Equal(a.Count, c.Count);
+ a.Add(double.PositiveInfinity);
+ Assert.Equal(a.Count, c.Count);
+
+ }
+
+}
diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs
index dc2de31d..a1adde8d 100644
--- a/Tests/Validations/Skender_Stock.cs
+++ b/Tests/Validations/Skender_Stock.cs
@@ -1,7 +1,7 @@
-using Xunit;
using System;
-using Skender.Stock.Indicators;
using QuanTAlib;
+using Skender.Stock.Indicators;
+using Xunit;
namespace Validation;
@@ -108,4 +108,13 @@ public class Skender_Stock
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 8), Math.Round(QL.Last().v, 8));
}
+
+ [Fact]
+ public void KAMA()
+ {
+ KAMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
+ var SK = this.quotes.GetKama(this.period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Kama!, 8), Math.Round(QL.Last().v, 8));
+ }
}