0.1.21 MAMA

This commit is contained in:
Miha Kralj
2022-11-17 22:10:11 -08:00
59 changed files with 1648 additions and 1625 deletions
+7 -1
View File
@@ -3,10 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32210.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuanTAlib", "Source\QuanTAlib.csproj", "{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuanTAlib", "Source\QuanTAlib.csproj", "{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quantower", "Quantower\Quantower.csproj", "{693713F9-F33A-4B33-8F98-63794CA9734C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|Any CPU.Build.0 = Release|Any CPU
{693713F9-F33A-4B33-8F98-63794CA9734C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{693713F9-F33A-4B33-8F98-63794CA9734C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{693713F9-F33A-4B33-8F98-63794CA9734C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{693713F9-F33A-4B33-8F98-63794CA9734C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+2 -2
View File
@@ -19,13 +19,13 @@ public class ENTP_chart : Indicator
private TBars bars;
///////
private ENTP_Series indicator;
private ENTROPY_Series indicator;
///////
public ENTP_chart()
{
this.SeparateWindow = true;
this.Name = "ENTP - Entropy (Unpredictability)";
this.Name = "ENTROPY - Entropy (Unpredictability)";
this.Description = "Entropy description";
this.AddLineSeries("ENTROPY", Color.RoyalBlue, 3, LineStyle.Solid);
}
+2 -2
View File
@@ -19,13 +19,13 @@ public class KURT_chart : Indicator
private TBars bars;
///////
private KURT_Series indicator;
private KURTOSIS_Series indicator;
///////
public KURT_chart()
{
this.SeparateWindow = true;
this.Name = "KURT - Kurtosis (Flatness)";
this.Name = "KURTOSIS - Kurtosis (Flatness)";
this.Description = "Kurtosis description";
this.AddLineSeries("KURTOSIS", Color.RoyalBlue, 3, LineStyle.Solid);
}
+1 -1
View File
@@ -19,7 +19,7 @@ public class MED_chart : Indicator
private TBars bars;
///////
private MED_Series indicator;
private MEDIAN_Series indicator;
///////
public MED_chart()
+4
View File
@@ -13,6 +13,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<Nullable>disable</Nullable>
<SignAssembly>False</SignAssembly>
<CodeAnalysisRuleSet>..\.sonarlint\mihakralj_quantalibcsharp.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize>
@@ -36,6 +37,9 @@
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles=".\bin\$(Configuration)\net48\Quantower_QTAlib.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
</Target>
<ItemGroup>
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
</ItemGroup>
<ItemGroup>
<Reference Include="TradingPlatform.BusinessLayer">
<HintPath>C:\Quantower\TradingPlatform\v1.124.6\bin\TradingPlatform.BusinessLayer.dll</HintPath>
+1 -2
View File
@@ -23,8 +23,7 @@ public class ADD_Series : Pair_TSeries_Indicator
public override void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update)
{
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,
TValue1.v+TValue2.v);
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v+TValue2.v);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
}
}
+4 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MAX - Maximum value in the given period in the series.
@@ -16,18 +17,9 @@ public class MAX_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _max = _buffer.Max();
double _max = TValue.v;
for (int i = 0; i < this._buffer.Count; i++)
{
_max = Math.Max(this._buffer[i], _max);
}
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
base.Add(result, update);
base.Add((TValue.t, _max), update, _NaN);
}
}
+2 -9
View File
@@ -21,12 +21,7 @@ public class MIDPOINT_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update)
{
if (update)
{ this._buffer[this._buffer.Count - 1] = TValue.v; }
else
{ this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0)
{ this._buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _max = TValue.v;
double _min = TValue.v;
@@ -37,8 +32,6 @@ public class MIDPOINT_Series : Single_TSeries_Indicator
}
double _mid = (_max + _min) * 0.5;
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid);
base.Add(result, update);
base.Add((TValue.t, _mid), update, _NaN);
}
}
+6 -24
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series.
@@ -19,32 +20,13 @@ public class MIDPRICE_Series : Single_TBars_Indicator
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update)
{
this._bufferhi[this._bufferhi.Count - 1] = TBar.h;
this._bufferlo[this._bufferlo.Count - 1] = TBar.l;
}
else
{
this._bufferhi.Add(TBar.h);
this._bufferlo.Add(TBar.l);
}
if (this._bufferhi.Count > this._p && this._p != 0)
{ this._bufferhi.RemoveAt(0); }
if (this._bufferlo.Count > this._p && this._p != 0)
{ this._bufferlo.RemoveAt(0); }
Add_Replace_Trim(_bufferhi, TBar.h, _p, update);
Add_Replace_Trim(_bufferlo, TBar.l, _p, update);
double _max = TBar.h;
double _min = TBar.l;
for (int i = 0; i < this._bufferhi.Count; i++)
{
_max = Math.Max(this._bufferhi[i], _max);
_min = Math.Min(this._bufferlo[i], _min);
}
double _max = _bufferhi.Max();
double _min = _bufferlo.Min();
double _mid = (_max + _min) * 0.5;
var result = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid);
base.Add(result, update);
base.Add((TBar.t, _mid), update, _NaN);
}
}
+4 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MIN - Minimum value in the given period in the series.
@@ -16,18 +17,9 @@ public class MIN_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _min = TValue.v;
for (int i = 0; i < this._buffer.Count; i++)
{
_min = Math.Min(this._buffer[i], _min);
}
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _min);
base.Add(result, update);
double _min = _buffer.Min();
base.Add((TValue.t, _min), update, _NaN);
}
}
@@ -1,148 +1,112 @@
namespace QuanTAlib;
using System;
/* <summary>
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods.
Indicator classess need to implement:
- Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
- optional Add(series) bulk insert class (for optimization of historical analysis)
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
</summary> */
public abstract class Single_TSeries_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _data;
// 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)
{
this._data = source;
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 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);
}
public abstract class Pair_TSeries_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _d1;
protected readonly TSeries _d2;
protected readonly double _dd1, _dd2;
// Chainable Constructors - add them at the end of primary constructors if needed
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN)
{
this._p = period;
this._NaN = useNaN;
this._d1 = source1;
this._d2 = source2;
this._dd1 = double.NaN;
this._dd2 = double.NaN;
this._d1.Pub += this.Sub;
this._d2.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
{
this._d1 = source1;
this._d2 = source2;
this._dd1 = double.NaN;
this._dd2 = double.NaN;
this._d1.Pub += this.Sub;
this._d2.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, double dd2)
{
this._d1 = source1;
this._d2 = new();
this._dd1 = double.NaN;
this._dd2 = dd2;
this._d1.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(double dd1, TSeries source2)
{
this._d1 = new();
this._d2 = source2;
this._dd1 = dd1;
this._dd2 = double.NaN;
this._d2.Pub += this.Sub;
}
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) => base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
public virtual void Add(TSeries d1, TSeries d2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); }}
public virtual void Add(TSeries d1, double dd2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }}
public virtual void Add(double dd1, TSeries d2) { for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }}
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
public void Add(bool update)
{
if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN))
{
// (Series, Series)
if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count))
{ this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); }
}
else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN))
{
// (Series, Double)
this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update);
}
else
{
// (Double, Series)
this.Add(TValue1: (this._d2[this._d2.Count - 1].t, this._dd1), TValue2: this._d2[this._d2.Count - 1], update: update);
}
}
public void Add() => this.Add(update: false);
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
}
public abstract class Single_TBars_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TBars _bars;
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
{
this._p = period;
this._bars = source;
this._NaN = useNaN;
this._bars.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 o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update);
// potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo)
public virtual void Add(TBars bars) { for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); }}
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }}
public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar) => this.Add(TBar: TBar, update: false);
public void Add(bool update) => this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
public void Add() => this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
}
namespace QuanTAlib;
using System;
using System.Collections.Generic;
/* <summary>
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods.
Indicator classess need to implement:
- Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
- optional Add(series) bulk insert class (for optimization of historical analysis)
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
</summary> */
public abstract class Pair_TSeries_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _d1;
protected readonly TSeries _d2;
protected readonly double _dd1, _dd2;
// Chainable Constructors - add them at the end of primary constructors if needed
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN)
{
this._p = period;
this._NaN = useNaN;
this._d1 = source1;
this._d2 = source2;
this._dd1 = double.NaN;
this._dd2 = double.NaN;
this._d1.Pub += this.Sub;
this._d2.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
{
this._d1 = source1;
this._d2 = source2;
this._dd1 = double.NaN;
this._dd2 = double.NaN;
this._d1.Pub += this.Sub;
this._d2.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, double dd2)
{
this._d1 = source1;
this._d2 = new();
this._dd1 = double.NaN;
this._dd2 = dd2;
this._d1.Pub += this.Sub;
}
protected Pair_TSeries_Indicator(double dd1, TSeries source2)
{
this._d1 = new();
this._d2 = source2;
this._dd1 = dd1;
this._dd2 = double.NaN;
this._d2.Pub += this.Sub;
}
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) => base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
public virtual void Add(TSeries d1, TSeries d2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); }}
public virtual void Add(TSeries d1, double dd2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }}
public virtual void Add(double dd1, TSeries d2) { for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }}
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
public void Add(bool update)
{
if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN))
{
// (Series, Series)
if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count))
{ this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); }
}
else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN))
{
// (Series, Double)
this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update);
}
else
{
// (Double, Series)
this.Add(TValue1: (this._d2[this._d2.Count - 1].t, this._dd1), TValue2: this._d2[this._d2.Count - 1], update: update);
}
}
public void Add() => this.Add(update: false);
public new void Sub(object source, TSeriesEventArgs e) => this.Add(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); }
}
}
+66
View File
@@ -0,0 +1,66 @@
namespace QuanTAlib;
using System;
using System.Collections.Generic;
/* <summary>
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods.
Indicator classess need to implement:
- Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
- optional Add(series) bulk insert class (for optimization of historical analysis)
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
</summary> */
public abstract class Single_TBars_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TBars _bars;
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
{
this._p = period;
this._bars = source;
this._NaN = useNaN;
this._bars.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 o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update);
public virtual void Add((System.DateTime t, double v) TValue, bool update, bool useNaN)
{
var res = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : TValue.v);
base.Add(res, update);
}
// potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo)
public virtual void Add(TBars bars) { for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); }}
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }}
public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar) => this.Add(TBar: TBar, update: false);
public void Add(bool update) => this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
public void Add() => this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
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); }
}
}
+63
View File
@@ -0,0 +1,63 @@
namespace QuanTAlib;
using System;
using System.Collections.Generic;
/* <summary>
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods.
Indicator classess need to implement:
- Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
- optional Add(series) bulk insert class (for optimization of historical analysis)
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
</summary> */
public abstract class Single_TSeries_Indicator : TSeries
{
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _data;
// 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)
{
this._data = source;
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)
{
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); }
}
}
+1 -2
View File
@@ -17,12 +17,11 @@ public class Alphavantage_Feed : TBars
public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo")
{
System.Net.Http.HttpClient client = new();
JsonElement json = new();
string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey;
var msg = client.GetStringAsync(req).Result;
var jres = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement;
jres.TryGetProperty("Time Series (Daily)", out json);
jres.TryGetProperty("Time Series (Daily)", out JsonElement json);
if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); }
foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); }
+4 -3
View File
@@ -9,12 +9,13 @@ Yahoo Finance - Free API feed to collect daily market quotes
Period: number of days of collected history (default: 252)
Usage:
Yahoo_Feed ticker = new("MSFT", 20)
</summary> */
public class Yahoo_Feed : TBars
{
public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
Period = (int)(Period*1.45);
string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
Symbol+"?interval=1d&period1="+
(int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+
@@ -22,7 +23,7 @@ public class Yahoo_Feed : TBars
System.Net.Http.HttpClient client = new();
var msg = client.GetStringAsync(requestUrl).Result;
var jresult = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement;
jresult.TryGetProperty("chart",out JsonElement json);
json.TryGetProperty("result",out json);
json[0].TryGetProperty("timestamp",out JsonElement datetime);
@@ -33,7 +34,7 @@ public class Yahoo_Feed : TBars
json[0].TryGetProperty("low",out JsonElement low);
json[0].TryGetProperty("close",out JsonElement close);
json[0].TryGetProperty("volume",out JsonElement volume);
for (int i=0; i<datetime.GetArrayLength(); i++) {
DateTime d = DateTimeOffset.FromUnixTimeSeconds(long.Parse(datetime[i].GetRawText())).DateTime;
double o = Math.Round(double.Parse(open[i].GetRawText()),3);
+6 -6
View File
@@ -1,5 +1,7 @@
namespace QuanTAlib;
using System;
using System.Linq;
using static System.Net.Mime.MediaTypeNames;
/* <summary>
CCI: Commodity Channel Index
@@ -32,18 +34,16 @@ public class CCI_Series : Single_TBars_Indicator
if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
// average TP over _tp buffer
double _avgTp = 0;
for (int i = 0; i < this._tp.Count; i++) { _avgTp+=this._tp[i]; }
_avgTp /= this._tp.Count;
double _avgTp = _tp.Average();
// average Deviation over _tp buffer
double _avgDv = 0;
for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
_avgDv /= this._tp.Count;
double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv);
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _cci);
base.Add(result, update);
}
base.Add((TBar.t, _cci), update, _NaN);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>QuanTAlib</Title>
<Version>0.1.20</Version>
<Version>0.1.21</Version>
<Product>Library of Technical Indicators for .NET</Product>
<Description>Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis</Description>
<RepositoryType>git</RepositoryType>
+5 -10
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
BIAS: Rate of change between the source and a moving average.
@@ -23,17 +24,11 @@ public class BIAS_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = 0;
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; }
_sma /= this._buffer.Count;
double _bias = (this._buffer[this._buffer.Count - 1] / ((_sma != 0) ? _sma : 1)) - 1;
double _sma = _buffer.Average();
double _bias = (_buffer[_buffer.Count - 1] / ((_sma != 0) ? _sma : 1)) - 1;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _bias);
base.Add(result, update);
base.Add((TValue.t, _bias), update, _NaN);
}
}
+35 -53
View File
@@ -1,5 +1,7 @@
namespace QuanTAlib;
using System;
using System.Collections.Generic;
using System.Linq;
/* <summary>
CORR: Pearson's Correlation Coefficient
@@ -14,57 +16,37 @@ Sources:
</summary> */
public class CORR_Series : Pair_TSeries_Indicator
{
public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
{
if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
}
private readonly System.Collections.Generic.List<double> _x = new();
private readonly System.Collections.Generic.List<double> _xx = new();
private readonly System.Collections.Generic.List<double> _y = new();
private readonly System.Collections.Generic.List<double> _yy = new();
private readonly System.Collections.Generic.List<double> _xy = new();
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
if (update)
{
_x[_x.Count - 1] = TValue1.v;
_xx[_xx.Count - 1] = TValue1.v * TValue1.v;
_y[_y.Count - 1] = TValue2.v;
_y[_yy.Count - 1] = TValue2.v * TValue2.v;
_xy[_xy.Count - 1] = TValue1.v * TValue2.v;
}
else
{
_x.Add(TValue1.v);
_xx.Add(TValue1.v * TValue1.v);
_y.Add(TValue2.v);
_yy.Add(TValue2.v * TValue2.v);
_xy.Add(TValue1.v * TValue2.v);
}
if (_x.Count > this._p) { _x.RemoveAt(0); }
if (_xx.Count > this._p) { _xx.RemoveAt(0); }
if (_y.Count > this._p) { _y.RemoveAt(0); }
if (_yy.Count > this._p) { _yy.RemoveAt(0); }
if (_xy.Count > this._p) { _xy.RemoveAt(0); }
double _sumx = 0;
for (int i = 0; i < _x.Count; i++) { _sumx += _x[i]; }
double _sumxx = 0;
for (int i = 0; i < _xx.Count; i++) { _sumxx += _xx[i]; }
double _sumy = 0;
for (int i = 0; i < _y.Count; i++) { _sumy += _y[i]; }
double _sumyy = 0;
for (int i = 0; i < _yy.Count; i++) { _sumyy += _yy[i]; }
double _sumxy = 0;
for (int i = 0; i < _xy.Count; i++) { _sumxy += _xy[i]; }
double _div = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
double _cor = (_div != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_div) : 0.0;
var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
{
public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
{
if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
}
}
private readonly System.Collections.Generic.List<double> _x = new();
private readonly System.Collections.Generic.List<double> _xx = new();
private readonly System.Collections.Generic.List<double> _y = new();
private readonly System.Collections.Generic.List<double> _yy = new();
private readonly System.Collections.Generic.List<double> _xy = new();
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
Add_Replace_Trim(_x, TValue1.v, _p, update);
Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update);
Add_Replace_Trim(_y, TValue2.v, _p, update);
Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update);
Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
double _sumx = _x.Sum();
double _sumxx = _xx.Sum();
double _sumy = _y.Sum();
double _sumyy = _yy.Sum();
double _sumxy = _xy.Sum();
double _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
double _cor = (_covar != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_covar) : 0.0;
var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
}
}
+9 -36
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
COVAR: Covariance
@@ -19,49 +20,21 @@ public class COVAR_Series : Pair_TSeries_Indicator
}
private readonly System.Collections.Generic.List<double> _x = new();
private readonly System.Collections.Generic.List<double> _xx = new();
private readonly System.Collections.Generic.List<double> _y = new();
private readonly System.Collections.Generic.List<double> _yy = new();
private readonly System.Collections.Generic.List<double> _xy = new();
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
if (update)
{
_x[_x.Count - 1] = TValue1.v;
_xx[_xx.Count - 1] = TValue1.v * TValue1.v;
_y[_y.Count - 1] = TValue2.v;
_y[_yy.Count - 1] = TValue2.v * TValue2.v;
_xy[_xy.Count - 1] = TValue1.v * TValue2.v;
}
else
{
_x.Add(TValue1.v);
_xx.Add(TValue1.v * TValue1.v);
_y.Add(TValue2.v);
_yy.Add(TValue2.v * TValue2.v);
_xy.Add(TValue1.v * TValue2.v);
}
if (_x.Count > this._p) { _x.RemoveAt(0); }
if (_xx.Count > this._p) { _xx.RemoveAt(0); }
if (_y.Count > this._p) { _y.RemoveAt(0); }
if (_yy.Count > this._p) { _yy.RemoveAt(0); }
if (_xy.Count > this._p) { _xy.RemoveAt(0); }
Add_Replace_Trim(_x, TValue1.v, _p, update);
Add_Replace_Trim(_y, TValue2.v, _p, update);
Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
double _sumx = 0;
for (int i = 0; i < _x.Count; i++) { _sumx += _x[i]; }
double _sumxx = 0;
for (int i = 0; i < _xx.Count; i++) { _sumxx += _xx[i]; }
double _sumy = 0;
for (int i = 0; i < _y.Count; i++) { _sumy += _y[i]; }
double _sumyy = 0;
for (int i = 0; i < _yy.Count; i++) { _sumyy += _yy[i]; }
double _sumxy = 0;
for (int i = 0; i < _xy.Count; i++) { _sumxy += _xy[i]; }
double _covar = (_sumxy / _p) - ((_sumx / _p) * (_sumy / _p));
double _avgx = _x.Average();
double _avgy = _y.Average();
double _avgxy = _xy.Average();
double _covar = _avgxy - (_avgx * _avgy);
var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _covar);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
}
}
}
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
ENTP: Entropy
@@ -16,9 +17,9 @@ Sources:
</summary> */
public class ENTP_Series : Single_TSeries_Indicator
public class ENTROPY_Series : Single_TSeries_Indicator
{
public ENTP_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
public ENTROPY_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
{
this._logbase = logbase;
if (base._data.Count > 0) { base.Add(base._data); }
@@ -29,24 +30,15 @@ public class ENTP_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _sum = 0;
for (int i = 0; i < this._buffer.Count; i++) { _sum += this._buffer[i]; }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sum = _buffer.Sum();
double _pp = this._buffer[this._buffer.Count - 1] / _sum;
double _ppp = -_pp * Math.Log(_pp) / Math.Log(this._logbase);
if (update) { this._buff2[this._buff2.Count - 1] = _ppp; }
else { this._buff2.Add(_ppp); }
if (this._buff2.Count > this._p && this._p != 0) { this._buff2.RemoveAt(0); }
Add_Replace_Trim(_buff2, _ppp, _p, update);
double _entp = _buff2.Sum();
double _entp = 0;
for (int i = 0; i < this._buff2.Count; i++) { _entp += this._buff2[i]; }
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _entp);
base.Add(result, update);
base.Add((TValue.t, _entp), update, _NaN);
}
}
@@ -1,62 +1,57 @@
namespace QuanTAlib;
using System;
/* <summary>
KURT: Kurtosis of population
Kurtosis characterizes the relative peakedness or flatness of a distribution
compared with the normal distribution. Positive kurtosis indicates a relatively
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
The normal curve is called Mesokurtic curve. If the curve of a distribution is
more outlier prone (or heavier-tailed) than a normal or mesokurtic curve then
it is referred to as a Leptokurtic curve. If a curve is less outlier prone (or
lighter-tailed) than a normal curve, it is called as a platykurtic curve.
Calculation:
sum4 = Σ(close-SMA)^4
sum2 = (Σ(close-SMA)^2)^2
KURT = length * (sum4/sum2)
Sources:
https://en.wikipedia.org/wiki/Kurtosis
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
</summary> */
public class KURT_Series : Single_TSeries_Indicator
{
public KURT_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
{
this._logbase = logbase;
if (base._data.Count > 0) { base.Add(base._data); }
}
protected double _logbase;
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _n = this._buffer.Count;
double _avg = 0;
for (int i = 0; i < this._buffer.Count; i++) { _avg += this._buffer[i]; }
_avg /= _n;
double _s2 = 0;
double _s4 = 0;
for (int i = 0; i < this._buffer.Count; i++)
{
_s2 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
_s4 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
}
double _Vx = _s2 / (_n - 1);
double _kurt = (_n > 3) ? ((((_n * (_n + 1)) / (((_n - 1) * (_n - 2)) * (_n - 3))) * (_s4 / (_Vx * _Vx))) - (3 * (((_n - 1) * (_n - 1)) / ((_n - 2) * (_n - 3))))) : Double.NaN;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
base.Add(result, update);
}
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
KURT: Kurtosis of population
Kurtosis characterizes the relative peakedness or flatness of a distribution
compared with the normal distribution. Positive kurtosis indicates a relatively
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
The normal curve is called Mesokurtic curve. If the curve of a distribution is
more outlier prone (or heavier-tailed) than a normal or mesokurtic curve then
it is referred to as a Leptokurtic curve. If a curve is less outlier prone (or
lighter-tailed) than a normal curve, it is called as a platykurtic curve.
Calculation:
sum4 = Σ(close-SMA)^4
sum2 = (Σ(close-SMA)^2)^2
KURT = length * (sum4/sum2)
Sources:
https://en.wikipedia.org/wiki/Kurtosis
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
</summary> */
public class KURTOSIS_Series : Single_TSeries_Indicator
{
public KURTOSIS_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
{
this._logbase = logbase;
if (base._data.Count > 0) { base.Add(base._data); }
}
protected double _logbase;
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _n = this._buffer.Count;
double _avg = _buffer.Average();
double _s2 = 0;
double _s4 = 0;
for (int i = 0; i < this._buffer.Count; i++)
{
_s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg);
_s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg);
}
double _Vx = _s2 / (_n - 1);
double _kurt = (_n > 3) ? ((((_n * (_n + 1)) / (((_n - 1) * (_n - 2)) * (_n - 3))) * (_s4 / (_Vx * _Vx))) - (3 * (((_n - 1) * (_n - 1)) / ((_n - 2) * (_n - 3))))) : Double.NaN;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
base.Add(result, update);
}
}
+2 -4
View File
@@ -34,9 +34,7 @@ public class LINREG_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
int _len = this._buffer.Count;
@@ -79,7 +77,7 @@ public class LINREG_Series : Single_TSeries_Indicator
double _RSquared = arrr * arrr;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope);
base.Add(ret, update);
base.Add(ret, update, _NaN);
ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
Intercept.Add(ret, update);
+4 -8
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MAD: Mean Absolute Deviation
@@ -24,19 +25,14 @@ public class MAD_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
double _sma = _buffer.Average();
double _mad = 0;
for (int i = 0; i < _buffer.Count; i++) { _mad += Math.Abs(_buffer[i] - _sma); }
_mad /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _mad);
base.Add(result, update);
base.Add((TValue.t, _mad), update, _NaN);
}
}
+8 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MAPE: Mean Absolute Percentage Error
@@ -27,19 +28,15 @@ public class MAPE_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _mape = 0;
for (int i = 0; i < _buffer.Count; i++) { _mape += (_buffer[i] != 0) ? Math.Abs(_buffer[i] - _sma) / Math.Abs(_buffer[i]) : double.PositiveInfinity; }
_mape /= this._buffer.Count;
for (int i = 0; i < _buffer.Count; i++) {
_mape += (_buffer[i] != 0) ? Math.Abs(_buffer[i] - _sma) / Math.Abs(_buffer[i]) : double.PositiveInfinity;
}
_mape /= (_buffer.Count>0) ? _buffer.Count : 1;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _mape);
base.Add(result, update);
base.Add((TValue.t, _mape), update, _NaN);
}
}
@@ -1,47 +1,44 @@
namespace QuanTAlib;
using System;
/* <summary>
MED - Median value
Median of numbers is the middlemost value of the given set of numbers.
It separates the higher half and the lower half of a given data sample.
At least half of the observations are smaller than or equal to median
and at least half of the observations are greater than or equal to the median.
If the number of values is odd, the middlemost observation of the sorted
list is the median of the given data. If the number of values is even,
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
If period = 0 => period is max
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
https://en.wikipedia.org/wiki/Median
</summary> */
public class MED_Series : Single_TSeries_Indicator
{
public MED_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
{
if (base._data.Count > 0) { base.Add(base._data); }
}
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
System.Collections.Generic.List<double> _s = new(this._buffer);
_s.Sort();
int _p1 = _s.Count / 2;
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med);
base.Add(result, update);
}
}
namespace QuanTAlib;
using System;
using static System.Net.Mime.MediaTypeNames;
/* <summary>
MED - Median value
Median of numbers is the middlemost value of the given set of numbers.
It separates the higher half and the lower half of a given data sample.
At least half of the observations are smaller than or equal to median
and at least half of the observations are greater than or equal to the median.
If the number of values is odd, the middlemost observation of the sorted
list is the median of the given data. If the number of values is even,
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
If period = 0 => period is max
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
https://en.wikipedia.org/wiki/Median
</summary> */
public class MEDIAN_Series : Single_TSeries_Indicator
{
public MEDIAN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
{
if (base._data.Count > 0) { base.Add(base._data); }
}
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{
Add_Replace_Trim(_buffer, TValue.v, _p, update);
System.Collections.Generic.List<double> _s = new(this._buffer);
_s.Sort();
int _p1 = _s.Count / 2;
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
base.Add((TValue.t, _med), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
MSE: Mean Square Error
@@ -20,19 +21,13 @@ public class MSE_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _mse = 0;
for (int i = 0; i < _buffer.Count; i++) { _mse += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_mse /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _mse);
base.Add(result, update);
base.Add((TValue.t, _mse), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SDEV: Population Standard Deviation
@@ -25,20 +26,14 @@ public class SDEV_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_pvar /= this._buffer.Count;
double _psdev = Math.Sqrt(_pvar);
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _psdev);
base.Add(result, update);
base.Add((TValue.t, _psdev), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SMAPE: Symmetric Mean Absolute Percentage Error
@@ -20,19 +21,13 @@ public class SMAPE_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _smape = 0;
for (int i = 0; i < _buffer.Count; i++) { _smape += Math.Abs(_buffer[i] - _sma) / (Math.Abs(_buffer[i]) + Math.Abs(_sma)); }
_smape /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _smape);
base.Add(result, update);
base.Add((TValue.t, _smape), update, _NaN);
}
}
+6 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SSDEV: (Corrected) Sample Standard Deviation
@@ -25,20 +26,14 @@ public class SSDEV_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _svar = 0;
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
_svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
for (int i = 0; i < this._buffer.Count; i++) { _svar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_svar /= (_buffer.Count > 1) ? _buffer.Count - 1 : 1; // Bessel's correction
double _ssdev = Math.Sqrt(_svar);
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ssdev);
base.Add(result, update);
base.Add((TValue.t, _ssdev), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SVAR: Sample Variance
@@ -25,19 +26,13 @@ public class SVAR_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _svar = 0;
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
_svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _svar);
base.Add(result, update);
base.Add((TValue.t, _svar), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
VAR: Population Variance
@@ -25,19 +26,13 @@ public class VAR_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_pvar /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _pvar);
base.Add(result, update);
base.Add((TValue.t, _pvar), update, _NaN);
}
}
+8 -11
View File
@@ -1,9 +1,12 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
WMAPE: Weighted Mean Absolute Percentage Error
Measures the size of the error in percentage terms
Measures the size of the error in percentage terms. Improves problems with MAPE
when there are zero or close-to-zero values because there would be a division by zero
or values of MAPE tending to infinity.
Sources:
https://en.wikipedia.org/wiki/WMAPE
@@ -20,13 +23,8 @@ public class WMAPE_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _div = 0;
double _wmape = 0;
@@ -35,9 +33,8 @@ public class WMAPE_Series : Single_TSeries_Indicator
_wmape += Math.Abs(_buffer[i] - _sma);
_div += Math.Abs(_buffer[i]);
}
_wmape /= _div;
_wmape = (_div!=0) ? _wmape/_div : double.PositiveInfinity;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _wmape);
base.Add(result, update);
base.Add((TValue.t, _wmape), update, _NaN);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
ZSCORE: number of standard deviations from SMA
@@ -31,13 +32,8 @@ public class ZSCORE_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
@@ -45,7 +41,6 @@ public class ZSCORE_Series : Single_TSeries_Indicator
double _psdev = Math.Sqrt(_pvar);
double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _zscore);
base.Add(result, update);
base.Add((TValue.t, _zscore), update, _NaN);
}
}
+41 -45
View File
@@ -19,49 +19,45 @@ TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma
</summary> */
public class ALMA_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double[] _weight;
private double _norm;
private readonly double _offset, _sigma;
public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
: base(source, period, useNaN)
{
_offset = offset;
_sigma = sigma;
_weight = new double[period];
if (this._data.Count > 0) { base.Add(this._data); }
}
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
if (this._buffer.Count <= _p) { calc_weights(); }
double _weightedSum = 0;
for (int i = 0; i < this._buffer.Count; i++) { _weightedSum += _weight[i] * _buffer[i]; }
double _alma = _weightedSum / _norm;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _alma);
base.Add(ret, update);
}
private void calc_weights()
{
int _len = this._buffer.Count;
_norm = 0;
double _m = _offset * (_len - 1);
double _s = _len / _sigma;
for (int i = 0; i < _len; i++)
{
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
_weight[i] = _wt;
_norm += _wt;
}
}
{
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double[] _weight;
private double _norm;
private readonly double _offset, _sigma;
public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
: base(source, period, useNaN)
{
_offset = offset;
_sigma = sigma;
_weight = new double[period];
if (this._data.Count > 0) { base.Add(this._data); }
}
public override void Add((System.DateTime t, double v) TValue, bool update)
{
Add_Replace_Trim(_buffer, TValue.v, _p, update);
if (this._buffer.Count <= _p)
{
int _len = this._buffer.Count;
_norm = 0;
double _m = _offset * (_len - 1);
double _s = _len / _sigma;
for (int i = 0; i < _len; i++)
{
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
_weight[i] = _wt;
_norm += _wt;
}
}
double _weightedSum = 0;
for (int i = 0; i < this._buffer.Count; i++)
{ _weightedSum += _weight[i] * _buffer[i]; }
double _alma = _weightedSum / _norm;
base.Add((TValue.t, _alma), update, _NaN);
}
}
+4 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
DEMA: Double Exponential Moving Average
@@ -41,16 +42,9 @@ public class DEMA_Series : Single_TSeries_Indicator
if (this.Count < this._p)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else
{
_buffer.Add(TValue.v);
}
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
_ema1 = _ema2 = _sma;
}
else
@@ -65,7 +59,6 @@ public class DEMA_Series : Single_TSeries_Indicator
this._lastema1 = _ema1;
this._lastema2 = _ema2;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _dema);
base.Add(ret, update);
base.Add((TValue.t, _dema), update, _NaN);
}
}
+5 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
EMA: Exponential Moving Average
@@ -35,20 +36,13 @@ public class EMA_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update)
{
double _ema = 0;
double _ema;
if (update) { this._lastema = this._lastlastema; }
if (this.Count < this._p)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else
{
this._buffer.Add(TValue.v);
}
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
for (int i = 0; i < this._buffer.Count; i++) { _ema += this._buffer[i]; }
_ema /= this._buffer.Count;
Add_Replace(_buffer, TValue.v, update);
_ema = _buffer.Average();
}
else
{
@@ -58,7 +52,6 @@ public class EMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema;
this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
base.Add(ret, update);
base.Add((TValue.t, _ema), update, _NaN);
}
}
+6 -14
View File
@@ -2,8 +2,8 @@
using System;
/* <summary>
HEMA: Hull-EMA Moving Average
Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation,
HEMA: Hull-EMA Moving Average - a hybrid indicator
Modified HUll Moving Average; instead of using WMA (Weighted MA) for calculation,
HEMA uses EMA for Hull's formula:
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
@@ -39,17 +39,11 @@ public class HEMA_Series : Single_TSeries_Indicator
this._lastema2 = this._lastlastema2;
this._lastema3 = this._lastlastema3;
}
double _ema1 = System.Double.IsNaN(this._lastema1)
? TValue.v
: TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
double _ema2 = System.Double.IsNaN(this._lastema2)
? TValue.v
: TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
double _ema1 = System.Double.IsNaN(this._lastema1) ? TValue.v : TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
double _ema2 = System.Double.IsNaN(this._lastema2) ? TValue.v : TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
double _rawhema = (2 * _ema1) - _ema2;
double _ema3 = System.Double.IsNaN(this._lastema3)
? _rawhema
: _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
double _ema3 = System.Double.IsNaN(this._lastema3) ? _rawhema : _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
this._lastlastema1 = this._lastema1;
this._lastlastema2 = this._lastema2;
@@ -58,8 +52,6 @@ public class HEMA_Series : Single_TSeries_Indicator
this._lastema2 = _ema2;
this._lastema3 = _ema3;
(System.DateTime t, double v) result =
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ema3);
base.Add(result, update);
base.Add((TValue.t, _ema3), update, _NaN);
}
}
+1 -2
View File
@@ -73,7 +73,6 @@ public class HMA_Series : TSeries
{
this._wma1 += this._buf1[i] * this._weights[i];
}
this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
this._wma2 = 0;
@@ -81,7 +80,6 @@ public class HMA_Series : TSeries
{
this._wma2 += this._buf2[i] * this._weights[i];
}
this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
if (update)
@@ -92,6 +90,7 @@ public class HMA_Series : TSeries
{
this._buf3.Add(2 * this._wma1 - this._wma2);
}
if (this._buf3.Count > (int)Math.Sqrt(this._p))
{
this._buf3.RemoveAt(0);
+4 -7
View File
@@ -150,12 +150,9 @@ public class JMA_Series : Single_TSeries_Indicator
double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) +
(this.prev_det1 * alpha * alpha);
this.prev_det1 = det1;
var jma = this.prev_jma + det1;
this.prev_jma = jma;
var _jma = this.prev_jma + det1;
this.prev_jma = _jma;
(System.DateTime t, double v) result =
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma);
base.Add(result, update);
}
base.Add((TValue.t, _jma), update, _NaN);
}
}
+3 -3
View File
@@ -44,6 +44,7 @@ public class KAMA_Series : Single_TSeries_Indicator
_buffer.Add(TValue.v);
}
if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
double _kama = 0;
if (this.Count < this._p) {
for (int i = 0; i < this._buffer.Count; i++) { _kama += this._buffer[i]; }
@@ -59,7 +60,6 @@ public class KAMA_Series : Single_TSeries_Indicator
}
_lastlastkama = _lastkama;
_lastkama = _kama;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama);
base.Add(result, update);
}
base.Add((TValue.t, _kama), update, _NaN);
}
}
+2 -3
View File
@@ -40,7 +40,6 @@ public class MACD_Series : Single_TSeries_Indicator
_TSfast.Add(TValue, true);
}
_macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
var result = (TValue.t, _macd);
base.Add(result, update);
}
base.Add((TValue.t, _macd), update, _NaN);
}
}
+131
View File
@@ -0,0 +1,131 @@
namespace QuanTAlib;
using System;
/* <summary>
MAMA: MESA Adaptive Moving Average
Created by John Ehlers, the MAMA indicator is a 5-period adaptive moving average of
high/low price that uses classic electrical radio-frequency signal processing algorithms
to reduce noise.
KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
Sources:
https://mesasoftware.com/papers/MAMA.pdf
https://www.tradingview.com/script/foQxLbU3-Ehlers-MESA-Adaptive-Moving-Average-LazyBear/
</summary> */
public class MAMA_Series : Single_TSeries_Indicator
{
public MAMA_Series(TSeries source, double fastlimit = 0.5, double slowlimit = 0.05, bool useNaN = false) : base(source, period: 5, useNaN)
{
fastl = fastlimit;
slowl = slowlimit;
i = 0;
if (base._data.Count > 0) { base.Add(base._data); }
}
private int i;
private double sumPr, jI, jQ, fastl, slowl;
private (double i, double i1, double i2, double i3, double i4, double i5, double i6, double io) pr, i1, q1, sm, dt;
private (double i, double i1, double io) i2, q2, re, im, pd, ph, mama, fama;
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) {
i--;
pr.i = pr.i1; pr.i1 = pr.i2; pr.i2 = pr.i3; pr.i3 = pr.i4; pr.i4 = pr.i5; pr.i5 = pr.i6; pr.i6 = pr.io;
i1.i = i1.i1; i1.i1 = i1.i2; i1.i2 = i1.i3; i1.i3 = i1.i4; i1.i4 = i1.i5; i1.i5 = i1.i6; i1.i6 = i1.io;
q1.i = q1.i1; q1.i1 = q1.i2; q1.i2 = q1.i3; q1.i3 = q1.i4; q1.i4 = q1.i5; q1.i5 = q1.i6; q1.i6 = q1.io;
dt.i = dt.i1; dt.i1 = dt.i2; dt.i2 = dt.i3; dt.i3 = dt.i4; dt.i4 = dt.i5; dt.i5 = dt.i6; dt.i6 = dt.io;
sm.i = sm.i1; sm.i1 = sm.i2; sm.i2 = sm.i3; sm.i3 = sm.i4; dt.i4 = sm.i5; sm.i5 = sm.i6; sm.i6 = sm.io;
i2.i = i2.i1; i2.i1 = i2.io;
q2.i = q2.i1; q2.i1 = q2.io;
re.i = re.i1; re.i1 = re.io;
im.i = im.i1; im.i1 = im.io;
pd.i = pd.i1; pd.i1 = pd.io;
ph.i = ph.i1; ph.i1 = ph.io;
mama.i = mama.i1; mama.i1 = mama.io;
fama.i = fama.i1; fama.i1 = fama.io;
}
pr.i = TValue.v;
if (i > 5) {
double adj = (0.075 * pd.i1) + 0.54;
// smooth and detrender
sm.i = ((4 * pr.i) + (3 * pr.i1) + (2 * pr.i2) + pr.i3) / 10;
dt.i = ((0.0962 * sm.i) + (0.5769 * sm.i2) - (0.5769 * sm.i4) - (0.0962 * sm.i6)) * adj;
// in-phase and quadrature
q1.i = ((0.0962 * dt.i) + (0.5769 * dt.i2) - (0.5769 * dt.i4) - (0.0962 * dt.i6)) * adj;
i1.i = dt.i3;
// advance the phases by 90 degrees
jI = ((0.0962 * i1.i) + (0.5769 * i1.i2) - (0.5769 * i1.i4) - (0.0962 * i1.i6)) * adj;
jQ = ((0.0962 * q1.i) + (0.5769 * q1.i2) - (0.5769 * q1.i4) - (0.0962 * q1.i6)) * adj;
// phasor addition for 3-bar averaging
i2.i = i1.i - jQ;
q2.i = q1.i + jI;
i2.i = (0.2 * i2.i) + (0.8 * i2.i1); // smoothing it
q2.i = (0.2 * q2.i) + (0.8 * q2.i1);
// homodyne discriminator
re.i = (i2.i * i2.i1) + (q2.i * q2.i1);
im.i = (i2.i * q2.i1) - (q2.i * i2.i1);
re.i = (0.2 * re.i) + (0.8 * re.i1); // smoothing it
im.i = (0.2 * im.i) + (0.8 * im.i1);
// calculate period
pd.i = (im.i != 0 && re.i != 0) ? (6.283185307179586 / Math.Atan(im.i / re.i)) : 0d;
// adjust period to thresholds
pd.i = (pd.i > 1.5 * pd.i1) ? 1.5 * pd.i1 : pd.i;
pd.i = (pd.i < 0.67 * pd.i1) ? 0.67 * pd.i1 : pd.i;
pd.i = (pd.i < 6d) ? 6d : pd.i;
pd.i = (pd.i > 50d) ? 50d : pd.i;
// smooth the period
pd.i = (0.2 * pd.i) + (0.8 * pd.i1);
// determine phase position
ph.i = (i1.i != 0) ? Math.Atan(q1.i / i1.i) * 57.29577951308232 : 0;
// change in phase
double delta = Math.Max(ph.i1 - ph.i, 1d);
// adaptive alpha value
double alpha = Math.Max(fastl / delta, slowl);
// final indicators
mama.i = ((alpha * pr.i) + ((1d - alpha) * mama.i1));
fama.i = ((0.5d * alpha * mama.i) + ((1d - (0.5d * alpha)) * fama.i1));
}
else {
sumPr += pr.i;
pd.i = sm.i = dt.i = i1.i = q1.i = i2.i = q2.i = re.i = im.i = ph.i = 0;
mama.i = fama.i = sumPr / (i+1);
}
i++;
pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i;
i1.io = i1.i6; i1.i6 = i1.i5; i1.i5 = i1.i4; i1.i4 = i1.i3; i1.i3 = i1.i2; i1.i2 = i1.i1; i1.i1 = i1.i;
q1.io = q1.i6; q1.i6 = q1.i5; q1.i5 = q1.i4; q1.i4 = q1.i3; q1.i3 = q1.i2; q1.i2 = q1.i1; q1.i1 = q1.i;
dt.io = dt.i6; dt.i6 = dt.i5; dt.i5 = dt.i4; dt.i4 = dt.i3; dt.i3 = dt.i2; dt.i2 = dt.i1; dt.i1 = dt.i;
sm.io = sm.i6; sm.i6 = sm.i5; sm.i5 = sm.i4; sm.i4 = sm.i3; sm.i3 = sm.i2; sm.i2 = sm.i1; sm.i1 = sm.i;
i2.io = i2.i1; i2.i1 = i2.i;
q2.io = q2.i1; q2.i1 = q2.i;
re.io = re.i1; re.i1 = re.i;
im.io = im.i1; im.i1 = im.i;
pd.io = pd.i1; pd.i1 = pd.i;
ph.io = ph.i1; ph.i1 = ph.i;
mama.io = mama.i1; mama.i1 = mama.i;
fama.io = fama.i1; fama.i1 = fama.i;
base.Add((TValue.t, mama.i), update, _NaN);
}
}
+6 -13
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
RMA: wildeR Moving Average
@@ -34,20 +35,13 @@ public class RMA_Series : Single_TSeries_Indicator
public override void Add((DateTime t, double v) TValue, bool update)
{
double _ema = 0;
double _ema;
if (update) { this._lastema = this._lastlastema; }
if (this.Count < this._p)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else
{
_buffer.Add(TValue.v);
}
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
_ema /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
_ema = _buffer.Average();
}
else
{
@@ -57,7 +51,6 @@ public class RMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema;
this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
base.Add(ret, update);
}
base.Add((TValue.t, _ema), update, _NaN);
}
}
+4 -10
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SMA: Simple Moving Average
@@ -26,16 +27,9 @@ public class SMA_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Sum() / _buffer.Count;
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sma);
base.Add(result, update);
base.Add((TValue.t, _sma), update, _NaN);
}
}
+5 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
SMMA: Smoothed Moving Average
@@ -34,15 +35,8 @@ public class SMMA_Series : Single_TSeries_Indicator
if (this.Count < this._p)
{
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
else
{
this._buffer.Add(TValue.v);
}
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
for (int i = 0; i < this._buffer.Count; i++) { _smma += this._buffer[i]; }
_smma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
_smma = _buffer.Average();
}
else
{
@@ -52,7 +46,6 @@ public class SMMA_Series : Single_TSeries_Indicator
this._lastlastsmma = this._lastsmma;
this._lastsmma = _smma;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _smma);
base.Add(ret, update);
}
base.Add((TValue.t, _smma), update, _NaN);
}
}
+5 -13
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
TEMA: Triple Exponential Moving Average
@@ -44,16 +45,8 @@ public class TEMA_Series : Single_TSeries_Indicator
if (this.Count < this._p)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else
{
_buffer.Add(TValue.v);
}
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
double _sma = 0;
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _sma = _buffer.Average();
_ema1 = _ema2 = _ema3 = _sma;
}
else
@@ -72,7 +65,6 @@ public class TEMA_Series : Single_TSeries_Indicator
this._lastema2 = _ema2;
this._lastema3 = _ema3;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _tema);
base.Add(ret, update);
}
base.Add((TValue.t, _tema), update, _NaN);
}
}
+5 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
TRIMA: Triangular Moving Average
@@ -31,19 +32,12 @@ public class TRIMA_Series : Single_TSeries_Indicator
{
if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
double _sma1 = 0;
for (int i = 0; i < _buffer1.Count; i++) { _sma1 += _buffer1[i]; }
_sma1 /= this._buffer1.Count;
double _sma1 = _buffer1.Average();
if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
double _trima = _buffer2.Average();
double _trima = 0;
for (int i = 0; i < _buffer2.Count; i++) { _trima += _buffer2[i]; }
_trima /= this._buffer2.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _trima);
base.Add(result, update);
}
base.Add((TValue.t, _trima), update, _NaN);
}
}
+2 -6
View File
@@ -24,16 +24,12 @@ public class WMA_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
Add_Replace_Trim(_buffer, TValue.v, _p, update);
double _wma = 0;
for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
_wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _wma);
base.Add(result, update);
base.Add((TValue.t, _wma), update, _NaN);
}
}
+5 -15
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
ZLEMA: Zero Lag Exponential Moving Average
@@ -45,18 +46,8 @@ public class ZLEMA_Series : Single_TSeries_Indicator
{ this._lastema = this._lastlastema; }
if (this.Count < this._p)
{
if (update)
{ this._buffer[this._buffer.Count - 1] = _zl; }
else
{
this._buffer.Add(_zl);
}
if (this._buffer.Count > this._p)
{ this._buffer.RemoveAt(0); }
for (int i = 0; i < this._buffer.Count; i++)
{ _ema += this._buffer[i]; }
_ema /= this._buffer.Count;
Add_Replace_Trim(_buffer, _zl, _p, update);
_ema = _buffer.Average();
}
else
{
@@ -66,7 +57,6 @@ public class ZLEMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema;
this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
base.Add(ret, update);
}
base.Add((TValue.t, _ema), update, _NaN);
}
}
+2 -3
View File
@@ -37,7 +37,6 @@ public class ADL_Series : Single_TBars_Indicator
this._lastlastadl = this._lastadl;
this._lastadl = _adl;
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl);
base.Add(ret, update);
}
base.Add((TBar.t, _adl), update, _NaN);
}
}
+3 -3
View File
@@ -3,13 +3,13 @@ using System;
using QuanTAlib;
namespace Statistics;
public class KURT_Test
public class KURTOSIS_Test
{
[Fact]
public void Add_Test()
{
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
KURT_Series c = new(a, 3);
KURTOSIS_Series c = new(a, 3);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class KURT_Test
public void Edge_Test()
{
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
KURT_Series c = new(a, 3);
KURTOSIS_Series c = new(a, 3);
Assert.Equal(a.Count, c.Count);
a.Add(double.NaN);
Assert.Equal(a.Count, c.Count);
+2 -2
View File
@@ -9,7 +9,7 @@ public class ENTP_Test
public void Add_Test()
{
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
ENTP_Series c = new(a, 3);
ENTROPY_Series c = new(a, 3);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class ENTP_Test
public void Edge_Test()
{
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
ENTP_Series c = new(a, 3);
ENTROPY_Series c = new(a, 3);
Assert.Equal(a.Count, c.Count);
a.Add(double.NaN);
Assert.Equal(a.Count, c.Count);
+2 -2
View File
@@ -9,7 +9,7 @@ public class MED_Test
public void Add_Test()
{
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
MED_Series c = new(a, 3);
MEDIAN_Series c = new(a, 3);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class MED_Test
public void Edge_Test()
{
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
MED_Series c = new(a, 3);
MEDIAN_Series c = new(a, 3);
Assert.Equal(a.Count, c.Count);
a.Add(double.NaN);
Assert.Equal(a.Count, c.Count);
-4
View File
@@ -15,10 +15,6 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="JetBrains.dotCover.CommandLineTools" Version="2022.3.0-eap07">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0-preview-20221003-04" />
<PackageReference Include="TALib.NETCore" Version="0.4.4" />
<PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" />
+264 -256
View File
@@ -1,198 +1,206 @@
using Xunit;
using System;
using QuanTAlib;
using Python.Runtime;
using Python.Included;
namespace Validations;
public class PandasTA : IDisposable
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly string OStype;
private dynamic np;
private dynamic ta;
private dynamic df;
public PandasTA()
{
bars = new(5000);
period = rnd.Next(28) + 3;
// 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(".");
Installer.SetupPython().Wait();
Installer.TryInstallPip();
Installer.PipInstallModule("pandas-ta");
//alternative: git+https://github.com/twopirllc/pandas-ta
Runtime.PythonDLL = OStype;
PythonEngine.Initialize();
np = Py.Import("numpy");
ta = Py.Import("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));
}
public void Dispose()
{
using Xunit;
using System;
using QuanTAlib;
using Python.Runtime;
using Python.Included;
namespace Validations;
public class PandasTA : IDisposable
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly string OStype;
private readonly dynamic np;
private readonly dynamic ta;
private readonly dynamic df;
public PandasTA()
{
bars = new(5000);
period = rnd.Next(28) + 3;
// 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(".");
Installer.SetupPython().Wait();
Installer.TryInstallPip();
Installer.PipInstallModule("pandas-ta");
//alternative: git+https://github.com/twopirllc/pandas-ta
Runtime.PythonDLL = OStype;
PythonEngine.Initialize();
np = Py.Import("numpy");
ta = Py.Import("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));
}
public void Dispose()
{
PythonEngine.Shutdown();
GC.SuppressFinalize(this);
}
[Fact]
void HL2()
{
var pta = df.ta.hl2(high: df.high, low: df.low);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HL2.Last().v, 4));
}
[Fact]
void HLC3()
{
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HLC3.Last().v, 4));
}
[Fact]
void OHLC4()
{
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.OHLC4.Last().v, 4));
}
[Fact]
void MEDIAN()
{
MED_Series QL = new(bars.Close, period);
var pta = df.ta.median(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void VARIANCE()
{
VAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof:0);
Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
}
[Fact]
void SVARIANCE()
{
SVAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
}
[Fact]
void ADL()
{
ADL_Series QL = new(bars);
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ADOSC()
{
ADOSC_Series QL = new(bars);
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TR()
{
TR_Series QL = new(bars);
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ATR()
{
ATR_Series QL = new(bars, period);
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void RSI()
{
RSI_Series QL = new(bars.Close, period);
var pta = df.ta.rsi(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TRIMA()
{
//TODO: return length to variable length (period) when Pandas-TA fixes trima
TRIMA_Series QL = new(bars.Close, 11);
var pta = df.ta.trima(close: df.close, length: 11);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void KAMA()
{
KAMA_Series QL = new(bars.Close, period);
var pta = df.ta.kama(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void HMA()
{
HMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.hma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.tema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
}
[Fact]
void HL2()
{
var pta = df.ta.hl2(high: df.high, low: df.low);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HL2.Last().v, 4));
}
[Fact]
void HLC3()
{
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HLC3.Last().v, 4));
}
[Fact]
void OHLC4()
{
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.OHLC4.Last().v, 4));
}
[Fact]
void MEDIAN()
{
MEDIAN_Series QL = new(bars.Close, period);
var pta = df.ta.median(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void VARIANCE()
{
VAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof:0);
Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
}
[Fact]
void SVARIANCE()
{
SVAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
}
[Fact]
void ADL()
{
ADL_Series QL = new(bars);
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ADOSC()
{
ADOSC_Series QL = new(bars);
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TR()
{
TR_Series QL = new(bars);
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void OBV()
{
OBV_Series QL = new(bars);
var pta = df.ta.obv(close: df.close, volume: df.volume);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ATR()
{
ATR_Series QL = new(bars, period);
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void RSI()
{
RSI_Series QL = new(bars.Close, period);
var pta = df.ta.rsi(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TRIMA()
{
// TODO: return length to variable length (period) when Pandas-TA fixes trima
TRIMA_Series QL = new(bars.Close, 11);
var pta = df.ta.trima(close: df.close, length: 11);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void KAMA()
{
KAMA_Series QL = new(bars.Close, period);
var pta = df.ta.kama(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void HMA()
{
HMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.hma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.tema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
}
[Fact]
@@ -219,67 +227,67 @@ public class PandasTA : IDisposable
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ENTP()
{
ENTP_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.entropy(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.wma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void RMA()
{
RMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.rma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ZLEMA()
{
ZLEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.zlma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.dema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void BIAS()
{
BIAS_Series QL = new(bars.Close, period, false);
var pta = df.ta.bias(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void KURT()
{
KURT_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.kurtosis(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void MAD()
{
MAD_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.mad(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ENTROPY()
{
ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.entropy(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.wma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void RMA()
{
RMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.rma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void ZLEMA()
{
ZLEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.zlma(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.dema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void BIAS()
{
BIAS_Series QL = new(bars.Close, period, false);
var pta = df.ta.bias(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void KURTOSIS()
{
KURTOSIS_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.kurtosis(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
[Fact]
void MAD()
{
MAD_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.mad(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
}
}
+318 -309
View File
@@ -5,314 +5,323 @@ using Xunit;
namespace Validations;
public class Skender_Stock
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly IEnumerable<Quote> quotes;
public Skender_Stock()
{
bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
period = rnd.Next(28) + 3;
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
});
}
[Fact]
public void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSma(period);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetEma(period);
Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetWma(period);
Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetDema(period);
Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetTema(period);
Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MAD()
{
MAD_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MSE()
{
MSE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MAPE()
{
MAPE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void COVAR()
{
COVAR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
Assert.Equal(Math.Round((double)SK.Last().Covariance!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void CORR()
{
CORR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
Assert.Equal(Math.Round((double)SK.Last().Correlation!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period);
Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(bars, period, false);
var SK = quotes.GetObv(period);
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5),
Math.Round(QL.Last().v, 5));
}
[Fact]
public void ADL()
{
ADL_Series QL = new(bars, false);
var SK = quotes.GetAdl();
Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
}
[Fact]
public void CCI()
{
CCI_Series QL = new(bars, period, false);
var SK = quotes.GetCci(period);
Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ATRP()
{
ATRP_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period);
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void KAMA()
{
KAMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetKama(period);
Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HMA()
{
HMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetHma(period);
Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void SMMA()
{
SMMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSmma(period);
Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MACD()
{
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
var SK = quotes.GetMacd(12, 26, 9);
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
}
[Fact]
public void BBANDS()
{
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
var SK = quotes.GetBollingerBands(period, 2.0);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
}
[Fact]
public void RSI()
{
RSI_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetRsi(period);
Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ALMA()
{
ALMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetAlma(period);
Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void SDEV()
{
SDEV_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ZSCORE()
{
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void LINREG()
{
LINREG_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSlope(period);
Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
}
[Fact]
public void TR()
{
TR_Series QL = new(bars, useNaN: false);
var SK = quotes.GetTr();
Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HL2()
{
TSeries QL = bars.HL2;
var SK = quotes.GetBaseQuote(CandlePart.HL2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OC2()
{
TSeries QL = bars.OC2;
var SK = quotes.GetBaseQuote(CandlePart.OC2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HLC3()
{
TSeries QL = bars.HLC3;
var SK = quotes.GetBaseQuote(CandlePart.HLC3);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OHL3()
{
TSeries QL = bars.OHL3;
var SK = quotes.GetBaseQuote(CandlePart.OHL3);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OHLC4()
{
TSeries QL = bars.OHLC4;
var SK = quotes.GetBaseQuote(CandlePart.OHLC4);
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly IEnumerable<Quote> quotes;
public Skender_Stock()
{
bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
period = rnd.Next(28) + 3;
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
});
}
[Fact]
public void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSma(period);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetEma(period);
Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetWma(period);
Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetDema(period);
Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetTema(period);
Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MAMA() {
MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
Assert.Equal(Math.Round((double)SK.Last().Mama!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MAD()
{
MAD_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MSE()
{
MSE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MAPE()
{
MAPE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void COVAR()
{
COVAR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
Assert.Equal(Math.Round((double)SK.Last().Covariance!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void CORR()
{
CORR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
Assert.Equal(Math.Round((double)SK.Last().Correlation!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period);
Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(bars, period, false);
var SK = quotes.GetObv(period);
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5),
Math.Round(QL.Last().v, 5));
}
[Fact]
public void ADL()
{
ADL_Series QL = new(bars, false);
var SK = quotes.GetAdl();
Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
}
[Fact]
public void CCI()
{
CCI_Series QL = new(bars, period, false);
var SK = quotes.GetCci(period);
Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ATRP()
{
ATRP_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period);
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void KAMA()
{
KAMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetKama(period);
Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HMA()
{
HMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetHma(period);
Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void SMMA()
{
SMMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSmma(period);
Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void MACD()
{
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
var SK = quotes.GetMacd(12, 26, 9);
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
}
[Fact]
public void BBANDS()
{
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
var SK = quotes.GetBollingerBands(period, 2.0);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
}
[Fact]
public void RSI()
{
RSI_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetRsi(period);
Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ALMA()
{
ALMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetAlma(period);
Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void SDEV()
{
SDEV_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void ZSCORE()
{
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void LINREG()
{
LINREG_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSlope(period);
Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
}
[Fact]
public void TR()
{
TR_Series QL = new(bars, useNaN: false);
var SK = quotes.GetTr();
Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HL2()
{
TSeries QL = bars.HL2;
var SK = quotes.GetBaseQuote(CandlePart.HL2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OC2()
{
TSeries QL = bars.OC2;
var SK = quotes.GetBaseQuote(CandlePart.OC2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void HLC3()
{
TSeries QL = bars.HLC3;
var SK = quotes.GetBaseQuote(CandlePart.HLC3);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OHL3()
{
TSeries QL = bars.OHL3;
var SK = quotes.GetBaseQuote(CandlePart.OHL3);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
[Fact]
public void OHLC4()
{
TSeries QL = bars.OHLC4;
var SK = quotes.GetBaseQuote(CandlePart.OHLC4);
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
}
}
+330 -318
View File
@@ -1,318 +1,330 @@
using Xunit;
using System;
using TALib;
using QuanTAlib;
namespace Validations;
public class TA_LIB
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly double[] TALIB;
private readonly double[] inopen;
private readonly double[] inhigh;
private readonly double[] inlow;
private readonly double[] inclose;
private readonly double[] involume;
public TA_LIB()
{
bars = new(5000);
period = rnd.Next(28) + 3;
TALIB = 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 ADD()
{
ADD_Series QL = new(bars.Open, bars.Close);
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SUB()
{
SUB_Series QL = new(bars.Open, bars.Close);
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MUL()
{
MUL_Series QL = new(bars.Open, bars.Close);
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void DIV()
{
DIV_Series QL = new(bars.Open, bars.Close);
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void CORR()
{
CORR_Series QL = new(bars.Open, bars.Close, period);
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SDEV()
{
SDEV_Series QL = new(bars.Close, period, false);
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SUM()
{
SUM_Series QL = new(bars.Close, period, false);
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MIDPRICE()
{
MIDPRICE_Series QL = new(bars, period, false);
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void VAR()
{
VAR_Series QL = new(bars.Close, period, false);
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 4, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 4));
}
[Fact]
public void MIDPOINT()
{
MIDPOINT_Series QL = new(bars.Close, period, false);
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TRIMA()
{
TRIMA_Series QL = new(bars.Close, period, false);
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MAX()
{
MAX_Series QL = new(bars.Close, period, false);
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MIN()
{
MIN_Series QL = new(bars.Close, period, false);
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ADL()
{
ADL_Series QL = new(bars, false);
Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(bars, period, false);
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ADOSC()
{
ADOSC_Series QL = new(bars, false);
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(bars, period, false);
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void CCI()
{
CCI_Series QL = new(bars, period, false);
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void RSI()
{
RSI_Series QL = new(bars.Close, period, false);
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TR()
{
TR_Series QL = new(bars, false);
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MACD()
{
double[] macdSignal = new double[bars.Count];
double[] macdHist = new double[bars.Count];
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void BBANDS()
{
double[] outMiddle = new double[bars.Count];
double[] outUpper = new double[bars.Count];
double[] outLower = new double[bars.Count];
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false);
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Upper.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Mid.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Lower.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HL2()
{
TSeries QL = bars.HL2;
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HLC3()
{
TSeries QL = bars.HLC3;
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void OHLC4()
{
TSeries QL = bars.OHLC4;
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HLCC4()
{
TSeries QL = bars.HLCC4;
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
}
using Xunit;
using System;
using TALib;
using QuanTAlib;
namespace Validations;
public class TA_LIB
{
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period;
private readonly double[] TALIB;
private readonly double[] TALIB2;
private readonly double[] inopen;
private readonly double[] inhigh;
private readonly double[] inlow;
private readonly double[] inclose;
private readonly double[] involume;
public TA_LIB()
{
bars = new(5000);
period = rnd.Next(28) + 3;
TALIB = new double[bars.Count];
TALIB2 = 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 ADD()
{
ADD_Series QL = new(bars.Open, bars.Close);
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SUB()
{
SUB_Series QL = new(bars.Open, bars.Close);
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MUL()
{
MUL_Series QL = new(bars.Open, bars.Close);
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void DIV()
{
DIV_Series QL = new(bars.Open, bars.Close);
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void CORR()
{
CORR_Series QL = new(bars.Open, bars.Close, period);
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SDEV()
{
SDEV_Series QL = new(bars.Close, period, false);
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SMA()
{
SMA_Series QL = new(bars.Close, period, false);
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void SUM()
{
SUM_Series QL = new(bars.Close, period, false);
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MIDPRICE()
{
MIDPRICE_Series QL = new(bars, period, false);
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void VAR()
{
VAR_Series QL = new(bars.Close, period, false);
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 4, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 4));
}
[Fact]
public void MIDPOINT()
{
MIDPOINT_Series QL = new(bars.Close, period, false);
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MAMA() {
MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05);
Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TRIMA()
{
TRIMA_Series QL = new(bars.Close, period, false);
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void EMA()
{
EMA_Series QL = new(bars.Close, period, false);
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void WMA()
{
WMA_Series QL = new(bars.Close, period, false);
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void DEMA()
{
DEMA_Series QL = new(bars.Close, period, false);
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TEMA()
{
TEMA_Series QL = new(bars.Close, period, false);
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MAX()
{
MAX_Series QL = new(bars.Close, period, false);
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MIN()
{
MIN_Series QL = new(bars.Close, period, false);
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ADL()
{
ADL_Series QL = new(bars, false);
Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void OBV()
{
OBV_Series QL = new(bars, period, false);
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ADOSC()
{
ADOSC_Series QL = new(bars, false);
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(bars, period, false);
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void CCI()
{
CCI_Series QL = new(bars, period, false);
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void RSI()
{
RSI_Series QL = new(bars.Close, period, false);
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void TR()
{
TR_Series QL = new(bars, false);
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void MACD()
{
double[] macdSignal = new double[bars.Count];
double[] macdHist = new double[bars.Count];
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void BBANDS()
{
double[] outMiddle = new double[bars.Count];
double[] outUpper = new double[bars.Count];
double[] outLower = new double[bars.Count];
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false);
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Upper.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Mid.Last().v, 6, MidpointRounding.AwayFromZero));
Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Lower.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HL2()
{
TSeries QL = bars.HL2;
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HLC3()
{
TSeries QL = bars.HLC3;
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void OHLC4()
{
TSeries QL = bars.OHLC4;
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
[Fact]
public void HLCC4()
{
TSeries QL = bars.HLCC4;
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
}
}
+2 -3
View File
@@ -17,7 +17,6 @@ Quantitative TA Library (**QuanTAlib**) is an easy-to-use C# library for quantit
**QuanTAlib** is written with some specific design criteria in mind - some reasons why there is '_yet another C# TA library_':
- Written in native C# - no code conversion from TA-LIB or other imported/converted TA libraries
- No usage of Decimal datatypes, LINQ, interface abstractions, or static classes with tons of methods (all for performance reasons)
- Supports both **historical data analysis** (working on bulk of historical arrays) and **real-time analysis** (adding one data item at the time without the need to re-calculate the whole history)
- Calculate early data right - no hiding of incomplete calculations with NaN values (unless explicitly requested with useNan: true), data is as valid as mathematically possible from the first value
- Usage of events - each data series is an event publisher, each indicator is a subscriber - this allows seamless data flow between indicators)
@@ -57,8 +56,8 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⭐ BIAS - Bias | `BIAS_Series` ||| bias |
| ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation ||
| ⭐ COVAR - Covariance | `COVAR_Series` || GetCorrelation ||
| ⭐ ENTP - Entropy | `ENTP_Series` ||| entropy |
| ⭐ KURT - Kurtosis | `KURT_Series` ||| kurtosis |
| ⭐ ENTROPY - Entropy | `ENTROPY_Series` ||| entropy |
| ⭐ KURTOSIS - Kurtosis | `KURT_Series` ||| kurtosis |
| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope ||
| ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma | mad |
| ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma ||