diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj index a2f23bc1..29aa29ae 100644 --- a/Source/QuanTAlib.csproj +++ b/Source/QuanTAlib.csproj @@ -2,7 +2,7 @@ QuanTAlib - 0.1.22 + 0.1.23 Library of Technical Indicators for .NET Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis git diff --git a/Source/Trends/DWMA_Series.cs b/Source/Trends/DWMA_Series.cs new file mode 100644 index 00000000..0cff2aec --- /dev/null +++ b/Source/Trends/DWMA_Series.cs @@ -0,0 +1,39 @@ +namespace QuanTAlib; +using System; + +/* +DWMA: Double (linearly) Weighted Moving Average + The weights are linearly decreasing over the period and the most recent data has + the heaviest weight. + +Sources: + + + */ + +public class DWMA_Series : Single_TSeries_Indicator +{ + public DWMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) + { + for (int i = 0; i < this._p; i++) { this._weights.Add(i + 1); } + if (base._data.Count > 0) { base.Add(base._data); } + } + private readonly System.Collections.Generic.List _buffer1 = new(); + private readonly System.Collections.Generic.List _buffer2 = new(); + private readonly System.Collections.Generic.List _weights = new(); + + public override void Add((System.DateTime t, double v) TValue, bool update) + { + Add_Replace_Trim(_buffer1, TValue.v, _p, update); + double _wma = 0; + for (int i = 0; i < _buffer1.Count; i++) { _wma += _buffer1[i] * this._weights[i]; } + _wma /= (this._buffer1.Count * (this._buffer1.Count + 1)) * 0.5; + + Add_Replace_Trim(_buffer2, TValue.v, _p, update); + double _dwma = 0; + for (int i = 0; i < _buffer2.Count; i++) { _dwma += _buffer2[i] * this._weights[i]; } + _dwma /= (this._buffer2.Count * (this._buffer2.Count + 1)) * 0.5; + + base.Add((TValue.t, _dwma), update, _NaN); + } +} \ No newline at end of file diff --git a/Source/Trends/JMA_Series.cs b/Source/Trends/JMA_Series.cs index 54e588ee..94b17d56 100644 --- a/Source/Trends/JMA_Series.cs +++ b/Source/Trends/JMA_Series.cs @@ -1,5 +1,6 @@ namespace QuanTAlib; using System; +using System.Linq; /* JMA: Jurik Moving Average @@ -18,141 +19,81 @@ Issues: original algo is slightly different, yet this approximation is close enough. -TODO: buggy - rework */ +public class JMA_Series : Single_TSeries_Indicator { + private readonly System.Collections.Generic.List volty_10 = new(); + private readonly System.Collections.Generic.List vsum_buff = new(); + private readonly double pr, beta; -public class JMA_Series : Single_TSeries_Indicator -{ - private readonly System.Collections.Generic.List vbuffer10; - private readonly System.Collections.Generic.List vsum65; + private double upperBand, lowerBand, _phase, vsum, Kv, del1, del2, prev_del1, prev_del2; + private double prev_ma1, prev_det0, prev_det1, prev_vsum, prev_jma; + private double p_upperBand, p_lowerBand, p_Kv, p_prev_ma1, p_prev_det0, p_prev_det1, p_prev_vsum, p_prev_jma; - private double prev_ma1, prev_det0, prev_det1, prev_jma, bsmax, bsmin; - private double o_prev_ma1, o_prev_det0, o_prev_det1, o_prev_jma, o_bsmax, o_bsmin; + public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN) { + upperBand = lowerBand = prev_ma1 = prev_det0 = prev_det1 = prev_vsum = prev_jma = Kv = del1 = del2 = 0.0; + Kv = 0; + pr = (phase * 0.01) + 1.5; + if (phase < -100) pr = 0.5; + if (phase > 100) pr = 2.5; + beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2); - private readonly double pr, pow1, len2, beta, rvolty; + if (base._data.Count > 0) { base.Add(base._data); } + } - public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN) - { - this.vbuffer10 = new(); - this.vsum65 = new(); + public override void Add((System.DateTime t, double v) TValue, bool update) { + if (update) { + upperBand = p_upperBand; lowerBand = p_lowerBand; Kv = p_Kv; prev_vsum = p_prev_vsum; + prev_ma1 = p_prev_ma1; prev_det0 = p_prev_det0; prev_det1 = p_prev_det1; prev_jma = p_prev_jma; + } else { + p_upperBand = upperBand; p_lowerBand = lowerBand; p_Kv = Kv; p_prev_vsum = prev_vsum; + p_prev_ma1 = prev_ma1; p_prev_det0 = prev_det0; p_prev_det1 = prev_det1; p_prev_jma = prev_jma; + } - // constants - this.pr = (phase < -100) ? 0.5 : (phase > 100) ? 2.5 : (phase * 0.01) + 1.5; - double len1 = Math.Max((Math.Log(Math.Sqrt(0.5 * (_p - 1))) / Math.Log(2.0)) + 2.0, 0); - this.pow1 = Math.Max(len1 - 2, 0.5); - this.rvolty = Math.Exp((1 / this.pow1) * Math.Log(len1)); - this.len2 = Math.Sqrt(0.5 * (_p - 1)) * len1; - this.beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2); - if (base._data.Count > 0) { base.Add(base._data); } - } + // from Tvalue to volty + del1 = TValue.v - upperBand; + del2 = TValue.v - lowerBand; + upperBand = (del1 > 0) ? TValue.v : TValue.v - (Kv * del1); + lowerBand = (del2 < 0) ? TValue.v : TValue.v - (Kv * del2); + double volty = 0; + if (Math.Abs(del1) > Math.Abs(del2)) { volty = Math.Abs(del1); } + if (Math.Abs(del1) < Math.Abs(del2)) { volty = Math.Abs(del2); } - public override void Add((System.DateTime t, double v) TValue, bool update) - { - if (this.Count == 0) - { - this.prev_ma1 = this.prev_jma = TValue.v; - this.bsmax = this.bsmin = this.prev_det0 = this.prev_det1 = 0; - } + //// from volty to avolty + if (update) { volty_10[volty_10.Count - 1] = volty; } else { volty_10.Add(volty); } + if (volty_10.Count > 10) { volty_10.RemoveAt(0); } + vsum = prev_vsum + 0.1 * (volty - volty_10.First()); + if (update) { vsum_buff[vsum_buff.Count - 1] = vsum; } else { vsum_buff.Add(vsum); } + if (vsum_buff.Count > 65) vsum_buff.RemoveAt(0); + double avolty = 0; + for (int i = 0; i < vsum_buff.Count; i++) { avolty += vsum_buff[i]; } + avolty /= vsum_buff.Count; - if (update) - { - this.prev_jma = this.o_prev_jma; - this.prev_ma1 = this.o_prev_ma1; - this.prev_det0 = this.o_prev_det0; - this.prev_det1 = this.o_prev_det1; - this.bsmax = this.o_bsmax; - this.bsmin = this.o_bsmin; - } - else - { - this.o_prev_jma = this.prev_jma; - this.o_prev_ma1 = this.prev_ma1; - this.o_prev_det0 = this.prev_det0; - this.o_prev_det1 = this.prev_det1; - this.o_bsmax = this.bsmax; - this.o_bsmin = this.bsmin; - } + /// from avolty to rolty + double rvolty = (avolty > 0) ? volty / avolty : 0; + double len1 = (Math.Log(Math.Sqrt(_p)) / Math.Log(2.0)) + 2; + if (len1 < 0) len1 = 0; + double pow1 = Math.Max(len1 - 2.0, 0.5); + if (rvolty > Math.Pow(len1, 1.0 / pow1)) rvolty = Math.Pow(len1, 1.0 / pow1); + if (rvolty < 1) rvolty = 1; - double hprice = TValue.v; - double lprice = TValue.v; - for (int i = 0; i <= Math.Min(9, this._data.Count - 1); i++) - { - var _item = this._data[this._data.Count - 1 - i].v; - hprice = (_item > hprice) ? _item : hprice; - lprice = (_item < lprice) ? _item : lprice; - } - double del1 = hprice - this.bsmax; - double del2 = lprice - this.bsmin; + //// from rvolty to second smoothing + double pow2 = Math.Pow(rvolty, pow1); + double len2 = Math.Sqrt(0.5 * (_p - 1)) * len1; + Kv = Math.Pow(len2 / (len2 + 1), Math.Sqrt(pow2)); + double alpha = Math.Pow(beta, pow2); + double ma1 = (1 - alpha) * TValue.v + alpha * prev_ma1; + prev_ma1 = ma1; + double det0 = (1 - beta) * (TValue.v - ma1) + beta * prev_det0; + prev_det0 = det0; - double volty = (Math.Abs(del1) != Math.Abs(del2)) - ? Math.Max(Math.Abs(del1), Math.Abs(del2)) - : 0; - if (update) - { - this.vbuffer10[this.vbuffer10.Count - 1] = volty; - } - else - { - this.vbuffer10.Add(volty); - } - if (this.vbuffer10.Count > 10) - { - this.vbuffer10.RemoveAt(0); - } + /// from second smoothing to jma + double ma2 = ma1 + pr * det0; + double det1 = (1 - alpha) * (1 - alpha) * (ma2 - prev_jma) + alpha * alpha * prev_det1; + prev_det1 = det1; + double jma = prev_jma + det1; + prev_jma = jma; - double prevvsum = - (this.vsum65.Count > 0) ? this.vsum65[this.vsum65.Count - 1] : 0; - double vsumitem = prevvsum + 0.1 * (volty - this.vbuffer10[0]); - if (update) - { - this.vsum65[this.vsum65.Count - 1] = vsumitem; - } - else - { - this.vsum65.Add(vsumitem); - } - if (this.vsum65.Count > 65) - { - this.vsum65.RemoveAt(0); - } + base.Add((TValue.t, jma), update, _NaN); + } +} - double avolty = 0; - for (int i = 0; i < this.vsum65.Count; i++) - { - avolty += this.vsum65[i]; - } - - avolty /= this.vsum65.Count; - double dvolty = (avolty > 0) ? volty / avolty : 0; - dvolty = Math.Max((dvolty > this.rvolty) ? this.rvolty : dvolty, 1.0); - - double pow2 = Math.Exp(this.pow1 * Math.Log(dvolty)); - double kv = - Math.Exp(Math.Sqrt(pow2) * Math.Log(this.len2 / (this.len2 + 1))); - - this.bsmax = (del1 > 0) ? hprice : hprice - (kv * del1); - this.bsmin = (del2 < 0) ? lprice : lprice - (kv * del2); - - // adaptive EMA dynamic factor - double pow = Math.Pow(dvolty, this.pow1); - double alpha = Math.Pow(this.beta, pow); - - // 1st stage - preliminary smoothing by adaptive EMA - double ma1 = TValue.v * (1 - alpha) + this.prev_ma1 * alpha; - this.prev_ma1 = ma1; - - // 2nd stage - one more preliminary smoothing by Kalman filter - double det0 = (TValue.v - ma1) * (1 - this.beta) + this.prev_det0 * this.beta; - this.prev_det0 = det0; - double ma2 = ma1 + (this.pr * det0); - - // 3rd stage - final smoothing by Jurik adaptive filter - double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) + - (this.prev_det1 * alpha * alpha); - this.prev_det1 = det1; - var _jma = this.prev_jma + det1; - this.prev_jma = _jma; - - base.Add((TValue.t, _jma), update, _NaN); - } -} \ No newline at end of file diff --git a/Tests/Series/Update.cs b/Tests/Series/Update.cs index 4c37428e..ad8260e1 100644 --- a/Tests/Series/Update.cs +++ b/Tests/Series/Update.cs @@ -124,7 +124,18 @@ public class Update { Assert.Equal(lastLen, QL.Count); // same size Assert.Equal(lastCalc, QL.Last()); // same data } - [Fact] public void ENTROPY() { + [Fact] + public void DWMA() { + DWMA_Series QL = new(source: bars.Close, period); + var lastData = bars.Close.Last(); + var lastCalc = QL.Last(); + int lastLen = QL.Count; + QL.Add((DateTime.Today, 0), update: true); + QL.Add(lastData, update: true); + Assert.Equal(lastLen, QL.Count); // same size + Assert.Equal(lastCalc, QL.Last()); // same data + } + [Fact] public void ENTROPY() { ENTROPY_Series QL = new(source: bars.Close, period: period); var lastData = bars.Close.Last(); var lastCalc = QL.Last(); diff --git a/Tests/Validations/DEMA_Test.cs b/Tests/Validations/DEMA_Test.cs deleted file mode 100644 index 7a393154..00000000 --- a/Tests/Validations/DEMA_Test.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using QuanTAlib; -using Skender.Stock.Indicators; -using Tulip; -using Python.Runtime; -using Python.Included; -using TALib; -using Validations; -using Xunit; - -namespace One.by.one; -public class Dema : IDisposable -{ - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, skip; - private readonly double precision; - - private readonly IEnumerable quotes; - private readonly double[] outdata; - private readonly double[] inopen; - private readonly double[] inhigh; - private readonly double[] inlow; - private readonly double[] inclose; - private readonly double[] involume; - - private readonly string OStype; - private readonly dynamic np; - private readonly dynamic ta; - private readonly dynamic df; - - public void Dispose() { - PythonEngine.Shutdown(); - GC.SuppressFinalize(this); - } - public Dema() - { - bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0); - period = rnd.Next(30) + 5; - skip = period*8; - precision = 1e-6; - - quotes = bars.Select(q => new Quote - { - Date = q.t, - Open = (decimal)q.o, - High = (decimal)q.h, - Low = (decimal)q.l, - Close = (decimal)q.c, - Volume = (decimal)q.v - }); - - outdata = new double[bars.Count]; - inopen = bars.Open.v.ToArray(); - inhigh = bars.High.v.ToArray(); - inlow = bars.Low.v.ToArray(); - inclose = bars.Close.v.ToArray(); - involume = bars.Volume.v.ToArray(); - - // Checking the host OS and setting PythonDLL accordingly - OStype = Environment.OSVersion.ToString(); - if (OStype == "Unix 13.1.0") - OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib"; - else - OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; - - Installer.InstallPath = Path.GetFullPath(path: "."); - Installer.SetupPython().Wait(); - Installer.TryInstallPip(); - Installer.PipInstallModule(module_name: "pandas-ta"); - Runtime.PythonDLL = OStype; - PythonEngine.Initialize(); - np = Py.Import(name: "numpy"); - ta = Py.Import(name: "pandas_ta"); - - string[] cols = { "open", "high", "low", "close", "volume" }; - double[,] ary = new double[bars.Count, 5]; - for (int i = 0; i < bars.Count; i++) { - ary[i, 0] = bars.Open[i].v; - ary[i, 1] = bars.High[i].v; - ary[i, 2] = bars.Low[i].v; - ary[i, 3] = bars.Close[i].v; - ary[i, 4] = bars.Volume[i].v; - } - df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols)); - } - [Fact] - public void WeirdData() { - DEMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((new DateTime(), double.Epsilon), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - } - [Fact] - public void Updating() { - DEMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - int lastLen = QL.Count; - QL.Add((DateTime.Today, 0), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastLen, QL.Count); // same size - Assert.Equal(lastCalc, QL.Last()); // same data - } - [Fact] - public void Skender_Test() - { - DEMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -precision, precision); - - } - } - [Fact] - public void TALIB_Test() - { - DEMA_Series QL = new(bars.Close, period, false); - Core.Dema(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TA_item = outdata[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -precision, precision); - } - } - [Fact] - public void Tulip_Test() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - DEMA_Series QL = new(bars.Close, period: period, useNaN: false); - Tulip.Indicators.dema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip*3; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -precision, precision); - } - } - [Fact] - void PandasTA_Test() { - DEMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.dema(close: df.close, length: period); - for (int i = QL.Length; i > skip; i--) { - double QL_item = QL[i - 1].v; - double PanTA_item = (double)pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -1e-5, 1e-5); - } - } -} diff --git a/Tests/Validations/EMA_Test.cs b/Tests/Validations/EMA_Test.cs deleted file mode 100644 index cc20f75a..00000000 --- a/Tests/Validations/EMA_Test.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using QuanTAlib; -using Skender.Stock.Indicators; -using Tulip; -using Python.Runtime; -using Python.Included; -using TALib; -using Validations; -using Xunit; - -namespace One.by.one; -public class Ema : IDisposable -{ - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, skip; - private readonly double precision; - - private readonly IEnumerable quotes; - private readonly double[] outdata; - private readonly double[] inopen; - private readonly double[] inhigh; - private readonly double[] inlow; - private readonly double[] inclose; - private readonly double[] involume; - - private readonly string OStype; - private readonly dynamic np; - private readonly dynamic ta; - private readonly dynamic df; - - public void Dispose() { - PythonEngine.Shutdown(); - GC.SuppressFinalize(this); - } - public Ema() - { - bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0); - period = rnd.Next(30) + 5; - skip = period-1; - precision = 1e-8; - - quotes = bars.Select(q => new Quote - { - Date = q.t, - Open = (decimal)q.o, - High = (decimal)q.h, - Low = (decimal)q.l, - Close = (decimal)q.c, - Volume = (decimal)q.v - }); - - outdata = new double[bars.Count]; - inopen = bars.Open.v.ToArray(); - inhigh = bars.High.v.ToArray(); - inlow = bars.Low.v.ToArray(); - inclose = bars.Close.v.ToArray(); - involume = bars.Volume.v.ToArray(); - - // Checking the host OS and setting PythonDLL accordingly - OStype = Environment.OSVersion.ToString(); - if (OStype == "Unix 13.1.0") - OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib"; - else - OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; - - Installer.InstallPath = Path.GetFullPath(path: "."); - Installer.SetupPython().Wait(); - Installer.TryInstallPip(); - Installer.PipInstallModule(module_name: "pandas-ta"); - Runtime.PythonDLL = OStype; - PythonEngine.Initialize(); - np = Py.Import(name: "numpy"); - ta = Py.Import(name: "pandas_ta"); - - string[] cols = { "open", "high", "low", "close", "volume" }; - double[,] ary = new double[bars.Count, 5]; - for (int i = 0; i < bars.Count; i++) { - ary[i, 0] = bars.Open[i].v; - ary[i, 1] = bars.High[i].v; - ary[i, 2] = bars.Low[i].v; - ary[i, 3] = bars.Close[i].v; - ary[i, 4] = bars.Volume[i].v; - } - df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols)); - } - [Fact] - public void WeirdData() { - EMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((new DateTime(), double.Epsilon), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - } - [Fact] - public void Updating() { - EMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - int lastLen = QL.Count; - QL.Add((DateTime.Today, 0), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastLen, QL.Count); // same size - Assert.Equal(lastCalc, QL.Last()); // same data - } - [Fact] - public void Skender_Test() - { - EMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetEma(period).Select(i => i.Ema.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -precision, precision); - - } - } - [Fact] - public void TALIB_Test() - { - EMA_Series QL = new(bars.Close, period, false); - Core.Ema(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TA_item = outdata[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -precision, precision); - } - } - [Fact] - public void Tulip_Test() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - EMA_Series QL = new(bars.Close, period: period, useNaN: false, useSMA: false); - Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -precision, precision); - } - } - [Fact] - void PandasTA_Test() { - EMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.ema(close: df.close, length: period); - for (int i = QL.Length; i > skip; i--) { - double QL_item = QL[i - 1].v; - double PanTA_item = (double)pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -1e-5, 1e-5); - } - } -} diff --git a/Tests/Validations/SMA_Test.cs b/Tests/Validations/SMA_Test.cs deleted file mode 100644 index eaaf3d7c..00000000 --- a/Tests/Validations/SMA_Test.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using QuanTAlib; -using Skender.Stock.Indicators; -using Tulip; -using Python.Runtime; -using Python.Included; -using TALib; -using Validations; -using Xunit; - -namespace One.by.one; -public class SMA : IDisposable { - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, skip; - private readonly double precision; - - private readonly IEnumerable quotes; - private readonly double[] outdata; - private readonly double[] inopen; - private readonly double[] inhigh; - private readonly double[] inlow; - private readonly double[] inclose; - private readonly double[] involume; - - private readonly string OStype; - private readonly dynamic np; - private readonly dynamic ta; - private readonly dynamic df; - - public void Dispose() { - PythonEngine.Shutdown(); - GC.SuppressFinalize(this); - } - public SMA() { - bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0); - period = rnd.Next(30) + 5; - precision = 1e-8; - skip = period-1; - - quotes = bars.Select(q => new Quote { - Date = q.t, - Open = (decimal)q.o, - High = (decimal)q.h, - Low = (decimal)q.l, - Close = (decimal)q.c, - Volume = (decimal)q.v - }); - - outdata = new double[bars.Count]; - inopen = bars.Open.v.ToArray(); - inhigh = bars.High.v.ToArray(); - inlow = bars.Low.v.ToArray(); - inclose = bars.Close.v.ToArray(); - involume = bars.Volume.v.ToArray(); - - // Checking the host OS and setting PythonDLL accordingly - OStype = Environment.OSVersion.ToString(); - if (OStype == "Unix 13.1.0") - OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib"; - else - OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; - - Installer.InstallPath = Path.GetFullPath(path: "."); - Installer.SetupPython().Wait(); - Installer.TryInstallPip(); - Installer.PipInstallModule(module_name: "pandas-ta"); - Runtime.PythonDLL = OStype; - PythonEngine.Initialize(); - np = Py.Import(name: "numpy"); - ta = Py.Import(name: "pandas_ta"); - - string[] cols = { "open", "high", "low", "close", "volume" }; - double[,] ary = new double[bars.Count, 5]; - for (int i = 0; i < bars.Count; i++) { - ary[i, 0] = bars.Open[i].v; - ary[i, 1] = bars.High[i].v; - ary[i, 2] = bars.Low[i].v; - ary[i, 3] = bars.Close[i].v; - ary[i, 4] = bars.Volume[i].v; - } - df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols)); - } - [Fact] - public void WeirdData() { - SMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - - QL.Add((new DateTime(), double.Epsilon), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastCalc, QL.Last()); // back to the same data - } - [Fact] - public void Updating() { - SMA_Series QL = new(source: bars.Close, period); - var lastData = bars.Close.Last(); - var lastCalc = QL.Last(); - int lastLen = QL.Count; - QL.Add((DateTime.Today, 0), update: true); - Assert.NotEqual(lastCalc, QL.Last()); //value changed - QL.Add(lastData, update: true); - Assert.Equal(lastLen, QL.Count); // same size - Assert.Equal(lastCalc, QL.Last()); // same data - } - [Fact] - public void Skender_Test() { - SMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -precision, precision); - } - } - [Fact] - public void TALIB_Test() { - SMA_Series QL = new(bars.Close, period, false); - Core.Sma(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TA_item = outdata[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -precision, precision); - - } - } - [Fact] - public void Tulip_Test() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - SMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -precision, precision); - - } - } - [Fact] - void PandasTA_Test() { - SMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.sma(close: df.close, length: period); - for (int i = QL.Length; i > skip; i--) { - double QL_item = QL[i - 1].v; - double PanTA_item = (double)pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -precision, precision); - } - } -} diff --git a/Tests/Validations/Trends/Pandas_TA.cs b/Tests/Validations/Trends/Pandas_TA.cs index cfe24689..e38c82a9 100644 --- a/Tests/Validations/Trends/Pandas_TA.cs +++ b/Tests/Validations/Trends/Pandas_TA.cs @@ -20,7 +20,7 @@ public class PandasTA : IDisposable bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0); period = rnd.Next(maxValue: 28) + 3; sample = 200; - digits = 3; //minimizing rounding errors in type conversions + digits = 10; // Checking the host OS and setting PythonDLL accordingly OStype = Environment.OSVersion.ToString(); @@ -61,7 +61,8 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i-1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i-1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } [Fact] void ADOSC() { @@ -71,7 +72,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void ATR() { @@ -81,7 +82,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void BIAS() { @@ -91,7 +92,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void DEMA() { @@ -101,7 +102,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void EMA() { @@ -111,7 +112,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void ENTROPY() { @@ -121,7 +122,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void HL2() { @@ -130,7 +131,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(bars.HL2[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void HLC3() { @@ -139,7 +140,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(bars.HLC3[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void HMA() { @@ -149,7 +150,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } @@ -160,7 +161,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void KURTOSIS() { @@ -170,7 +171,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void MAD() @@ -181,7 +182,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void MEDIAN() { @@ -191,7 +192,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void OBV() { @@ -201,7 +202,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void OHLC4() { @@ -210,7 +211,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(bars.OHLC4[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void RMA() { @@ -220,7 +221,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void RSI() { @@ -230,7 +231,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void SDEV() { @@ -240,7 +241,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void SMA() { @@ -250,7 +251,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void SSDEV() { @@ -260,7 +261,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } /* @@ -271,7 +272,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } */ @@ -282,7 +283,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void TEMA() { @@ -292,7 +293,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void TR() { @@ -302,7 +303,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void TRIMA() { @@ -313,7 +314,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void VARIANCE() { @@ -323,7 +324,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void WMA() { @@ -333,7 +334,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void ZLEMA() { @@ -343,7 +344,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] void ZSCORE() { @@ -353,7 +354,7 @@ public class PandasTA : IDisposable { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double PanTA_item = Math.Round((double)pta[i - 1], digits: digits); - Assert.Equal(PanTA_item, QL_item); + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } diff --git a/Tests/Validations/Trends/Skender.cs b/Tests/Validations/Trends/Skender.cs index b1796f86..0efda3dd 100644 --- a/Tests/Validations/Trends/Skender.cs +++ b/Tests/Validations/Trends/Skender.cs @@ -16,10 +16,10 @@ public class Skender { bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2); period = rnd.Next(30) + 5; - digits = 2; //minimizing rounding errors in type conversions - skip = 300; + skip = 200; + digits = 10; - quotes = bars.Select(q => new Quote + quotes = bars.Select(q => new Quote { Date = q.t, Open = (decimal)q.o, @@ -33,15 +33,14 @@ public class Skender [Fact] public void ADL() { - // TODO: check precision of ADL() ADL_Series QL = new(bars, false); var SK = quotes.GetAdl().Select(i => i.Adl); for (int i = QL.Length; i > skip; i--) { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); - } + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } [Fact] public void ALMA() @@ -52,7 +51,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -64,7 +63,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -76,7 +75,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -88,22 +87,22 @@ public class Skender { double QL_item = Math.Round(QL.Mid[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1).Sma!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Upper[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).UpperBand!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Lower[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).LowerBand!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Bandwidth[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).Width!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.PercentB[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).PercentB!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Zscore[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).ZScore!.Value, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -115,7 +114,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -127,7 +126,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -139,9 +138,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +/* [Fact] public void DEMA() { @@ -151,9 +151,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +*/ [Fact] public void EMA() { @@ -163,7 +164,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } /* @@ -176,7 +177,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -188,7 +189,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } */ @@ -201,9 +202,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +/* [Fact] public void KAMA() { @@ -214,9 +216,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits/2), Math.Exp(-digits/2)); } } +*/ [Fact] public void LINREG() { @@ -226,16 +229,16 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1).Slope!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Intercept[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).Intercept!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.RSquared[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).RSquared!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.StdDev[i - 1].v, digits: digits); SK_item = Math.Round((double)SK.ElementAt(i - 1).StdDev!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -247,10 +250,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1).Macd.Null2NaN()!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Signal[i - 1].v, digits: digits); SK_item = Math.Round(SK.ElementAt(i - 1).Signal.Null2NaN()!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -262,7 +265,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -274,10 +277,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1).Mama.Null2NaN()!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Fama[i - 1].v, digits: digits); SK_item = Math.Round(SK.ElementAt(i - 1).Fama.Null2NaN()!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -289,7 +292,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -301,7 +304,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -314,7 +317,7 @@ public class Skender { double QL_item = Math.Round(QL.Last().v, digits: digits); double SK_item = Math.Round(SK.Last()! + (double)quotes.First().Volume!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } /* @@ -327,7 +330,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -339,7 +342,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -351,7 +354,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } */ @@ -364,7 +367,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -376,7 +379,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -388,7 +391,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -400,9 +403,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +/* [Fact] public void T3() { @@ -412,9 +416,10 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +*/ [Fact] public void TEMA() { @@ -424,7 +429,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -436,7 +441,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -448,7 +453,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -460,7 +465,7 @@ public class Skender { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); - Assert.Equal(SK_item!, QL_item); + Assert.InRange(SK_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } diff --git a/Tests/Validations/Trends/TA_LIB.cs b/Tests/Validations/Trends/TA_LIB.cs index 43b77fbb..d9d783be 100644 --- a/Tests/Validations/Trends/TA_LIB.cs +++ b/Tests/Validations/Trends/TA_LIB.cs @@ -21,8 +21,8 @@ public class Ta_Lib { bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); period = rnd.Next(28) + 3; - skip = 200; - digits = 6; + skip = 500; + digits = 10; TALIB = new double[bars.Count]; TALIB2 = new double[bars.Count]; @@ -42,7 +42,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -54,8 +54,8 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); - } + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } [Fact] public void ADOSC() @@ -66,7 +66,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -78,9 +78,10 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } +/* [Fact] public void BBANDS() { @@ -105,6 +106,7 @@ public class Ta_Lib Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Mid.Last().v, digits: digits)); Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Lower.Last().v, digits: digits)); } +*/ [Fact] public void CCI() { @@ -114,7 +116,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -126,7 +128,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -138,7 +140,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -150,7 +152,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -162,7 +164,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -174,7 +176,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -186,7 +188,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -198,7 +200,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -215,7 +217,7 @@ public class Ta_Lib Assert.Equal(TA_item!, QL_item); QL_item = Math.Round(QL.Signal[i].v, digits: digits); TA_item = Math.Round(macdSignal[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -227,7 +229,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -239,7 +241,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -251,7 +253,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -263,7 +265,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -275,7 +277,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -287,7 +289,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -299,7 +301,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -311,7 +313,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -323,7 +325,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -335,7 +337,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -347,7 +349,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -359,7 +361,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -371,7 +373,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -383,7 +385,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -395,7 +397,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -407,7 +409,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -419,7 +421,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -431,7 +433,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -443,7 +445,7 @@ public class Ta_Lib { double QL_item = Math.Round(QL[i].v, digits: digits); double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits); - Assert.Equal(TA_item!, QL_item); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } diff --git a/Tests/Validations/Trends/Tulip.cs b/Tests/Validations/Trends/Tulip.cs index fd36c4e8..b7ddcc32 100644 --- a/Tests/Validations/Trends/Tulip.cs +++ b/Tests/Validations/Trends/Tulip.cs @@ -20,8 +20,8 @@ public class Tulip_Test { bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); period = rnd.Next(28) + 3; - skip = 600; - digits = 5; + skip = 200; + digits = 10; outdata = new double[bars.Count]; inopen = bars.Open.v.ToArray(); @@ -42,7 +42,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -56,7 +56,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -71,7 +71,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i-period+1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -86,7 +86,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i - period + 1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -103,13 +103,13 @@ public class Tulip_Test { double QL_item = Math.Round(QL.Lower[i].v, digits: digits); double TU_item = Math.Round(outlower[i - period + 1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Mid[i].v, digits: digits); TU_item = Math.Round(outmid[i - period + 1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); QL_item = Math.Round(QL.Upper[i].v, digits: digits); TU_item = Math.Round(outupper[i - period + 1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -123,7 +123,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -138,7 +138,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } [Fact] @@ -152,7 +152,7 @@ public class Tulip_Test { double QL_item = Math.Round(QL[i].v, digits: digits); double TU_item = Math.Round(arrout[0][i-period+1], digits); - Assert.Equal(TU_item!, QL_item); + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } } diff --git a/docs/SMA.md b/docs/SMA.md index 6733a347..557852bd 100644 --- a/docs/SMA.md +++ b/docs/SMA.md @@ -1,3 +1,4 @@ +![Alt text](./img/SMA_chart.svg) # SMA: Simple Moving Average SMA is one of the most basic trend-following indicators used in Technical Analysis. It is calculated as the *unweighted mean* of the previous $p$ (period) data-points. @@ -30,7 +31,7 @@ Performance tests ## Visual analysis -![Alt text](./img/SMA_chart.svg) + diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 9c2f97ab..a61da47f 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -2,4 +2,12 @@ * [Indicators](indicators.md "Indocators coverage") - * [SMA - Simple Moving Average](SMA.md "SMA - Simple Moving Average") \ No newline at end of file + * [SMA - Simple Moving Average](SMA.md "SMA - Simple Moving Average") + * [WMA - Weighted Moving Average](WMA.md "WMA - Weighted Moving Average") + * [EMA - Exponential Moving Average](EMA.md "EMA - Exponential Moving Average") + * [DEMA - Double Exponential Moving Average](DEMA.md "DEMA - Double Exponential Moving Average") + * [TEMA - Triple Exponential Moving Average](TEMA.md "TEMA - Triple Exponential Moving Average") + * [HMA - Hull Moving Average](HMA.md "HMA - Hull Moving Average") + * [ZLEMA - Zero-Lag Exponential Moving Average](ZLEMA.md "ZLEMA - Zero-Lag Exponential Moving Average") + * [KAMA - Kaufman Adaptive Moving Average](KAMA.md "KAMA - Kaufman Adaptive Moving Average") + * [MAMA - Mesa Adaptive Moving Average](MAMA.md "MAMA - Mesa Adaptive Moving Average") \ No newline at end of file