From af33331d8c2dca12c09c6883f39a65b0b1fa9403 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 7 Nov 2022 09:43:33 -0800 Subject: [PATCH] ADL with tests --- Source/Indicators/ADL_Series.cs | 43 ++++++++++++++++++++++++++++++ Tests/Validations/Skender_Stock.cs | 9 +++++++ Tests/Validations/TA_LIB.cs | 12 +++++++++ 3 files changed, 64 insertions(+) create mode 100644 Source/Indicators/ADL_Series.cs diff --git a/Source/Indicators/ADL_Series.cs b/Source/Indicators/ADL_Series.cs new file mode 100644 index 00000000..15822ba5 --- /dev/null +++ b/Source/Indicators/ADL_Series.cs @@ -0,0 +1,43 @@ +namespace QuanTAlib; +using System; + +/* +ADL: Chaikin Accumulation/Distribution Line + ADL is a volume-based indicator that measures the cumulative Money Flow Volume: + + 1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low) + 2. Money Flow Volume = Money Flow Multiplier x Volume for the Period + 3. ADL = Previous ADL + Current Period's Money Flow Volume + +Sources: + https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line + + */ + +public class ADL_Series : Single_TBars_Indicator +{ + private double _lastadl, _lastlastadl; + + public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN) + { + this._lastadl = this._lastlastadl = 0; + if (_bars.Count > 0) + { base.Add(_bars); } + } + + public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) + { + if (update) + { this._lastadl = this._lastlastadl; } + + double _mfm = ((TBar.c - TBar.l) - (TBar.h - TBar.c)) / (TBar.h - TBar.l); + double _mfv = _mfm * TBar.v; + double _adl = this._lastadl + _mfv; + + this._lastlastadl = this._lastadl; + this._lastadl = _adl; + + var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl); + base.Add(ret, update); + } +} \ No newline at end of file diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs index 319ed5ca..ad4ab415 100644 --- a/Tests/Validations/Skender_Stock.cs +++ b/Tests/Validations/Skender_Stock.cs @@ -99,6 +99,15 @@ public class Skender_Stock Assert.Equal(Math.Round((double)SK.Last().Atr!, 8), Math.Round(QL.Last().v, 8)); } + [Fact] + public void ADL() + { + ADL_Series QL = new(this.bars, false); + var SK = this.quotes.GetAdl(); + + Assert.Equal(Math.Round((double)SK.Last().Adl!, 6), Math.Round(QL.Last().v, 6)); + } + [Fact] public void CCI() { diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs index fef809ac..d6aaf804 100644 --- a/Tests/Validations/TA_LIB.cs +++ b/Tests/Validations/TA_LIB.cs @@ -13,6 +13,7 @@ public class TA_LIB private readonly double[] inhigh; private readonly double[] inlow; private readonly double[] inclose; + private readonly double[] involume; public TA_LIB() { @@ -22,6 +23,7 @@ public class TA_LIB this.inhigh = this.bars.High.v.ToArray(); this.inlow = this.bars.Low.v.ToArray(); this.inclose = this.bars.Close.v.ToArray(); + this.involume = this.bars.Volume.v.ToArray(); } ///////////////////////////////////////// @@ -98,6 +100,16 @@ public class TA_LIB Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); } + [Fact] + public void ADL() + { + ADL_Series QL = new(this.bars, false); + Core.Ad(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); + + Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); + } + + [Fact] public void ATR() {