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 # Visual Studio Version 17
VisualStudioVersion = 17.2.32210.308 VisualStudioVersion = 17.2.32210.308
MinimumVisualStudioVersion = 10.0.40219.1 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quantower", "Quantower\Quantower.csproj", "{693713F9-F33A-4B33-8F98-63794CA9734C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+2 -2
View File
@@ -19,13 +19,13 @@ public class ENTP_chart : Indicator
private TBars bars; private TBars bars;
/////// ///////
private ENTP_Series indicator; private ENTROPY_Series indicator;
/////// ///////
public ENTP_chart() public ENTP_chart()
{ {
this.SeparateWindow = true; this.SeparateWindow = true;
this.Name = "ENTP - Entropy (Unpredictability)"; this.Name = "ENTROPY - Entropy (Unpredictability)";
this.Description = "Entropy description"; this.Description = "Entropy description";
this.AddLineSeries("ENTROPY", Color.RoyalBlue, 3, LineStyle.Solid); 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 TBars bars;
/////// ///////
private KURT_Series indicator; private KURTOSIS_Series indicator;
/////// ///////
public KURT_chart() public KURT_chart()
{ {
this.SeparateWindow = true; this.SeparateWindow = true;
this.Name = "KURT - Kurtosis (Flatness)"; this.Name = "KURTOSIS - Kurtosis (Flatness)";
this.Description = "Kurtosis description"; this.Description = "Kurtosis description";
this.AddLineSeries("KURTOSIS", Color.RoyalBlue, 3, LineStyle.Solid); 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 TBars bars;
/////// ///////
private MED_Series indicator; private MEDIAN_Series indicator;
/////// ///////
public MED_chart() public MED_chart()
+4
View File
@@ -13,6 +13,7 @@
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<Nullable>disable</Nullable> <Nullable>disable</Nullable>
<SignAssembly>False</SignAssembly> <SignAssembly>False</SignAssembly>
<CodeAnalysisRuleSet>..\.sonarlint\mihakralj_quantalibcsharp.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize> <Optimize>True</Optimize>
@@ -36,6 +37,9 @@
<Target Name="CopyCustomContent" AfterTargets="AfterBuild"> <Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles=".\bin\$(Configuration)\net48\Quantower_QTAlib.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" /> <Copy SourceFiles=".\bin\$(Configuration)\net48\Quantower_QTAlib.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
</Target> </Target>
<ItemGroup>
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="TradingPlatform.BusinessLayer"> <Reference Include="TradingPlatform.BusinessLayer">
<HintPath>C:\Quantower\TradingPlatform\v1.124.6\bin\TradingPlatform.BusinessLayer.dll</HintPath> <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) 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, (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v+TValue2.v);
TValue1.v+TValue2.v);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); } if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
} }
} }
+4 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MAX - Maximum value in the given period in the series. 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) public override void Add((DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); } double _max = _buffer.Max();
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _max = TValue.v; base.Add((TValue.t, _max), update, _NaN);
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);
} }
} }
+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) public override void Add((DateTime t, double v) TValue, bool update)
{ {
if (update) Add_Replace_Trim(_buffer, TValue.v, _p, 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 _max = TValue.v; double _max = TValue.v;
double _min = TValue.v; double _min = TValue.v;
@@ -37,8 +32,6 @@ public class MIDPOINT_Series : Single_TSeries_Indicator
} }
double _mid = (_max + _min) * 0.5; double _mid = (_max + _min) * 0.5;
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); base.Add((TValue.t, _mid), update, _NaN);
base.Add(result, update);
} }
} }
+6 -24
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series. 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) public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{ {
if (update) Add_Replace_Trim(_bufferhi, TBar.h, _p, update);
{ Add_Replace_Trim(_bufferlo, TBar.l, _p, 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); }
double _max = TBar.h; double _max = _bufferhi.Max();
double _min = TBar.l; double _min = _bufferlo.Min();
for (int i = 0; i < this._bufferhi.Count; i++)
{
_max = Math.Max(this._bufferhi[i], _max);
_min = Math.Min(this._bufferlo[i], _min);
}
double _mid = (_max + _min) * 0.5; double _mid = (_max + _min) * 0.5;
var result = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); base.Add((TBar.t, _mid), update, _NaN);
base.Add(result, update);
} }
} }
+4 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MIN - Minimum value in the given period in the series. 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _min = TValue.v; double _min = _buffer.Min();
for (int i = 0; i < this._buffer.Count; i++) base.Add((TValue.t, _min), update, _NaN);
{
_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);
} }
} }
@@ -1,148 +1,112 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
/* <summary> using System.Collections.Generic;
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods. /* <summary>
Indicator classess need to implement: Abstract classes with all scaffolding required to build indicators.
- Chaining constructor (Abstract's constructor executes first) All abstracts support period, NaN, and all permutations of Add() methods.
- Default Add(value) class Indicator classess need to implement:
- optional Add(series) bulk insert class (for optimization of historical analysis) - Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out. - optional Add(series) bulk insert class (for optimization of historical analysis)
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out. Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
</summary> */ Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
public abstract class Single_TSeries_Indicator : TSeries
{ </summary> */
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _data; public abstract class Pair_TSeries_Indicator : TSeries
{
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN) protected readonly int _p;
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN) protected readonly bool _NaN;
{ protected readonly TSeries _d1;
this._data = source; protected readonly TSeries _d2;
this._p = period; protected readonly double _dd1, _dd2;
this._NaN = useNaN;
this._data.Pub += this.Sub; // Chainable Constructors - add them at the end of primary constructors if needed
} protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN)
{
// overridable Add() method to add/update a single item at the end of the list this._p = period;
public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update); this._NaN = useNaN;
this._d1 = source1;
// potentially overridable Add() method for the whole series (could be replaced with faster bulk algo) this._d2 = source2;
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }} this._dd1 = double.NaN;
this._dd2 = double.NaN;
public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false); this._d1.Pub += this.Sub;
public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update); this._d2.Pub += this.Sub;
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 Pair_TSeries_Indicator(TSeries source1, TSeries source2)
} {
this._d1 = source1;
public abstract class Pair_TSeries_Indicator : TSeries this._d2 = source2;
{ this._dd1 = double.NaN;
protected readonly int _p; this._dd2 = double.NaN;
protected readonly bool _NaN; this._d1.Pub += this.Sub;
protected readonly TSeries _d1; this._d2.Pub += this.Sub;
protected readonly TSeries _d2; }
protected readonly double _dd1, _dd2; protected Pair_TSeries_Indicator(TSeries source1, double dd2)
{
// Chainable Constructors - add them at the end of primary constructors if needed this._d1 = source1;
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN) this._d2 = new();
{ this._dd1 = double.NaN;
this._p = period; this._dd2 = dd2;
this._NaN = useNaN; this._d1.Pub += this.Sub;
this._d1 = source1; }
this._d2 = source2; protected Pair_TSeries_Indicator(double dd1, TSeries source2)
this._dd1 = double.NaN; {
this._dd2 = double.NaN; this._d1 = new();
this._d1.Pub += this.Sub; this._d2 = source2;
this._d2.Pub += this.Sub; this._dd1 = dd1;
} this._dd2 = double.NaN;
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2) this._d2.Pub += this.Sub;
{ }
this._d1 = source1;
this._d2 = source2; // overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
this._dd1 = double.NaN; 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
this._dd2 = double.NaN;
this._d1.Pub += this.Sub; // potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
this._d2.Pub += this.Sub; 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); }}
protected Pair_TSeries_Indicator(TSeries source1, double dd2) 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); }}
{
this._d1 = source1; public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
this._d2 = new();
this._dd1 = double.NaN; public void Add(bool update)
this._dd2 = dd2; {
this._d1.Pub += this.Sub; if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN))
} {
protected Pair_TSeries_Indicator(double dd1, TSeries source2) // (Series, Series)
{ if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count))
this._d1 = new(); { this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); }
this._d2 = source2; }
this._dd1 = dd1; else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN))
this._dd2 = double.NaN; {
this._d2.Pub += this.Sub; // (Series, Double)
} this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update);
}
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list else
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 {
// (Double, Series)
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos) this.Add(TValue1: (this._d2[this._d2.Count - 1].t, this._dd1), TValue2: this._d2[this._d2.Count - 1], update: update);
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() => this.Add(update: false);
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false); public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
public void Add(bool update) protected static void Add_Replace(List<double> l, double v, bool update)
{ {
if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN)) if (update)
{ { l[l.Count - 1] = v; }
// (Series, Series) else
if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count)) { l.Add(v); }
{ this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); } }
} protected static void Add_Replace_Trim(List<double> l, double v, int p, bool update)
else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN)) {
{ Add_Replace(l, v, update);
// (Series, Double) if (l.Count > p && p != 0)
this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update); { l.RemoveAt(0); }
} }
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);
}
+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") public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo")
{ {
System.Net.Http.HttpClient client = new(); 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; string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey;
var msg = client.GetStringAsync(req).Result; var msg = client.GetStringAsync(req).Result;
var jres = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement; 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"); } if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); }
foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); } 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) Period: number of days of collected history (default: 252)
Usage: Usage:
Yahoo_Feed ticker = new("MSFT", 20) Yahoo_Feed ticker = new("MSFT", 20)
</summary> */ </summary> */
public class Yahoo_Feed : TBars public class Yahoo_Feed : TBars
{ {
public Yahoo_Feed(string Symbol = "IBM", int Period = 252) { public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
Period = (int)(Period*1.45);
string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+ string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
Symbol+"?interval=1d&period1="+ Symbol+"?interval=1d&period1="+
(int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+ (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(); System.Net.Http.HttpClient client = new();
var msg = client.GetStringAsync(requestUrl).Result; var msg = client.GetStringAsync(requestUrl).Result;
var jresult = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement; var jresult = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement;
jresult.TryGetProperty("chart",out JsonElement json); jresult.TryGetProperty("chart",out JsonElement json);
json.TryGetProperty("result",out json); json.TryGetProperty("result",out json);
json[0].TryGetProperty("timestamp",out JsonElement datetime); 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("low",out JsonElement low);
json[0].TryGetProperty("close",out JsonElement close); json[0].TryGetProperty("close",out JsonElement close);
json[0].TryGetProperty("volume",out JsonElement volume); json[0].TryGetProperty("volume",out JsonElement volume);
for (int i=0; i<datetime.GetArrayLength(); i++) { for (int i=0; i<datetime.GetArrayLength(); i++) {
DateTime d = DateTimeOffset.FromUnixTimeSeconds(long.Parse(datetime[i].GetRawText())).DateTime; DateTime d = DateTimeOffset.FromUnixTimeSeconds(long.Parse(datetime[i].GetRawText())).DateTime;
double o = Math.Round(double.Parse(open[i].GetRawText()),3); double o = Math.Round(double.Parse(open[i].GetRawText()),3);
+6 -6
View File
@@ -1,5 +1,7 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
using static System.Net.Mime.MediaTypeNames;
/* <summary> /* <summary>
CCI: Commodity Channel Index 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); } if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
// average TP over _tp buffer // average TP over _tp buffer
double _avgTp = 0; double _avgTp = _tp.Average();
for (int i = 0; i < this._tp.Count; i++) { _avgTp+=this._tp[i]; }
_avgTp /= this._tp.Count;
// average Deviation over _tp buffer // average Deviation over _tp buffer
double _avgDv = 0; double _avgDv = 0;
for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); } for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
_avgDv /= this._tp.Count; _avgDv /= this._tp.Count;
double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv); 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((TBar.t, _cci), update, _NaN);
base.Add(result, update); }
}
} }
+1 -1
View File
@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Title>QuanTAlib</Title> <Title>QuanTAlib</Title>
<Version>0.1.20</Version> <Version>0.1.21</Version>
<Product>Library of Technical Indicators for .NET</Product> <Product>Library of Technical Indicators for .NET</Product>
<Description>Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis</Description> <Description>Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis</Description>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
+5 -10
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
BIAS: Rate of change between the source and a moving average. 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
double _sma = 0; double _sma = _buffer.Average();
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; } double _bias = (_buffer[_buffer.Count - 1] / ((_sma != 0) ? _sma : 1)) - 1;
_sma /= this._buffer.Count;
double _bias = (this._buffer[this._buffer.Count - 1] / ((_sma != 0) ? _sma : 1)) - 1;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _bias); base.Add((TValue.t, _bias), update, _NaN);
base.Add(result, update);
} }
} }
+35 -53
View File
@@ -1,5 +1,7 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Collections.Generic;
using System.Linq;
/* <summary> /* <summary>
CORR: Pearson's Correlation Coefficient CORR: Pearson's Correlation Coefficient
@@ -14,57 +16,37 @@ Sources:
</summary> */ </summary> */
public class CORR_Series : Pair_TSeries_Indicator public class CORR_Series : Pair_TSeries_Indicator
{ {
public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN) 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); } } 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); }
} }
}
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; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
COVAR: Covariance 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> _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> _y = new();
private readonly System.Collections.Generic.List<double> _yy = new();
private readonly System.Collections.Generic.List<double> _xy = 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) public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{ {
if (update) Add_Replace_Trim(_x, TValue1.v, _p, update);
{ Add_Replace_Trim(_y, TValue2.v, _p, update);
_x[_x.Count - 1] = TValue1.v; Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
_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; double _avgx = _x.Average();
for (int i = 0; i < _x.Count; i++) { _sumx += _x[i]; } double _avgy = _y.Average();
double _sumxx = 0; double _avgxy = _xy.Average();
for (int i = 0; i < _xx.Count; i++) { _sumxx += _xx[i]; } double _covar = _avgxy - (_avgx * _avgy);
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));
var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _covar); 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); } if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
} }
} }
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
ENTP: Entropy ENTP: Entropy
@@ -16,9 +17,9 @@ Sources:
</summary> */ </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; this._logbase = logbase;
if (base._data.Count > 0) { base.Add(base._data); } 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); } double _sum = _buffer.Sum();
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]; }
double _pp = this._buffer[this._buffer.Count - 1] / _sum; double _pp = this._buffer[this._buffer.Count - 1] / _sum;
double _ppp = -_pp * Math.Log(_pp) / Math.Log(this._logbase); double _ppp = -_pp * Math.Log(_pp) / Math.Log(this._logbase);
if (update) { this._buff2[this._buff2.Count - 1] = _ppp; } Add_Replace_Trim(_buff2, _ppp, _p, update);
else { this._buff2.Add(_ppp); } double _entp = _buff2.Sum();
if (this._buff2.Count > this._p && this._p != 0) { this._buff2.RemoveAt(0); }
double _entp = 0; base.Add((TValue.t, _entp), update, _NaN);
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);
} }
} }
@@ -1,62 +1,57 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary>
KURT: Kurtosis of population /* <summary>
Kurtosis characterizes the relative peakedness or flatness of a distribution KURT: Kurtosis of population
compared with the normal distribution. Positive kurtosis indicates a relatively Kurtosis characterizes the relative peakedness or flatness of a distribution
peaked distribution. Negative kurtosis indicates a relatively flat 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 The normal curve is called Mesokurtic curve. If the curve of a distribution is
it is referred to as a Leptokurtic curve. If a curve is less outlier prone (or more outlier prone (or heavier-tailed) than a normal or mesokurtic curve then
lighter-tailed) than a normal curve, it is called as a platykurtic curve. 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 Calculation:
sum2 = (Σ(close-SMA)^2)^2 sum4 = Σ(close-SMA)^4
KURT = length * (sum4/sum2) sum2 = (Σ(close-SMA)^2)^2
KURT = length * (sum4/sum2)
Sources:
https://en.wikipedia.org/wiki/Kurtosis Sources:
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/ 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> */
</summary> */
public class KURT_Series : Single_TSeries_Indicator
{ public class KURTOSIS_Series : Single_TSeries_Indicator
public KURT_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN) {
{ 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); } this._logbase = logbase;
} if (base._data.Count > 0) { base.Add(base._data); }
protected double _logbase; }
private readonly System.Collections.Generic.List<double> _buffer = new(); protected double _logbase;
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{ 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); } Add_Replace_Trim(_buffer, TValue.v, _p, update);
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); } double _n = this._buffer.Count;
double _avg = _buffer.Average();
double _n = this._buffer.Count;
double _s2 = 0;
double _avg = 0; double _s4 = 0;
for (int i = 0; i < this._buffer.Count; i++) { _avg += this._buffer[i]; } for (int i = 0; i < this._buffer.Count; i++)
_avg /= _n; {
_s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg);
double _s2 = 0; _s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg);
double _s4 = 0; }
for (int i = 0; i < this._buffer.Count; i++)
{ double _Vx = _s2 / (_n - 1);
_s2 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg); 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;
_s4 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
} var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
base.Add(result, update);
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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
int _len = this._buffer.Count; int _len = this._buffer.Count;
@@ -79,7 +77,7 @@ public class LINREG_Series : Single_TSeries_Indicator
double _RSquared = arrr * arrr; double _RSquared = arrr * arrr;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope); 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); ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
Intercept.Add(ret, update); Intercept.Add(ret, update);
+4 -8
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MAD: Mean Absolute Deviation 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0; double _sma = _buffer.Average();
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
_sma /= this._buffer.Count;
double _mad = 0; double _mad = 0;
for (int i = 0; i < _buffer.Count; i++) { _mad += Math.Abs(_buffer[i] - _sma); } for (int i = 0; i < _buffer.Count; i++) { _mad += Math.Abs(_buffer[i] - _sma); }
_mad /= this._buffer.Count; _mad /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _mad); base.Add((TValue.t, _mad), update, _NaN);
base.Add(result, update);
} }
} }
+8 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MAPE: Mean Absolute Percentage Error 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _mape = 0; 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; } for (int i = 0; i < _buffer.Count; i++) {
_mape /= this._buffer.Count; _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((TValue.t, _mape), update, _NaN);
base.Add(result, update);
} }
} }
@@ -1,47 +1,44 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using static System.Net.Mime.MediaTypeNames;
/* <summary>
MED - Median value /* <summary>
Median of numbers is the middlemost value of the given set of numbers. MED - Median value
It separates the higher half and the lower half of a given data sample. Median of numbers is the middlemost value of the given set of numbers.
At least half of the observations are smaller than or equal to median It separates the higher half and the lower half of a given data sample.
and at least half of the observations are greater than or equal to the median. 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, If the number of values is odd, the middlemost observation of the sorted
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list. list is the median of the given data. If the number of values is even,
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
If period = 0 => period is max
If period = 0 => period is max
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/other/median/ Sources:
https://en.wikipedia.org/wiki/Median https://corporatefinanceinstitute.com/resources/knowledge/other/median/
https://en.wikipedia.org/wiki/Median
</summary> */
</summary> */
public class MED_Series : Single_TSeries_Indicator
{ public class MEDIAN_Series : Single_TSeries_Indicator
public MED_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
{ public MEDIAN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
if (base._data.Count > 0) { base.Add(base._data); } {
} if (base._data.Count > 0) { base.Add(base._data); }
private readonly System.Collections.Generic.List<double> _buffer = new(); }
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((System.DateTime t, double v) TValue, bool update)
{ 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); } Add_Replace_Trim(_buffer, TValue.v, _p, update);
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
System.Collections.Generic.List<double> _s = new(this._buffer);
System.Collections.Generic.List<double> _s = new(this._buffer); _s.Sort();
_s.Sort(); int _p1 = _s.Count / 2;
int _p1 = _s.Count / 2; int _p2 = Math.Max(0, (_s.Count / 2) - 1);
int _p2 = Math.Max(0, (_s.Count / 2) - 1); double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
base.Add((TValue.t, _med), update, _NaN);
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med); }
}
base.Add(result, update);
}
}
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
MSE: Mean Square Error 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _mse = 0; double _mse = 0;
for (int i = 0; i < _buffer.Count; i++) { _mse += (_buffer[i] - _sma) * (_buffer[i] - _sma); } for (int i = 0; i < _buffer.Count; i++) { _mse += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_mse /= this._buffer.Count; _mse /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _mse); base.Add((TValue.t, _mse), update, _NaN);
base.Add(result, update);
} }
} }
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SDEV: Population Standard Deviation 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _pvar = 0; double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_pvar /= this._buffer.Count; _pvar /= this._buffer.Count;
double _psdev = Math.Sqrt(_pvar); double _psdev = Math.Sqrt(_pvar);
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _psdev); base.Add((TValue.t, _psdev), update, _NaN);
base.Add(result, update);
} }
} }
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SMAPE: Symmetric Mean Absolute Percentage Error 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _smape = 0; double _smape = 0;
for (int i = 0; i < _buffer.Count; i++) { _smape += Math.Abs(_buffer[i] - _sma) / (Math.Abs(_buffer[i]) + Math.Abs(_sma)); } 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; _smape /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _smape); base.Add((TValue.t, _smape), update, _NaN);
base.Add(result, update);
} }
} }
+6 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SSDEV: (Corrected) Sample Standard Deviation 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _svar = 0; double _svar = 0;
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); } for (int i = 0; i < this._buffer.Count; i++) { _svar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction _svar /= (_buffer.Count > 1) ? _buffer.Count - 1 : 1; // Bessel's correction
double _ssdev = Math.Sqrt(_svar); double _ssdev = Math.Sqrt(_svar);
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ssdev); base.Add((TValue.t, _ssdev), update, _NaN);
base.Add(result, update);
} }
} }
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SVAR: Sample Variance 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _svar = 0; double _svar = 0;
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); } 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 _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((TValue.t, _svar), update, _NaN);
base.Add(result, update);
} }
} }
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
VAR: Population Variance 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _pvar = 0; double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
_pvar /= this._buffer.Count; _pvar /= this._buffer.Count;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _pvar); base.Add((TValue.t, _pvar), update, _NaN);
base.Add(result, update);
} }
} }
+8 -11
View File
@@ -1,9 +1,12 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
WMAPE: Weighted Mean Absolute Percentage Error 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: Sources:
https://en.wikipedia.org/wiki/WMAPE 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _div = 0; double _div = 0;
double _wmape = 0; double _wmape = 0;
@@ -35,9 +33,8 @@ public class WMAPE_Series : Single_TSeries_Indicator
_wmape += Math.Abs(_buffer[i] - _sma); _wmape += Math.Abs(_buffer[i] - _sma);
_div += Math.Abs(_buffer[i]); _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((TValue.t, _wmape), update, _NaN);
base.Add(result, update);
} }
} }
+4 -9
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
ZSCORE: number of standard deviations from SMA 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Average();
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;
double _pvar = 0; double _pvar = 0;
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } 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 _psdev = Math.Sqrt(_pvar);
double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev; 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((TValue.t, _zscore), update, _NaN);
base.Add(result, update);
} }
} }
+41 -45
View File
@@ -19,49 +19,45 @@ TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma
</summary> */ </summary> */
public class ALMA_Series : Single_TSeries_Indicator public class ALMA_Series : Single_TSeries_Indicator
{ {
private readonly System.Collections.Generic.List<double> _buffer = new(); private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double[] _weight; private readonly double[] _weight;
private double _norm; private double _norm;
private readonly double _offset, _sigma; private readonly double _offset, _sigma;
public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false) public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
: base(source, period, useNaN) : base(source, period, useNaN)
{ {
_offset = offset; _offset = offset;
_sigma = sigma; _sigma = sigma;
_weight = new double[period]; _weight = new double[period];
if (this._data.Count > 0) { base.Add(this._data); } if (this._data.Count > 0) { base.Add(this._data); }
} }
public override void Add((System.DateTime t, double v) TValue, bool update) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { this._buffer.Add(TValue.v); }
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); } if (this._buffer.Count <= _p)
{
if (this._buffer.Count <= _p) { calc_weights(); } int _len = this._buffer.Count;
_norm = 0;
double _weightedSum = 0; double _m = _offset * (_len - 1);
for (int i = 0; i < this._buffer.Count; i++) { _weightedSum += _weight[i] * _buffer[i]; } double _s = _len / _sigma;
double _alma = _weightedSum / _norm; for (int i = 0; i < _len; i++)
{
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _alma); double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
base.Add(ret, update); _weight[i] = _wt;
} _norm += _wt;
}
private void calc_weights() }
{
int _len = this._buffer.Count; double _weightedSum = 0;
_norm = 0; for (int i = 0; i < this._buffer.Count; i++)
double _m = _offset * (_len - 1); { _weightedSum += _weight[i] * _buffer[i]; }
double _s = _len / _sigma; double _alma = _weightedSum / _norm;
for (int i = 0; i < _len; i++)
{ base.Add((TValue.t, _alma), update, _NaN);
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s)); }
_weight[i] = _wt;
_norm += _wt;
}
}
} }
+4 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
DEMA: Double Exponential Moving Average DEMA: Double Exponential Moving Average
@@ -41,16 +42,9 @@ public class DEMA_Series : Single_TSeries_Indicator
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else double _sma = _buffer.Average();
{
_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;
_ema1 = _ema2 = _sma; _ema1 = _ema2 = _sma;
} }
else else
@@ -65,7 +59,6 @@ public class DEMA_Series : Single_TSeries_Indicator
this._lastema1 = _ema1; this._lastema1 = _ema1;
this._lastema2 = _ema2; this._lastema2 = _ema2;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _dema); base.Add((TValue.t, _dema), update, _NaN);
base.Add(ret, update);
} }
} }
+5 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
EMA: Exponential Moving Average 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) public override void Add((DateTime t, double v) TValue, bool update)
{ {
double _ema = 0; double _ema;
if (update) { this._lastema = this._lastlastema; } if (update) { this._lastema = this._lastlastema; }
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace(_buffer, TValue.v, update);
else _ema = _buffer.Average();
{
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;
} }
else else
{ {
@@ -58,7 +52,6 @@ public class EMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
this._lastema = _ema; this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema); base.Add((TValue.t, _ema), update, _NaN);
base.Add(ret, update);
} }
} }
+6 -14
View File
@@ -2,8 +2,8 @@
using System; using System;
/* <summary> /* <summary>
HEMA: Hull-EMA Moving Average HEMA: Hull-EMA Moving Average - a hybrid indicator
Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation, Modified HUll Moving Average; instead of using WMA (Weighted MA) for calculation,
HEMA uses EMA for Hull's formula: HEMA uses EMA for Hull's formula:
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1) 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._lastema2 = this._lastlastema2;
this._lastema3 = this._lastlastema3; this._lastema3 = this._lastlastema3;
} }
double _ema1 = System.Double.IsNaN(this._lastema1) double _ema1 = System.Double.IsNaN(this._lastema1) ? TValue.v : TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
? TValue.v double _ema2 = System.Double.IsNaN(this._lastema2) ? TValue.v : TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
: 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 _rawhema = (2 * _ema1) - _ema2;
double _ema3 = System.Double.IsNaN(this._lastema3) double _ema3 = System.Double.IsNaN(this._lastema3) ? _rawhema : _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
? _rawhema
: _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
this._lastlastema1 = this._lastema1; this._lastlastema1 = this._lastema1;
this._lastlastema2 = this._lastema2; this._lastlastema2 = this._lastema2;
@@ -58,8 +52,6 @@ public class HEMA_Series : Single_TSeries_Indicator
this._lastema2 = _ema2; this._lastema2 = _ema2;
this._lastema3 = _ema3; this._lastema3 = _ema3;
(System.DateTime t, double v) result = base.Add((TValue.t, _ema3), update, _NaN);
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ema3);
base.Add(result, update);
} }
} }
+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[i] * this._weights[i];
} }
this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5; this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
this._wma2 = 0; this._wma2 = 0;
@@ -81,7 +80,6 @@ public class HMA_Series : TSeries
{ {
this._wma2 += this._buf2[i] * this._weights[i]; this._wma2 += this._buf2[i] * this._weights[i];
} }
this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5; this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
if (update) if (update)
@@ -92,6 +90,7 @@ public class HMA_Series : TSeries
{ {
this._buf3.Add(2 * this._wma1 - this._wma2); this._buf3.Add(2 * this._wma1 - this._wma2);
} }
if (this._buf3.Count > (int)Math.Sqrt(this._p)) if (this._buf3.Count > (int)Math.Sqrt(this._p))
{ {
this._buf3.RemoveAt(0); 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)) + double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) +
(this.prev_det1 * alpha * alpha); (this.prev_det1 * alpha * alpha);
this.prev_det1 = det1; this.prev_det1 = det1;
var jma = this.prev_jma + det1; var _jma = this.prev_jma + det1;
this.prev_jma = jma; this.prev_jma = _jma;
(System.DateTime t, double v) result = base.Add((TValue.t, _jma), update, _NaN);
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma); }
base.Add(result, update);
}
} }
+3 -3
View File
@@ -44,6 +44,7 @@ public class KAMA_Series : Single_TSeries_Indicator
_buffer.Add(TValue.v); _buffer.Add(TValue.v);
} }
if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); } if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
double _kama = 0; double _kama = 0;
if (this.Count < this._p) { if (this.Count < this._p) {
for (int i = 0; i < this._buffer.Count; i++) { _kama += this._buffer[i]; } 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; _lastlastkama = _lastkama;
_lastkama = _kama; _lastkama = _kama;
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama); base.Add((TValue.t, _kama), update, _NaN);
base.Add(result, update); }
}
} }
+2 -3
View File
@@ -40,7 +40,6 @@ public class MACD_Series : Single_TSeries_Indicator
_TSfast.Add(TValue, true); _TSfast.Add(TValue, true);
} }
_macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v; _macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
var result = (TValue.t, _macd); base.Add((TValue.t, _macd), update, _NaN);
base.Add(result, update); }
}
} }
+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; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
RMA: wildeR Moving Average 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) public override void Add((DateTime t, double v) TValue, bool update)
{ {
double _ema = 0; double _ema;
if (update) { this._lastema = this._lastlastema; } if (update) { this._lastema = this._lastlastema; }
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else _ema = _buffer.Average();
{
_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;
} }
else else
{ {
@@ -57,7 +51,6 @@ public class RMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
this._lastema = _ema; this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema); base.Add((TValue.t, _ema), update, _NaN);
base.Add(ret, update); }
}
} }
+4 -10
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SMA: Simple Moving Average 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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); } double _sma = _buffer.Sum() / _buffer.Count;
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _sma = 0; base.Add((TValue.t, _sma), update, _NaN);
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);
} }
} }
+5 -12
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
SMMA: Smoothed Moving Average SMMA: Smoothed Moving Average
@@ -34,15 +35,8 @@ public class SMMA_Series : Single_TSeries_Indicator
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else _smma = _buffer.Average();
{
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;
} }
else else
{ {
@@ -52,7 +46,6 @@ public class SMMA_Series : Single_TSeries_Indicator
this._lastlastsmma = this._lastsmma; this._lastlastsmma = this._lastsmma;
this._lastsmma = _smma; this._lastsmma = _smma;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _smma); base.Add((TValue.t, _smma), update, _NaN);
base.Add(ret, update); }
}
} }
+5 -13
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
TEMA: Triple Exponential Moving Average TEMA: Triple Exponential Moving Average
@@ -44,16 +45,8 @@ public class TEMA_Series : Single_TSeries_Indicator
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else double _sma = _buffer.Average();
{
_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;
_ema1 = _ema2 = _ema3 = _sma; _ema1 = _ema2 = _ema3 = _sma;
} }
else else
@@ -72,7 +65,6 @@ public class TEMA_Series : Single_TSeries_Indicator
this._lastema2 = _ema2; this._lastema2 = _ema2;
this._lastema3 = _ema3; this._lastema3 = _ema3;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _tema); base.Add((TValue.t, _tema), update, _NaN);
base.Add(ret, update); }
}
} }
+5 -11
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
TRIMA: Triangular Moving Average 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 (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); } if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
double _sma1 = _buffer1.Average();
double _sma1 = 0;
for (int i = 0; i < _buffer1.Count; i++) { _sma1 += _buffer1[i]; }
_sma1 /= this._buffer1.Count;
if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); } if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); } if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
double _trima = _buffer2.Average();
double _trima = 0; base.Add((TValue.t, _trima), update, _NaN);
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);
}
} }
+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) public override void Add((System.DateTime t, double v) TValue, bool update)
{ {
if (update) { _buffer[_buffer.Count - 1] = TValue.v; } Add_Replace_Trim(_buffer, TValue.v, _p, update);
else { _buffer.Add(TValue.v); }
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
double _wma = 0; double _wma = 0;
for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; } for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
_wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5; _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((TValue.t, _wma), update, _NaN);
base.Add(result, update);
} }
} }
+5 -15
View File
@@ -1,5 +1,6 @@
namespace QuanTAlib; namespace QuanTAlib;
using System; using System;
using System.Linq;
/* <summary> /* <summary>
ZLEMA: Zero Lag Exponential Moving Average ZLEMA: Zero Lag Exponential Moving Average
@@ -45,18 +46,8 @@ public class ZLEMA_Series : Single_TSeries_Indicator
{ this._lastema = this._lastlastema; } { this._lastema = this._lastlastema; }
if (this.Count < this._p) if (this.Count < this._p)
{ {
if (update) Add_Replace_Trim(_buffer, _zl, _p, update);
{ this._buffer[this._buffer.Count - 1] = _zl; } _ema = _buffer.Average();
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;
} }
else else
{ {
@@ -66,7 +57,6 @@ public class ZLEMA_Series : Single_TSeries_Indicator
this._lastlastema = this._lastema; this._lastlastema = this._lastema;
this._lastema = _ema; this._lastema = _ema;
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema); base.Add((TValue.t, _ema), update, _NaN);
base.Add(ret, update); }
}
} }
+2 -3
View File
@@ -37,7 +37,6 @@ public class ADL_Series : Single_TBars_Indicator
this._lastlastadl = this._lastadl; this._lastlastadl = this._lastadl;
this._lastadl = _adl; this._lastadl = _adl;
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl); base.Add((TBar.t, _adl), update, _NaN);
base.Add(ret, update); }
}
} }
+3 -3
View File
@@ -3,13 +3,13 @@ using System;
using QuanTAlib; using QuanTAlib;
namespace Statistics; namespace Statistics;
public class KURT_Test public class KURTOSIS_Test
{ {
[Fact] [Fact]
public void Add_Test() public void Add_Test()
{ {
TSeries a = new() { 0, 1, 2, 3, 4, 5 }; 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); Assert.Equal(6, c.Count);
a.Add(5); a.Add(5);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class KURT_Test
public void Edge_Test() public void Edge_Test()
{ {
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; 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); Assert.Equal(a.Count, c.Count);
a.Add(double.NaN); a.Add(double.NaN);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
+2 -2
View File
@@ -9,7 +9,7 @@ public class ENTP_Test
public void Add_Test() public void Add_Test()
{ {
TSeries a = new() { 0, 1, 2, 3, 4, 5 }; 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); Assert.Equal(6, c.Count);
a.Add(5); a.Add(5);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class ENTP_Test
public void Edge_Test() public void Edge_Test()
{ {
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; 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); Assert.Equal(a.Count, c.Count);
a.Add(double.NaN); a.Add(double.NaN);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
+2 -2
View File
@@ -9,7 +9,7 @@ public class MED_Test
public void Add_Test() public void Add_Test()
{ {
TSeries a = new() { 0, 1, 2, 3, 4, 5 }; 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); Assert.Equal(6, c.Count);
a.Add(5); a.Add(5);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
@@ -21,7 +21,7 @@ public class MED_Test
public void Edge_Test() public void Edge_Test()
{ {
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; 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); Assert.Equal(a.Count, c.Count);
a.Add(double.NaN); a.Add(double.NaN);
Assert.Equal(a.Count, c.Count); Assert.Equal(a.Count, c.Count);
-4
View File
@@ -15,10 +15,6 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </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="Microsoft.NET.Test.Sdk" Version="17.5.0-preview-20221003-04" />
<PackageReference Include="TALib.NETCore" Version="0.4.4" /> <PackageReference Include="TALib.NETCore" Version="0.4.4" />
<PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" /> <PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" />
+264 -256
View File
@@ -1,198 +1,206 @@
using Xunit; using Xunit;
using System; using System;
using QuanTAlib; using QuanTAlib;
using Python.Runtime; using Python.Runtime;
using Python.Included; using Python.Included;
namespace Validations; namespace Validations;
public class PandasTA : IDisposable public class PandasTA : IDisposable
{ {
private readonly GBM_Feed bars; private readonly GBM_Feed bars;
private readonly Random rnd = new(); private readonly Random rnd = new();
private readonly int period; private readonly int period;
private readonly string OStype; private readonly string OStype;
private dynamic np; private readonly dynamic np;
private dynamic ta; private readonly dynamic ta;
private dynamic df; private readonly dynamic df;
public PandasTA() public PandasTA()
{ {
bars = new(5000); bars = new(5000);
period = rnd.Next(28) + 3; period = rnd.Next(28) + 3;
// Checking the host OS and setting PythonDLL accordingly // Checking the host OS and setting PythonDLL accordingly
OStype = Environment.OSVersion.ToString(); OStype = Environment.OSVersion.ToString();
if (OStype == "Unix 13.1.0") 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"; OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
} }
else else
{ {
OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
} }
Installer.InstallPath = Path.GetFullPath("."); Installer.InstallPath = Path.GetFullPath(".");
Installer.SetupPython().Wait(); Installer.SetupPython().Wait();
Installer.TryInstallPip(); Installer.TryInstallPip();
Installer.PipInstallModule("pandas-ta"); Installer.PipInstallModule("pandas-ta");
//alternative: git+https://github.com/twopirllc/pandas-ta //alternative: git+https://github.com/twopirllc/pandas-ta
Runtime.PythonDLL = OStype; Runtime.PythonDLL = OStype;
PythonEngine.Initialize(); PythonEngine.Initialize();
np = Py.Import("numpy"); np = Py.Import("numpy");
ta = Py.Import("pandas_ta"); ta = Py.Import("pandas_ta");
string[] cols = { "open", "high", "low", "close", "volume" }; string[] cols = { "open", "high", "low", "close", "volume" };
double[,] ary = new double[bars.Count, 5]; double[,] ary = new double[bars.Count, 5];
for (int i = 0; i < bars.Count; i++) for (int i = 0; i < bars.Count; i++)
{ {
ary[i, 0] = bars.Open[i].v; ary[i, 0] = bars.Open[i].v;
ary[i, 1] = bars.High[i].v; ary[i, 1] = bars.High[i].v;
ary[i, 2] = bars.Low[i].v; ary[i, 2] = bars.Low[i].v;
ary[i, 3] = bars.Close[i].v; ary[i, 3] = bars.Close[i].v;
ary[i, 4] = bars.Volume[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)); df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
} }
public void Dispose() public void Dispose()
{ {
PythonEngine.Shutdown(); PythonEngine.Shutdown();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
[Fact] [Fact]
void HL2() void HL2()
{ {
var pta = df.ta.hl2(high: df.high, low: df.low); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HL2.Last().v, 4));
} }
[Fact] [Fact]
void HLC3() void HLC3()
{ {
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.HLC3.Last().v, 4));
} }
[Fact] [Fact]
void OHLC4() void OHLC4()
{ {
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(bars.OHLC4.Last().v, 4));
} }
[Fact] [Fact]
void MEDIAN() void MEDIAN()
{ {
MED_Series QL = new(bars.Close, period); MEDIAN_Series QL = new(bars.Close, period);
var pta = df.ta.median(close: df.close, length: 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void VARIANCE() void VARIANCE()
{ {
VAR_Series QL = new(bars.Close, period); VAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof:0); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
} }
[Fact] [Fact]
void SVARIANCE() void SVARIANCE()
{ {
SVAR_Series QL = new(bars.Close, period); SVAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 1); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5));
} }
[Fact] [Fact]
void ADL() void ADL()
{ {
ADL_Series QL = new(bars); ADL_Series QL = new(bars);
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void ADOSC() void ADOSC()
{ {
ADOSC_Series QL = new(bars); ADOSC_Series QL = new(bars);
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void TR() void TR()
{ {
TR_Series QL = new(bars); TR_Series QL = new(bars);
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void ATR() void OBV()
{ {
ATR_Series QL = new(bars, period); OBV_Series QL = new(bars);
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void RSI() void ATR()
{ {
RSI_Series QL = new(bars.Close, period); ATR_Series QL = new(bars, period);
var pta = df.ta.rsi(close: df.close, length: 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void TRIMA() void RSI()
{ {
//TODO: return length to variable length (period) when Pandas-TA fixes trima RSI_Series QL = new(bars.Close, period);
TRIMA_Series QL = new(bars.Close, 11); var pta = df.ta.rsi(close: df.close, length: period);
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));
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4)); }
}
[Fact]
[Fact] void TRIMA()
void KAMA() {
{ // TODO: return length to variable length (period) when Pandas-TA fixes trima
KAMA_Series QL = new(bars.Close, period); TRIMA_Series QL = new(bars.Close, 11);
var pta = df.ta.kama(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void HMA() void KAMA()
{ {
HMA_Series QL = new(bars.Close, period, false); KAMA_Series QL = new(bars.Close, period);
var pta = df.ta.hma(close: df.close, length: 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void SMA() void HMA()
{ {
SMA_Series QL = new(bars.Close, period, false); HMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void EMA() void SMA()
{ {
EMA_Series QL = new(bars.Close, period, false); SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void TEMA() void EMA()
{ {
TEMA_Series QL = new(bars.Close, period, false); EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.tema(close: df.close, length: period); var pta = df.ta.ema(close: df.close, length: period);
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); 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] [Fact]
@@ -219,67 +227,67 @@ public class PandasTA : IDisposable
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void ENTP() void ENTROPY()
{ {
ENTP_Series QL = new(bars.Close, period, useNaN: false); ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.entropy(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void WMA() void WMA()
{ {
WMA_Series QL = new(bars.Close, period, false); WMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.wma(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void RMA() void RMA()
{ {
RMA_Series QL = new(bars.Close, period, false); RMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.rma(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void ZLEMA() void ZLEMA()
{ {
ZLEMA_Series QL = new(bars.Close, period, false); ZLEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.zlma(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void DEMA() void DEMA()
{ {
DEMA_Series QL = new(bars.Close, period, false); DEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.dema(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void BIAS() void BIAS()
{ {
BIAS_Series QL = new(bars.Close, period, false); BIAS_Series QL = new(bars.Close, period, false);
var pta = df.ta.bias(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void KURT() void KURTOSIS()
{ {
KURT_Series QL = new(bars.Close, period, useNaN: false); KURTOSIS_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.kurtosis(close: df.close, length: period); 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)); Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
} }
[Fact] [Fact]
void MAD() void MAD()
{ {
MAD_Series QL = new(bars.Close, period, useNaN: false); MAD_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.mad(close: df.close, length: period); 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)); 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; namespace Validations;
public class Skender_Stock public class Skender_Stock
{ {
private readonly GBM_Feed bars; private readonly GBM_Feed bars;
private readonly Random rnd = new(); private readonly Random rnd = new();
private readonly int period; private readonly int period;
private readonly IEnumerable<Quote> quotes; private readonly IEnumerable<Quote> quotes;
public Skender_Stock() public Skender_Stock()
{ {
bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0); bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
period = rnd.Next(28) + 3; period = rnd.Next(28) + 3;
quotes = bars.Select( quotes = bars.Select(
q => new Quote q => new Quote
{ {
Date = q.t, Date = q.t,
Open = (decimal)q.o, Open = (decimal)q.o,
High = (decimal)q.h, High = (decimal)q.h,
Low = (decimal)q.l, Low = (decimal)q.l,
Close = (decimal)q.c, Close = (decimal)q.c,
Volume = (decimal)q.v Volume = (decimal)q.v
}); });
} }
[Fact] [Fact]
public void SMA() public void SMA()
{ {
SMA_Series QL = new(bars.Close, period, false); SMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSma(period); var SK = quotes.GetSma(period);
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void EMA() public void EMA()
{ {
EMA_Series QL = new(bars.Close, period, false); EMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetEma(period); var SK = quotes.GetEma(period);
Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void WMA() public void WMA()
{ {
WMA_Series QL = new(bars.Close, period, false); WMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetWma(period); var SK = quotes.GetWma(period);
Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void DEMA() public void DEMA()
{ {
DEMA_Series QL = new(bars.Close, period, false); DEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetDema(period); var SK = quotes.GetDema(period);
Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void TEMA() public void TEMA()
{ {
TEMA_Series QL = new(bars.Close, period, false); TEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetTema(period); var SK = quotes.GetTema(period);
Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact]
public void MAD() [Fact]
{ public void MAMA() {
MAD_Series QL = new(bars.Close, period, false); MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
var SK = quotes.GetSmaAnalysis(period); var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Mama!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void MSE() public void MAD()
{ {
MSE_Series QL = new(bars.Close, period, false); MAD_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period); var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void MAPE() public void MSE()
{ {
MAPE_Series QL = new(bars.Close, period, false); MSE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period); var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void COVAR() public void MAPE()
{ {
COVAR_Series QL = new(bars.High, bars.Low, period, false); MAPE_Series QL = new(bars.Close, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period); var SK = quotes.GetSmaAnalysis(period);
Assert.Equal(Math.Round((double)SK.Last().Covariance!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void CORR() public void COVAR()
{ {
CORR_Series QL = new(bars.High, bars.Low, period, false); COVAR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period); 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)); Assert.Equal(Math.Round((double)SK.Last().Covariance!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void ATR() public void CORR()
{ {
ATR_Series QL = new(bars, period, false); CORR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.GetAtr(period); var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Correlation!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void OBV() public void ATR()
{ {
OBV_Series QL = new(bars, period, false); ATR_Series QL = new(bars, period, false);
var SK = quotes.GetObv(period); var SK = quotes.GetAtr(period);
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5), }
Math.Round(QL.Last().v, 5));
} [Fact]
public void OBV()
[Fact] {
public void ADL() OBV_Series QL = new(bars, period, false);
{ var SK = quotes.GetObv(period);
ADL_Series QL = new(bars, false);
var SK = quotes.GetAdl(); // 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),
Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5)); Math.Round(QL.Last().v, 5));
} }
[Fact] [Fact]
public void CCI() public void ADL()
{ {
CCI_Series QL = new(bars, period, false); ADL_Series QL = new(bars, false);
var SK = quotes.GetCci(period); var SK = quotes.GetAdl();
Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
} }
[Fact] [Fact]
public void ATRP() public void CCI()
{ {
ATRP_Series QL = new(bars, period, false); CCI_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period); var SK = quotes.GetCci(period);
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void KAMA() public void ATRP()
{ {
KAMA_Series QL = new(bars.Close, period, useNaN: false); ATRP_Series QL = new(bars, period, false);
var SK = quotes.GetKama(period); var SK = quotes.GetAtr(period);
Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void HMA() public void KAMA()
{ {
HMA_Series QL = new(bars.Close, period, useNaN: false); KAMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetHma(period); var SK = quotes.GetKama(period);
Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void SMMA() public void HMA()
{ {
SMMA_Series QL = new(bars.Close, period, useNaN: false); HMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSmma(period); var SK = quotes.GetHma(period);
Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void MACD() public void SMMA()
{ {
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false); SMMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetMacd(12, 26, 9); var SK = quotes.GetSmma(period);
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6)); }
}
[Fact]
[Fact] public void MACD()
public void BBANDS() {
{ MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false); var SK = quotes.GetMacd(12, 26, 9);
var SK = quotes.GetBollingerBands(period, 2.0);
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.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)); [Fact]
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6)); public void BBANDS()
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6)); {
} BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
var SK = quotes.GetBollingerBands(period, 2.0);
[Fact]
public void RSI() 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));
RSI_Series QL = new(bars.Close, period, useNaN: false); Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
var SK = quotes.GetRsi(period); 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().Rsi!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
} }
[Fact] [Fact]
public void ALMA() public void RSI()
{ {
ALMA_Series QL = new(bars.Close, period, useNaN: false); RSI_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetAlma(period); var SK = quotes.GetRsi(period);
Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void SDEV() public void ALMA()
{ {
SDEV_Series QL = new(bars.Close, period, useNaN: false); ALMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period); var SK = quotes.GetAlma(period);
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void ZSCORE() public void SDEV()
{ {
ZSCORE_Series QL = new(bars.Close, period, useNaN: false); SDEV_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period); var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void LINREG() public void ZSCORE()
{ {
LINREG_Series QL = new(bars.Close, period, useNaN: false); ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSlope(period); var SK = quotes.GetStdDev(period);
Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().ZScore!, 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 LINREG()
{
[Fact] LINREG_Series QL = new(bars.Close, period, useNaN: false);
public void TR() var SK = quotes.GetSlope(period);
{
TR_Series QL = new(bars, useNaN: false); Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
var SK = quotes.GetTr(); 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().Tr!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
} }
[Fact] [Fact]
public void HL2() public void TR()
{ {
TSeries QL = bars.HL2; TR_Series QL = new(bars, useNaN: false);
var SK = quotes.GetBaseQuote(CandlePart.HL2); var SK = quotes.GetTr();
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void OC2() public void HL2()
{ {
TSeries QL = bars.OC2; TSeries QL = bars.HL2;
var SK = quotes.GetBaseQuote(CandlePart.OC2); var SK = quotes.GetBaseQuote(CandlePart.HL2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void HLC3() public void OC2()
{ {
TSeries QL = bars.HLC3; TSeries QL = bars.OC2;
var SK = quotes.GetBaseQuote(CandlePart.HLC3); var SK = quotes.GetBaseQuote(CandlePart.OC2);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void OHL3() public void HLC3()
{ {
TSeries QL = bars.OHL3; TSeries QL = bars.HLC3;
var SK = quotes.GetBaseQuote(CandlePart.OHL3); var SK = quotes.GetBaseQuote(CandlePart.HLC3);
Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6)); Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
} }
[Fact] [Fact]
public void OHLC4() public void OHL3()
{ {
TSeries QL = bars.OHLC4; TSeries QL = bars.OHL3;
var SK = quotes.GetBaseQuote(CandlePart.OHLC4); var SK = quotes.GetBaseQuote(CandlePart.OHL3);
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6)); 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 Xunit;
using System; using System;
using TALib; using TALib;
using QuanTAlib; using QuanTAlib;
namespace Validations; namespace Validations;
public class TA_LIB public class TA_LIB
{ {
private readonly GBM_Feed bars; private readonly GBM_Feed bars;
private readonly Random rnd = new(); private readonly Random rnd = new();
private readonly int period; private readonly int period;
private readonly double[] TALIB; private readonly double[] TALIB;
private readonly double[] inopen; private readonly double[] TALIB2;
private readonly double[] inhigh; private readonly double[] inopen;
private readonly double[] inlow; private readonly double[] inhigh;
private readonly double[] inclose; private readonly double[] inlow;
private readonly double[] involume; private readonly double[] inclose;
private readonly double[] involume;
public TA_LIB()
{ public TA_LIB()
bars = new(5000); {
period = rnd.Next(28) + 3; bars = new(5000);
TALIB = new double[bars.Count]; period = rnd.Next(28) + 3;
inopen = bars.Open.v.ToArray(); TALIB = new double[bars.Count];
inhigh = bars.High.v.ToArray(); TALIB2 = new double[bars.Count];
inlow = bars.Low.v.ToArray(); inopen = bars.Open.v.ToArray();
inclose = bars.Close.v.ToArray(); inhigh = bars.High.v.ToArray();
involume = bars.Volume.v.ToArray(); inlow = bars.Low.v.ToArray();
} inclose = bars.Close.v.ToArray();
involume = bars.Volume.v.ToArray();
///////////////////////////////////////// }
[Fact] /////////////////////////////////////////
public void ADD()
{ [Fact]
ADD_Series QL = new(bars.Open, bars.Close); public void ADD()
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
ADD_Series QL = new(bars.Open, bars.Close);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
SUB_Series QL = new(bars.Open, bars.Close); public void SUB()
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
SUB_Series QL = new(bars.Open, bars.Close);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
MUL_Series QL = new(bars.Open, bars.Close); public void MUL()
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
MUL_Series QL = new(bars.Open, bars.Close);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
DIV_Series QL = new(bars.Open, bars.Close); public void DIV()
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
DIV_Series QL = new(bars.Open, bars.Close);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
CORR_Series QL = new(bars.Open, bars.Close, period); public void CORR()
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period); {
CORR_Series QL = new(bars.Open, bars.Close, period);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
SDEV_Series QL = new(bars.Close, period, false); public void SDEV()
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
SDEV_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
SMA_Series QL = new(bars.Close, period, false); public void SMA()
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
SMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
SUM_Series QL = new(bars.Close, period, false); public void SUM()
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
SUM_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
MIDPRICE_Series QL = new(bars, period, false); public void MIDPRICE()
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
MIDPRICE_Series QL = new(bars, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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()
{ [Fact]
VAR_Series QL = new(bars.Close, period, false); public void VAR()
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
VAR_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 4, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 4)); 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()
{ [Fact]
MIDPOINT_Series QL = new(bars.Close, period, false); public void MIDPOINT()
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
MIDPOINT_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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); [Fact]
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); public void MAMA() {
MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 EMA()
{ [Fact]
EMA_Series QL = new(bars.Close, period, false); public void TRIMA()
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
TRIMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 WMA()
{ [Fact]
WMA_Series QL = new(bars.Close, period, false); public void EMA()
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
EMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 DEMA()
{ [Fact]
DEMA_Series QL = new(bars.Close, period, false); public void WMA()
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
WMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 TEMA()
{ [Fact]
TEMA_Series QL = new(bars.Close, period, false); public void DEMA()
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
DEMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 MAX()
{ [Fact]
MAX_Series QL = new(bars.Close, period, false); public void TEMA()
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
TEMA_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 MIN()
{ [Fact]
MIN_Series QL = new(bars.Close, period, false); public void MAX()
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
MAX_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 ADL()
{ [Fact]
ADL_Series QL = new(bars, false); public void MIN()
Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
MIN_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 OBV()
{ [Fact]
OBV_Series QL = new(bars, period, false); public void ADL()
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
ADL_Series QL = new(bars, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 ADOSC()
{ [Fact]
ADOSC_Series QL = new(bars, false); public void OBV()
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
OBV_Series QL = new(bars, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 ATR()
{ [Fact]
ATR_Series QL = new(bars, period, false); public void ADOSC()
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
ADOSC_Series QL = new(bars, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 CCI()
{ [Fact]
CCI_Series QL = new(bars, period, false); public void ATR()
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
ATR_Series QL = new(bars, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 RSI()
{ [Fact]
RSI_Series QL = new(bars.Close, period, false); public void CCI()
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); {
CCI_Series QL = new(bars, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 TR()
{ [Fact]
TR_Series QL = new(bars, false); public void RSI()
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
RSI_Series QL = new(bars.Close, period, false);
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 MACD()
{ [Fact]
double[] macdSignal = new double[bars.Count]; public void TR()
double[] macdHist = new double[bars.Count]; {
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false); TR_Series QL = new(bars, false);
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _); 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));
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero)); Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
} }
[Fact] [Fact]
public void BBANDS() public void MACD()
{ {
double[] outMiddle = new double[bars.Count]; double[] macdSignal = new double[bars.Count];
double[] outUpper = new double[bars.Count]; double[] macdHist = new double[bars.Count];
double[] outLower = new double[bars.Count]; MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false); Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
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(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
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(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.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 BBANDS()
[Fact] {
public void HL2() double[] outMiddle = new double[bars.Count];
{ double[] outUpper = new double[bars.Count];
TSeries QL = bars.HL2; double[] outLower = new double[bars.Count];
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); 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(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 HLC3()
{ [Fact]
TSeries QL = bars.HLC3; public void HL2()
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
TSeries QL = bars.HL2;
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 OHLC4()
{ [Fact]
TSeries QL = bars.OHLC4; public void HLC3()
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
TSeries QL = bars.HLC3;
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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 HLCC4()
{ [Fact]
TSeries QL = bars.HLCC4; public void OHLC4()
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); {
TSeries QL = bars.OHLC4;
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); 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_': **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 - 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) - 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 - 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) - 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 | | ⭐ BIAS - Bias | `BIAS_Series` ||| bias |
| ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation || | ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation ||
| ⭐ COVAR - Covariance | `COVAR_Series` || GetCorrelation || | ⭐ COVAR - Covariance | `COVAR_Series` || GetCorrelation ||
| ⭐ ENTP - Entropy | `ENTP_Series` ||| entropy | | ⭐ ENTROPY - Entropy | `ENTROPY_Series` ||| entropy |
| ⭐ KURT - Kurtosis | `KURT_Series` ||| kurtosis | | ⭐ KURTOSIS - Kurtosis | `KURT_Series` ||| kurtosis |
| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope || | ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope ||
| ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma | mad | | ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma | mad |
| ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma || | ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma ||