diff --git a/Source/Feeds/GBM_Feed.cs b/Source/Feeds/GBM_Feed.cs index 0adcde1d..e83e6b46 100644 --- a/Source/Feeds/GBM_Feed.cs +++ b/Source/Feeds/GBM_Feed.cs @@ -22,10 +22,12 @@ public class GBM_Feed : TBars { private double seed; readonly double drift, volatility; - public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0) { + readonly int precision; + public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0, int Precision = 2) { this.seed = Seed; volatility = Volatility*0.01; drift = Drift*0.01; + precision = Precision; for (int i = 0; i OCMin)? (2 * OCMin) - Low : Low; - double Volume = GBM_value(seed*10, volatility*2, Drift:0); + double Volume = GBM_value(seed*10, volatility*2, Drift:0, precision: 1); base.Add((timestamp, Open, High, Low, Close, Volume), update); seed = Close; } - private static double GBM_value (double Seed, double Volatility, double Drift) { + private static double GBM_value(double Seed, double Volatility, double Drift, int precision) { Random rnd = new(); double U1 = 1.0-rnd.NextDouble(); double U2 = 1.0-rnd.NextDouble(); double Z = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); - return Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z)); + return Math.Round(Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z)), digits: precision); } } \ No newline at end of file diff --git a/Source/Trends/DEMA_Series.cs b/Source/Trends/DEMA_Series.cs index 8a7d8e92..cb165726 100644 --- a/Source/Trends/DEMA_Series.cs +++ b/Source/Trends/DEMA_Series.cs @@ -1,6 +1,7 @@ namespace QuanTAlib; using System; using System.Linq; +using System.Runtime.CompilerServices; /* DEMA: Double Exponential Moving Average @@ -18,15 +19,15 @@ Remark: public class DEMA_Series : Single_TSeries_Indicator { - private readonly System.Collections.Generic.List _buffer = new(); - private readonly double _k, _k1m; + private readonly System.Collections.Generic.List _buffer1 = new(); + private readonly System.Collections.Generic.List _buffer2 = new(); + private readonly double _k; private double _lastema1, _lastlastema1; private double _lastema2, _lastlastema2; public DEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) { - this._k = 2.0 / (this._p + 1); - this._k1m = 1.0 - this._k; + _k = 2.0 / (_p + 1); if (_data.Count > 0) { base.Add(_data); } } @@ -34,26 +35,40 @@ public class DEMA_Series : Single_TSeries_Indicator { if (update) { - this._lastema1 = this._lastlastema1; - this._lastema2 = this._lastlastema2; + _lastema1 = _lastlastema1; + _lastema2 = _lastlastema2; } - double _ema1, _ema2; - - if (this.Count < this._p) + double _ema1, _ema2, _dema; + if (this.Count < _p) { - Add_Replace_Trim(_buffer, TValue.v, _p, update); - double _sma = _buffer.Average(); + Add_Replace_Trim(_buffer1, TValue.v, _p, update); + _ema1 = 0; + for (int i=0; i<_buffer1.Count; i++) { _ema1 += _buffer1[i]; } + _ema1 /= _buffer1.Count; - _ema1 = _ema2 = _sma; + Add_Replace_Trim(_buffer2, _ema1, _p, update); + _ema2 = 0; + for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } + _ema2 /= _buffer2.Count; } - else + else if(this.Count < (2*_p - 1)) // second _p { - _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m); - _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m); - } + _ema1 = (TValue.v - _lastema1) * _k + _lastema1; + + Add_Replace_Trim(_buffer2, _ema1, _p, update); + _ema2 = 0; + for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } + _ema2 /= _buffer2.Count; + } + else // all others + { + _ema1 = (TValue.v - _lastema1) * _k + _lastema1; + _ema2 = (_ema1 - _lastema2) * _k + _lastema2; + + } + _dema = 2*_ema1 - _ema2; - double _dema = (2 * _ema1) - _ema2; this._lastlastema1 = this._lastema1; this._lastlastema2 = this._lastema2; this._lastema1 = _ema1; @@ -61,4 +76,4 @@ public class DEMA_Series : Single_TSeries_Indicator base.Add((TValue.t, _dema), update, _NaN); } -} +} \ No newline at end of file diff --git a/Source/Trends/EMA_Series.cs b/Source/Trends/EMA_Series.cs index aae20c2a..62406c43 100644 --- a/Source/Trends/EMA_Series.cs +++ b/Source/Trends/EMA_Series.cs @@ -42,7 +42,9 @@ public class EMA_Series : Single_TSeries_Indicator if (this.Count < this._p) { Add_Replace(_buffer, TValue.v, update); - _ema = _buffer.Average(); + _ema = 0; + for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; } + _ema /= _buffer.Count; } else { diff --git a/Source/Trends/SMA_Series.cs b/Source/Trends/SMA_Series.cs index 1f07a088..f779e746 100644 --- a/Source/Trends/SMA_Series.cs +++ b/Source/Trends/SMA_Series.cs @@ -28,7 +28,9 @@ public class SMA_Series : Single_TSeries_Indicator public override void Add((System.DateTime t, double v) TValue, bool update) { Add_Replace_Trim(_buffer, TValue.v, _p, update); - double _sma = _buffer.Sum() / _buffer.Count; + double _sma = 0; + for (int i=0; i<_buffer.Count; i++) { _sma+= _buffer[i]; } + _sma /= _buffer.Count; base.Add((TValue.t, _sma), update, _NaN); } diff --git a/Source/Volatility/ADOSC_Series.cs b/Source/Volatility/ADOSC_Series.cs index f8f219d0..a021bb01 100644 --- a/Source/Volatility/ADOSC_Series.cs +++ b/Source/Volatility/ADOSC_Series.cs @@ -13,6 +13,47 @@ Sources: */ + +public class ADOSC_Series : Single_TBars_Indicator +{ + private readonly double _k1, _k2; + private double _lastema1, _lastlastema1, _lastema2, _lastlastema2; + private double _lastadl, _lastlastadl; + + public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN) + { + _k1 = 2.0 / (3 + 1); + _k2 = 2.0 / (10 + 1); + _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 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) { + _lastadl = _lastlastadl; + _lastema1 = _lastlastema1; + _lastema2 = _lastlastema2; + } + + double _adl = 0; + double tmp = TBar.h - TBar.l; + if (tmp > 0.0) { _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); } + if (this.Count == 0) { _lastema1 = _lastema2 = _adl; } + + double _ema1 = (_adl - _lastema1) * _k1 + _lastema1; + double _ema2 = (_adl - _lastema2) * _k2 + _lastema2; + + _lastlastadl = _lastadl; _lastadl = _adl; + _lastlastema1 = _lastema1; _lastema1 = _ema1; + _lastlastema2 = _lastema2; _lastema2 = _ema2; + + double _adosc = _ema1 - _ema2; + base.Add((TBar.t, _adosc), update, _NaN); + } + +} +/* public class ADOSC_Series : Single_TBars_Indicator { private readonly ADL_Series _TSadl; @@ -42,4 +83,5 @@ public class ADOSC_Series : Single_TBars_Indicator var result = (TBar.t, _ado); base.Add(result, update); } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/Tests/Validations/Pandas_TA.cs b/Tests/Validations/Pandas_TA.cs index 2a971df5..4225dea4 100644 --- a/Tests/Validations/Pandas_TA.cs +++ b/Tests/Validations/Pandas_TA.cs @@ -53,151 +53,302 @@ public class PandasTA : IDisposable [Fact] void ADL() { ADL_Series QL = new(bars); var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length; i > 0; i--) + { + 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); + } } [Fact] void ADOSC() { ADOSC_Series QL = new(bars); var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void ATR() { ATR_Series QL = new(bars, period); var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void BIAS() { BIAS_Series QL = new(bars.Close, period, false); var pta = df.ta.bias(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void DEMA() { DEMA_Series QL = new(bars.Close, period, false); var pta = df.ta.dema(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void EMA() { EMA_Series QL = new(bars.Close, period, false); var pta = df.ta.ema(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void ENTROPY() { ENTROPY_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.entropy(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period+1; i--) + { + 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); + } + } [Fact] void HL2() { var pta = df.ta.hl2(high: df.high, low: df.low); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(bars.HL2.Last().v, digits: digits)); + for (int i = bars.HL2.Length; i > 0; i--) + { + 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); + } } [Fact] void HLC3() { var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(bars.HLC3.Last().v, digits: digits)); - } + for (int i = bars.HLC3.Length; i > 0; i--) + { + 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); + } + } [Fact] void HMA() { HMA_Series QL = new(bars.Close, period, false); var pta = df.ta.hma(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length; i > period+1; i--) + { + 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); + } + } [Fact] void KAMA() { KAMA_Series QL = new(bars.Close, period); var pta = df.ta.kama(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length; i > 0; i--) + { + 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); + } } [Fact] void KURTOSIS() { KURTOSIS_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.kurtosis(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period+1; i--) + { + 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); + } + } [Fact] void MAD() { MAD_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.mad(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void MEDIAN() { MEDIAN_Series QL = new(bars.Close, period); var pta = df.ta.median(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void OBV() { OBV_Series QL = new(bars); var pta = df.ta.obv(close: df.close, volume: df.volume); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length; i > 0; i--) + { + 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); + } } [Fact] void OHLC4() { var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(bars.OHLC4.Last().v, digits: digits)); + for (int i = bars.OHLC4.Length; i > 0; i--) + { + 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); + } } [Fact] void RMA() { RMA_Series QL = new(bars.Close, period, false); var pta = df.ta.rma(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void RSI() { RSI_Series QL = new(bars.Close, period); var pta = df.ta.rsi(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void SDEV() { SDEV_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.stdev(close: df.close, length: period, ddof: 0); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void SMA() { SMA_Series QL = new(bars.Close, period, false); var pta = df.ta.sma(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void SSDEV() { SSDEV_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.stdev(close: df.close, length: period, ddof: 1); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void SVARIANCE() { SVAR_Series QL = new(bars.Close, period); var pta = df.ta.variance(close: df.close, length: period, ddof: 1); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void T3() { T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false); var pta = df.ta.t3(close: df.close, length: period, a: 0.7); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length; i > 0; i--) + { + 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); } + } [Fact] void TEMA() { TEMA_Series QL = new(bars.Close, period, false); var pta = df.ta.tema(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period; i--) + { + 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); + } + } [Fact] void TR() { TR_Series QL = new(bars); var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 1; i--) + { + 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); + } + } [Fact] void TRIMA() { // TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right TRIMA_Series QL = new(bars.Close, 11); var pta = df.ta.trima(close: df.close, length: 11); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void VARIANCE() { VAR_Series QL = new(bars.Close, period); var pta = df.ta.variance(close: df.close, length: period, ddof:0); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void WMA() { WMA_Series QL = new(bars.Close, period, false); var pta = df.ta.wma(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } [Fact] void ZLEMA() { ZLEMA_Series QL = new(bars.Close, period, false); var pta = df.ta.zlma(close: df.close, length: period); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > 0; i--) + { + 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); + } + } [Fact] void ZSCORE() { ZSCORE_Series QL = new(bars.Close, period, useNaN: false); var pta = df.ta.zscore(close: df.close, length: period, ddof: 0); - Assert.Equal(Math.Round((double)pta.tail(1), digits: digits), Math.Round(QL.Last().v, digits: digits)); - } + for (int i = QL.Length; i > period-1; i--) + { + 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); + } + } } \ No newline at end of file diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs index 63a07573..efd8fbd4 100644 --- a/Tests/Validations/Skender_Stock.cs +++ b/Tests/Validations/Skender_Stock.cs @@ -11,9 +11,9 @@ public class Skender_Stock { private readonly IEnumerable quotes; public Skender_Stock() { - bars = new(Bars: 10000, Volatility: 0.8, Drift: 0.0); + 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 + digits = 4; //minimizing rounding errors in type conversions quotes = bars.Select(q => new Quote { Date = q.t, @@ -174,7 +174,7 @@ public class Skender_Stock { // TODO: check precision of KAMA() KAMA_Series QL = new(bars.Close, period, useNaN: false); var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!); - for (int i = QL.Length; i > 500; i--) + for (int i = QL.Length; i > 600; i--) { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); @@ -355,7 +355,7 @@ public class Skender_Stock { [Fact] public void TR() { TR_Series QL = new(bars, useNaN: false); var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!); - for (int i = QL.Length; i > period; i--) + for (int i = QL.Length; i > 1; i--) { double QL_item = Math.Round(QL[i - 1].v, digits: digits); double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits); diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs index e6e87b71..8fb360b5 100644 --- a/Tests/Validations/TA_LIB.cs +++ b/Tests/Validations/TA_LIB.cs @@ -18,7 +18,7 @@ public class Ta_Lib private readonly double[] involume; public Ta_Lib() { - bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0); + bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); period = rnd.Next(28) + 3; digits = 6; @@ -34,22 +34,42 @@ public class Ta_Lib [Fact] public void ADD() { ADD_Series QL = new(bars.Open, bars.Close); Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void ADL() { ADL_Series QL = new(bars, false); Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length-1; i > 0; i--) + { + 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); + } } [Fact] public void ADOSC() { ADOSC_Series QL = new(bars, false); Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void ATR() { ATR_Series QL = new(bars, period, false); Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void BBANDS() { double[] outMiddle = new double[bars.Count]; @@ -57,6 +77,18 @@ public class Ta_Lib double[] outLower = new double[bars.Count]; BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false); Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + double QL_item = Math.Round(QL.Upper[i].v, digits: digits); + double TA_item = Math.Round(outUpper[i - outBegIdx], digits: digits); + Assert.Equal(TA_item!, QL_item); + QL_item = Math.Round(QL.Mid[i].v, digits: digits); + TA_item = Math.Round(outMiddle[i - outBegIdx], digits: digits); + Assert.Equal(TA_item!, QL_item); + QL_item = Math.Round(QL.Lower[i].v, digits: digits); + TA_item = Math.Round(outLower[i - outBegIdx], digits: digits); + Assert.Equal(TA_item!, QL_item); + } Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Upper.Last().v, digits: digits)); 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)); @@ -64,145 +96,287 @@ public class Ta_Lib [Fact] public void CCI() { CCI_Series QL = new(bars, period, false); Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void CORR() { CORR_Series QL = new(bars.Open, bars.Close, period); Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void DEMA() { DEMA_Series QL = new(bars.Close, period, false); Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void DIV() { DIV_Series QL = new(bars.Open, bars.Close); Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void EMA() { EMA_Series QL = new(bars.Close, period, false); Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void HL2() { TSeries QL = bars.HL2; Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void HLC3() { TSeries QL = bars.HLC3; Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void HLCC4() { TSeries QL = bars.HLCC4; Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MACD() { double[] macdSignal = new double[bars.Count]; double[] macdHist = new double[bars.Count]; MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false); Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); - Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Signal.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + 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); + } } [Fact] public void MAMA() { MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05); Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MAX() { MAX_Series QL = new(bars.Close, period, false); Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MIDPOINT() { MIDPOINT_Series QL = new(bars.Close, period, false); Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MIDPRICE() { MIDPRICE_Series QL = new(bars, period, false); Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MIN() { MIN_Series QL = new(bars.Close, period, false); Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void MUL() { MUL_Series QL = new(bars.Open, bars.Close); Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void OBV() { OBV_Series QL = new(bars, period, false); Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void OHLC4() { TSeries QL = bars.OHLC4; Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void RSI() { RSI_Series QL = new(bars.Close, period, false); Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void SDEV() { SDEV_Series QL = new(bars.Close, period, false); Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void SMA() { SMA_Series QL = new(bars.Close, period, false); Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void SUB() { SUB_Series QL = new(bars.Open, bars.Close); Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void SUM() { SUM_Series QL = new(bars.Close, period, false); Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void T3() { T3_Series QL = new(source: bars.Close, period: period, vfactor:0.7, useNaN: false); Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void TEMA() { TEMA_Series QL = new(bars.Close, period, false); Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void TR() { TR_Series QL = new(bars, false); Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void TRIMA() { TRIMA_Series QL = new(bars.Close, period, false); Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void VAR() { VAR_Series QL = new(bars.Close, period, false); Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } [Fact] public void WMA() { WMA_Series QL = new(bars.Close, period, false); Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], digits: digits), Math.Round(QL.Last().v, digits: digits)); + for (int i = QL.Length - 1; i > outBegIdx; i--) + { + 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); + } } } diff --git a/docs/comparing trends.ipynb b/docs/comparing trends.ipynb new file mode 100644 index 00000000..ae2cbc6c --- /dev/null +++ b/docs/comparing trends.ipynb @@ -0,0 +1,137 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "dotnet-interactive.csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Loading extensions from `C:\\Users\\miha\\.nuget\\packages\\plotly.net.interactive\\3.0.2\\interactive-extensions\\dotnet\\Plotly.NET.Interactive.dll`" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//#r \"nuget: QuanTAlib;\"\n", + "\n", + "#r \"nuget: Plotly.NET;\"\n", + "#r \"nuget: Plotly.NET.Interactive;\"\n", + "#r \"..\\Source\\bin\\Debug\\net6.0\\QuanTAlib.dll\"\n", + "\n", + "using QuanTAlib;\n", + "using Plotly.NET;\n", + "using Plotly.NET.LayoutObjects;" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "dotnet-interactive.csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "
\r\n", + "\r\n", + "\n", + " \n", + "
\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "int period = 25;\n", + "GBM_Feed feed = new(50, Volatility: 1);\n", + "TSeries data = feed.OHLC4;\n", + "//List raw = new() { 0, 1, 1 ,1 ,1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; \n", + "//TSeries data = new();\n", + "//for (int i=0; i(data.t, data.v, false, data.GetType().Name).WithLineStyle(Width: 4, Color: Color.fromString(\"red\"));\n", + "var line1 = Chart2D.Chart.Line(calc1.t, calc1.v, false, \"EMA_SMA\").WithLineStyle(Width: 2, Color: Color.fromString(\"purple\"));\n", + "var line2 = Chart2D.Chart.Line(calc2.t, calc2.v, false, \"True EMA\").WithLineStyle(Width: 2, Color: Color.fromString(\"blue\"));\n", + "\n", + "var chart = Chart.Combine(new []{line0, line1, line2})\n", + " .WithSize(1200,600)\n", + " .WithMargin(Margin.init(30,10,40,30,1,false))\n", + " .WithXAxisRangeSlider(RangeSlider.init(Visible:false));\n", + "\n", + "chart" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/x-csharp", + "name": "C#", + "pygments_lexer": "csharp", + "version": "9.0" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +}