mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 13:58:04 +00:00
refactoring
This commit is contained in:
@@ -354,3 +354,4 @@ MigrationBackup/
|
|||||||
# Ionide (cross platform F# VS Code tools) working folder
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
.ionide/
|
.ionide/
|
||||||
dotCover.Output.dcvr
|
dotCover.Output.dcvr
|
||||||
|
/Tests/GlobalSuppressions.cs
|
||||||
|
|||||||
@@ -34,9 +34,11 @@
|
|||||||
<Link>QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
<Link>QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<!--
|
||||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
|
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
|
||||||
<Copy SourceFiles=".\bin\$(Configuration)\net48\Quantower_QTAlib.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
|
<Copy SourceFiles=".\bin\$(Configuration)\net48\Quantower_QTAlib.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
|
||||||
</Target>
|
</Target>
|
||||||
|
-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
|
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
/* <summary>
|
/* <summary>
|
||||||
Abstract classes with all scaffolding required to build indicators.
|
Abstract classes with all scaffolding required to build indicators.
|
||||||
@@ -17,50 +18,54 @@ Abstract classes with all scaffolding required to build indicators.
|
|||||||
</summary> */
|
</summary> */
|
||||||
public abstract class Single_TSeries_Indicator : TSeries
|
public abstract class Single_TSeries_Indicator : TSeries
|
||||||
{
|
{
|
||||||
protected readonly int _period;
|
protected readonly int _period;
|
||||||
protected readonly bool _NaN;
|
protected readonly bool _NaN;
|
||||||
protected readonly TSeries _data;
|
protected readonly TSeries _data;
|
||||||
protected int _p;
|
protected int _p;
|
||||||
|
|
||||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
||||||
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN)
|
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN)
|
||||||
|
{
|
||||||
|
this._data = source;
|
||||||
|
this._period = period;
|
||||||
|
this._p = _period;
|
||||||
|
this._NaN = useNaN;
|
||||||
|
this._data.Pub += this.Sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
// overridable Add() method to add/update a single item at the end of the list
|
||||||
|
|
||||||
|
public virtual void Add((System.DateTime t, double v) TValue, bool update, bool useNaN)
|
||||||
|
{
|
||||||
|
if (_period == 0) { _p = this.Length; }
|
||||||
|
var res = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : TValue.v);
|
||||||
|
base.Add(res, 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)
|
||||||
|
public virtual void Add(TSeries data) { 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) => 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() => 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);
|
||||||
|
|
||||||
|
protected static void Add_Replace(List<double> l, double v, bool update)
|
||||||
|
{
|
||||||
|
if (update)
|
||||||
|
{ l[l.Count - 1] = v; }
|
||||||
|
else
|
||||||
|
{ l.Add(v); }
|
||||||
|
}
|
||||||
|
protected static double Add_Replace_Trim(List<double> l, double v, int p, bool update)
|
||||||
|
{
|
||||||
|
Add_Replace(l, v, update);
|
||||||
|
double ret = (l.Count > 0) ? l.First() : 0;
|
||||||
|
if (l.Count > p && p != 0)
|
||||||
{
|
{
|
||||||
this._data = source;
|
l.RemoveAt(0);
|
||||||
this._period = period;
|
|
||||||
this._p = _period;
|
|
||||||
this._NaN = useNaN;
|
|
||||||
this._data.Pub += this.Sub;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overridable Add() method to add/update a single item at the end of the list
|
|
||||||
|
|
||||||
public virtual void Add((System.DateTime t, double v) TValue, bool update, bool useNaN)
|
|
||||||
{
|
|
||||||
if (_period == 0) { _p = this.Length; }
|
|
||||||
var res = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : TValue.v);
|
|
||||||
base.Add(res, 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)
|
|
||||||
public virtual void Add(TSeries data) { 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) => 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() => 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);
|
|
||||||
|
|
||||||
protected static void Add_Replace(List<double> l, double v, bool update)
|
|
||||||
{
|
|
||||||
if (update)
|
|
||||||
{ l[l.Count - 1] = v; }
|
|
||||||
else
|
|
||||||
{ l.Add(v); }
|
|
||||||
}
|
|
||||||
protected static void Add_Replace_Trim(List<double> l, double v, int p, bool update)
|
|
||||||
{
|
|
||||||
Add_Replace(l, v, update);
|
|
||||||
if (l.Count > p && p!=0)
|
|
||||||
{ l.RemoveAt(0); }
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ public class EMA_Series : Single_TSeries_Indicator
|
|||||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||||
private readonly double _k, _k1m;
|
private readonly double _k, _k1m;
|
||||||
private double _lastema, _lastlastema;
|
private double _lastema, _lastlastema;
|
||||||
|
private bool _useSMA;
|
||||||
|
|
||||||
public EMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
public EMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
|
||||||
{
|
{
|
||||||
this._k = 2.0 / (this._p + 1);
|
this._k = 2.0 / (this._p + 1);
|
||||||
this._k1m = 1.0 - this._k;
|
this._k1m = 1.0 - this._k;
|
||||||
this._lastema = this._lastlastema = double.NaN;
|
this._lastema = this._lastlastema = 0;
|
||||||
|
_useSMA = useSMA;
|
||||||
if (this._data.Count > 0) { base.Add(this._data); }
|
if (this._data.Count > 0) { base.Add(this._data); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +40,9 @@ public class EMA_Series : Single_TSeries_Indicator
|
|||||||
{
|
{
|
||||||
double _ema;
|
double _ema;
|
||||||
if (update) { this._lastema = this._lastlastema; }
|
if (update) { this._lastema = this._lastlastema; }
|
||||||
|
if (this.Count == 0) { _lastema = TValue.v; }
|
||||||
|
|
||||||
if (this.Count < this._p)
|
if (this.Count < this._p && _useSMA)
|
||||||
{
|
{
|
||||||
Add_Replace(_buffer, TValue.v, update);
|
Add_Replace(_buffer, TValue.v, update);
|
||||||
_ema = 0;
|
_ema = 0;
|
||||||
|
|||||||
+40
-15
@@ -1,6 +1,5 @@
|
|||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
/* <summary>
|
/* <summary>
|
||||||
SMA: Simple Moving Average
|
SMA: Simple Moving Average
|
||||||
@@ -19,19 +18,45 @@ Remark:
|
|||||||
|
|
||||||
public class SMA_Series : Single_TSeries_Indicator
|
public class SMA_Series : Single_TSeries_Indicator
|
||||||
{
|
{
|
||||||
public SMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||||
{
|
private double _sma, _oldsma;
|
||||||
if (base._data.Count > 0) { base.Add(base._data); }
|
private double _topv, _oldtopv;
|
||||||
}
|
public SMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
{
|
||||||
|
if (base._data.Count > 0)
|
||||||
|
{ base.Add(base._data); }
|
||||||
|
}
|
||||||
|
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||||
|
{
|
||||||
|
_topv = Add_Replace_Trim(_buffer, TValue.v, _p, update);
|
||||||
|
|
||||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
// rolling back if update, storing data for potential future update
|
||||||
{
|
if (update)
|
||||||
Add_Replace_Trim(_buffer, TValue.v, _p, update);
|
{
|
||||||
double _sma = 0;
|
_sma = _oldsma;
|
||||||
for (int i=0; i<_buffer.Count; i++) { _sma+= _buffer[i]; }
|
_topv = _oldtopv;
|
||||||
_sma /= _buffer.Count;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_oldsma = _sma;
|
||||||
|
_oldtopv = _topv;
|
||||||
|
}
|
||||||
|
|
||||||
base.Add((TValue.t, _sma), update, _NaN);
|
// main additive calculation of SMA - for data points that are larger than _p period
|
||||||
}
|
// this.Count > _p
|
||||||
}
|
if (this.Count > _p)
|
||||||
|
{
|
||||||
|
_sma += (TValue.v - _topv) / _p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// calculate SMA the traditional way (sum all, divide with _p) for data points within _p period
|
||||||
|
_sma = 0;
|
||||||
|
for (int i = 0; i < _buffer.Count; i++)
|
||||||
|
{ _sma += _buffer[i]; }
|
||||||
|
_sma /= _buffer.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Add((TValue.t, _sma), update, _NaN);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,10 +20,10 @@ public class ADOSC_Series : Single_TBars_Indicator
|
|||||||
private double _lastema1, _lastlastema1, _lastema2, _lastlastema2;
|
private double _lastema1, _lastlastema1, _lastema2, _lastlastema2;
|
||||||
private double _lastadl, _lastlastadl;
|
private double _lastadl, _lastlastadl;
|
||||||
|
|
||||||
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
|
public ADOSC_Series(TBars source, int shortPeriod = 3, int longPeriod =10, bool useNaN = false) : base(source, period: 0, useNaN)
|
||||||
{
|
{
|
||||||
_k1 = 2.0 / (3 + 1);
|
_k1 = 2.0 / (shortPeriod + 1);
|
||||||
_k2 = 2.0 / (10 + 1);
|
_k2 = 2.0 / (longPeriod + 1);
|
||||||
_lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
|
_lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
|
||||||
if (_bars.Count > 0) { base.Add(_bars); }
|
if (_bars.Count > 0) { base.Add(_bars); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
<PackageReference Include="TALib.NETCore" Version="0.4.4" />
|
<PackageReference Include="TALib.NETCore" Version="0.4.4" />
|
||||||
<PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" />
|
<PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" />
|
||||||
<PackageReference Include="pythonnet" Version="3.0.1" />
|
<PackageReference Include="pythonnet" Version="3.0.1" />
|
||||||
|
<PackageReference Include="Tulip.NETCore" Version="0.8.0.1" />
|
||||||
|
<PackageReference Include="System.Text.Json" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -28,5 +30,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Python.Included" />
|
<None Remove="Python.Included" />
|
||||||
<None Remove="pythonnet" />
|
<None Remove="pythonnet" />
|
||||||
|
<None Remove="Tulip.NETCore" />
|
||||||
|
<None Remove="System.Text.Json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using QuanTAlib;
|
||||||
|
using Skender.Stock.Indicators;
|
||||||
|
using Tulip;
|
||||||
|
using Python.Runtime;
|
||||||
|
using Python.Included;
|
||||||
|
using TALib;
|
||||||
|
using Validations;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace One.by.one;
|
||||||
|
public class Dema : IDisposable
|
||||||
|
{
|
||||||
|
private readonly GBM_Feed bars;
|
||||||
|
private readonly Random rnd = new();
|
||||||
|
private readonly int period, skip;
|
||||||
|
private readonly double precision;
|
||||||
|
|
||||||
|
private readonly IEnumerable<Quote> quotes;
|
||||||
|
private readonly double[] outdata;
|
||||||
|
private readonly double[] inopen;
|
||||||
|
private readonly double[] inhigh;
|
||||||
|
private readonly double[] inlow;
|
||||||
|
private readonly double[] inclose;
|
||||||
|
private readonly double[] involume;
|
||||||
|
|
||||||
|
private readonly string OStype;
|
||||||
|
private readonly dynamic np;
|
||||||
|
private readonly dynamic ta;
|
||||||
|
private readonly dynamic df;
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
PythonEngine.Shutdown();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
public Dema()
|
||||||
|
{
|
||||||
|
bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0);
|
||||||
|
period = rnd.Next(30) + 5;
|
||||||
|
skip = period*8;
|
||||||
|
precision = 1e-6;
|
||||||
|
|
||||||
|
quotes = bars.Select(q => new Quote
|
||||||
|
{
|
||||||
|
Date = q.t,
|
||||||
|
Open = (decimal)q.o,
|
||||||
|
High = (decimal)q.h,
|
||||||
|
Low = (decimal)q.l,
|
||||||
|
Close = (decimal)q.c,
|
||||||
|
Volume = (decimal)q.v
|
||||||
|
});
|
||||||
|
|
||||||
|
outdata = new double[bars.Count];
|
||||||
|
inopen = bars.Open.v.ToArray();
|
||||||
|
inhigh = bars.High.v.ToArray();
|
||||||
|
inlow = bars.Low.v.ToArray();
|
||||||
|
inclose = bars.Close.v.ToArray();
|
||||||
|
involume = bars.Volume.v.ToArray();
|
||||||
|
|
||||||
|
// Checking the host OS and setting PythonDLL accordingly
|
||||||
|
OStype = Environment.OSVersion.ToString();
|
||||||
|
if (OStype == "Unix 13.1.0")
|
||||||
|
OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
|
||||||
|
else
|
||||||
|
OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
||||||
|
|
||||||
|
Installer.InstallPath = Path.GetFullPath(path: ".");
|
||||||
|
Installer.SetupPython().Wait();
|
||||||
|
Installer.TryInstallPip();
|
||||||
|
Installer.PipInstallModule(module_name: "pandas-ta");
|
||||||
|
Runtime.PythonDLL = OStype;
|
||||||
|
PythonEngine.Initialize();
|
||||||
|
np = Py.Import(name: "numpy");
|
||||||
|
ta = Py.Import(name: "pandas_ta");
|
||||||
|
|
||||||
|
string[] cols = { "open", "high", "low", "close", "volume" };
|
||||||
|
double[,] ary = new double[bars.Count, 5];
|
||||||
|
for (int i = 0; i < bars.Count; i++) {
|
||||||
|
ary[i, 0] = bars.Open[i].v;
|
||||||
|
ary[i, 1] = bars.High[i].v;
|
||||||
|
ary[i, 2] = bars.Low[i].v;
|
||||||
|
ary[i, 3] = bars.Close[i].v;
|
||||||
|
ary[i, 4] = bars.Volume[i].v;
|
||||||
|
}
|
||||||
|
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void WeirdData() {
|
||||||
|
DEMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((new DateTime(), double.Epsilon), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Updating() {
|
||||||
|
DEMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
int lastLen = QL.Count;
|
||||||
|
QL.Add((DateTime.Today, 0), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastLen, QL.Count); // same size
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Skender_Test()
|
||||||
|
{
|
||||||
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!);
|
||||||
|
for (int i = QL.Length; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double SK_item = SK.ElementAt(i - 1);
|
||||||
|
Assert.InRange(SK_item! - QL_item, -precision, precision);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void TALIB_Test()
|
||||||
|
{
|
||||||
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Core.Dema(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TA_item = outdata[i - outBegIdx];
|
||||||
|
Assert.InRange(TA_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Tulip_Test() {
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
DEMA_Series QL = new(bars.Close, period: period, useNaN: false);
|
||||||
|
Tulip.Indicators.dema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip*3; i--) {
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TU_item = arrout[0][i];
|
||||||
|
Assert.InRange(TU_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
void PandasTA_Test() {
|
||||||
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var pta = df.ta.dema(close: df.close, length: period);
|
||||||
|
for (int i = QL.Length; i > skip; i--) {
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double PanTA_item = (double)pta[i - 1];
|
||||||
|
Assert.InRange(PanTA_item! - QL_item, -1e-5, 1e-5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using QuanTAlib;
|
||||||
|
using Skender.Stock.Indicators;
|
||||||
|
using Tulip;
|
||||||
|
using Python.Runtime;
|
||||||
|
using Python.Included;
|
||||||
|
using TALib;
|
||||||
|
using Validations;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace One.by.one;
|
||||||
|
public class Ema : IDisposable
|
||||||
|
{
|
||||||
|
private readonly GBM_Feed bars;
|
||||||
|
private readonly Random rnd = new();
|
||||||
|
private readonly int period, skip;
|
||||||
|
private readonly double precision;
|
||||||
|
|
||||||
|
private readonly IEnumerable<Quote> quotes;
|
||||||
|
private readonly double[] outdata;
|
||||||
|
private readonly double[] inopen;
|
||||||
|
private readonly double[] inhigh;
|
||||||
|
private readonly double[] inlow;
|
||||||
|
private readonly double[] inclose;
|
||||||
|
private readonly double[] involume;
|
||||||
|
|
||||||
|
private readonly string OStype;
|
||||||
|
private readonly dynamic np;
|
||||||
|
private readonly dynamic ta;
|
||||||
|
private readonly dynamic df;
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
PythonEngine.Shutdown();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
public Ema()
|
||||||
|
{
|
||||||
|
bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0);
|
||||||
|
period = rnd.Next(30) + 5;
|
||||||
|
skip = period-1;
|
||||||
|
precision = 1e-8;
|
||||||
|
|
||||||
|
quotes = bars.Select(q => new Quote
|
||||||
|
{
|
||||||
|
Date = q.t,
|
||||||
|
Open = (decimal)q.o,
|
||||||
|
High = (decimal)q.h,
|
||||||
|
Low = (decimal)q.l,
|
||||||
|
Close = (decimal)q.c,
|
||||||
|
Volume = (decimal)q.v
|
||||||
|
});
|
||||||
|
|
||||||
|
outdata = new double[bars.Count];
|
||||||
|
inopen = bars.Open.v.ToArray();
|
||||||
|
inhigh = bars.High.v.ToArray();
|
||||||
|
inlow = bars.Low.v.ToArray();
|
||||||
|
inclose = bars.Close.v.ToArray();
|
||||||
|
involume = bars.Volume.v.ToArray();
|
||||||
|
|
||||||
|
// Checking the host OS and setting PythonDLL accordingly
|
||||||
|
OStype = Environment.OSVersion.ToString();
|
||||||
|
if (OStype == "Unix 13.1.0")
|
||||||
|
OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
|
||||||
|
else
|
||||||
|
OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
||||||
|
|
||||||
|
Installer.InstallPath = Path.GetFullPath(path: ".");
|
||||||
|
Installer.SetupPython().Wait();
|
||||||
|
Installer.TryInstallPip();
|
||||||
|
Installer.PipInstallModule(module_name: "pandas-ta");
|
||||||
|
Runtime.PythonDLL = OStype;
|
||||||
|
PythonEngine.Initialize();
|
||||||
|
np = Py.Import(name: "numpy");
|
||||||
|
ta = Py.Import(name: "pandas_ta");
|
||||||
|
|
||||||
|
string[] cols = { "open", "high", "low", "close", "volume" };
|
||||||
|
double[,] ary = new double[bars.Count, 5];
|
||||||
|
for (int i = 0; i < bars.Count; i++) {
|
||||||
|
ary[i, 0] = bars.Open[i].v;
|
||||||
|
ary[i, 1] = bars.High[i].v;
|
||||||
|
ary[i, 2] = bars.Low[i].v;
|
||||||
|
ary[i, 3] = bars.Close[i].v;
|
||||||
|
ary[i, 4] = bars.Volume[i].v;
|
||||||
|
}
|
||||||
|
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void WeirdData() {
|
||||||
|
EMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((new DateTime(), double.Epsilon), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Updating() {
|
||||||
|
EMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
int lastLen = QL.Count;
|
||||||
|
QL.Add((DateTime.Today, 0), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastLen, QL.Count); // same size
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Skender_Test()
|
||||||
|
{
|
||||||
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var SK = quotes.GetEma(period).Select(i => i.Ema.Null2NaN()!);
|
||||||
|
for (int i = QL.Length; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double SK_item = SK.ElementAt(i - 1);
|
||||||
|
Assert.InRange(SK_item! - QL_item, -precision, precision);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void TALIB_Test()
|
||||||
|
{
|
||||||
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Core.Ema(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TA_item = outdata[i - outBegIdx];
|
||||||
|
Assert.InRange(TA_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Tulip_Test() {
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
EMA_Series QL = new(bars.Close, period: period, useNaN: false, useSMA: false);
|
||||||
|
Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--) {
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TU_item = arrout[0][i];
|
||||||
|
Assert.InRange(TU_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
void PandasTA_Test() {
|
||||||
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var pta = df.ta.ema(close: df.close, length: period);
|
||||||
|
for (int i = QL.Length; i > skip; i--) {
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double PanTA_item = (double)pta[i - 1];
|
||||||
|
Assert.InRange(PanTA_item! - QL_item, -1e-5, 1e-5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
using System;
|
||||||
|
using QuanTAlib;
|
||||||
|
using Skender.Stock.Indicators;
|
||||||
|
using Tulip;
|
||||||
|
using Python.Runtime;
|
||||||
|
using Python.Included;
|
||||||
|
using TALib;
|
||||||
|
using Validations;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace One.by.one;
|
||||||
|
public class SMA : IDisposable {
|
||||||
|
private readonly GBM_Feed bars;
|
||||||
|
private readonly Random rnd = new();
|
||||||
|
private readonly int period, skip;
|
||||||
|
private readonly double precision;
|
||||||
|
|
||||||
|
private readonly IEnumerable<Quote> quotes;
|
||||||
|
private readonly double[] outdata;
|
||||||
|
private readonly double[] inopen;
|
||||||
|
private readonly double[] inhigh;
|
||||||
|
private readonly double[] inlow;
|
||||||
|
private readonly double[] inclose;
|
||||||
|
private readonly double[] involume;
|
||||||
|
|
||||||
|
private readonly string OStype;
|
||||||
|
private readonly dynamic np;
|
||||||
|
private readonly dynamic ta;
|
||||||
|
private readonly dynamic df;
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
PythonEngine.Shutdown();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
public SMA() {
|
||||||
|
bars = new(Bars: 1000, Volatility: 0.5, Drift: 0.0);
|
||||||
|
period = rnd.Next(30) + 5;
|
||||||
|
precision = 1e-8;
|
||||||
|
skip = period-1;
|
||||||
|
|
||||||
|
quotes = bars.Select(q => new Quote {
|
||||||
|
Date = q.t,
|
||||||
|
Open = (decimal)q.o,
|
||||||
|
High = (decimal)q.h,
|
||||||
|
Low = (decimal)q.l,
|
||||||
|
Close = (decimal)q.c,
|
||||||
|
Volume = (decimal)q.v
|
||||||
|
});
|
||||||
|
|
||||||
|
outdata = new double[bars.Count];
|
||||||
|
inopen = bars.Open.v.ToArray();
|
||||||
|
inhigh = bars.High.v.ToArray();
|
||||||
|
inlow = bars.Low.v.ToArray();
|
||||||
|
inclose = bars.Close.v.ToArray();
|
||||||
|
involume = bars.Volume.v.ToArray();
|
||||||
|
|
||||||
|
// Checking the host OS and setting PythonDLL accordingly
|
||||||
|
OStype = Environment.OSVersion.ToString();
|
||||||
|
if (OStype == "Unix 13.1.0")
|
||||||
|
OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
|
||||||
|
else
|
||||||
|
OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
||||||
|
|
||||||
|
Installer.InstallPath = Path.GetFullPath(path: ".");
|
||||||
|
Installer.SetupPython().Wait();
|
||||||
|
Installer.TryInstallPip();
|
||||||
|
Installer.PipInstallModule(module_name: "pandas-ta");
|
||||||
|
Runtime.PythonDLL = OStype;
|
||||||
|
PythonEngine.Initialize();
|
||||||
|
np = Py.Import(name: "numpy");
|
||||||
|
ta = Py.Import(name: "pandas_ta");
|
||||||
|
|
||||||
|
string[] cols = { "open", "high", "low", "close", "volume" };
|
||||||
|
double[,] ary = new double[bars.Count, 5];
|
||||||
|
for (int i = 0; i < bars.Count; i++) {
|
||||||
|
ary[i, 0] = bars.Open[i].v;
|
||||||
|
ary[i, 1] = bars.High[i].v;
|
||||||
|
ary[i, 2] = bars.Low[i].v;
|
||||||
|
ary[i, 3] = bars.Close[i].v;
|
||||||
|
ary[i, 4] = bars.Volume[i].v;
|
||||||
|
}
|
||||||
|
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void WeirdData() {
|
||||||
|
SMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
QL.Add((DateTime.Today.AddDays(1), double.NaN), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((DateTime.Today.AddDays(-1), double.NegativeInfinity), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
|
||||||
|
QL.Add((new DateTime(), double.Epsilon), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // back to the same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Updating() {
|
||||||
|
SMA_Series QL = new(source: bars.Close, period);
|
||||||
|
var lastData = bars.Close.Last();
|
||||||
|
var lastCalc = QL.Last();
|
||||||
|
int lastLen = QL.Count;
|
||||||
|
QL.Add((DateTime.Today, 0), update: true);
|
||||||
|
Assert.NotEqual(lastCalc, QL.Last()); //value changed
|
||||||
|
QL.Add(lastData, update: true);
|
||||||
|
Assert.Equal(lastLen, QL.Count); // same size
|
||||||
|
Assert.Equal(lastCalc, QL.Last()); // same data
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Skender_Test() {
|
||||||
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!);
|
||||||
|
for (int i = QL.Length; i > skip; i--) {
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double SK_item = SK.ElementAt(i - 1);
|
||||||
|
Assert.InRange(SK_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void TALIB_Test() {
|
||||||
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Core.Sma(inclose, 0, bars.Count - 1, outdata, out int outBegIdx, out _, period);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--) {
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TA_item = outdata[i - outBegIdx];
|
||||||
|
Assert.InRange(TA_item! - QL_item, -precision, precision);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Tulip_Test() {
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--) {
|
||||||
|
double QL_item = QL[i].v;
|
||||||
|
double TU_item = arrout[0][i - period + 1];
|
||||||
|
Assert.InRange(TU_item! - QL_item, -precision, precision);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
void PandasTA_Test() {
|
||||||
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
|
var pta = df.ta.sma(close: df.close, length: period);
|
||||||
|
for (int i = QL.Length; i > skip; i--) {
|
||||||
|
double QL_item = QL[i - 1].v;
|
||||||
|
double PanTA_item = (double)pta[i - 1];
|
||||||
|
Assert.InRange(PanTA_item! - QL_item, -precision, precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,354 +1,360 @@
|
|||||||
using Xunit;
|
using Xunit;
|
||||||
using System;
|
using System;
|
||||||
using QuanTAlib;
|
using QuanTAlib;
|
||||||
using Python.Runtime;
|
using Python.Runtime;
|
||||||
using Python.Included;
|
using Python.Included;
|
||||||
|
|
||||||
namespace Validations;
|
namespace Validations;
|
||||||
public class PandasTA : IDisposable
|
public class PandasTA : IDisposable
|
||||||
{
|
{
|
||||||
private readonly GBM_Feed bars;
|
private readonly GBM_Feed bars;
|
||||||
private readonly Random rnd = new();
|
private readonly Random rnd = new();
|
||||||
private readonly int period;
|
private readonly int period, sample;
|
||||||
private int digits;
|
private int digits;
|
||||||
private readonly string OStype;
|
private readonly string OStype;
|
||||||
private readonly dynamic np;
|
private readonly dynamic np;
|
||||||
private readonly dynamic ta;
|
private readonly dynamic ta;
|
||||||
private readonly dynamic df;
|
private readonly dynamic df;
|
||||||
|
|
||||||
public PandasTA() {
|
public PandasTA() {
|
||||||
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0);
|
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0);
|
||||||
period = rnd.Next(maxValue: 28) + 3;
|
period = rnd.Next(maxValue: 28) + 3;
|
||||||
digits = 4; //minimizing rounding errors in type conversions
|
sample = 200;
|
||||||
|
digits = 3; //minimizing rounding errors in type conversions
|
||||||
// Checking the host OS and setting PythonDLL accordingly
|
|
||||||
OStype = Path.GetFullPath(path: ".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
// Checking the host OS and setting PythonDLL accordingly
|
||||||
|
OStype = Environment.OSVersion.ToString();
|
||||||
Installer.InstallPath = Path.GetFullPath(path: ".");
|
if (OStype == "Unix 13.1.0")
|
||||||
Installer.SetupPython().Wait();
|
OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
|
||||||
Installer.TryInstallPip();
|
else OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
||||||
Installer.PipInstallModule(module_name: "pandas-ta");
|
|
||||||
Runtime.PythonDLL = OStype;
|
Installer.InstallPath = Path.GetFullPath(path: ".");
|
||||||
PythonEngine.Initialize();
|
Installer.SetupPython().Wait();
|
||||||
np = Py.Import(name: "numpy");
|
Installer.TryInstallPip();
|
||||||
ta = Py.Import(name: "pandas_ta");
|
Installer.PipInstallModule(module_name: "pandas-ta");
|
||||||
|
Runtime.PythonDLL = OStype;
|
||||||
string[] cols = { "open", "high", "low", "close", "volume" };
|
PythonEngine.Initialize();
|
||||||
double[,] ary = new double[bars.Count, 5];
|
np = Py.Import(name: "numpy");
|
||||||
for (int i = 0; i < bars.Count; i++) {
|
ta = Py.Import(name: "pandas_ta");
|
||||||
ary[i, 0] = bars.Open[i].v;
|
|
||||||
ary[i, 1] = bars.High[i].v;
|
string[] cols = { "open", "high", "low", "close", "volume" };
|
||||||
ary[i, 2] = bars.Low[i].v;
|
double[,] ary = new double[bars.Count, 5];
|
||||||
ary[i, 3] = bars.Close[i].v;
|
for (int i = 0; i < bars.Count; i++) {
|
||||||
ary[i, 4] = bars.Volume[i].v;
|
ary[i, 0] = bars.Open[i].v;
|
||||||
}
|
ary[i, 1] = bars.High[i].v;
|
||||||
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
ary[i, 2] = bars.Low[i].v;
|
||||||
}
|
ary[i, 3] = bars.Close[i].v;
|
||||||
public void Dispose()
|
ary[i, 4] = bars.Volume[i].v;
|
||||||
{
|
}
|
||||||
PythonEngine.Shutdown();
|
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
||||||
GC.SuppressFinalize(this);
|
}
|
||||||
}
|
public void Dispose()
|
||||||
|
{
|
||||||
[Fact] void ADL() {
|
PythonEngine.Shutdown();
|
||||||
ADL_Series QL = new(bars);
|
GC.SuppressFinalize(this);
|
||||||
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
|
||||||
{
|
[Fact] void ADL() {
|
||||||
double QL_item = Math.Round(QL[i-1].v, digits: digits);
|
ADL_Series QL = new(bars);
|
||||||
double PanTA_item = Math.Round((double)pta[i-1], digits: digits);
|
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i-1].v, digits: digits);
|
||||||
[Fact] void ADOSC() {
|
double PanTA_item = Math.Round((double)pta[i-1], digits: digits);
|
||||||
ADOSC_Series QL = new(bars);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void ADOSC() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
ADOSC_Series QL = new(bars);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void ATR() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
ATR_Series QL = new(bars, period);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void ATR() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
ATR_Series QL = new(bars, period);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void BIAS() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
BIAS_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.bias(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void BIAS() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
BIAS_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.bias(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void DEMA() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
DEMA_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.dema(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void DEMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.dema(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void EMA() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
EMA_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.ema(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void EMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.ema(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void ENTROPY() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.entropy(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period+1; i--)
|
}
|
||||||
{
|
[Fact] void ENTROPY() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.entropy(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void HL2() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
var pta = df.ta.hl2(high: df.high, low: df.low);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
for (int i = bars.HL2.Length; i > 0; i--)
|
}
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(bars.HL2[i - 1].v, digits: digits);
|
[Fact] void HL2() {
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.hl2(high: df.high, low: df.low);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = bars.HL2.Length; i > bars.HL2.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(bars.HL2[i - 1].v, digits: digits);
|
||||||
[Fact] void HLC3() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
for (int i = bars.HLC3.Length; i > 0; i--)
|
}
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(bars.HLC3[i - 1].v, digits: digits);
|
[Fact] void HLC3() {
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = bars.HLC3.Length; i > bars.HLC3.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(bars.HLC3[i - 1].v, digits: digits);
|
||||||
[Fact] void HMA() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
HMA_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.hma(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period+1; i--)
|
}
|
||||||
{
|
[Fact] void HMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
HMA_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.hma(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
}
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
[Fact] void KAMA() {
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
KAMA_Series QL = new(bars.Close, period);
|
}
|
||||||
var pta = df.ta.kama(close: df.close, length: period);
|
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void KAMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
KAMA_Series QL = new(bars.Close, period);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.kama(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void KURTOSIS() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
KURTOSIS_Series QL = new(bars.Close, period, useNaN: false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.kurtosis(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period+1; i--)
|
}
|
||||||
{
|
[Fact] void KURTOSIS() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
KURTOSIS_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.kurtosis(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void MAD()
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
{
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
MAD_Series QL = new(bars.Close, period, useNaN: false);
|
}
|
||||||
var pta = df.ta.mad(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
[Fact] void MAD()
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
MAD_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.mad(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void MEDIAN() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
MEDIAN_Series QL = new(bars.Close, period);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.median(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void MEDIAN() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
MEDIAN_Series QL = new(bars.Close, period);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.median(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void OBV() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
OBV_Series QL = new(bars);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.obv(close: df.close, volume: df.volume);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void OBV() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
OBV_Series QL = new(bars);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.obv(close: df.close, volume: df.volume);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void OHLC4() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
for (int i = bars.OHLC4.Length; i > 0; i--)
|
}
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(bars.OHLC4[i - 1].v, digits: digits);
|
[Fact] void OHLC4() {
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = bars.OHLC4.Length; i > bars.OHLC4.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(bars.OHLC4[i - 1].v, digits: digits);
|
||||||
[Fact] void RMA() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
RMA_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.rma(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void RMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
RMA_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.rma(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void RSI() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
RSI_Series QL = new(bars.Close, period);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.rsi(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
[Fact] void RSI() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
RSI_Series QL = new(bars.Close, period);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.rsi(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void SDEV() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
SDEV_Series QL = new(bars.Close, period, useNaN: false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.stdev(close: df.close, length: period, ddof: 0);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void SDEV() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
SDEV_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.stdev(close: df.close, length: period, ddof: 0);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void SMA() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
SMA_Series QL = new(bars.Close, period, false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.sma(close: df.close, length: period);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void SMA() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.sma(close: df.close, length: period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void SSDEV() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
SSDEV_Series QL = new(bars.Close, period, useNaN: false);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.stdev(close: df.close, length: period, ddof: 1);
|
}
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
[Fact] void SSDEV() {
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
SSDEV_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
var pta = df.ta.stdev(close: df.close, length: period, ddof: 1);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
}
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
[Fact] void SVARIANCE() {
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
SVAR_Series QL = new(bars.Close, period);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
|
}
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
/*
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
[Fact] void SVARIANCE() {
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
SVAR_Series QL = new(bars.Close, period);
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
}
|
{
|
||||||
[Fact] void T3() {
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
var pta = df.ta.t3(close: df.close, length: period, a: 0.7);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
for (int i = QL.Length; i > 0; i--)
|
}
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
*/
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void T3() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
|
||||||
}
|
var pta = df.ta.t3(close: df.close, length: period, a: 0.7);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void TEMA() {
|
{
|
||||||
TEMA_Series QL = new(bars.Close, period, false);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.tema(close: df.close, length: period);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > period; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void TEMA() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
TEMA_Series QL = new(bars.Close, period, false);
|
||||||
}
|
var pta = df.ta.tema(close: df.close, length: period);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void TR() {
|
{
|
||||||
TR_Series QL = new(bars);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > 1; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void TR() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
TR_Series QL = new(bars);
|
||||||
}
|
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void TRIMA() {
|
{
|
||||||
// TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
TRIMA_Series QL = new(bars.Close, 11);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
var pta = df.ta.trima(close: df.close, length: 11);
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
}
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
[Fact] void TRIMA() {
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
// TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
TRIMA_Series QL = new(bars.Close, 11);
|
||||||
}
|
var pta = df.ta.trima(close: df.close, length: 11);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void VARIANCE() {
|
{
|
||||||
VAR_Series QL = new(bars.Close, period);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.variance(close: df.close, length: period, ddof:0);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > 0; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void VARIANCE() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
VAR_Series QL = new(bars.Close, period);
|
||||||
}
|
var pta = df.ta.variance(close: df.close, length: period, ddof:0);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void WMA() {
|
{
|
||||||
WMA_Series QL = new(bars.Close, period, false);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.wma(close: df.close, length: period);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void WMA() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
WMA_Series QL = new(bars.Close, period, false);
|
||||||
}
|
var pta = df.ta.wma(close: df.close, length: period);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void ZLEMA() {
|
{
|
||||||
ZLEMA_Series QL = new(bars.Close, period, false);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.zlma(close: df.close, length: period);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > 0; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void ZLEMA() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
ZLEMA_Series QL = new(bars.Close, period, false);
|
||||||
}
|
var pta = df.ta.zlma(close: df.close, length: period);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
[Fact] void ZSCORE() {
|
{
|
||||||
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
var pta = df.ta.zscore(close: df.close, length: period, ddof: 0);
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
for (int i = QL.Length; i > period-1; i--)
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
{
|
}
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
}
|
||||||
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
[Fact] void ZSCORE() {
|
||||||
Assert.Equal(PanTA_item, QL_item);
|
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
}
|
var pta = df.ta.zscore(close: df.close, length: period, ddof: 0);
|
||||||
}
|
for (int i = QL.Length; i > QL.Length-sample; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
|
double PanTA_item = Math.Round((double)pta[i - 1], digits: digits);
|
||||||
|
Assert.Equal(PanTA_item, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,23 @@
|
|||||||
using System;
|
using System;
|
||||||
using QuanTAlib;
|
using QuanTAlib;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Validations;
|
namespace Validations;
|
||||||
public class Skender_Stock
|
public class Skender
|
||||||
{
|
{
|
||||||
private readonly GBM_Feed bars;
|
private readonly GBM_Feed bars;
|
||||||
private readonly Random rnd = new();
|
private readonly Random rnd = new();
|
||||||
private readonly int period, digits;
|
private readonly int period, digits, skip;
|
||||||
private readonly IEnumerable<Quote> quotes;
|
private readonly IEnumerable<Quote> quotes;
|
||||||
|
|
||||||
|
|
||||||
public Skender_Stock()
|
public Skender()
|
||||||
{
|
{
|
||||||
bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2);
|
bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2);
|
||||||
period = rnd.Next(30) + 5;
|
period = rnd.Next(30) + 5;
|
||||||
digits = 4; //minimizing rounding errors in type conversions
|
digits = 2; //minimizing rounding errors in type conversions
|
||||||
|
skip = 300;
|
||||||
|
|
||||||
quotes = bars.Select(q => new Quote
|
quotes = bars.Select(q => new Quote
|
||||||
{
|
{
|
||||||
@@ -27,27 +29,26 @@ public class Skender_Stock
|
|||||||
Volume = (decimal)q.v
|
Volume = (decimal)q.v
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ADL()
|
public void ADL()
|
||||||
{
|
{
|
||||||
// TODO: check precision of ADL()
|
// TODO: check precision of ADL()
|
||||||
ADL_Series QL = new(bars, false);
|
ADL_Series QL = new(bars, false);
|
||||||
var SK = quotes.GetAdl().Select(i => i.Adl);
|
var SK = quotes.GetAdl().Select(i => i.Adl);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1)!, digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ALMA()
|
public void ALMA()
|
||||||
{
|
{
|
||||||
ALMA_Series QL = new(bars.Close, period, useNaN: false);
|
ALMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetAlma(period).Select(i => i.Alma.Null2NaN()!);
|
var SK = quotes.GetAlma(period).Select(i => i.Alma.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -59,7 +60,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
ATR_Series QL = new(bars, period, false);
|
ATR_Series QL = new(bars, period, false);
|
||||||
var SK = quotes.GetAtr(period).Select(i => i.Atr.Null2NaN()!);
|
var SK = quotes.GetAtr(period).Select(i => i.Atr.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -71,7 +72,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
ATRP_Series QL = new(bars, period, false);
|
ATRP_Series QL = new(bars, period, false);
|
||||||
var SK = quotes.GetAtr(period).Select(i => i.Atrp.Null2NaN()!);
|
var SK = quotes.GetAtr(period).Select(i => i.Atrp.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -83,7 +84,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
|
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
|
||||||
var SK = quotes.GetBollingerBands(period, 2.0);
|
var SK = quotes.GetBollingerBands(period, 2.0);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL.Mid[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL.Mid[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1).Sma!.Value, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1).Sma!.Value, digits: digits);
|
||||||
@@ -110,7 +111,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
CCI_Series QL = new(bars, period, false);
|
CCI_Series QL = new(bars, period, false);
|
||||||
var SK = quotes.GetCci(period).Select(i => i.Cci.Null2NaN()!);
|
var SK = quotes.GetCci(period).Select(i => i.Cci.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -122,20 +123,19 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
CORR_Series QL = new(bars.High, bars.Low, period, false);
|
CORR_Series QL = new(bars.High, bars.Low, period, false);
|
||||||
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Correlation.Null2NaN()!);
|
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Correlation.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void COVAR()
|
public void COVAR()
|
||||||
{
|
{
|
||||||
COVAR_Series QL = new(bars.High, bars.Low, period, false);
|
COVAR_Series QL = new(bars.High, bars.Low, period, false);
|
||||||
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Covariance.Null2NaN()!);
|
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Covariance.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -147,33 +147,32 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
DEMA_Series QL = new(bars.Close, period, false);
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!);
|
var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EMA()
|
public void EMA()
|
||||||
{
|
{
|
||||||
EMA_Series QL = new(bars.Close, period, false);
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetEma(period).Select(i => i.Ema.Null2NaN()!);
|
var SK = quotes.GetEma(period).Select(i => i.Ema.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[Fact]
|
[Fact]
|
||||||
public void HL2()
|
public void HL2()
|
||||||
{
|
{
|
||||||
TSeries QL = bars.HL2;
|
TSeries QL = bars.HL2;
|
||||||
var SK = quotes.GetBaseQuote(CandlePart.HL2).Select(i => i.Value);
|
var SK = quotes.GetBaseQuote(CandlePart.HL2).Select(i => i.Value);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
||||||
@@ -185,33 +184,33 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.HLC3;
|
TSeries QL = bars.HLC3;
|
||||||
var SK = quotes.GetBaseQuote(CandlePart.HLC3).Select(i => i.Value);
|
var SK = quotes.GetBaseQuote(CandlePart.HLC3).Select(i => i.Value);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
[Fact]
|
[Fact]
|
||||||
public void HMA()
|
public void HMA()
|
||||||
{
|
{
|
||||||
HMA_Series QL = new(bars.Close, period, useNaN: false);
|
HMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetHma(period).Select(i => i.Hma.Null2NaN()!);
|
var SK = quotes.GetHma(period).Select(i => i.Hma.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void KAMA()
|
public void KAMA()
|
||||||
{
|
{
|
||||||
// TODO: check precision of KAMA()
|
// TODO: check precision of KAMA()
|
||||||
KAMA_Series QL = new(bars.Close, period, useNaN: false);
|
KAMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!);
|
var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > 600; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -223,7 +222,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
LINREG_Series QL = new(bars.Close, period, useNaN: false);
|
LINREG_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetSlope(period);
|
var SK = quotes.GetSlope(period);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1).Slope!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1).Slope!, digits: digits);
|
||||||
@@ -244,7 +243,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
|
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
|
||||||
var SK = quotes.GetMacd(12, 26, 9);
|
var SK = quotes.GetMacd(12, 26, 9);
|
||||||
for (int i = QL.Length; i > 500; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1).Macd.Null2NaN()!, digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1).Macd.Null2NaN()!, digits: digits);
|
||||||
@@ -259,7 +258,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
MAD_Series QL = new(bars.Close, period, false);
|
MAD_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mad.Null2NaN()!);
|
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mad.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -271,7 +270,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
|
MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
|
||||||
var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
|
var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1).Mama.Null2NaN()!, digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1).Mama.Null2NaN()!, digits: digits);
|
||||||
@@ -286,7 +285,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
MAPE_Series QL = new(bars.Close, period, false);
|
MAPE_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mape.Null2NaN()!);
|
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mape.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -298,7 +297,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
MSE_Series QL = new(bars.Close, period, false);
|
MSE_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mse.Null2NaN()!);
|
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mse.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -311,27 +310,32 @@ public class Skender_Stock
|
|||||||
OBV_Series QL = new(bars, period, false);
|
OBV_Series QL = new(bars, period, false);
|
||||||
var SK = quotes.GetObv(period).Select(i => i.Obv!);
|
var SK = quotes.GetObv(period).Select(i => i.Obv!);
|
||||||
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
|
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
|
||||||
Assert.Equal(Math.Round(SK.Last()! + (double)quotes.First().Volume!, digits: digits), Math.Round(QL.Last().v, digits: digits));
|
for (int i = QL.Length; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL.Last().v, digits: digits);
|
||||||
|
double SK_item = Math.Round(SK.Last()! + (double)quotes.First().Volume!, digits: digits);
|
||||||
|
Assert.Equal(SK_item!, QL_item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OC2()
|
public void OC2()
|
||||||
{
|
{
|
||||||
TSeries QL = bars.OC2;
|
TSeries QL = bars.OC2;
|
||||||
var SK = quotes.GetBaseQuote(CandlePart.OC2).Select(i => i.Value);
|
var SK = quotes.GetBaseQuote(CandlePart.OC2).Select(i => i.Value);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OHL3()
|
public void OHL3()
|
||||||
{
|
{
|
||||||
TSeries QL = bars.OHL3;
|
TSeries QL = bars.OHL3;
|
||||||
var SK = quotes.GetBaseQuote(CandlePart.OHL3).Select(i => i.Value);
|
var SK = quotes.GetBaseQuote(CandlePart.OHL3).Select(i => i.Value);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
||||||
@@ -343,20 +347,20 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.OHLC4;
|
TSeries QL = bars.OHLC4;
|
||||||
var SK = quotes.GetBaseQuote(CandlePart.OHLC4).Select(i => i.Value);
|
var SK = quotes.GetBaseQuote(CandlePart.OHLC4).Select(i => i.Value);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
double SK_item = Math.Round((double)SK.ElementAt(i - 1)!, digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RSI()
|
public void RSI()
|
||||||
{
|
{
|
||||||
RSI_Series QL = new(bars.Close, period, useNaN: false);
|
RSI_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetRsi(period).Select(i => i.Rsi.Null2NaN()!);
|
var SK = quotes.GetRsi(period).Select(i => i.Rsi.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -368,7 +372,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
SDEV_Series QL = new(bars.Close, period, useNaN: false);
|
SDEV_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetStdDev(period).Select(i => i.StdDev.Null2NaN()!);
|
var SK = quotes.GetStdDev(period).Select(i => i.StdDev.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -380,7 +384,7 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
SMA_Series QL = new(bars.Close, period, false);
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!);
|
var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -392,33 +396,31 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
SMMA_Series QL = new(bars.Close, period, useNaN: false);
|
SMMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetSmma(period).Select(i => i.Smma.Null2NaN()!);
|
var SK = quotes.GetSmma(period).Select(i => i.Smma.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void T3()
|
public void T3()
|
||||||
{
|
{
|
||||||
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, false);
|
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, false);
|
||||||
var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!);
|
var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TEMA()
|
public void TEMA()
|
||||||
{
|
{
|
||||||
TEMA_Series QL = new(bars.Close, period, false);
|
TEMA_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetTema(period).Select(i => i.Tema.Null2NaN()!);
|
var SK = quotes.GetTema(period).Select(i => i.Tema.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
@@ -430,38 +432,36 @@ public class Skender_Stock
|
|||||||
{
|
{
|
||||||
TR_Series QL = new(bars, useNaN: false);
|
TR_Series QL = new(bars, useNaN: false);
|
||||||
var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!);
|
var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > 1; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WMA()
|
public void WMA()
|
||||||
{
|
{
|
||||||
WMA_Series QL = new(bars.Close, period, false);
|
WMA_Series QL = new(bars.Close, period, false);
|
||||||
var SK = quotes.GetWma(period).Select(i => i.Wma.Null2NaN()!);
|
var SK = quotes.GetWma(period).Select(i => i.Wma.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ZSCORE()
|
public void ZSCORE()
|
||||||
{
|
{
|
||||||
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
|
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
|
||||||
var SK = quotes.GetStdDev(period).Select(i => i.ZScore.Null2NaN()!);
|
var SK = quotes.GetStdDev(period).Select(i => i.ZScore.Null2NaN()!);
|
||||||
for (int i = QL.Length; i > period; i--)
|
for (int i = QL.Length; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
double QL_item = Math.Round(QL[i - 1].v, digits: digits);
|
||||||
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
double SK_item = Math.Round(SK.ElementAt(i - 1), digits: digits);
|
||||||
Assert.Equal(SK_item!, QL_item);
|
Assert.Equal(SK_item!, QL_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
private readonly GBM_Feed bars;
|
private readonly GBM_Feed bars;
|
||||||
private readonly Random rnd = new();
|
private readonly Random rnd = new();
|
||||||
private readonly int period, digits;
|
private readonly int period, digits, skip;
|
||||||
private readonly double[] TALIB;
|
private readonly double[] TALIB;
|
||||||
private readonly double[] TALIB2;
|
private readonly double[] TALIB2;
|
||||||
private readonly double[] inopen;
|
private readonly double[] inopen;
|
||||||
@@ -21,6 +21,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3);
|
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3);
|
||||||
period = rnd.Next(28) + 3;
|
period = rnd.Next(28) + 3;
|
||||||
|
skip = 200;
|
||||||
digits = 6;
|
digits = 6;
|
||||||
|
|
||||||
TALIB = new double[bars.Count];
|
TALIB = new double[bars.Count];
|
||||||
@@ -37,7 +38,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
ADD_Series QL = new(bars.Open, bars.Close);
|
ADD_Series QL = new(bars.Open, bars.Close);
|
||||||
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -59,9 +60,9 @@ public class Ta_Lib
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void ADOSC()
|
public void ADOSC()
|
||||||
{
|
{
|
||||||
ADOSC_Series QL = new(bars, false);
|
ADOSC_Series QL = new(bars, 3, 10, false);
|
||||||
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -73,7 +74,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
ATR_Series QL = new(bars, period, false);
|
ATR_Series QL = new(bars, period, false);
|
||||||
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 15; i--)
|
for (int i = QL.Length - 1; i > skip * 15; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -88,7 +89,7 @@ public class Ta_Lib
|
|||||||
double[] outLower = new double[bars.Count];
|
double[] outLower = new double[bars.Count];
|
||||||
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false);
|
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false);
|
||||||
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
|
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL.Upper[i].v, digits: digits);
|
double QL_item = Math.Round(QL.Upper[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(outUpper[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(outUpper[i - outBegIdx], digits: digits);
|
||||||
@@ -109,7 +110,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
CCI_Series QL = new(bars, period, false);
|
CCI_Series QL = new(bars, period, false);
|
||||||
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -121,7 +122,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
CORR_Series QL = new(bars.Open, bars.Close, period);
|
CORR_Series QL = new(bars.Open, bars.Close, period);
|
||||||
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
|
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -133,7 +134,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
DEMA_Series QL = new(bars.Close, period, false);
|
DEMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -145,7 +146,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
DIV_Series QL = new(bars.Open, bars.Close);
|
DIV_Series QL = new(bars.Open, bars.Close);
|
||||||
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -157,7 +158,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
EMA_Series QL = new(bars.Close, period, false);
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -169,7 +170,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.HL2;
|
TSeries QL = bars.HL2;
|
||||||
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -181,7 +182,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.HLC3;
|
TSeries QL = bars.HLC3;
|
||||||
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -193,7 +194,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.HLCC4;
|
TSeries QL = bars.HLCC4;
|
||||||
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -207,7 +208,7 @@ public class Ta_Lib
|
|||||||
double[] macdHist = new double[bars.Count];
|
double[] macdHist = new double[bars.Count];
|
||||||
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
|
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
|
||||||
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
|
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 10; i--)
|
for (int i = QL.Length - 1; i > skip * 10; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -222,7 +223,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05);
|
MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05);
|
||||||
Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05);
|
Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 15; i--)
|
for (int i = QL.Length - 1; i > skip * 15; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -234,7 +235,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MAX_Series QL = new(bars.Close, period, false);
|
MAX_Series QL = new(bars.Close, period, false);
|
||||||
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -246,7 +247,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MIDPOINT_Series QL = new(bars.Close, period, false);
|
MIDPOINT_Series QL = new(bars.Close, period, false);
|
||||||
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -258,7 +259,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MIDPRICE_Series QL = new(bars, period, false);
|
MIDPRICE_Series QL = new(bars, period, false);
|
||||||
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -270,7 +271,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MIN_Series QL = new(bars.Close, period, false);
|
MIN_Series QL = new(bars.Close, period, false);
|
||||||
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -282,7 +283,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
MUL_Series QL = new(bars.Open, bars.Close);
|
MUL_Series QL = new(bars.Open, bars.Close);
|
||||||
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -294,7 +295,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
OBV_Series QL = new(bars, period, false);
|
OBV_Series QL = new(bars, period, false);
|
||||||
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -306,7 +307,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TSeries QL = bars.OHLC4;
|
TSeries QL = bars.OHLC4;
|
||||||
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -318,7 +319,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
RSI_Series QL = new(bars.Close, period, false);
|
RSI_Series QL = new(bars.Close, period, false);
|
||||||
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -330,7 +331,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
SDEV_Series QL = new(bars.Close, period, false);
|
SDEV_Series QL = new(bars.Close, period, false);
|
||||||
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -342,7 +343,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
SMA_Series QL = new(bars.Close, period, false);
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -354,7 +355,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
SUB_Series QL = new(bars.Open, bars.Close);
|
SUB_Series QL = new(bars.Open, bars.Close);
|
||||||
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -366,7 +367,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
SUM_Series QL = new(bars.Close, period, false);
|
SUM_Series QL = new(bars.Close, period, false);
|
||||||
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -378,7 +379,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
|
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
|
||||||
Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7);
|
Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 15; i--)
|
for (int i = QL.Length - 1; i > skip * 15; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -390,7 +391,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TEMA_Series QL = new(bars.Close, period, false);
|
TEMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 15; i--)
|
for (int i = QL.Length - 1; i > skip * 15; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -402,7 +403,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TR_Series QL = new(bars, false);
|
TR_Series QL = new(bars, false);
|
||||||
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -414,7 +415,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
TRIMA_Series QL = new(bars.Close, period, false);
|
TRIMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -426,7 +427,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
VAR_Series QL = new(bars.Close, period, false);
|
VAR_Series QL = new(bars.Close, period, false);
|
||||||
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx * 15; i--)
|
for (int i = QL.Length - 1; i > skip * 15; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -438,7 +439,7 @@ public class Ta_Lib
|
|||||||
{
|
{
|
||||||
WMA_Series QL = new(bars.Close, period, false);
|
WMA_Series QL = new(bars.Close, period, false);
|
||||||
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||||
for (int i = QL.Length - 1; i > outBegIdx; i--)
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
{
|
{
|
||||||
double QL_item = Math.Round(QL[i].v, digits: digits);
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
double TA_item = Math.Round(TALIB[i - outBegIdx], digits: digits);
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using Tulip;
|
||||||
|
using QuanTAlib;
|
||||||
|
|
||||||
|
namespace Validations;
|
||||||
|
public class Tulip_Test
|
||||||
|
{
|
||||||
|
private readonly GBM_Feed bars;
|
||||||
|
private readonly Random rnd = new();
|
||||||
|
private readonly int period, digits, skip;
|
||||||
|
private readonly double[] outdata;
|
||||||
|
private readonly double[] inopen;
|
||||||
|
private readonly double[] inhigh;
|
||||||
|
private readonly double[] inlow;
|
||||||
|
private readonly double[] inclose;
|
||||||
|
private readonly double[] involume;
|
||||||
|
|
||||||
|
public Tulip_Test()
|
||||||
|
{
|
||||||
|
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3);
|
||||||
|
period = rnd.Next(28) + 3;
|
||||||
|
skip = 600;
|
||||||
|
digits = 5;
|
||||||
|
|
||||||
|
outdata = new double[bars.Count];
|
||||||
|
inopen = bars.Open.v.ToArray();
|
||||||
|
inhigh = bars.High.v.ToArray();
|
||||||
|
inlow = bars.Low.v.ToArray();
|
||||||
|
inclose = bars.Close.v.ToArray()!;
|
||||||
|
involume = bars.Volume.v.ToArray()!;
|
||||||
|
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void AD()
|
||||||
|
{
|
||||||
|
double[][] arrin = {inhigh, inlow, inclose, involume };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
ADL_Series QL = new(bars, false);
|
||||||
|
Tulip.Indicators.ad.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void ADD()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inhigh, inlow };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
ADD_Series QL = new(bars.High, bars.Low);
|
||||||
|
Tulip.Indicators.add.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void ADOSC()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inhigh, inlow, inclose, involume };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
int s = 3;
|
||||||
|
ADOSC_Series QL = new(bars, s, period, false);
|
||||||
|
Tulip.Indicators.adosc.Run(inputs: arrin, options: new double[] { s, period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i-period+1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void ATR()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inhigh, inlow, inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
|
||||||
|
ATR_Series QL = new(bars, period, false);
|
||||||
|
Tulip.Indicators.atr.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i - period + 1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void BBANDS()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[] outmid = new double[bars.Count];
|
||||||
|
double[] outlower = new double[bars.Count];
|
||||||
|
double[] outupper = new double[bars.Count];
|
||||||
|
double[][] arrout = { outlower, outmid, outupper};
|
||||||
|
BBANDS_Series QL = new(bars.Close, period, 2, false);
|
||||||
|
Tulip.Indicators.bbands.Run(inputs: arrin, options: new double[] { period, 2 }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL.Lower[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(outlower[i - period + 1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
QL_item = Math.Round(QL.Mid[i].v, digits: digits);
|
||||||
|
TU_item = Math.Round(outmid[i - period + 1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
QL_item = Math.Round(QL.Upper[i].v, digits: digits);
|
||||||
|
TU_item = Math.Round(outupper[i - period + 1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void EMA()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
EMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void AVGPRICE()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inopen, inhigh, inlow, inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
|
||||||
|
TSeries QL = bars.OHLC4;
|
||||||
|
Tulip.Indicators.avgprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void SMA()
|
||||||
|
{
|
||||||
|
double[][] arrin = { inclose };
|
||||||
|
double[][] arrout = { outdata };
|
||||||
|
SMA_Series QL = new(bars.Close, period, false);
|
||||||
|
Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
|
||||||
|
for (int i = QL.Length - 1; i > skip; i--)
|
||||||
|
{
|
||||||
|
double QL_item = Math.Round(QL[i].v, digits: digits);
|
||||||
|
double TU_item = Math.Round(arrout[0][i-period+1], digits);
|
||||||
|
Assert.Equal(TU_item!, QL_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
# SMA: Simple Moving Average
|
||||||
|
SMA is one of the most basic trend-following indicators used in Technical Analysis. It is calculated as the *unweighted mean* of the previous $p$ (period) data-points.
|
||||||
|
|
||||||
|
|
||||||
|
## Calculation
|
||||||
|
|
||||||
|
SMA is a rolling calculation looking backwards from the position ${n}$ and is denoted as ${SMA}_{p}{(data)}$ where $p$ represents the period and $data$ represents the list of data points:
|
||||||
|
$$
|
||||||
|
SMA_p{(data)} = \frac{1}{p}\sum_{i=n-p+1}^{n} data_i
|
||||||
|
$$
|
||||||
|
When calculating the value of next $SMA_{p,next}$ while knowing all previous SMA values, SMA calculation can be reduced to:
|
||||||
|
$$
|
||||||
|
SMA_{p,next} = SMA_{p,prev}+\frac{1}{p}\left( data_{n+1}-data_{n+1-p}\right)
|
||||||
|
$$
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
``` csharp
|
||||||
|
SMA_Series mean = new(source: data, period: p, useNaN: false);
|
||||||
|
|
||||||
|
QuanTA fluent = data.SMA(period: p);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
- `TSeries source` - List of value tuples (DateTime, double)
|
||||||
|
- `int period` - Integer representing the period of SMA
|
||||||
|
- `bool useNaN` - if true, initial values from 1 to period-1 will be replaced with NaN. If false, the initial calculation will return values for SMA(length) instead of SMA(period)
|
||||||
|
|
||||||
|
## Sample chart
|
||||||
|
|
||||||
|
picture of SMA
|
||||||
|
|
||||||
|
## Comparison & Validation
|
||||||
|
|
||||||
|
Validation tests
|
||||||
|
Performance tests
|
||||||
|
|
||||||
|
## References
|
||||||
|
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 89 KiB |
+93
-101
@@ -2,7 +2,14 @@
|
|||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"# Quick Start\n",
|
"# Quick Start\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -17,35 +24,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<div><div></div><div></div><div></div></div>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ename": "Error",
|
|
||||||
"evalue": "(3,1): error CS0246: The type or namespace name 'Yahoo_Feed' could not be found (are you missing a using directive or an assembly reference?)\r\n(10,15): error CS0019: Operator '<' cannot be applied to operands of type 'int' and 'method group'",
|
|
||||||
"output_type": "error",
|
|
||||||
"traceback": [
|
|
||||||
"(3,1): error CS0246: The type or namespace name 'Yahoo_Feed' could not be found (are you missing a using directive or an assembly reference?)\r\n",
|
|
||||||
"(10,15): error CS0019: Operator '<' cannot be applied to operands of type 'int' and 'method group'"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"#r \"nuget:QuanTAlib;\"\n",
|
"#r \"nuget:QuanTAlib;\"\n",
|
||||||
"using QuanTAlib;\n",
|
"using QuanTAlib;\n",
|
||||||
@@ -63,7 +51,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"## Understanding QuanTAlib data model\n",
|
"## Understanding QuanTAlib data model\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -72,26 +67,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<table><thead><tr><th><i>index</i></th><th>Item1</th><th>Item2</th></tr></thead><tbody><tr><td>0</td><td><span>2022-11-10 00:00:00Z</span></td><td><div class=\"dni-plaintext\">105.3</div></td></tr><tr><td>1</td><td><span>2022-11-10 15:47:46Z</span></td><td><div class=\"dni-plaintext\">293.1</div></td></tr><tr><td>2</td><td><span>2022-11-10 15:47:46Z</span></td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>3</td><td><span>2022-11-07 15:47:46Z</span></td><td><div class=\"dni-plaintext\">10</div></td></tr></tbody></table>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"var item1 = (DateTime.Today, 105.3); // (DateTime, Value) tuple\n",
|
"var item1 = (DateTime.Today, 105.3); // (DateTime, Value) tuple\n",
|
||||||
"double item2 = 293.1; // a simple double\n",
|
"double item2 = 293.1; // a simple double\n",
|
||||||
@@ -107,66 +92,60 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"TSeries list can display only values (without timestamps) or only timestamps (without values) by using `.v` or `.t` properties"
|
"TSeries list can display only values (without timestamps) or only timestamps (without values) by using `.v` or `.t` properties"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><div class=\"dni-plaintext\">105.3</div></td></tr><tr><td>1</td><td><div class=\"dni-plaintext\">293.1</div></td></tr><tr><td>2</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>3</td><td><div class=\"dni-plaintext\">10</div></td></tr></tbody></table>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"data.v"
|
"data.v"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"The last element on the list can be accessed by .Last() or by [^1] - and using `.t` (time) and `.v` (value) properties. Also, casting a TSeries into (double) will return the value of the last element"
|
"The last element on the list can be accessed by .Last() or by [^1] - and using `.t` (time) and `.v` (value) properties. Also, casting a TSeries into (double) will return the value of the last element"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 12,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<div class=\"dni-plaintext\">10</div>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"bool IsTheSame = data.Last().v == data[^1].v;\n",
|
"bool IsTheSame = data.Last().v == data[^1].v;\n",
|
||||||
"double lastvalue = data;\n",
|
"double lastvalue = data;\n",
|
||||||
@@ -176,33 +155,30 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"All indicators are just modified TSeries classes; they get all required input during class construction (source of the datafeed, period...) and they automatically subscribe to events of the datafeed. Whenever datafeed gets a new value, indicator will calculate its own value. Indicators are also event publishers, so other indicators can subscribe to their results, chaining indicators together:"
|
"All indicators are just modified TSeries classes; they get all required input during class construction (source of the datafeed, period...) and they automatically subscribe to events of the datafeed. Whenever datafeed gets a new value, indicator will calculate its own value. Indicators are also event publishers, so other indicators can subscribe to their results, chaining indicators together:"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><div class=\"dni-plaintext\">Infinity</div></td></tr><tr><td>1</td><td><div class=\"dni-plaintext\">0.6666666666666666</div></td></tr><tr><td>2</td><td><div class=\"dni-plaintext\">0.3333333333333333</div></td></tr><tr><td>3</td><td><div class=\"dni-plaintext\">0.2</div></td></tr><tr><td>4</td><td><div class=\"dni-plaintext\">0.14285714285714285</div></td></tr><tr><td>5</td><td><div class=\"dni-plaintext\">0.1111111111111111</div></td></tr><tr><td>6</td><td><div class=\"dni-plaintext\">0.09090909090909091</div></td></tr><tr><td>7</td><td><div class=\"dni-plaintext\">0.07692307692307693</div></td></tr><tr><td>8</td><td><div class=\"dni-plaintext\">0.06666666666666667</div></td></tr><tr><td>9</td><td><div class=\"dni-plaintext\">0.058823529411764705</div></td></tr><tr><td>10</td><td><div class=\"dni-plaintext\">0.25</div></td></tr></tbody></table>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"TSeries t1 = new() {0,1,2,3,4,5,6,7,8,9}; // t1 is loaded with data and activated as a publisher\n",
|
"TSeries t1 = new() {0,1,2,3,4,5,6,7,8,9}; // t1 is loaded with data and activated as a publisher\n",
|
||||||
"EMA_Series t2 = new(t1, 3); // t2 will auto-load all history of t1 and wait for events from t1\n",
|
"EMA_Series t2 = new(t1, 3); // t2 will auto-load all history of t1 and wait for events from t1\n",
|
||||||
@@ -218,7 +194,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"dotnet_interactive": {
|
||||||
|
"language": "csharp"
|
||||||
|
},
|
||||||
|
"polyglot_notebook": {
|
||||||
|
"kernelName": "csharp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"# MACD compounded indicator\n",
|
"# MACD compounded indicator\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -227,26 +210,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"dotnet_interactive": {
|
"dotnet_interactive": {
|
||||||
"language": "csharp"
|
"language": "csharp"
|
||||||
},
|
},
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"languageId": "dotnet-interactive.csharp"
|
"languageId": "polyglot-notebook"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/html": [
|
|
||||||
"<table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>1</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>2</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>3</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>4</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>5</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>6</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>7</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>8</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>9</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>10</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>11</td><td><div class=\"dni-plaintext\">0</div></td></tr><tr><td>12</td><td><div class=\"dni-plaintext\">0.13543589743590018</div></td></tr><tr><td>13</td><td><div class=\"dni-plaintext\">-0.03897954353340993</div></td></tr><tr><td>14</td><td><div class=\"dni-plaintext\">-0.17731008431411102</div></td></tr><tr><td>15</td><td><div class=\"dni-plaintext\">-0.24030671152304095</div></td></tr><tr><td>16</td><td><div class=\"dni-plaintext\">-0.08247055673614988</div></td></tr><tr><td>17</td><td><div class=\"dni-plaintext\">-0.47898448490240814</div></td></tr><tr><td>18</td><td><div class=\"dni-plaintext\">-0.9020715041856615</div></td></tr><tr><td>19</td><td><div class=\"dni-plaintext\">-1.3489730137363423</div></td></tr><tr><td colspan=\"2\"><i>(51 more)</i></td></tr></tbody></table>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"Yahoo_Feed aapl = new(\"AAPL\", 100);\n",
|
"Yahoo_Feed aapl = new(\"AAPL\", 100);\n",
|
||||||
"TSeries close = aapl.Close; // close will get data from history\n",
|
"TSeries close = aapl.Close; // close will get data from history\n",
|
||||||
@@ -266,14 +239,33 @@
|
|||||||
"language": "C#",
|
"language": "C#",
|
||||||
"name": ".net-csharp"
|
"name": ".net-csharp"
|
||||||
},
|
},
|
||||||
"language_info": {
|
"polyglot_notebook": {
|
||||||
"file_extension": ".cs",
|
"kernelInfo": {
|
||||||
"mimetype": "text/x-csharp",
|
"defaultKernelName": "csharp",
|
||||||
"name": "C#",
|
"items": [
|
||||||
"pygments_lexer": "csharp",
|
{
|
||||||
"version": "9.0"
|
"aliases": [
|
||||||
},
|
"c#",
|
||||||
"orig_nbformat": 4
|
"C#"
|
||||||
|
],
|
||||||
|
"languageName": "C#",
|
||||||
|
"name": "csharp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliases": [
|
||||||
|
"frontend"
|
||||||
|
],
|
||||||
|
"languageName": null,
|
||||||
|
"name": "vscode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliases": [],
|
||||||
|
"languageName": "KQL",
|
||||||
|
"name": "kql"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
"nbformat_minor": 2
|
"nbformat_minor": 2
|
||||||
|
|||||||
+13
-7
@@ -6,20 +6,26 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
<meta name="description" content="Description">
|
<meta name="description" content="Description">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css">
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script>
|
<script>
|
||||||
window.$docsify = {
|
window.$docsify = {
|
||||||
name: 'QuanTAlib',
|
name: '',
|
||||||
repo: 'mihakralj/quantalib'
|
repo: '',
|
||||||
}
|
latex: {
|
||||||
|
inlineMath : [['$', '$'], ['\\(', '\\)']], // default
|
||||||
|
displayMath : [['$$', '$$']], // default
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-csharp.min.js"></script>
|
|
||||||
<!-- Docsify v4 -->
|
<!-- Docsify v4 -->
|
||||||
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
||||||
<script src="//cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
|
<!-- LaTeX display engine -->
|
||||||
<script src="//unpkg.com/@rakutentech/docsify-code-inline/dist/index.min.js"></script>
|
<script src="//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||||
|
<!-- docsify-latex plugin -->
|
||||||
|
<script src="//cdn.jsdelivr.net/npm/docsify-latex@0"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+43
-32
@@ -34,28 +34,31 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
|||||||
|
|
||||||
⛔= Not implemented (yet)
|
⛔= Not implemented (yet)
|
||||||
|
|
||||||
| **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | **Tulip** |
|
||||||
|--|:--:|:--:|:--:|:--:|
|
|--|:--:|:--:|:--:|:--:|:--:|
|
||||||
| ⭐ OC2 - (Open+Close)/2 |️ `.OC2` || CandlePart.OC2 ||
|
| ⭐ OC2 - (Open+Close)/2 |️ `.OC2` || CandlePart.OC2 ||
|
||||||
| ⭐ HL2 - Median Price | `.HL2` | MEDPRICE | CandlePart.HL2 | hl2 |
|
| ⭐ HL2 - Median Price | `.HL2` | MEDPRICE | CandlePart.HL2 | hl2 |
|
||||||
| ⭐ HLC3 - Typical Price | `.HLC3` | TYPPRICE | CandlePart.HLC3 | hlc3 |
|
| ⭐ HLC3 - Typical Price | `.HLC3` | TYPPRICE | CandlePart.HLC3 | hlc3 |
|
||||||
| ⭐ OHL3 - (Open+High+Low)/3 | `.OHL3` || CandlePart.OHL3 ||
|
| ⭐ OHL3 - (Open+High+Low)/3 | `.OHL3` || CandlePart.OHL3 ||
|
||||||
| ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE |️ CandlePart.OHLC4 | ohlc4 |
|
| ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE |️ CandlePart.OHLC4 | ohlc4 | avgprice |
|
||||||
| ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE | CandlePart.HLCC4 ||
|
| ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE | CandlePart.HLCC4 ||
|
||||||
| ⭐ MIDPOINT - Midpoint value | `MIDPOINT_Series` | MIDPOINT || midpoint |
|
| ⭐ MIDPOINT - Midpoint value | `MIDPOINT_Series` | MIDPOINT || midpoint |
|
||||||
| ⭐ MIDPRICE - Midpoint price | `MIDPRICE_Series` | MIDPRICE || midprice |
|
| ⭐ MIDPRICE - Midpoint price | `MIDPRICE_Series` | MIDPRICE || midprice |
|
||||||
| ⭐ MAX - Max value | `MAX_Series` | MAX |||
|
| ⭐ MAX - Max value | `MAX_Series` | MAX ||| max |
|
||||||
| ⭐ MIN - Min value | `MIN_Series` | MIN |||
|
| ⭐ MIN - Min value | `MIN_Series` | MIN ||| min |
|
||||||
| ⭐ SUM - Summation | `SUM_Series` | SUM |||
|
| ⭐ SUM - Summation | `SUM_Series` | SUM ||| sum |
|
||||||
| ⭐ ADD - Addition | `ADD_Series` | ADD |||
|
| ⭐ ADD - Addition | `ADD_Series` | ADD ||| add |
|
||||||
| ⭐ SUB - Subtraction | `SUB_Series` | SUB |||
|
| ⭐ SUB - Subtraction | `SUB_Series` | SUB ||| sub |
|
||||||
| ⭐ MUL - Multiplication | `MUL_Series` | MUL |||
|
| ⭐ MUL - Multiplication | `MUL_Series` | MUL ||| mul |
|
||||||
| ⭐ DIV - Division | `DIV_Series` | DIV |||
|
| ⭐ DIV - Division | `DIV_Series` | DIV ||| div |
|
||||||
|||||
|
|||||
|
||||||
| **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **STATISTICS & NUMERICAL ANALYSIS** |
|
||||||
|
||||||
|
||||||
| ⭐ BIAS - Bias | `BIAS_Series` ||| bias |
|
| ⭐ BIAS - Bias | `BIAS_Series` ||| bias |
|
||||||
| ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation ||
|
| ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation ||
|
||||||
| ⭐ COVAR - Covariance | `COVAR_Series` || GetCorrelation ||
|
| ⭐ COVAR - Covariance | `COVAR_Series` || GetCorrelation ||
|
||||||
|
| ⛔ DECAY - Linear Decay ||||| decay |
|
||||||
|
| ⛔ EDECAY - Exponential Decay ||||| edecay |
|
||||||
| ⭐ ENTROPY - Entropy | `ENTROPY_Series` ||| entropy |
|
| ⭐ ENTROPY - Entropy | `ENTROPY_Series` ||| entropy |
|
||||||
| ⭐ KURTOSIS - Kurtosis | `KURT_Series` ||| kurtosis |
|
| ⭐ KURTOSIS - Kurtosis | `KURT_Series` ||| kurtosis |
|
||||||
| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope ||
|
| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope ||
|
||||||
@@ -73,22 +76,23 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
|||||||
| ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` ||||
|
| ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` ||||
|
||||||
| ⭐ ZSCORE - Number of standard deviations from mean | `ZSCORE_Series` || GetStdDev | zscore |
|
| ⭐ ZSCORE - Number of standard deviations from mean | `ZSCORE_Series` || GetStdDev | zscore |
|
||||||
||||||
|
||||||
|
||||||
| **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **TREND INDICATORS & AVERAGES** |
|
||||||
|
||||||
|
||||||
| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average |||||
|
| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average |||||
|
||||||
| ⭐ ALMA - Arnaud Legoux Moving Average | `ALMA_Series` || GetAlma | alma |
|
| ⭐ ALMA - Arnaud Legoux Moving Average | `ALMA_Series` || GetAlma | alma |
|
||||||
| ⛔ ARIMA - Autoregressive Integrated Moving Average |||||
|
| ⛔ ARIMA - Autoregressive Integrated Moving Average |||||
|
||||||
| ⭐ DEMA - Double EMA Average | `DEMA_Series` | DEMA | GetDema | dema |
|
| ⭐ DEMA - Double EMA Average | `DEMA_Series` | DEMA | GetDema | dema | dema |
|
||||||
| ⭐ EMA - Exponential Moving Average | `EMA_Series` | EMA | GetEma | ema |
|
| ⭐ EMA - Exponential Moving Average | `EMA_Series` | EMA | GetEma | ema | ema |
|
||||||
| ⛔ EPMA - Endpoint Moving Average ||| GetEpma ||
|
| ⛔ EPMA - Endpoint Moving Average ||| GetEpma ||
|
||||||
| ⛔ FRAMA - Fractal Adaptive Moving Average |||||
|
| ⛔ FRAMA - Fractal Adaptive Moving Average |||||
|
||||||
| ⛔ FWMA - Fibonacci's Weighted Moving Average |||| fwma |
|
| ⛔ FWMA - Fibonacci's Weighted Moving Average |||| fwma |
|
||||||
| ⛔ HILO - Gann High-Low Activator |||| hilo |
|
| ⛔ HILO - Gann High-Low Activator |||| hilo |
|
||||||
| ✔️ HEMA - Hull/EMA Average | `HEMA_Series` ||||
|
| ✔️ 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 |
|
| ⭐ HMA - Hull Moving Average | `HMA_Series` || GetHma | hma | hma |
|
||||||
| ⛔ HWMA - Holt-Winter Moving Average |||| hwma |
|
| ⛔ HWMA - Holt-Winter Moving Average |||| hwma |
|
||||||
| ✔️ JMA - Jurik Moving Average | `JMA_Series` ||| jma |
|
| ✔️ JMA - Jurik Moving Average | `JMA_Series` ||| jma |
|
||||||
| ⭐ KAMA - Kaufman's Adaptive Moving Average | `KAMA_Series` | KAMA | GetKama | kama |
|
| ⭐ KAMA - Kaufman's Adaptive Moving Average | `KAMA_Series` | KAMA | GetKama | kama | kama |
|
||||||
| ⛔ KDJ - KDJ Indicator (trend reversal) |||| kdj |
|
| ⛔ KDJ - KDJ Indicator (trend reversal) |||| kdj |
|
||||||
| ⛔ LSMA - Least Squares Moving Average |||||
|
| ⛔ LSMA - Least Squares Moving Average |||||
|
||||||
| ⭐ MACD - Moving Average Convergence/Divergence | `MACD_Series` | MACD | GetMacd | macd |
|
| ⭐ MACD - Moving Average Convergence/Divergence | `MACD_Series` | MACD | GetMacd | macd |
|
||||||
@@ -113,17 +117,20 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
|||||||
| ⭐ WMA - Weighted Moving Average | `WMA_Series` | WMA | GetWma | wma |
|
| ⭐ WMA - Weighted Moving Average | `WMA_Series` | WMA | GetWma | wma |
|
||||||
| ⭐ ZLEMA - Zero Lag EMA Average | `ZLEMA_Series` ||| zlma |
|
| ⭐ ZLEMA - Zero Lag EMA Average | `ZLEMA_Series` ||| zlma |
|
||||||
||||||
|
||||||
|
||||||
| **VOLATILITY INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **VOLATILITY INDICATORS** |
|
||||||
| ⭐ ADL - Chaikin Accumulation Distribution Line | `ADL_Series` | AD | GetAdl | ad |
|
||||||
|
||||||
| ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | `ADOSC_Series` | ADOSC| GetAdl | adosc |
|
| ⭐ ADL - Chaikin Accumulation Distribution Line | `ADL_Series` | AD | GetAdl | ad | ad |
|
||||||
| ⭐ ATR - Average True Range | `ATR_Series` | ATR | GetAtr | atr |
|
| ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | `ADOSC_Series` | ADOSC| GetAdl | adosc | adosc |
|
||||||
|
| ⭐ ATR - Average True Range | `ATR_Series` | ATR | GetAtr | atr | atr |
|
||||||
| ⭐ 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 || bbands |
|
||||||
| ⛔ CHAND - Chandelier Exit ||| GetChandelier ||
|
| ⛔ CHAND - Chandelier Exit ||| GetChandelier ||
|
||||||
| ⛔ CRSI - Connor RSI ||| GetConnorsRsi ||
|
| ⛔ CRSI - Connor RSI ||| GetConnorsRsi ||
|
||||||
|
| ⛔ CVI - Chaikins Volatility ||||| cvi |
|
||||||
| ⛔ DON - Donchian Channels ||| GetDonchian ||
|
| ⛔ DON - Donchian Channels ||| GetDonchian ||
|
||||||
| ⛔ FCB - Fractal Chaos Bands ||| GetFcb ||
|
| ⛔ FCB - Fractal Chaos Bands ||| GetFcb ||
|
||||||
|
| ⛔ FISHER - Fisher Transform ||| GetFcb || fisher |
|
||||||
| ⛔ HV - Historical Volatility |||||
|
| ⛔ HV - Historical Volatility |||||
|
||||||
| ⛔ ICH - Ichimoku ||| GetIchimoku ||
|
| ⛔ ICH - Ichimoku ||| GetIchimoku ||
|
||||||
| ⛔ KEL - Keltner Channels ||| GetKeltner ||
|
| ⛔ KEL - Keltner Channels ||| GetKeltner ||
|
||||||
@@ -137,23 +144,25 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
|||||||
| ⛔ UI - Ulcer Index |||||
|
| ⛔ UI - Ulcer Index |||||
|
||||||
| ⛔ VSTOP - Volatility Stop |||||
|
| ⛔ VSTOP - Volatility Stop |||||
|
||||||
||||||
|
||||||
|
||||||
| **MOMENTUM INDICATORS & OSCILLATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **MOMENTUM INDICATORS & OSCILLATORS** |
|
||||||
|
||||||
|
||||||
| ⛔ AC - Acceleration Oscillator |||||
|
| ⛔ AC - Acceleration Oscillator |||||
|
||||||
| ⛔ ADX - Average Directional Movement Index || ADX | GetAdx ||
|
| ⛔ ADX - Average Directional Movement Index || ADX | GetAdx || adx |
|
||||||
| ⛔ ADXR - Average Directional Movement Index Rating || ADXR | GetAdx ||
|
| ⛔ ADXR - Average Directional Movement Index Rating || ADXR | GetAdx || adxr |
|
||||||
| ⛔ AO - Awesome Oscillator ||| GetAwesome ||
|
| ⛔ AO - Awesome Oscillator ||| GetAwesome || ao |
|
||||||
| ⛔ APO - Absolute Price Oscillator || APO |||
|
| ⛔ APO - Absolute Price Oscillator || APO ||| apo |
|
||||||
| ⛔ AROON - Aroon oscillator || AROON | GetAroon ||
|
| ⛔ AROON - Aroon oscillator || AROON | GetAroon || aroon |
|
||||||
| ⛔ BOP - Balance of Power || BOP | GetBop ||
|
| ⛔ BOP - Balance of Power || BOP | GetBop || bop |
|
||||||
| ⭐ CCI - Commodity Channel Index | `CCI_Series` | CCI | GetCci ||
|
| ⭐ CCI - Commodity Channel Index | `CCI_Series` | CCI | GetCci || cci |
|
||||||
| ⛔ CFO - Chande Forcast Oscillator |||||
|
| ⛔ CFO - Chande Forcast Oscillator |||||
|
||||||
| ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo ||
|
| ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo || cmo |
|
||||||
| ⛔ COG - Center of Gravity |||||
|
| ⛔ COG - Center of Gravity |||||
|
||||||
| ⛔ COPPOCK - Coppock Curve |||||
|
| ⛔ 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 ||
|
||||||
| ⛔ EFI - Elder Ray's Force Index ||| GetElderRay ||
|
| ⛔ EFI - Elder Ray's Force Index ||| GetElderRay ||
|
||||||
|
| ⛔ FOSC - Forecast oscillator ||||| fosc |
|
||||||
| ⛔ GAT - Alligator oscillator ||| GetGator ||
|
| ⛔ GAT - Alligator oscillator ||| GetGator ||
|
||||||
| ⛔ HURST - Hurst Exponent ||| GetHurst ||
|
| ⛔ HURST - Hurst Exponent ||| GetHurst ||
|
||||||
| ⛔ KRI - Kairi Relative Index |||||
|
| ⛔ KRI - Kairi Relative Index |||||
|
||||||
@@ -176,10 +185,12 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
|||||||
| ⛔ WILLR - Larry Williams' %R || WILLR | GetWilliamsR ||
|
| ⛔ WILLR - Larry Williams' %R || WILLR | GetWilliamsR ||
|
||||||
| ⛔ WGAT - Williams Alligator |||||
|
| ⛔ WGAT - Williams Alligator |||||
|
||||||
||||||
|
||||||
|
||||||
| **VOLUME INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
|
| **VOLUME INDICATORS** |
|
||||||
|
||||||
|
||||||
| ⛔ AOBV - Archer On-Balance Volume |||||
|
| ⛔ AOBV - Archer On-Balance Volume |||||
|
||||||
| ⛔ CMF - Chaikin Money Flow |||||
|
| ⛔ CMF - Chaikin Money Flow |||||
|
||||||
| ⛔ EOM - Ease of Movement |||||
|
| ⛔ EOM - Ease of Movement ||||| emv |
|
||||||
|
| ⛔ KVO - Klinger Volume Oscilaltor ||||| kvo |
|
||||||
| ⭐ OBV - On-Balance Volume | `OBV_Series` | OBV | GetObv ||
|
| ⭐ OBV - On-Balance Volume | `OBV_Series` | OBV | GetObv ||
|
||||||
| ⛔ PRS - Price Relative Strength ||||
|
| ⛔ PRS - Price Relative Strength ||||
|
||||||
| ⛔ PVOL - Price-Volume |||||
|
| ⛔ PVOL - Price-Volume |||||
|
||||||
|
|||||||
Reference in New Issue
Block a user