mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-01 11:17:46 +00:00
KAMA w. SMA warmup
This commit is contained in:
@@ -1,63 +1,67 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
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.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KAMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private static double _scFast, _scSlow;
|
||||
private readonly System.Collections.Generic.List<double> _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;
|
||||
|
||||
/* <summary>
|
||||
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.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KAMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private static double _scFast, _scSlow;
|
||||
private readonly System.Collections.Generic.List<double> _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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user