diff --git a/Docs/Comparing_w_TALIB.ipynb b/Docs/Comparing_w_TALIB.ipynb
index cf547f51..4f245ac7 100644
--- a/Docs/Comparing_w_TALIB.ipynb
+++ b/Docs/Comparing_w_TALIB.ipynb
@@ -15,7 +15,7 @@
{
"data": {
"text/html": [
- "
Installed Packages- QuantLib, 1.0.7
- TALib.NETCore, 0.4.4
"
+ "Installed Packages- QuanTAlib, 0.1.10-beta
- TALib.NETCore, 0.4.4
"
]
},
"metadata": {},
@@ -24,7 +24,7 @@
],
"source": [
"#r \"nuget: TALib.NETCore, 0.4.4\" \n",
- "#r \"nuget:QuanTAlib\" \n",
+ "#r \"nuget: QuanTAlib, 0.1.10-beta\" \n",
"\n",
"using QuanTAlib;\n",
"using TALib;\n"
@@ -43,13 +43,12 @@
},
"outputs": [
{
- "data": {
- "text/html": [
- "1394
"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
+ "ename": "Error",
+ "evalue": "(1,1): error CS0246: The type or namespace name 'YAHOO_Feed' could not be found (are you missing a using directive or an assembly reference?)",
+ "output_type": "error",
+ "traceback": [
+ "(1,1): error CS0246: The type or namespace name 'YAHOO_Feed' could not be found (are you missing a using directive or an assembly reference?)"
+ ]
}
],
"source": [
diff --git a/Docs/coverage.md b/Docs/coverage.md
index 16fd465b..906d5d1c 100644
--- a/Docs/coverage.md
+++ b/Docs/coverage.md
@@ -42,7 +42,8 @@
| AFIRMA - Autoregressive Finite Impulse Response Moving Average |||||
| ALMA - Arnaud Legoux Moving Average |||✔️|✔️|
| ARIMA - Autoregressive Integrated Moving Average |||||
-| ATR - Average True Range ||✔️|✔️|✔️|
+| ATR - Average True Range |✔️|✔️|✔️|✔️|
+| ATRP - Average True Range Percent |✔️||✔️||
| DEMA - Double EMA |✔️|✔️|✔️|✔️|
| EMA - Exponential Moving Average |✔️|✔️|✔️|✔️|
| EPMA - Endpoint Moving Average |||✔️||
diff --git a/Source/Basics/ADD_Series.cs b/Source/Basics/ADD_Series.cs
index 7c6c1959..13cc8bb5 100644
--- a/Source/Basics/ADD_Series.cs
+++ b/Source/Basics/ADD_Series.cs
@@ -1,6 +1,13 @@
-// ADD - adding TSeries+TSeries together, or TSeries+double, or double+TSeries
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+ADD - adding TSeries+TSeries together, or TSeries+double, or double+TSeries
+
+Remarks:
+ Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator.
+
+ */
public class ADD_Series : Pair_TSeries_Indicator
{
diff --git a/Source/Basics/Abstract_Indicators.cs b/Source/Basics/Abstracts.cs
similarity index 88%
rename from Source/Basics/Abstract_Indicators.cs
rename to Source/Basics/Abstracts.cs
index 99e779a4..1233687c 100644
--- a/Source/Basics/Abstract_Indicators.cs
+++ b/Source/Basics/Abstracts.cs
@@ -1,6 +1,18 @@
namespace QuanTAlib;
using System;
+/*
+Abstract classes with all scaffolding required to build indicators.
+ All abstracts support period, NaN, and all permutations of Add() methods.
+ Indicator classess need to implement:
+ - Chaining constructor (Abstract's constructor executes first)
+ - Default Add(value) class
+ - optional Add(series) bulk insert class (for optimization of historical analysis)
+ Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
+ Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
+ Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
+
+ */
public abstract class Single_TSeries_Indicator : TSeries
{
protected readonly int _p;
@@ -124,8 +136,9 @@ public abstract class Single_TBars_Indicator : TSeries
protected readonly TBars _bars;
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
- protected Single_TBars_Indicator(TBars source, bool useNaN)
+ protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
{
+ this._p = period;
this._bars = source;
this._NaN = useNaN;
this._bars.Close.Pub += this.Sub;
diff --git a/Source/Basics/DIV_Series.cs b/Source/Basics/DIV_Series.cs
index 11dedb01..16069917 100644
--- a/Source/Basics/DIV_Series.cs
+++ b/Source/Basics/DIV_Series.cs
@@ -1,6 +1,12 @@
-// DIV - divide TSeries/TSeries , or TSeries/double, or double/TSeries
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+DIV - divide TSeries/TSeries , or TSeries/double, or double/TSeries
+
+Remarks:
+ Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator.
+ */
public class DIV_Series : Pair_TSeries_Indicator
{
diff --git a/Source/Statistics/MAX_Series.cs b/Source/Basics/MAX_Series.cs
similarity index 77%
rename from Source/Statistics/MAX_Series.cs
rename to Source/Basics/MAX_Series.cs
index 150eacd8..38228eae 100644
--- a/Source/Statistics/MAX_Series.cs
+++ b/Source/Basics/MAX_Series.cs
@@ -1,20 +1,18 @@
namespace QuanTAlib;
-/*
-MAX - Maximum value in the given period in the series.
-
-If period = 0 => period = full length of the series
-
-*/
-
using System;
-using System.Collections.Generic;
+
+/*
+MAX - Maximum value in the given period in the series.
+ If period = 0 => period = full length of the series
+ */
+
public class MAX_Series : Single_TSeries_Indicator
{
public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
{
if (base._data.Count > 0) { base.Add(base._data); }
}
- private readonly List _buffer = new();
+ private readonly System.Collections.Generic.List _buffer = new();
public override void Add((DateTime t, double v) d, bool update)
{
@@ -24,7 +22,7 @@ public class MAX_Series : Single_TSeries_Indicator
double _max = d.v;
for (int i = 0; i < this._buffer.Count; i++)
- { _max = this._buffer[i] > _max ? this._buffer[i] : _max; }
+ { _max = (this._buffer[i] > _max) ? this._buffer[i] : _max; }
var result = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
diff --git a/Source/Statistics/MIN_Series.cs b/Source/Basics/MIN_Series.cs
similarity index 92%
rename from Source/Statistics/MIN_Series.cs
rename to Source/Basics/MIN_Series.cs
index 408bd183..d2f66892 100644
--- a/Source/Statistics/MIN_Series.cs
+++ b/Source/Basics/MIN_Series.cs
@@ -1,12 +1,10 @@
-/*
-MIN - Minimum value in the given period in the series.
-
-If period = 0 => period = full length of the series
-
-*/
-
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+MIN - Minimum value in the given period in the series.
+ If period = 0 => period = full length of the series
+ */
public class MIN_Series : Single_TSeries_Indicator
{
diff --git a/Source/Basics/MUL_Series.cs b/Source/Basics/MUL_Series.cs
index 0965543f..c1c573bd 100644
--- a/Source/Basics/MUL_Series.cs
+++ b/Source/Basics/MUL_Series.cs
@@ -1,6 +1,10 @@
-// MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries
+
+ */
public class MUL_Series : Pair_TSeries_Indicator
{
diff --git a/Source/Basics/RND_Feed.cs b/Source/Basics/RND_Feed.cs
index 6c886d02..b7c42e27 100644
--- a/Source/Basics/RND_Feed.cs
+++ b/Source/Basics/RND_Feed.cs
@@ -1,20 +1,28 @@
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+Random Bars generator - used for testing, validation and fun
+ Returns 'bars' number of candles that follow common market movement.
+ volatility defines how 'jumpy' is the series of
+ startvalue defines beginning closing price that then guides the rest of series
+
+ */
public class RND_Feed : TBars
{
- public RND_Feed(int days, double volatility = 0.05, double startvalue = 100.0)
+ public RND_Feed(int bars, double volatility = 0.05, double startvalue = 100.0)
{
Random rnd = new();
double c = startvalue;
- for (int i = 0; i < days; i++)
+ for (int i = 0; i < bars; i++)
{
double o = Math.Round(c + c * (volatility * 0.1 * rnd.NextDouble() - 0.005), 2);
double h = Math.Round(o + c * volatility * rnd.NextDouble(), 2);
double l = Math.Round(o - c * volatility * rnd.NextDouble(), 2);
c = Math.Round(l + (h - l) * rnd.NextDouble(), 2);
double v = Math.Round(1000 * rnd.NextDouble(), 2);
- this.Add(DateTime.Today.AddDays(i - days), o, h, l, c, v);
+ this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v);
}
}
}
\ No newline at end of file
diff --git a/Source/Basics/SUB_Series.cs b/Source/Basics/SUB_Series.cs
index abf37a8a..88511f81 100644
--- a/Source/Basics/SUB_Series.cs
+++ b/Source/Basics/SUB_Series.cs
@@ -1,6 +1,11 @@
-// SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries
-using System;
namespace QuanTAlib;
+using System;
+
+/*
+SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries
+
+ */
+
public class SUB_Series : Pair_TSeries_Indicator
{
diff --git a/Source/Basics/TBars.cs b/Source/Basics/TBars.cs
index 6e79174e..5502253d 100644
--- a/Source/Basics/TBars.cs
+++ b/Source/Basics/TBars.cs
@@ -1,7 +1,15 @@
namespace QuanTAlib;
-
using System;
+/*
+TBars class - includes all series for common data used in indicators and other calculations.
+ Has a bit limited overloading and casting (compared to TSeries)
+ Includes Select(int) method to simplify choosing the most optimal data source for indicators
+ Includes the most basic pricing calcs: HL2, OC2, OHL3, HLC3, OHLC4, HLCC4
+ (it is 'cheaper' to calculate them once during data capture than each time during data analysis)
+
+ */
+
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)>
{
private readonly TSeries _open = new();
diff --git a/Source/Basics/TR_Series.cs b/Source/Basics/TR_Series.cs
new file mode 100644
index 00000000..3b760851
--- /dev/null
+++ b/Source/Basics/TR_Series.cs
@@ -0,0 +1,38 @@
+namespace QuanTAlib;
+using System;
+
+/*
+TR: True Range
+ True Range was introduced by J. Welles Wilder in his book New Concepts in Technical Trading Systems.
+ It measures the daily range plus any gap from the closing price of the preceding day.
+
+Calculation:
+ d1 = ABS(High - Low)
+ d2 = ABS(High - Previous close)
+ d3 = ABS(Previous close - Low)
+ TR = MAX(d1,d2,d3)
+
+Sources:
+ https://www.macroption.com/true-range/
+
+ */
+
+public class TR_Series : Single_TBars_Indicator
+{
+ private double _cm1 = double.NaN;
+ public TR_Series(TBars source, bool useNaN = false) : base(source, period:0, useNaN:useNaN) {
+ if (this._bars.Count > 0) { base.Add(this._bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TValue, bool update = false)
+ {
+ if (_cm1 is double.NaN) { _cm1 = TValue.c; }
+
+ double d1 = Math.Abs(TValue.h - TValue.l);
+ double d2 = Math.Abs(_cm1 - TValue.h);
+ double d3 = Math.Abs(_cm1 - TValue.l);
+ var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : Math.Max(d1,Math.Max(d2,d3)) );
+ base.Add(ret, update);
+ _cm1 = TValue.c;
+ }
+}
\ No newline at end of file
diff --git a/Source/Basics/TSeries.cs b/Source/Basics/TSeries.cs
index ff6f5315..2fcb13e9 100644
--- a/Source/Basics/TSeries.cs
+++ b/Source/Basics/TSeries.cs
@@ -1,8 +1,18 @@
namespace QuanTAlib;
-
using System;
using System.Linq;
+/*
+TSeries is the cornerstone of all QuanTAlib classess.
+ TSeries is a single List of tuples (time, value) and contains several operators, casts, overloads
+ and other helpers that simplify usage of library.
+ Think of TSeries as an equivalent of Numpy array.
+
+ - includes Length property (to mimic array's method)
+ - includes publishing and subscribing methods that attach to events
+ - uses Linq only for two transmutations - needs to be refactored out eventually (for speed)
+
+ */
public class TSeries : System.Collections.Generic.List<(DateTime t, double v)>
{
// when asked for a (t,v) tuple, return the last (t,v) on the List
diff --git a/Source/Indicators/ATRP_Series.cs b/Source/Indicators/ATRP_Series.cs
new file mode 100644
index 00000000..af3f6bab
--- /dev/null
+++ b/Source/Indicators/ATRP_Series.cs
@@ -0,0 +1,64 @@
+namespace QuanTAlib;
+using System;
+
+/*
+ATR: wildeR Moving Average
+ The average true range (ATR) is a price volatility indicator
+ showing the average price variation of assets within a given time period.
+
+Sources:
+ https://en.wikipedia.org/wiki/Average_true_range
+ https://www.tradingview.com/wiki/Average_True_Range_(ATR)
+ https://www.investopedia.com/terms/a/atr.asp
+
+ */
+
+
+public class ATR_Series : Single_TBars_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k, _k1m;
+ private double _lastema, _lastlastema, _lastcm1;
+ private double _cm1 = double.NaN;
+
+ public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._k = 1.0 / (double)(this._p);
+ this._k1m = 1.0 - this._k;
+ this._lastema = this._lastlastema = double.NaN;
+ 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 = false)
+ {
+ if (update) {
+ this._lastema = this._lastlastema;
+ this._cm1 = this._lastcm1;
+ }
+
+ if (_cm1 is double.NaN) { _cm1 = TBar.c; }
+ double d1 = Math.Abs(TBar.h - TBar.l);
+ double d2 = Math.Abs(_cm1 - TBar.h);
+ double d3 = Math.Abs(_cm1 - TBar.l);
+ (DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
+ _lastcm1 = _cm1;
+ _cm1 = TBar.c;
+
+ double _ema = 0;
+ if (this.Count < this._p)
+ {
+ if (update) { _buffer[_buffer.Count - 1] = d.v; }
+ else { _buffer.Add(d.v); }
+ if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
+ for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
+ _ema /= this._buffer.Count;
+ }
+ else { _ema = d.v * _k + _lastema * _k1m; }
+
+ this._lastlastema = this._lastema;
+ this._lastema = _ema;
+
+ var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
+ base.Add(ret, update);
+ }
+}
\ No newline at end of file
diff --git a/Source/Indicators/ATR_Series.cs b/Source/Indicators/ATR_Series.cs
new file mode 100644
index 00000000..ebcec9b8
--- /dev/null
+++ b/Source/Indicators/ATR_Series.cs
@@ -0,0 +1,63 @@
+namespace QuanTAlib;
+using System;
+
+/*
+ATRP: Average True Range Percent
+ Average True Range Percent is (ATR/Close Price)*100.
+ This normalizes so it can be compared to other stocks.
+
+Sources:
+ https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
+
+ */
+
+public class ATRP_Series : Single_TBars_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k, _k1m;
+ private double _lastema, _lastlastema, _lastcm1;
+ private double _cm1 = double.NaN;
+
+ public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._k = 1.0 / (double)(this._p);
+ this._k1m = 1.0 - this._k;
+ this._lastema = this._lastlastema = double.NaN;
+ 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 = false)
+ {
+ if (update) {
+ this._lastema = this._lastlastema;
+ this._cm1 = this._lastcm1;
+ }
+
+ if (_cm1 is double.NaN) { _cm1 = TBar.c; }
+ double d1 = Math.Abs(TBar.h - TBar.l);
+ double d2 = Math.Abs(_cm1 - TBar.h);
+ double d3 = Math.Abs(_cm1 - TBar.l);
+ (DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
+ _lastcm1 = _cm1;
+ _cm1 = TBar.c;
+
+ double _ema = 0;
+ if (this.Count < this._p)
+ {
+ if (update) { _buffer[_buffer.Count - 1] = d.v; }
+ else { _buffer.Add(d.v); }
+ if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
+ for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
+ _ema /= this._buffer.Count;
+ }
+ else { _ema = d.v * _k + _lastema * _k1m; }
+
+ this._lastlastema = this._lastema;
+ this._lastema = _ema;
+
+ double _atrp = 100 * (_ema / TBar.c);
+
+ var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
+ base.Add(ret, update);
+ }
+}
\ No newline at end of file
diff --git a/Source/MovingAvg/DEMA_Series.cs b/Source/Indicators/DEMA_Series.cs
similarity index 91%
rename from Source/MovingAvg/DEMA_Series.cs
rename to Source/Indicators/DEMA_Series.cs
index 1d740254..41cdcbae 100644
--- a/Source/MovingAvg/DEMA_Series.cs
+++ b/Source/Indicators/DEMA_Series.cs
@@ -1,8 +1,9 @@
namespace QuanTAlib;
+using System;
-/**
+/*
DEMA: Double Exponential Moving Average
-DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
+ DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
@@ -11,13 +12,12 @@ Remark:
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
DEMA = 2 * ema1 - ema2
-**/
-using System;
-using System.Collections.Generic;
+ */
+
public class DEMA_Series : Single_TSeries_Indicator
{
- private readonly List _buffer = new();
+ private readonly System.Collections.Generic.List _buffer = new();
private readonly double _k, _k1m;
private double _lastema1, _lastlastema1;
private double _lastema2, _lastlastema2;
diff --git a/Source/MovingAvg/EMA_Series.cs b/Source/Indicators/EMA_Series.cs
similarity index 77%
rename from Source/MovingAvg/EMA_Series.cs
rename to Source/Indicators/EMA_Series.cs
index a1ba2c14..2d53b02e 100644
--- a/Source/MovingAvg/EMA_Series.cs
+++ b/Source/Indicators/EMA_Series.cs
@@ -1,26 +1,27 @@
namespace QuanTAlib;
+using System;
-/**
+/*
EMA: Exponential Moving Average
+ EMA needs very short history buffer and calculates the EMA value using just the
+ previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
-EMA needs very short history buffer and calculates the EMA value using just the
-previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
+
Issues:
There is no consensus what the first EMA value should be - a zero, a first
-datapoint, or an average of the initial Period bars. All three starting methods
-converge within 20+ bars to the same moving average. Most implementations (including this one)
-use SMA() for the first Period bars as a seeding value for EMA.
-**/
+ datapoint, or an average of the initial Period bars. All three starting methods
+ converge within 20+ bars to the same moving average. Most implementations (including this one)
+ use SMA() for the first Period bars as a seeding value for EMA.
+
+ */
-using System;
-using System.Collections.Generic;
public class EMA_Series : Single_TSeries_Indicator
{
- private readonly List _buffer = new();
+ private readonly System.Collections.Generic.List _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema;
diff --git a/Source/MovingAvg/HEMA_Series.cs b/Source/Indicators/HEMA_Series.cs
similarity index 91%
rename from Source/MovingAvg/HEMA_Series.cs
rename to Source/Indicators/HEMA_Series.cs
index 3ffe260b..ac6a2f78 100644
--- a/Source/MovingAvg/HEMA_Series.cs
+++ b/Source/Indicators/HEMA_Series.cs
@@ -1,16 +1,17 @@
-using System;
-namespace QuanTAlib;
+namespace QuanTAlib;
+using System;
-/**
+/*
HEMA: Hull-EMA Moving Average
-Modified HUll Moving Average; instead of using WMA (Weighted MA) for a
-calculation, HEMA uses EMA for Hull's formula:
+ Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation,
+ HEMA uses EMA for Hull's formula:
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
EMA2 = EMA(n) of price - where k = 3/(n+1)
Raw HMA = (2 * EMA1) - EMA2
EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
-**/
+
+ */
public class HEMA_Series : Single_TSeries_Indicator
{
diff --git a/Source/MovingAvg/HMA_Series.cs b/Source/Indicators/HMA_Series.cs
similarity index 93%
rename from Source/MovingAvg/HMA_Series.cs
rename to Source/Indicators/HMA_Series.cs
index 41250bbe..e620b2f8 100644
--- a/Source/MovingAvg/HMA_Series.cs
+++ b/Source/Indicators/HMA_Series.cs
@@ -1,19 +1,21 @@
-using System;
-namespace QuanTAlib;
+namespace QuanTAlib;
+using System;
-/**
+/*
HMA: Hull Moving Average
-Developed by Alan Hull, an extremely fast and smooth moving average; almost
-eliminates lag altogether and manages to improve smoothing at the same time.
+ Developed by Alan Hull, an extremely fast and smooth moving average; almost
+ eliminates lag altogether and manages to improve smoothing at the same time.
Sources:
https://alanhull.com/hull-moving-average
https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
+
WMA1 = WMA(n/2) of price
WMA2 = WMA(n) of price
Raw HMA = (2 * WMA1) - WMA2
HMA = WMA(sqrt(n)) of Raw HMA
-**/
+
+ */
public class HMA_Series : TSeries
{
diff --git a/Source/MovingAvg/JMA_Series.cs b/Source/Indicators/JMA_Series.cs
similarity index 91%
rename from Source/MovingAvg/JMA_Series.cs
rename to Source/Indicators/JMA_Series.cs
index 2e0c4789..2cf373b9 100644
--- a/Source/MovingAvg/JMA_Series.cs
+++ b/Source/Indicators/JMA_Series.cs
@@ -1,11 +1,11 @@
-using System;
-namespace QuanTAlib;
+namespace QuanTAlib;
+using System;
-/**
+/*
JMA: Jurik Moving Average
-Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
-underlying activity. It has extremely low lag, is very smooth and is responsive
-to market gaps.
+ Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
+ underlying activity. It has extremely low lag, is very smooth and is responsive
+ to market gaps.
Sources:
https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
@@ -13,10 +13,12 @@ Sources:
Issues:
Real JMA algorithm is not published and this formula is derived through
-deduction and reverse analysis of JMA behavior. It is really close, but not
-exact - published JMA tests against JMA.CSV fail with small deviation. The
-original algo is slightly different, yet this approximation is close enough.
-**/
+ deduction and reverse analysis of JMA behavior. It is really close, but not
+ exact - published JMA tests against JMA.CSV fail with small deviation. The
+ original algo is slightly different, yet this approximation is close enough.
+
+ */
+
public class JMA_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List vbuffer10;
diff --git a/Source/MovingAvg/RMA_Series.cs b/Source/Indicators/RMA_Series.cs
similarity index 87%
rename from Source/MovingAvg/RMA_Series.cs
rename to Source/Indicators/RMA_Series.cs
index 5e28083b..220acc23 100644
--- a/Source/MovingAvg/RMA_Series.cs
+++ b/Source/Indicators/RMA_Series.cs
@@ -1,12 +1,13 @@
namespace QuanTAlib;
+using System;
-/**
+/*
RMA: wildeR Moving Average
+ J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
+ set as 1/period, giving less weight to the new data compared to EMA.
-J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
-set as 1/period, giving less weight to the new data compared to EMA. Sources:
+Sources:
https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
-
https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
https://www.incrediblecharts.com/indicators/wilder_moving_average.php
@@ -15,13 +16,11 @@ Issues:
pandas.ewm().mean() and returns incorrect first (period) of bars compared to
published formula. This implementation passess the validation test in Wilder's book.
-**/
+ */
-using System;
-using System.Collections.Generic;
public class RMA_Series : Single_TSeries_Indicator
{
- private readonly List _buffer = new();
+ private readonly System.Collections.Generic.List _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema;
diff --git a/Source/MovingAvg/SMA_Series.cs b/Source/Indicators/SMA_Series.cs
similarity index 74%
rename from Source/MovingAvg/SMA_Series.cs
rename to Source/Indicators/SMA_Series.cs
index bc6d143c..6dbc3064 100644
--- a/Source/MovingAvg/SMA_Series.cs
+++ b/Source/Indicators/SMA_Series.cs
@@ -1,17 +1,20 @@
namespace QuanTAlib;
+using System;
-/**
+/*
SMA: Simple Moving Average
-The weights are equally distributed across the period, resulting in a mean() of
-the data within the period/
+ The weights are equally distributed across the period, resulting in a mean() of
+ the data within the period/
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
https://stats.stackexchange.com/a/24739
Remark:
- This calc doesn't use LINQ or SUM() or any of iterative methods.
-**/
+ This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
+ implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
+
+ */
public class SMA_Series : Single_TSeries_Indicator
{
diff --git a/Source/MovingAvg/TEMA_Series.cs b/Source/Indicators/TEMA_Series.cs
similarity index 92%
rename from Source/MovingAvg/TEMA_Series.cs
rename to Source/Indicators/TEMA_Series.cs
index 7fb9e8e4..5439f7b4 100644
--- a/Source/MovingAvg/TEMA_Series.cs
+++ b/Source/Indicators/TEMA_Series.cs
@@ -1,8 +1,9 @@
namespace QuanTAlib;
+using System;
-/**
+/*
TEMA: Triple Exponential Moving Average
-TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
+ TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
@@ -12,13 +13,12 @@ Remark:
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
TEMA = 3 * (ema1 - ema2) + ema3
-**/
-using System;
-using System.Collections.Generic;
+ */
+
public class TEMA_Series : Single_TSeries_Indicator
{
- private readonly List _buffer = new();
+ private readonly System.Collections.Generic.List _buffer = new();
private readonly double _k, _k1m;
private double _lastema1, _lastlastema1;
private double _lastema2, _lastlastema2;
diff --git a/Source/MovingAvg/WMA_Series.cs b/Source/Indicators/WMA_Series.cs
similarity index 89%
rename from Source/MovingAvg/WMA_Series.cs
rename to Source/Indicators/WMA_Series.cs
index 20ec89ef..4c63bde0 100644
--- a/Source/MovingAvg/WMA_Series.cs
+++ b/Source/Indicators/WMA_Series.cs
@@ -1,14 +1,16 @@
namespace QuanTAlib;
+using System;
-/**
+/*
WMA: (linearly) Weighted Moving Average
-The weights are linearly decreasing over the period and the most recent data has
-the heaviest weight.
+ The weights are linearly decreasing over the period and the most recent data has
+ the heaviest weight.
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
-**/
+
+ */
public class WMA_Series : Single_TSeries_Indicator
{
diff --git a/Source/MovingAvg/ZLEMA_Series.cs b/Source/Indicators/ZLEMA_Series.cs
similarity index 68%
rename from Source/MovingAvg/ZLEMA_Series.cs
rename to Source/Indicators/ZLEMA_Series.cs
index 8370b625..9ae072ae 100644
--- a/Source/MovingAvg/ZLEMA_Series.cs
+++ b/Source/Indicators/ZLEMA_Series.cs
@@ -1,22 +1,23 @@
-using System;
-namespace QuanTAlib;
+namespace QuanTAlib;
+using System;
-/**
+/*
ZLEMA: Zero Lag Exponential Moving Average
-
-The Zero lag exponential moving average (ZLEMA) indicator was created by John
-Ehlers and Ric Way.
+ The Zero lag exponential moving average (ZLEMA) indicator was created by John
+ Ehlers and Ric Way.
The formula for a given N-Day period and for a given Data series is:
-Lag = (Period-1)/2
-Ema Data = {Data+(Data-Data(Lag days ago))
-ZLEMA = EMA (EmaData,Period)
+ Lag = (Period-1)/2
+ Ema Data = {Data+(Data-Data(Lag days ago))
+ ZLEMA = EMA (EmaData,Period)
-The idea is do a regular exponential moving average (EMA) calculation but on a
-de-lagged data instead of doing it on the regular data. Data is de-lagged by
-removing the data from "lag" days ago thus removing (or attempting to remove)
-the cumulative lag effect of the moving average.
-**/
+Remark:
+ The idea is do a regular exponential moving average (EMA) calculation but on a
+ de-lagged data instead of doing it on the regular data. Data is de-lagged by
+ removing the data from "lag" days ago thus removing (or attempting to remove)
+ the cumulative lag effect of the moving average.
+
+ */
public class ZLEMA_Series : Single_TSeries_Indicator
{
diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj
index ae809740..2d29fbca 100644
--- a/Source/QuanTAlib.csproj
+++ b/Source/QuanTAlib.csproj
@@ -1,6 +1,6 @@
- 0.1.10-beta
+ 0.1.11
QuanTAlib
Library of Technical Indicators for .NET
diff --git a/Source/Statistics/BIAS_Series.cs b/Source/Statistics/BIAS_Series.cs
index 26427a5c..3fb543b7 100644
--- a/Source/Statistics/BIAS_Series.cs
+++ b/Source/Statistics/BIAS_Series.cs
@@ -1,18 +1,17 @@
-/**
- BIAS: Rate of change between the source and a moving average.
+namespace QuanTAlib;
+using System;
- Bias is a statistical term which means a systematic deviation from the actual value.
+/*
+BIAS: Rate of change between the source and a moving average.
+ Bias is a statistical term which means a systematic deviation from the actual value.
- BIAS = (close - SMA) / SMA
+BIAS = (close - SMA) / SMA
= (close / SMA) - 1
Sources:
- https://en.wikipedia.org/wiki/Bias_of_an_estimator
+ https://en.wikipedia.org/wiki/Bias_of_an_estimator
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class BIAS_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/ENTP_Series.cs b/Source/Statistics/ENTP_Series.cs
index f1d64cfd..d39c58cd 100644
--- a/Source/Statistics/ENTP_Series.cs
+++ b/Source/Statistics/ENTP_Series.cs
@@ -1,8 +1,10 @@
-/**
-ENTP: Entropy
+namespace QuanTAlib;
+using System;
-Introduced by Claude Shannon in 1948, entropy measures the unpredictability
-of the data, or equivalently, of its average information.
+/*
+ENTP: Entropy
+ Introduced by Claude Shannon in 1948, entropy measures the unpredictability
+ of the data, or equivalently, of its average information.
Calculation:
P = close / Σ(close)
@@ -12,9 +14,8 @@ Sources:
https://en.wikipedia.org/wiki/Entropy_(information_theory)
https://math.stackexchange.com/questions/3428693/how-to-calculate-entropy-from-a-set-of-correlated-samples
-**/
-namespace QuanTAlib;
-using System;
+ */
+
public class ENTP_Series : Single_TSeries_Indicator
{
public ENTP_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
diff --git a/Source/Statistics/KURT_Series.cs b/Source/Statistics/KURT_Series.cs
index cc5a1c63..2dc265d2 100644
--- a/Source/Statistics/KURT_Series.cs
+++ b/Source/Statistics/KURT_Series.cs
@@ -1,6 +1,8 @@
-/**
-KURT: Kurtosis of population
+namespace QuanTAlib;
+using System;
+/*
+KURT: Kurtosis of population
Kurtosis characterizes the relative peakedness or flatness of a distribution
compared with the normal distribution. Positive kurtosis indicates a relatively
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
@@ -19,12 +21,7 @@ Sources:
https://en.wikipedia.org/wiki/Kurtosis
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
-**/
-
-using System;
-namespace QuanTAlib;
-
-// https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
+ */
public class KURT_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/MAD_Series.cs b/Source/Statistics/MAD_Series.cs
index 72723afe..30f1e0af 100644
--- a/Source/Statistics/MAD_Series.cs
+++ b/Source/Statistics/MAD_Series.cs
@@ -1,8 +1,10 @@
-/**
-MAD: Mean Absolute Deviation
+namespace QuanTAlib;
+using System;
-Also known as AAD - Average Absolute Deviation, to differentiate it from Median Absolute Deviation
-MAD defines the degree of variation across the series.
+/*
+MAD: Mean Absolute Deviation
+ Also known as AAD - Average Absolute Deviation, to differentiate it from Median Absolute Deviation
+ MAD defines the degree of variation across the series.
Calculation:
MAD = Σ(|close-SMA|) / period
@@ -10,10 +12,7 @@ Calculation:
Sources:
https://en.wikipedia.org/wiki/Average_absolute_deviation
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class MAD_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/MAPE_Series.cs b/Source/Statistics/MAPE_Series.cs
index 9b5f9d10..a30185cc 100644
--- a/Source/Statistics/MAPE_Series.cs
+++ b/Source/Statistics/MAPE_Series.cs
@@ -1,7 +1,9 @@
-/**
-MAPE: Mean Absolute Percentage Error
+namespace QuanTAlib;
+using System;
-Measures the size of the error in percentage terms
+/*
+MAPE: Mean Absolute Percentage Error
+ Measures the size of the error in percentage terms
Calculation:
MAPE = Σ(|close – SMA| / |close|) / n
@@ -9,13 +11,11 @@ Calculation:
Sources:
https://en.wikipedia.org/wiki/Mean_absolute_percentage_error
-Remark: returns infinity if any of observations is 0.
-Use SMAPE or WMAPE instead to avoid division-by-zero in MAPE
+Remark:
+ returns infinity if any of observations is 0.
+ Use SMAPE or WMAPE instead to avoid division-by-zero in MAPE
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class MAPE_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/MED_Series.cs b/Source/Statistics/MED_Series.cs
index 60629067..56c9bbcb 100644
--- a/Source/Statistics/MED_Series.cs
+++ b/Source/Statistics/MED_Series.cs
@@ -1,25 +1,24 @@
-/*
+namespace QuanTAlib;
+using System;
+
+/*
MED - Median value
+ Median of numbers is the middlemost value of the given set of numbers.
+ It separates the higher half and the lower half of a given data sample.
+ At least half of the observations are smaller than or equal to median
+ and at least half of the observations are greater than or equal to the median.
-Median of numbers is the middlemost value of the given set of numbers.
-It separates the higher half and the lower half of a given data sample.
-At least half of the observations are smaller than or equal to median
-and at least half of the observations are greater than or equal to the median.
+ If the number of values is odd, the middlemost observation of the sorted
+ list is the median of the given data. If the number of values is even,
+ median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
-If the number of values is odd, the middlemost observation of the sorted
-list is the median of the given data. If the number of values is even,
-median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
-
-If period = 0 => period is max
+ If period = 0 => period is max
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
https://en.wikipedia.org/wiki/Median
-*/
-
-using System;
-namespace QuanTAlib;
+ */
public class MED_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/MSE_Series.cs b/Source/Statistics/MSE_Series.cs
index 4f634758..1b25ff8a 100644
--- a/Source/Statistics/MSE_Series.cs
+++ b/Source/Statistics/MSE_Series.cs
@@ -1,17 +1,14 @@
-/**
-MSE: Mean Square Error
+namespace QuanTAlib;
+using System;
-Defined as a Mean (Average) of the Square of the difference between actual and estimated values.
+/*
+MSE: Mean Square Error
+ Defined as a Mean (Average) of the Square of the difference between actual and estimated values.
Sources:
https://en.wikipedia.org/wiki/Mean_squared_error
-Remark:
-
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class MSE_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/PSDEV_Series.cs b/Source/Statistics/PSDEV_Series.cs
index a5567784..d2a8bba1 100644
--- a/Source/Statistics/PSDEV_Series.cs
+++ b/Source/Statistics/PSDEV_Series.cs
@@ -1,8 +1,10 @@
-/**
-PSDEV: Population Standard Deviation
+namespace QuanTAlib;
+using System;
-Population Standard Deviation is the square root of the biased variance, also knons as
-Uncorrected Sample Standard Deviation
+/*
+PSDEV: Population Standard Deviation
+ Population Standard Deviation is the square root of the biased variance, also knons as
+ Uncorrected Sample Standard Deviation
Sources:
https://en.wikipedia.org/wiki/Standard_deviation#Uncorrected_sample_standard_deviation
@@ -11,10 +13,7 @@ Remark:
PSDEV (Population Standard Deviation) is also known as a biased/uncorrected Standard Deviation.
For unbiased version that uses Bessel's correction, use SDEV instead.
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class PSDEV_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/PVAR_Series.cs b/Source/Statistics/PVAR_Series.cs
index 384cc5c4..487aefd2 100644
--- a/Source/Statistics/PVAR_Series.cs
+++ b/Source/Statistics/PVAR_Series.cs
@@ -1,7 +1,9 @@
-/**
-PVAR: Population Variance
+namespace QuanTAlib;
+using System;
-Population variance....
+/*
+PVAR: Population Variance
+ Population variance without Bessel's correction
Sources:
https://en.wikipedia.org/wiki/Variance
@@ -11,10 +13,7 @@ Remark:
PVAR (Population Variance) is also known as a biased Sample Variance. For unbiased
sample variance use SVAR instead.
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class PVAR_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/SDEV_Series.cs b/Source/Statistics/SDEV_Series.cs
index c4fe6d79..73253d53 100644
--- a/Source/Statistics/SDEV_Series.cs
+++ b/Source/Statistics/SDEV_Series.cs
@@ -1,21 +1,19 @@
-/**
-SDEV: (Corrected) Sample Standard Deviation
+namespace QuanTAlib;
+using System;
-Sample Standard Deviaton uses Bessel's correction to correct the bias in the variance.
+/*
+SDEV: (Corrected) Sample Standard Deviation
+ Sample Standard Deviaton uses Bessel's correction to correct the bias in the variance.
Sources:
https://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
Remark:
-
SSDEV (Sample Standard Deviation) is also known as a unbiased/corrected Standard Deviation.
For a population/biased/uncorrected Standard Deviation, use PSDEV instead
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class SDEV_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/SMAPE_Series.cs b/Source/Statistics/SMAPE_Series.cs
index 0674a859..7fe8dd07 100644
--- a/Source/Statistics/SMAPE_Series.cs
+++ b/Source/Statistics/SMAPE_Series.cs
@@ -1,15 +1,14 @@
-/**
-SMAPE: Symmetric Mean Absolute Percentage Error
+namespace QuanTAlib;
+using System;
-Measures the size of the error in percentage terms
+/*
+SMAPE: Symmetric Mean Absolute Percentage Error
+ Measures the size of the error in percentage terms
Sources:
https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class SMAPE_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/VAR_Series.cs b/Source/Statistics/VAR_Series.cs
index 2e2a0150..7d98b1c6 100644
--- a/Source/Statistics/VAR_Series.cs
+++ b/Source/Statistics/VAR_Series.cs
@@ -1,7 +1,9 @@
-/**
-VAR: Sample Variance
+namespace QuanTAlib;
+using System;
-Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
+/*
+VAR: Sample Variance
+ Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
Sources:
https://en.wikipedia.org/wiki/Variance
@@ -11,10 +13,7 @@ Remark:
VAR is also known as the Unbiased Sample Variance, while PVAR (Population Variance) is known as
the Biased Sample Variance.
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class VAR_Series : Single_TSeries_Indicator
{
diff --git a/Source/Statistics/WMAPE_Series.cs b/Source/Statistics/WMAPE_Series.cs
index 9ed41183..c9780f9c 100644
--- a/Source/Statistics/WMAPE_Series.cs
+++ b/Source/Statistics/WMAPE_Series.cs
@@ -1,15 +1,14 @@
-/**
-WMAPE: Weighted Mean Absolute Percentage Error
+namespace QuanTAlib;
+using System;
-Measures the size of the error in percentage terms
+/*
+WMAPE: Weighted Mean Absolute Percentage Error
+ Measures the size of the error in percentage terms
Sources:
https://en.wikipedia.org/wiki/WMAPE
-**/
-
-using System;
-namespace QuanTAlib;
+ */
public class WMAPE_Series : Single_TSeries_Indicator
{
diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs
index fb59a3ed..dc2de31d 100644
--- a/Tests/Validations/Skender_Stock.cs
+++ b/Tests/Validations/Skender_Stock.cs
@@ -90,4 +90,22 @@ public class Skender_Stock
Assert.Equal(Math.Round((double)SK.Last().Mape!, 8), Math.Round(QL.Last().v, 8));
}
+ [Fact]
+ public void ATR()
+ {
+ ATR_Series QL = new(this.bars, this.period, false);
+ var SK = this.quotes.GetAtr(this.period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Atr!, 8), Math.Round(QL.Last().v, 8));
+ }
+
+
+ [Fact]
+ public void ATRP()
+ {
+ ATRP_Series QL = new(this.bars, this.period, false);
+ var SK = this.quotes.GetAtr(this.period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Atrp!, 8), Math.Round(QL.Last().v, 8));
+ }
}
diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs
index 89246cd7..2d5406b4 100644
--- a/Tests/Validations/TA_LIB.cs
+++ b/Tests/Validations/TA_LIB.cs
@@ -10,14 +10,22 @@ public class TA_LIB
private readonly Random rnd = new();
private readonly int period;
private readonly double[] TALIB;
- private readonly double[] input;
+ private readonly double[] inopen;
+ private readonly double[] inhigh;
+ private readonly double[] inlow;
+ private readonly double[] inclose;
+ private readonly double[] involume;
public TA_LIB()
{
this.bars = new(1000);
this.period = this.rnd.Next(28) + 3;
this.TALIB = new double[this.bars.Count];
- this.input = this.bars.Close.v.ToArray();
+ this.inopen = this.bars.Open.v.ToArray();
+ this.inhigh = this.bars.High.v.ToArray();
+ this.inlow = this.bars.Low.v.ToArray();
+ this.inclose = this.bars.Close.v.ToArray();
+ this.involume = this.bars.Volume.v.ToArray();
}
/////////////////////////////////////////
@@ -26,7 +34,7 @@ public class TA_LIB
public void SMA()
{
SMA_Series QL = new(this.bars.Close, this.period, false);
- Core.Sma(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Sma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -35,7 +43,7 @@ public class TA_LIB
public void EMA()
{
EMA_Series QL = new(this.bars.Close, this.period, false);
- Core.Ema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Ema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -44,7 +52,7 @@ public class TA_LIB
public void WMA()
{
WMA_Series QL = new(this.bars.Close, this.period, false);
- Core.Wma(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Wma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -53,7 +61,7 @@ public class TA_LIB
public void DEMA()
{
DEMA_Series QL = new(this.bars.Close, this.period, false);
- Core.Dema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Dema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -62,7 +70,7 @@ public class TA_LIB
public void TEMA()
{
TEMA_Series QL = new(this.bars.Close, this.period, false);
- Core.Tema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Tema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -71,7 +79,7 @@ public class TA_LIB
public void MAX()
{
MAX_Series QL = new(this.bars.Close, this.period, false);
- Core.Max(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Max(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -80,9 +88,17 @@ public class TA_LIB
public void MIN()
{
MIN_Series QL = new(this.bars.Close, this.period, false);
- Core.Min(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+ Core.Min(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
+ [Fact]
+ public void ATR()
+ {
+ ATR_Series QL = new(this.bars, this.period, false);
+ Core.Atr(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
+
+ Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
+ }
}