Merge branch 'dev' into main

This commit is contained in:
Miha Kralj
2022-11-11 21:21:12 -08:00
77 changed files with 556 additions and 628 deletions
+14
View File
@@ -87,6 +87,20 @@ jobs:
title: "Latest Build" title: "Latest Build"
files: /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll files: /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll
- name: Authenticate to Github packages source
run: dotnet nuget add source
--username mihakralj
--password ${{ secrets.GITHUB_TOKEN }}
--store-password-in-clear-text
--name github "https://nuget.pkg.github.com/mihakralj/index.json"
- name: Push package to github
if: ${{ github.ref == 'refs/heads/dev' }}
run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
--source https://nuget.pkg.github.com/mihakralj/index.json
--skip-duplicate
--no-symbols
- name: Push package to nuget.org - name: Push package to nuget.org
if: ${{ github.ref == 'refs/heads/main' }} if: ${{ github.ref == 'refs/heads/main' }}
run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg' run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
-5
View File
@@ -51,11 +51,6 @@ public class WMAPE_chart : Indicator
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update); this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
double result = this.indicator[this.indicator.Count - 1].v; double result = this.indicator[this.indicator.Count - 1].v;
this.SetValue(result, 0); this.SetValue(result, 0);
} }
} }
-93
View File
@@ -1,93 +0,0 @@
using System.Collections;
using System.Drawing;
using System.Drawing.Text;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class ZLMA_chart : Indicator
{
#region Parameters
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
private readonly int Period = 10;
[InputParameter("Data source", 1, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private readonly int DataSource = 3;
[InputParameter("MA algorithm", 2, variants: new object[]
{ "SMA", 0,
"WMA", 1,
"EMA", 2,
"DEMA", 3,
"TEMA", 4,
"HMA", 5,
"KAMA", 6,
"JMA", 7,
"SMMA", 8
})]
private readonly int matype = 2;
#endregion Parameters
private TBars bars;
///////
private TSeries indicator;
///////
public ZLMA_chart()
{
this.SeparateWindow = false;
this.Name = "ZLMA - Zero-lag Moving Average";
this.Description = "Zero-Lag Moving Average description";
this.AddLineSeries("ZLMA", Color.RoyalBlue, 3, LineStyle.Solid);
}
protected override void OnInit()
{
this.bars = new();
string maname = matype switch
{
0 => "SMA",
1 => "WMA",
2 => "EMA",
3 => "DEMA",
4 => "TEMA",
5 => "HMA",
6 => "KAMA",
7 => "JMA",
8 => "SMMA",
_ => "???"
};
this.ShortName = "ZLMA (" + maname + ", " + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
ZL_Series zerolag = new(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.indicator = matype switch
{
0 => new SMA_Series(source: zerolag, period: this.Period, useNaN: false),
1 => new WMA_Series(source: zerolag, period: this.Period, useNaN: false),
2 => new EMA_Series(source: zerolag, period: this.Period, useNaN: false),
3 => new DEMA_Series(source: zerolag, period: this.Period, useNaN: false),
4 => new TEMA_Series(source: zerolag, period: this.Period, useNaN: false),
5 => new HMA_Series(source: zerolag, period: this.Period, useNaN: false),
6 => new KAMA_Series(source: zerolag, period: this.Period, useNaN: false),
7 => new JMA_Series(source: zerolag, period: this.Period, useNaN: false),
8 => new SMMA_Series(source: zerolag, period: this.Period, useNaN: false),
_ => new EMA_Series(source: zerolag, period: this.Period, useNaN: false)
};
}
protected override void OnUpdate(UpdateArgs args)
{
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
this.GetPrice(PriceType.Close),
this.GetPrice(PriceType.Volume), update);
double result = this.indicator[this.indicator.Count-1].v;
this.SetValue(result);
}
}
+17 -51
View File
@@ -32,23 +32,14 @@ public abstract class Single_TSeries_Indicator : TSeries
public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update); public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
// potentially overridable Add() method for the whole series (could be replaced with faster bulk algo) // potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
public virtual void Add(TSeries data) public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }}
{
for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }
}
public new void Add((System.DateTime t, double v) TValue) public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
=> this.Add(TValue: TValue, update: false); public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
public void Add(bool update) public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
=> this.Add(TValue: this._data[this._data.Count - 1], update: update); public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
public void Add()
=> this.Add(TValue: this._data[this._data.Count - 1], update: false);
public new void Sub(object source, TSeriesEventArgs e)
=> this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
} }
public abstract class Pair_TSeries_Indicator : TSeries public abstract class Pair_TSeries_Indicator : TSeries
{ {
protected readonly TSeries _d1; protected readonly TSeries _d1;
@@ -83,24 +74,14 @@ public abstract class Pair_TSeries_Indicator : TSeries
} }
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list // overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) => base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
=> base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos) // potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
public virtual void Add(TSeries d1, TSeries d2) { public virtual void Add(TSeries d1, TSeries d2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); }}
for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); } public virtual void Add(TSeries d1, double dd2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }}
} public virtual void Add(double dd1, TSeries d2) { for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }}
public virtual void Add(TSeries d1, double dd2) {
for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }
}
public virtual void Add(double dd1, TSeries d2) {
for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }
}
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2)
=> this.Add(TValue1, TValue2, update: false);
public void Add(bool update) public void Add(bool update)
{ {
@@ -123,12 +104,9 @@ public abstract class Pair_TSeries_Indicator : TSeries
} }
public void Add() => this.Add(update: false); public void Add() => this.Add(update: false);
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
public new void Sub(object source, TSeriesEventArgs e)
=> this.Add(e.update);
} }
public abstract class Single_TBars_Indicator : TSeries public abstract class Single_TBars_Indicator : TSeries
{ {
protected readonly int _p; protected readonly int _p;
@@ -148,22 +126,10 @@ public abstract class Single_TBars_Indicator : TSeries
public virtual void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update); public virtual void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update);
// potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo) // potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo)
public virtual void Add(TBars bars) public virtual void Add(TBars bars) { for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); }}
{ public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }}
for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); } public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar) => this.Add(TBar: TBar, update: false);
} public void Add(bool update) => this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
public void Add() => this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
public virtual void Add(TSeries data) public new void Sub(object source, TSeriesEventArgs e) => this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
{
for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }
}
public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar)
=> this.Add(TBar: TBar, update: false);
public void Add(bool update)
=> this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
public void Add()
=> this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
public new void Sub(object source, TSeriesEventArgs e)
=> this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
} }
+4 -1
View File
@@ -22,7 +22,10 @@ public class MAX_Series : Single_TSeries_Indicator
double _max = TValue.v; double _max = TValue.v;
for (int i = 0; i < this._buffer.Count; i++) 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;
_max = Math.Max(this._buffer[i], _max);
}
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max); var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
+4 -1
View File
@@ -22,7 +22,10 @@ public class MIN_Series : Single_TSeries_Indicator
double _min = TValue.v; double _min = TValue.v;
for (int i = 0; i < this._buffer.Count; i++) for (int i = 0; i < this._buffer.Count; i++)
{ _min = (this._buffer[i] < _min) ? this._buffer[i] : _min; } {
//_min = (this._buffer[i] < _min) ? this._buffer[i] : _min;
_min = Math.Min(this._buffer[i], _min);
}
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _min); var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _min);
-3
View File
@@ -75,7 +75,6 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
}; };
} }
public void Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false) public void Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false)
=> Add(i.t, i.o, i.h, i.l, i.c, i.v, update); => Add(i.t, i.o, i.h, i.l, i.c, i.v, update);
@@ -130,6 +129,4 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
Pub(this, new TSeriesEventArgs { update = update }); Pub(this, new TSeriesEventArgs { update = update });
} }
} }
} }
-1
View File
@@ -30,6 +30,5 @@ public class ZL_Series : Single_TSeries_Indicator
var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : _zl ); var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : _zl );
base.Add(ret, update); base.Add(ret, update);
} }
} }
-1
View File
@@ -55,4 +55,3 @@ public class Alphavantage_Feed : TBars
return (date, o, h, l, c, v); return (date, o, h, l, c, v);
} }
} }
+3 -3
View File
@@ -38,11 +38,11 @@ public class GBM_Feed : TBars
double OCMax = Math.Max(Open,Close); double OCMax = Math.Max(Open,Close);
double High = (GBM_value(seed, volatility*0.5, 0)); double High = (GBM_value(seed, volatility*0.5, 0));
High = (High<OCMax)? 2*OCMax-High : High; High = (High<OCMax)? (2 * OCMax) - High : High;
double OCMin = Math.Min(Open,Close); double OCMin = Math.Min(Open,Close);
double Low = (GBM_value(seed, volatility*0.5, 0)); double Low = (GBM_value(seed, volatility*0.5, 0));
Low = (Low>OCMin)? 2*OCMin-Low : Low; Low = (Low>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);
@@ -55,6 +55,6 @@ public class GBM_Feed : TBars
double U1 = 1.0-rnd.NextDouble(); double U1 = 1.0-rnd.NextDouble();
double U2 = 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); 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 Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z));
} }
} }
+4 -4
View File
@@ -17,10 +17,10 @@ public class RND_Feed : TBars
double c = startvalue; double c = startvalue;
for (int i = 0; i < bars; i++) for (int i = 0; i < bars; i++)
{ {
double o = Math.Round(c + c * (volatility * 0.1 * rnd.NextDouble() - 0.005), 2); 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 h = Math.Round(o + (c * volatility * rnd.NextDouble()), 2);
double l = 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); c = Math.Round(l + ((h - l) * rnd.NextDouble()), 2);
double v = Math.Round(1000 * rnd.NextDouble(), 2); double v = Math.Round(1000 * rnd.NextDouble(), 2);
this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v); this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v);
} }
@@ -20,14 +20,13 @@ public class CCI_Series : Single_TBars_Indicator
{ {
private readonly System.Collections.Generic.List<double> _tp = new(); private readonly System.Collections.Generic.List<double> _tp = new();
public CCI_Series(TBars source, int period = 10, bool useNaN = false) public CCI_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
: base(source, period: period, useNaN: useNaN) { {
if (_bars.Count > 0) { base.Add(_bars); } 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) { public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0; double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); } if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); }
if (this._tp.Count > this._p) { this._tp.RemoveAt(0); } if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Version>0.1.17</Version> <Version>0.1.18</Version>
<releaseNotes> <releaseNotes>
</releaseNotes> </releaseNotes>
<Title>QuanTAlib</Title> <Title>QuanTAlib</Title>
+1 -1
View File
@@ -54,7 +54,7 @@ public class KURT_Series : Single_TSeries_Indicator
} }
double _Vx = _s2 / (_n - 1); double _Vx = _s2 / (_n - 1);
double _kurt = (_n > 3) ? (((_n * (_n + 1)) / ((_n - 1) * (_n - 2) * (_n - 3))) * (_s4 / (_Vx * _Vx)) - (3 * ((_n - 1) * (_n - 1) / ((_n - 2) * (_n - 3))))) : Double.NaN; double _kurt = (_n > 3) ? ((((_n * (_n + 1)) / (((_n - 1) * (_n - 2)) * (_n - 3))) * (_s4 / (_Vx * _Vx))) - (3 * (((_n - 1) * (_n - 1)) / ((_n - 2) * (_n - 3))))) : Double.NaN;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt); var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
base.Add(result, update); base.Add(result, update);
+1 -1
View File
@@ -37,7 +37,7 @@ public class MED_Series : Single_TSeries_Indicator
System.Collections.Generic.List<double> _s = new(this._buffer); System.Collections.Generic.List<double> _s = new(this._buffer);
_s.Sort(); _s.Sort();
int _p1 = _s.Count / 2; int _p1 = _s.Count / 2;
int _p2 = Math.Max(0, _s.Count / 2 - 1); int _p2 = Math.Max(0, (_s.Count / 2) - 1);
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2; double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med); var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med);
@@ -62,7 +62,4 @@ public class ALMA_Series : Single_TSeries_Indicator
_norm += _wt; _norm += _wt;
} }
} }
} }
@@ -31,7 +31,6 @@ public class DEMA_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update) public override void Add((DateTime t, double v) TValue, bool update)
{ {
if (update) if (update)
{ {
this._lastema1 = this._lastlastema1; this._lastema1 = this._lastlastema1;
@@ -53,15 +52,14 @@ public class DEMA_Series : Single_TSeries_Indicator
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; } for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count; _sma /= this._buffer.Count;
_ema1 = _ema2 = _sma; _ema1 = _ema2 = _sma;
} }
else else
{ {
_ema1 = TValue.v * this._k + this._lastema1 * this._k1m; _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
_ema2 = _ema1 * this._k + this._lastema2 * this._k1m; _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
} }
double _dema = 2 * _ema1 - _ema2; double _dema = (2 * _ema1) - _ema2;
this._lastlastema1 = this._lastema1; this._lastlastema1 = this._lastema1;
this._lastlastema2 = this._lastema2; this._lastlastema2 = this._lastema2;
this._lastema1 = _ema1; this._lastema1 = _ema1;
@@ -52,7 +52,7 @@ public class EMA_Series : Single_TSeries_Indicator
} }
else else
{ {
_ema = TValue.v * this._k + this._lastema * this._k1m; _ema = (TValue.v * this._k) + (this._lastema * this._k1m);
} }
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
@@ -51,7 +51,7 @@ public class RMA_Series : Single_TSeries_Indicator
} }
else else
{ {
_ema = TValue.v * _k + _lastema * _k1m; _ema = (TValue.v * _k) + (_lastema * _k1m);
} }
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
@@ -33,7 +33,6 @@ public class TEMA_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update) public override void Add((DateTime t, double v) TValue, bool update)
{ {
if (update) if (update)
{ {
this._lastema1 = this._lastlastema1; this._lastema1 = this._lastlastema1;
@@ -59,12 +58,12 @@ public class TEMA_Series : Single_TSeries_Indicator
} }
else else
{ {
_ema1 = TValue.v * this._k + this._lastema1 * this._k1m; _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
_ema2 = _ema1 * this._k + this._lastema2 * this._k1m; _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
_ema3 = _ema2 * this._k + this._lastema3 * this._k1m; _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
} }
double _tema = 3 * (_ema1 - _ema2) + _ema3; double _tema = (3 * (_ema1 - _ema2)) + _ema3;
this._lastlastema1 = this._lastema1; this._lastlastema1 = this._lastema1;
this._lastlastema2 = this._lastema2; this._lastlastema2 = this._lastema2;
+49
View File
@@ -0,0 +1,49 @@
namespace QuanTAlib;
using System;
/* <summary>
TRIMA: Triangular Moving Average
A weighted moving average where the shape of the weights are triangular and the greatest
weight is in the middle of the period,
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
Remark:
trima = sma(sma(signal, n/2), n/2)
</summary> */
public class TRIMA_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List<double> _buffer1 = new();
private readonly System.Collections.Generic.List<double> _buffer2 = new();
private readonly int _p1a, _p1b;
public TRIMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
{
_p1a = (int) Math.Floor((period * 0.5) + 1);
_p1b = (int) Math.Ceiling(0.5 * period);
if (base._data.Count > 0) { base.Add(base._data); }
}
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
double _sma1 = 0;
for (int i = 0; i < _buffer1.Count; i++) { _sma1 += _buffer1[i]; }
_sma1 /= this._buffer1.Count;
if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
double _trima = 0;
for (int i = 0; i < _buffer2.Count; i++) { _trima += _buffer2[i]; }
_trima /= this._buffer2.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _trima);
base.Add(result, update);
}
}
@@ -60,7 +60,7 @@ public class ZLEMA_Series : Single_TSeries_Indicator
} }
else else
{ {
_ema = _zl * this._k + this._lastema * this._k1m; _ema = (_zl * this._k) + (this._lastema * this._k1m);
} }
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
@@ -50,7 +50,7 @@ public class ATRP_Series : Single_TBars_Indicator
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; } for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
_ema /= this._buffer.Count; _ema /= this._buffer.Count;
} }
else { _ema = d.v * _k + _lastema * _k1m; } else { _ema = (d.v * _k) + (_lastema * _k1m); }
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
this._lastema = _ema; this._lastema = _ema;
@@ -13,7 +13,6 @@ Sources:
</summary> */ </summary> */
public class ATR_Series : Single_TBars_Indicator public class ATR_Series : Single_TBars_Indicator
{ {
private readonly System.Collections.Generic.List<double> _buffer = new(); private readonly System.Collections.Generic.List<double> _buffer = new();
@@ -53,7 +52,7 @@ public class ATR_Series : Single_TBars_Indicator
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; } for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
_ema /= this._buffer.Count; _ema /= this._buffer.Count;
} }
else { _ema = d.v * _k + _lastema * _k1m; } else { _ema = (d.v * _k) + (_lastema * _k1m); }
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
this._lastema = _ema; this._lastema = _ema;
+62
View File
@@ -0,0 +1,62 @@
namespace QuanTAlib;
using System;
/* <summary>
OBV: On-Balance Volume
On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
Granville's New Key to Stock Market Profits.
| +volume; if close > close[previous]
OBV = OBV[previous] + | 0; if close = close[previous]
| -volume; if close < close[previous]
Sources:
https://www.investopedia.com/terms/o/onbalancevolume.asp
https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
https://www.motivewave.com/studies/on_balance_volume.htm
Note:
There is no consensus on what is the first OBV value in the series:
- TA-LIB uses the first volume: OBV[0] = volume[0]
- Skender stock library uses 0: OBV[0] = 0
</summary> */
public class OBV_Series : Single_TBars_Indicator
{
private double _lastobv, _lastlastobv;
private double _lastclose, _lastlastclose;
public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
{
this._lastobv = this._lastlastobv = 0;
this._lastclose = this._lastlastclose = 0;
if (_bars.Count > 0) { base.Add(_bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update)
{
this._lastobv = this._lastlastobv;
this._lastclose = this._lastlastclose;
}
double _obv = this._lastobv;
if (TBar.c > this._lastclose) { _obv += TBar.v; }
if (TBar.c < this._lastclose) { _obv -= TBar.v; }
// Unclear what the first value in OBV series is - currently set to volume[0]
// if (this.Count == 0) { _obv = 0; }
this._lastlastobv = this._lastobv;
this._lastobv = _obv;
this._lastlastclose = this._lastclose;
this._lastclose = TBar.c;
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
base.Add(result, update);
}
}
-1
View File
@@ -108,6 +108,5 @@ public class TBars_Test
s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false); s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false);
Assert.Equal(s.Close.v, t.v); Assert.Equal(s.Close.v, t.v);
Assert.Equal(s.Close.Count, t.Count); Assert.Equal(s.Close.Count, t.Count);
} }
} }
-2
View File
@@ -48,7 +48,6 @@ public class TSeries_Test
TSeries t = s; TSeries t = s;
Assert.Equal(5, (double)t); Assert.Equal(5, (double)t);
Assert.Equal(5, t.Count); Assert.Equal(5, t.Count);
} }
[Fact] [Fact]
public void BroadcastingEvents() public void BroadcastingEvents()
@@ -58,6 +57,5 @@ public class TSeries_Test
s.Pub += t.Sub; s.Pub += t.Sub;
s.Add(0.0, update: true); s.Add(0.0, update: true);
Assert.Equal(0.0, (double)t); Assert.Equal(0.0, (double)t);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class ALMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -52,7 +52,5 @@ public class BBANDS_Test
Assert.Equal(a.Count, c.PercentB.Count); Assert.Equal(a.Count, c.PercentB.Count);
Assert.Equal(a.Count, c.Zscore.Count); Assert.Equal(a.Count, c.Zscore.Count);
Assert.Equal(a.Count, c.Bandwidth.Count); Assert.Equal(a.Count, c.Bandwidth.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class DEMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class EMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class HEMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class HMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class JMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class KAMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MACD_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class RMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class RSI_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class SMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class SMMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class TEMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class WMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class ZLEMA_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class BIAS_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class KURT_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class ENTP_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class LINREG_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MAD_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MAPE_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MAX_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MED_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MIN_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class MSE_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class PSDEV_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class PVAR_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class SDEV_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class SMAPE_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class VAR_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-2
View File
@@ -27,7 +27,5 @@ public class WMAPE_Test
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity); a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
} }
} }
-3
View File
@@ -1,5 +1,3 @@
using Xunit; using Xunit;
using System; using System;
using QuanTAlib; using QuanTAlib;
@@ -120,5 +118,4 @@ public class PandasTA
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
} }
*/ */
} }
+47 -38
View File
@@ -3,7 +3,6 @@ using QuanTAlib;
using Skender.Stock.Indicators; using Skender.Stock.Indicators;
using Xunit; using Xunit;
namespace Validation; namespace Validation;
public class Skender_Stock public class Skender_Stock
{ {
@@ -14,7 +13,7 @@ public class Skender_Stock
public Skender_Stock() public Skender_Stock()
{ {
this.bars = new(1000); this.bars = new(Bars: 1, Volatility:0.7, Drift:0.0);
this.period = this.rnd.Next(28) + 3; this.period = this.rnd.Next(28) + 3;
this.quotes = this.bars.Select( this.quotes = this.bars.Select(
q => new Quote q => new Quote
@@ -34,7 +33,7 @@ public class Skender_Stock
SMA_Series QL = new(this.bars.Close, this.period, false); SMA_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetSma(this.period); var SK = this.quotes.GetSma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -43,7 +42,7 @@ public class Skender_Stock
EMA_Series QL = new(this.bars.Close, this.period, false); EMA_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetEma(this.period); var SK = this.quotes.GetEma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Ema!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void WMA() public void WMA()
@@ -51,7 +50,7 @@ public class Skender_Stock
WMA_Series QL = new(this.bars.Close, this.period, false); WMA_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetWma(this.period); var SK = this.quotes.GetWma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Wma!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -60,7 +59,7 @@ public class Skender_Stock
DEMA_Series QL = new(this.bars.Close, this.period, false); DEMA_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetDema(this.period); var SK = this.quotes.GetDema(this.period);
Assert.Equal(Math.Round((double)SK.Last().Dema!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -69,7 +68,7 @@ public class Skender_Stock
TEMA_Series QL = new(this.bars.Close, this.period, false); TEMA_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetTema(this.period); var SK = this.quotes.GetTema(this.period);
Assert.Equal(Math.Round((double)SK.Last().Tema!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -78,7 +77,7 @@ public class Skender_Stock
MAD_Series QL = new(this.bars.Close, this.period, false); MAD_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetSmaAnalysis(this.period); var SK = this.quotes.GetSmaAnalysis(this.period);
Assert.Equal(Math.Round((double)SK.Last().Mad!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -87,7 +86,7 @@ public class Skender_Stock
MAPE_Series QL = new(this.bars.Close, this.period, false); MAPE_Series QL = new(this.bars.Close, this.period, false);
var SK = this.quotes.GetSmaAnalysis(this.period); var SK = this.quotes.GetSmaAnalysis(this.period);
Assert.Equal(Math.Round((double)SK.Last().Mape!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -96,7 +95,18 @@ public class Skender_Stock
ATR_Series QL = new(this.bars, this.period, false); ATR_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetAtr(this.period); var SK = this.quotes.GetAtr(this.period);
Assert.Equal(Math.Round((double)SK.Last().Atr!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetObv(this.period);
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
Assert.Equal(Math.Round((double)SK.Last().Obv!, 6) + Math.Round((double)this.quotes.First().Volume!, 6),
Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -105,7 +115,7 @@ public class Skender_Stock
ADL_Series QL = new(this.bars, false); ADL_Series QL = new(this.bars, false);
var SK = this.quotes.GetAdl(); var SK = this.quotes.GetAdl();
Assert.Equal(Math.Round((double)SK.Last().Adl!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
} }
[Fact] [Fact]
@@ -114,7 +124,7 @@ public class Skender_Stock
CCI_Series QL = new(this.bars, this.period, false); CCI_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetCci(this.period); var SK = this.quotes.GetCci(this.period);
Assert.Equal(Math.Round((double)SK.Last().Cci!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -123,7 +133,7 @@ public class Skender_Stock
ATRP_Series QL = new(this.bars, this.period, false); ATRP_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetAtr(this.period); var SK = this.quotes.GetAtr(this.period);
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -132,7 +142,7 @@ public class Skender_Stock
KAMA_Series QL = new(this.bars.Close, this.period, useNaN: false); KAMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetKama(this.period); var SK = this.quotes.GetKama(this.period);
Assert.Equal(Math.Round((double)SK.Last().Kama!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -141,7 +151,7 @@ public class Skender_Stock
HMA_Series QL = new(this.bars.Close, this.period, useNaN: false); HMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetHma(this.period); var SK = this.quotes.GetHma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Hma!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -150,7 +160,7 @@ public class Skender_Stock
SMMA_Series QL = new(this.bars.Close, this.period, useNaN: false); SMMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetSmma(this.period); var SK = this.quotes.GetSmma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Smma!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -159,8 +169,8 @@ public class Skender_Stock
MACD_Series QL = new(this.bars.Close, 26,12,9, useNaN: false); MACD_Series QL = new(this.bars.Close, 26,12,9, useNaN: false);
var SK = this.quotes.GetMacd(12,26,9); var SK = this.quotes.GetMacd(12,26,9);
Assert.Equal(Math.Round((double)SK.Last().Macd!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Signal!, 8), Math.Round(QL.Signal.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
} }
[Fact] [Fact]
@@ -169,22 +179,21 @@ public class Skender_Stock
BBANDS_Series QL = new(this.bars.Close, this.period, 2.0, useNaN: false); BBANDS_Series QL = new(this.bars.Close, this.period, 2.0, useNaN: false);
var SK = this.quotes.GetBollingerBands(this.period, 2.0); var SK = this.quotes.GetBollingerBands(this.period, 2.0);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 8), Math.Round(QL.Mid.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 8), Math.Round(QL.Upper.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 8), Math.Round(QL.Lower.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Width!, 8), Math.Round(QL.Bandwidth.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 8), Math.Round(QL.PercentB.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 8), Math.Round(QL.Zscore.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
} }
[Fact] [Fact]
public void RSI() public void RSI()
{ {
RSI_Series QL = new(this.bars.Close, this.period, useNaN: false); RSI_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetRsi(this.period); var SK = this.quotes.GetRsi(this.period);
Assert.Equal(Math.Round((double)SK.Last().Rsi!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -193,7 +202,7 @@ public class Skender_Stock
ALMA_Series QL = new(this.bars.Close, this.period, useNaN: false); ALMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetAlma(this.period); var SK = this.quotes.GetAlma(this.period);
Assert.Equal(Math.Round((double)SK.Last().Alma!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -202,7 +211,7 @@ public class Skender_Stock
SDEV_Series QL = new(this.bars.Close, this.period, useNaN: false); SDEV_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetStdDev(this.period); var SK = this.quotes.GetStdDev(this.period);
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -211,10 +220,10 @@ public class Skender_Stock
LINREG_Series QL = new(this.bars.Close, this.period, useNaN: false); LINREG_Series QL = new(this.bars.Close, this.period, useNaN: false);
var SK = this.quotes.GetSlope(this.period); var SK = this.quotes.GetSlope(this.period);
Assert.Equal(Math.Round((double)SK.Last().Slope!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Intercept!, 8), Math.Round(QL.Intercept.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().RSquared!, 8), Math.Round(QL.RSquared.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 8), Math.Round(QL.StdDev.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
} }
[Fact] [Fact]
@@ -223,7 +232,7 @@ public class Skender_Stock
TR_Series QL = new(this.bars, useNaN: false); TR_Series QL = new(this.bars, useNaN: false);
var SK = this.quotes.GetTr(); var SK = this.quotes.GetTr();
Assert.Equal(Math.Round((double)SK.Last().Tr!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -232,7 +241,7 @@ public class Skender_Stock
TSeries QL = this.bars.HL2; TSeries QL = this.bars.HL2;
var SK = this.quotes.GetBaseQuote(CandlePart.HL2); var SK = this.quotes.GetBaseQuote(CandlePart.HL2);
Assert.Equal(Math.Round((double)SK.Last().Value!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -241,7 +250,7 @@ public class Skender_Stock
TSeries QL = this.bars.OC2; TSeries QL = this.bars.OC2;
var SK = this.quotes.GetBaseQuote(CandlePart.OC2); var SK = this.quotes.GetBaseQuote(CandlePart.OC2);
Assert.Equal(Math.Round((double)SK.Last().Value!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -250,7 +259,7 @@ public class Skender_Stock
TSeries QL = this.bars.HLC3; TSeries QL = this.bars.HLC3;
var SK = this.quotes.GetBaseQuote(CandlePart.HLC3); var SK = this.quotes.GetBaseQuote(CandlePart.HLC3);
Assert.Equal(Math.Round((double)SK.Last().Value!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -259,7 +268,7 @@ public class Skender_Stock
TSeries QL = this.bars.OHL3; TSeries QL = this.bars.OHL3;
var SK = this.quotes.GetBaseQuote(CandlePart.OHL3); var SK = this.quotes.GetBaseQuote(CandlePart.OHL3);
Assert.Equal(Math.Round((double)SK.Last().Value!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
@@ -268,6 +277,6 @@ public class Skender_Stock
TSeries QL = this.bars.OHLC4; TSeries QL = this.bars.OHLC4;
var SK = this.quotes.GetBaseQuote(CandlePart.OHLC4); var SK = this.quotes.GetBaseQuote(CandlePart.OHLC4);
Assert.Equal(Math.Round((double)SK.Last().Value!, 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
} }
+46 -33
View File
@@ -18,7 +18,7 @@ public class TA_LIB
public TA_LIB() public TA_LIB()
{ {
this.bars = new(1000); this.bars = new(5000);
this.period = this.rnd.Next(28) + 3; this.period = this.rnd.Next(28) + 3;
this.TALIB = new double[this.bars.Count]; this.TALIB = new double[this.bars.Count];
this.inopen = this.bars.Open.v.ToArray(); this.inopen = this.bars.Open.v.ToArray();
@@ -36,7 +36,7 @@ public class TA_LIB
ADD_Series QL = new(this.bars.Open, this.bars.Close); ADD_Series QL = new(this.bars.Open, this.bars.Close);
Core.Add(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.Add(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -45,7 +45,7 @@ public class TA_LIB
SUB_Series QL = new(this.bars.Open, this.bars.Close); SUB_Series QL = new(this.bars.Open, this.bars.Close);
Core.Sub(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.Sub(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -54,7 +54,7 @@ public class TA_LIB
MUL_Series QL = new(this.bars.Open, this.bars.Close); MUL_Series QL = new(this.bars.Open, this.bars.Close);
Core.Mult(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.Mult(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -63,7 +63,7 @@ public class TA_LIB
DIV_Series QL = new(this.bars.Open, this.bars.Close); DIV_Series QL = new(this.bars.Open, this.bars.Close);
Core.Div(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.Div(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -72,17 +72,25 @@ public class TA_LIB
SDEV_Series QL = new(this.bars.Close, this.period, false); SDEV_Series QL = new(this.bars.Close, this.period, false);
Core.StdDev(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period); Core.StdDev(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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
public void SMA() public void SMA()
{ {
SMA_Series QL = new(this.bars.Close, this.period, false); SMA_Series QL = new(this.bars.Close, this.period, false);
Core.Sma(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TRIMA()
{
TRIMA_Series QL = new(this.bars.Close, this.period, false);
Core.Trima(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], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -91,7 +99,7 @@ public class TA_LIB
EMA_Series QL = new(this.bars.Close, this.period, false); EMA_Series QL = new(this.bars.Close, this.period, false);
Core.Ema(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -100,7 +108,7 @@ public class TA_LIB
WMA_Series QL = new(this.bars.Close, this.period, false); WMA_Series QL = new(this.bars.Close, this.period, false);
Core.Wma(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -109,7 +117,7 @@ public class TA_LIB
DEMA_Series QL = new(this.bars.Close, this.period, false); DEMA_Series QL = new(this.bars.Close, this.period, false);
Core.Dema(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -118,7 +126,7 @@ public class TA_LIB
TEMA_Series QL = new(this.bars.Close, this.period, false); TEMA_Series QL = new(this.bars.Close, this.period, false);
Core.Tema(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -127,7 +135,7 @@ public class TA_LIB
MAX_Series QL = new(this.bars.Close, this.period, false); MAX_Series QL = new(this.bars.Close, this.period, false);
Core.Max(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -136,7 +144,7 @@ public class TA_LIB
MIN_Series QL = new(this.bars.Close, this.period, false); MIN_Series QL = new(this.bars.Close, this.period, false);
Core.Min(this.inclose, 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -145,7 +153,16 @@ public class TA_LIB
ADL_Series QL = new(this.bars, false); ADL_Series QL = new(this.bars, false);
Core.Ad(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.Ad(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(this.bars, this.period, false);
Core.Obv(this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -154,7 +171,7 @@ public class TA_LIB
ADOSC_Series QL = new(this.bars, false); ADOSC_Series QL = new(this.bars, false);
Core.AdOsc(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.AdOsc(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -163,7 +180,7 @@ public class TA_LIB
ATR_Series QL = new(this.bars, this.period, false); 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); 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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -172,7 +189,7 @@ public class TA_LIB
CCI_Series QL = new(this.bars, this.period, false); CCI_Series QL = new(this.bars, this.period, false);
Core.Cci(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period); Core.Cci(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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -181,7 +198,7 @@ public class TA_LIB
RSI_Series QL = new(this.bars.Close, this.period, false); RSI_Series QL = new(this.bars.Close, this.period, false);
Core.Rsi(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period); Core.Rsi(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)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -190,7 +207,7 @@ public class TA_LIB
TR_Series QL = new(this.bars, false); TR_Series QL = new(this.bars, false);
Core.TRange(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.TRange(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -200,8 +217,8 @@ public class TA_LIB
double[] macdHist = new double[this.bars.Count]; double[] macdHist = new double[this.bars.Count];
MACD_Series QL = new(this.bars.Close, slow: 26, fast: 12, signal: 9, false); MACD_Series QL = new(this.bars.Close, slow: 26, fast: 12, signal: 9, false);
Core.Macd(this.inclose, 0, this.bars.Count - 1, outMacd: this.TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _); Core.Macd(this.inclose, 0, this.bars.Count - 1, outMacd: this.TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 8), Math.Round(QL.Signal.Last().v, 8)); Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -212,21 +229,18 @@ public class TA_LIB
double[] outLower = new double[this.bars.Count]; double[] outLower = new double[this.bars.Count];
BBANDS_Series QL = new(this.bars.Close, period:26, multiplier:2.0, false); BBANDS_Series QL = new(this.bars.Close, period:26, multiplier:2.0, false);
Core.Bbands(this.inclose, 0, this.bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod:26, optInNbDevUp:2.0, optInNbDevDn:2.0); Core.Bbands(this.inclose, 0, this.bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod:26, optInNbDevUp:2.0, optInNbDevDn:2.0);
Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 7), Math.Round(QL.Upper.Last().v, 7)); Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Upper.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 7), Math.Round(QL.Mid.Last().v, 7)); Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Mid.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 7), Math.Round(QL.Lower.Last().v, 7)); Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Lower.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
public void HL2() public void HL2()
{ {
TSeries QL = this.bars.HL2; TSeries QL = this.bars.HL2;
Core.MedPrice(this.inhigh, this.inlow, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.MedPrice(this.inhigh, this.inlow, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -235,7 +249,7 @@ public class TA_LIB
TSeries QL = this.bars.HLC3; TSeries QL = this.bars.HLC3;
Core.TypPrice(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.TypPrice(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -244,7 +258,7 @@ public class TA_LIB
TSeries QL = this.bars.OHLC4; TSeries QL = this.bars.OHLC4;
Core.AvgPrice(this.inopen, this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.AvgPrice(this.inopen, this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
@@ -253,7 +267,6 @@ public class TA_LIB
TSeries QL = this.bars.HLCC4; TSeries QL = this.bars.HLCC4;
Core.WclPrice( this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _); Core.WclPrice( this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
} }
+12 -21
View File
File diff suppressed because one or more lines are too long
+73 -74
View File
@@ -37,84 +37,91 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** | | **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** |
|--|:--:|:--:|:--:| |--|:--:|:--:|:--:|
| ✔️ OC2 - (Open+Close)/2 | `.OC2` || `GetBaseQuote` | | ✔️ OC2 - (Open+Close)/2 | `.OC2` || GetBaseQuote |
| ⭐ HL2 - Median Price | `.HL2` | `MEDPRICE` | `GetBaseQuote` | | ⭐ HL2 - Median Price | `.HL2` | MEDPRICE | GetBaseQuote |
| ⭐ HLC3 - Typical Price | `.HLC3` | `TYPPRICE` || | ⭐ HLC3 - Typical Price | `.HLC3` | TYPPRICE ||
| ✔️ OHL3 - (Open+High+Low)/3 | `.OHL3` ||| | ✔️ OHL3 - (Open+High+Low)/3 | `.OHL3` |||
| ⭐ OHLC4 - Average Price | `.OHLC4` | `AVGPRICE` | `GetBaseQuote` | | ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE | GetBaseQuote |
| ⭐ HLCC4 - Weighted Price | `.HLCC4` | `WCLPRICE` || | ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE ||
| ✔️ ZL - De-lagged price (Zero-Lag) | `ZL_Series` ||| | ⭐ MAX - Max value | `MAX_Series` | MAX ||
| ⭐ MAX - Max value | `MAX_Series` | `MAX` || | ⭐ MIN - Min value | `MIN_Series` | MIN ||
| ⛔ MID - Midpoint value || `MIDPOINT` || | ⛔ MID - Midpoint value || MIDPOINT ||
| ⛔ MIDP - Midpoint price || `MIDPRICE` || | ⛔ MIDP - Midpoint price || MIDPRICE ||
| ⭐ MIN - Min value | `MIN_Series` | `MIN` || | ⛔ SUM - Summation || SUM ||
| ⭐ ADD - Addition | `ADD_Series` | `ADD` || | ⭐ ADD - Addition | `ADD_Series` | ADD ||
| ⭐ SUB - Subtraction | `SUB_Series` | `SUB` || | ⭐ SUB - Subtraction | `SUB_Series` | SUB ||
| ⭐ MUL - Multiplication | `MUL_Series` | `MUL` || | ⭐ MUL - Multiplication | `MUL_Series` | MUL ||
| ⭐ DIV - Division | `DIV_Series` | `DIV` || | ⭐ DIV - Division | `DIV_Series` | DIV ||
||||| |||||
| **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** | | **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** |
| ✔️ BIAS - Bias | BIAS_Series ||| | ✔️ BIAS - Bias | `BIAS_Series` |||
| ⛔ CORREL - Pearson's Correlation Coefficient || CORREL | GetCorrelation | | ⛔ CORREL - Pearson's Correlation Coefficient || CORREL | GetCorrelation |
| ⛔ COVAR - Covariance ||| GetCorrelation | | ⛔ COVAR - Covariance ||| GetCorrelation |
| ✔️ ENTP - Entropy | ENTP_Series ||| | ✔️ ENTP - Entropy | `ENTP_Series` |||
| ✔️ KURT - Kurtosis | KURT_Series ||| | ✔️ KURT - Kurtosis | `KURT_Series` |||
| ⭐ LINREG - Linear Regression | LINREG_Series || GetSlope | | ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope |
| ⭐ MAD - Mean Absolute Deviation | MAD_Series || GetSma | | ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma |
| ⭐ MAPE - Mean Absolute Percent Error | MAPE_Series || GetSma | | ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma |
| ✔️ MED - Median value | MED_Series ||| | ✔️ MED - Median value | `MED_Series` |||
| ✔️ MSE - Mean Squared Error | MSE_Series || GetSma | | ✔️ MSE - Mean Squared Error | `MSE_Series` || GetSma |
| ⛔ SKEW - Skewness |||| | ⛔ SKEW - Skewness ||||
| ⭐ SDEV - Standard Deviation (Volatility) | SDEV_Series ||| | ⭐ SDEV - Standard Deviation (Volatility) | `SDEV_Series` | STDDEV ||
| ✔️ SSDEV - Sample Standard Deviation | SSDEV_Series ||| | ✔️ SSDEV - Sample Standard Deviation | `SSDEV_Series` |||
| ✔️ SMAPE - Symmetric Mean Absolute Percent Error | SMAPE_Series ||| | ✔️ SMAPE - Symmetric Mean Absolute Percent Error | `SMAPE_Series` |||
| ✔️ VAR - Population Variance | VAR_Series ||| | ✔️ VAR - Population Variance | `VAR_Series` | VAR ||
| ✔️ SVAR - Sample Variance | SVAR_Series ||| | ✔️ SVAR - Sample Variance | `SVAR_Series` |||
| ⛔ QUANT - Quantile |||| | ⛔ QUANT - Quantile ||||
| ✔️ WMAPE - Weighted Mean Absolute Percent Error | WMAPE_Series ||| | ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` |||
| ⛔ ZSCORE - Number of standard deviations from mean |||| | ⛔ ZSCORE - Number of standard deviations from mean ||||
||||| |||||
| **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** | | **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** |
| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average |||| | ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average ||||
| ⭐ ALMA - Arnaud Legoux Moving Average | ALMA_Series || GetAlma | | ⭐ ALMA - Arnaud Legoux Moving Average | `ALMA_Series` || GetAlma |
| ⛔ ARIMA - Autoregressive Integrated Moving Average |||| | ⛔ ARIMA - Autoregressive Integrated Moving Average ||||
| ⭐ DEMA - Double EMA Average | DEMA_Series | DEMA | GetDema | | ⭐ DEMA - Double EMA Average | `DEMA_Series` | DEMA | GetDema |
| ⭐ EMA - Exponential Moving Average | EMA_Series || GetEma | | ⭐ EMA - Exponential Moving Average | `EMA_Series` || GetEma |
| ⛔ EPMA - Endpoint Moving Average ||| GetEpma | | ⛔ EPMA - Endpoint Moving Average ||| GetEpma |
| ⛔ FRAMA - Fractal Adaptive Moving Average ||||
| ⛔ FWMA - Fibonacci's Weighted Moving Average |||| | ⛔ FWMA - Fibonacci's Weighted Moving Average ||||
| ✔️ HEMA - Hull/EMA Average | HEMA_Series ||| | ⛔ HILO - Gann High-Low Activator ||||
| ✔️ HEMA - Hull/EMA Average | `HEMA_Series` |||
| ⛔ Hilbert Transform Instantaneous Trendline || HT_TRENDLINE | GetHtTrendline | | ⛔ Hilbert Transform Instantaneous Trendline || HT_TRENDLINE | GetHtTrendline |
| ⭐ HMA - Hull Moving Average | HMA_Series || GetHma | | ⭐ HMA - Hull Moving Average | `HMA_Series` || GetHma |
| ⛔ HWMA - Holt-Winter Moving Average |||| | ⛔ HWMA - Holt-Winter Moving Average ||||
| ✔️ JMA - Jurik Moving Average | JMA_Series ||| | ✔️ JMA - Jurik Moving Average | `JMA_Series` |||
| ⭐ KAMA - Kaufman's Adaptive Moving Average | KAMA_Series | KAMA | GetKama | | ⭐ KAMA - Kaufman's Adaptive Moving Average | `KAMA_Series` | KAMA | GetKama |
| ⛔ KDJ - KDJ Indicator (trend reversal) ||||
| ⛔ LSMA - Least Squares Moving Average |||| | ⛔ LSMA - Least Squares Moving Average ||||
| ⭐ MACD - Moving Average Convergence/Divergence | MACD_Series | MACD | GetMacd | | ⭐ MACD - Moving Average Convergence/Divergence | `MACD_Series` | MACD | GetMacd |
| ⛔ MAMA - MESA Adaptive Moving Average || MAMA | GetMama | | ⛔ MAMA - MESA Adaptive Moving Average || MAMA | GetMama |
| ⛔ MCGD - McGinley Dynamic ||||
| ⛔ MMA - Modified Moving Average |||| | ⛔ MMA - Modified Moving Average ||||
| ⛔ PPMA - Pivot Point Moving Average |||| | ⛔ PPMA - Pivot Point Moving Average ||||
| ⛔ PWMA - Pascal's Weighted Moving Average |||| | ⛔ PWMA - Pascal's Weighted Moving Average ||||
| ✔️ RMA - WildeR's Moving Average | RMA__Series ||| | ✔️ RMA - WildeR's Moving Average | `RMA_Series` |||
| ⛔ SINWMA - Sine Weighted Moving Average |||| | ⛔ SINWMA - Sine Weighted Moving Average ||||
| ⭐ SMA - Simple Moving Average | SMA_Series ||| | ⭐ SMA - Simple Moving Average | `SMA_Series` | SMA | GetSma |
| ⭐ SMMA - Smoothed Moving Average | SMMA_Series ||| | ⭐ SMMA - Smoothed Moving Average | `SMMA_Series` |||
| ⛔ SSF - Ehler's Super Smoother Filter |||| | ⛔ SSF - Ehler's Super Smoother Filter ||||
| ⛔ SUP - Supertrend |||| | ⛔ SUP - Supertrend ||||
| ⛔ SWMA - Symmetric Weighted Moving Average |||| | ⛔ SWMA - Symmetric Weighted Moving Average ||||
| ⛔ T3 - Tillson T3 Moving Average |||| | ⛔ T3 - Tillson T3 Moving Average || T3 | GetT3 |
| ⭐ TEMA - Triple EMA Average | TEMA_Series ||| | ⭐ TEMA - Triple EMA Average | `TEMA_Series` | TEMA | GetTema |
| TRIMA - Triangular Moving Average |||| | TRIMA - Triangular Moving Average | `TRIMA_Series` | TRIMA ||
| ⛔ TSF - Time Series Forecast || TSF ||
| ⛔ VIDYA - Variable Index Dynamic Average |||| | ⛔ VIDYA - Variable Index Dynamic Average ||||
| ⭐ WMA - Weighted Moving Average | WMA_Series ||| | ⛔ VOR - Vortex Indicator ||||
| ✔️ ZLEMA - Zero Lag EMA Average | ZLEMA_Series ||| | ⭐ WMA - Weighted Moving Average | `WMA_Series` | WMA | GetWma |
| ✔️ ZLEMA - Zero Lag EMA Average | `ZLEMA_Series` |||
||||| |||||
| **VOLATILITY INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | | **VOLATILITY INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** |
| ⭐ ADL - Chaikin Accumulation Distribution Line | ADL_Series | AD | GetAdl | | ⭐ ADL - Chaikin Accumulation Distribution Line | `ADL_Series` | AD | GetAdl |
| ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | ADOSC_Series | ADOSC| GetAdl | | ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | `ADOSC_Series` | ADOSC| GetAdl |
| ⭐ ATR - Average True Range | ATR_Series | ATR | GetAtr | | ⭐ ATR - Average True Range | `ATR_Series` | ATR | GetAtr |
| ⭐ ATRP - Average True Range Percent | ATRP_Series || GetAtr | | ⭐ ATRP - Average True Range Percent | `ATRP_Series` || GetAtr |
| ✔️ BETA - Beta coefficient || BETA | GetBeta | | BETA - Beta coefficient || BETA | GetBeta |
| ⭐ BBANDS - Bollinger Bands® | BBANDS_Series | BBANDS | GetBollingerBands | | ⭐ BBANDS - Bollinger Bands® | `BBANDS_Series` | BBANDS | GetBollingerBands |
| ⛔ CHAND - Chandelier Exit ||| GetChandelier |
| ⛔ CRSI - Connor RSI ||| GetConnorsRsi | | ⛔ CRSI - Connor RSI ||| GetConnorsRsi |
| ⛔ DON - Donchian Channels ||| GetDonchian | | ⛔ DON - Donchian Channels ||| GetDonchian |
| ⛔ FCB - Fractal Chaos Bands ||| GetFcb | | ⛔ FCB - Fractal Chaos Bands ||| GetFcb |
@@ -122,11 +129,12 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⛔ ICH - Ichimoku ||| GetIchimoku | | ⛔ ICH - Ichimoku ||| GetIchimoku |
| ⛔ KEL - Keltner Channels ||| GetKeltner | | ⛔ KEL - Keltner Channels ||| GetKeltner |
| ⛔ NATR - Normalized Average True Range || NATR | GetAtr | | ⛔ NATR - Normalized Average True Range || NATR | GetAtr |
| ⭐ RSI - Relative Strength Index | RSI_Series || | ⛔ CHN - Price Channel Indicator ||||
| ⭐ RSI - Relative Strength Index | `RSI_Series` | RSI | GetRsi |
| ⛔ SAR - Parabolic Stop and Reverse || SAR | GetParabolicSar | | ⛔ SAR - Parabolic Stop and Reverse || SAR | GetParabolicSar |
| ⛔ SRSI - Stochastic RSI |||| | ⛔ SRSI - Stochastic RSI || STOCHRSI | GetStochRsi |
| ⛔ STARC - Starc Bands |||| | ⛔ STARC - Starc Bands ||||
| ⭐ TR - True Range | TR_Series ||| | ⭐ TR - True Range | `TR_Series` | TRANGE | GetTr |
| ⛔ UI - Ulcer Index |||| | ⛔ UI - Ulcer Index ||||
| ⛔ VSTOP - Volatility Stop |||| | ⛔ VSTOP - Volatility Stop ||||
||||| |||||
@@ -138,11 +146,11 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⛔ APO - Absolute Price Oscillator || APO || | ⛔ APO - Absolute Price Oscillator || APO ||
| ⛔ AROON - Aroon oscillator || AROON | GetAroon | | ⛔ AROON - Aroon oscillator || AROON | GetAroon |
| ⛔ BOP - Balance of Power || BOP | GetBop | | ⛔ BOP - Balance of Power || BOP | GetBop |
| ⭐ CCI - Commodity Channel Index | CCI_Series | CCI | GetCci | | ⭐ CCI - Commodity Channel Index | `CCI_Series` | CCI | GetCci |
| ⛔ CFO - Chande Forcast Oscillator |||| | ⛔ CFO - Chande Forcast Oscillator ||||
| ⛔ CMF - Chaikin Money Flow ||||
| ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo | | ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo |
| ⛔ COG - Center of Gravity |||| | ⛔ COG - Center of Gravity ||||
| ⛔ COPPOCK - Coppock Curve ||||
| ⛔ CTI - Ehler's Correlation Trend Indicator |||| | ⛔ CTI - Ehler's Correlation Trend Indicator ||||
| ⛔ DPO - Detrended Price Oscillator ||| GetDpo | | ⛔ DPO - Detrended Price Oscillator ||| GetDpo |
| ⛔ DMI - Directional Movement Index || DX | GetAdx | | ⛔ DMI - Directional Movement Index || DX | GetAdx |
@@ -152,23 +160,28 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⛔ KRI - Kairi Relative Index |||| | ⛔ KRI - Kairi Relative Index ||||
| ⛔ KVO - Klinger Volume Oscillator |||| | ⛔ KVO - Klinger Volume Oscillator ||||
| ⛔ MFI - Money Flow Index || MFI | GetMfi | | ⛔ MFI - Money Flow Index || MFI | GetMfi |
| ⛔ ROC - Rate of Change (Momentum) || MOM | GetRoc | | ⛔ MOM - Momentum || MOM ||
| ⛔ NVI - Negative Volume Index |||| | ⛔ NVI - Negative Volume Index ||||
| ⛔ PO - Price Oscillator |||| | ⛔ PO - Price Oscillator ||||
| ⛔ PPO - Percentage Price Oscillator || PPO || | ⛔ PPO - Percentage Price Oscillator || PPO ||
| ⛔ PMO - Price Momentum Oscillator |||| | ⛔ PMO - Price Momentum Oscillator ||||
| ⛔ PVI - Positive Volume Index |||| | ⛔ PVI - Positive Volume Index ||||
| ⛔ ROC - Rate of Change || MOM | GetRoc |
| ⛔ RVGI - Relative Vigor Index |||| | ⛔ RVGI - Relative Vigor Index ||||
| ⛔ SMI - Stochastic Momentum Index |||| | ⛔ SMI - Stochastic Momentum Index ||||
| ⛔ STOCH - Stochastic Oscillator |||| | ⛔ STC - Schaff Trend Cycle ||||
| ⛔ TRIX - 1-day ROC of TEMA |||| | ⛔ STOCH - Stochastic Oscillator || STOCH | GetStoch |
| ⛔ TRIX - 1-day ROC of TEMA || TRIX | GetTrix |
| ⛔ TSI - True Strength Index |||| | ⛔ TSI - True Strength Index ||||
| ⛔ UO - Ultimate Oscillator |||| | ⛔ UO - Ultimate Oscillator || ULTOSC | GetUltimate |
| ⛔ WILLR - Larry Williams' %R || WILLR | GetWilliamsR |
| ⛔ WGAT - Williams Alligator |||| | ⛔ WGAT - Williams Alligator ||||
||||| |||||
| **VOLUME INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | | **VOLUME INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** |
| ⛔ AOBV - Archer On-Balance Volume |||| | ⛔ AOBV - Archer On-Balance Volume ||||
| ⛔ OBV - On-Balance Volume || OBV | GetObv | | ⛔ CMF - Chaikin Money Flow ||||
| ⛔ EOM - Ease of Movement ||||
| ⭐ OBV - On-Balance Volume | `OBV_Series` | OBV | GetObv |
| ⛔ PRS - Price Relative Strength ||| | ⛔ PRS - Price Relative Strength |||
| ⛔ PVOL - Price-Volume |||| | ⛔ PVOL - Price-Volume ||||
| ⛔ PVO - Percentage Volume Oscillator |||| | ⛔ PVO - Percentage Volume Oscillator ||||
@@ -177,17 +190,3 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⛔ VP - Volume Profile |||| | ⛔ VP - Volume Profile ||||
| ⛔ VWAP - Volume Weighted Average Price |||| | ⛔ VWAP - Volume Weighted Average Price ||||
| ⛔ VWMA - Volume Weighted Moving Average |||| | ⛔ VWMA - Volume Weighted Moving Average ||||
|||||
|**Unsorted** | **QuanTAlib** | **TA-LIB** | **Skender** |
| ⛔ CHN - Price Channel ||||
| ⛔ COPPOCK - Coppock Curve ||||
| ⛔ EOM - Ease of Movement ||||
| ⛔ HILO - Gann High-Low Activator ||||
| ⛔ HT - HT Trendline ||||
| ⛔ MCGD - McGinley Dynamic ||||
| ⛔ STC - Schaff Trend Cycle ||||
| ⛔ WILLR - Larry Williams' %R ||||
| ⛔ VOR - Vortex Indicator ||||
| ⛔ PVT - Pivot Points ||||
| ⛔ KDJ - KDJ Index ||||
| ⛔ CHAND - Chandelier Exit ||||