mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-20 19:48:05 +00:00
0.1.21 MAMA
This commit is contained in:
+7
-1
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,5 +1,7 @@
|
|||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
/* <summary>
|
/* <summary>
|
||||||
Abstract classes with all scaffolding required to build indicators.
|
Abstract classes with all scaffolding required to build indicators.
|
||||||
All abstracts support period, NaN, and all permutations of Add() methods.
|
All abstracts support period, NaN, and all permutations of Add() methods.
|
||||||
@@ -13,32 +15,7 @@ Abstract classes with all scaffolding required to build indicators.
|
|||||||
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
|
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
|
||||||
|
|
||||||
</summary> */
|
</summary> */
|
||||||
public abstract class Single_TSeries_Indicator : TSeries
|
|
||||||
{
|
|
||||||
protected readonly int _p;
|
|
||||||
protected readonly bool _NaN;
|
|
||||||
protected readonly TSeries _data;
|
|
||||||
|
|
||||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
|
||||||
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN)
|
|
||||||
{
|
|
||||||
this._data = source;
|
|
||||||
this._p = period;
|
|
||||||
this._NaN = useNaN;
|
|
||||||
this._data.Pub += this.Sub;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overridable Add() method to add/update a single item at the end of the list
|
|
||||||
public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
|
|
||||||
|
|
||||||
// potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
|
|
||||||
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }}
|
|
||||||
|
|
||||||
public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
|
|
||||||
public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
|
|
||||||
public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
|
|
||||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class Pair_TSeries_Indicator : TSeries
|
public abstract class Pair_TSeries_Indicator : TSeries
|
||||||
{
|
{
|
||||||
@@ -118,31 +95,18 @@ public abstract class Pair_TSeries_Indicator : TSeries
|
|||||||
|
|
||||||
public void Add() => this.Add(update: false);
|
public void Add() => this.Add(update: false);
|
||||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
|
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class Single_TBars_Indicator : TSeries
|
protected static void Add_Replace(List<double> l, double v, bool update)
|
||||||
{
|
|
||||||
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;
|
if (update)
|
||||||
this._bars = source;
|
{ l[l.Count - 1] = v; }
|
||||||
this._NaN = useNaN;
|
else
|
||||||
this._bars.Pub += this.Sub;
|
{ 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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
@@ -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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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); }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)); }
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Yahoo Finance - Free API feed to collect daily market quotes
|
|||||||
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="+
|
||||||
|
|||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -28,43 +30,23 @@ public class CORR_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)
|
||||||
{
|
{
|
||||||
if (update)
|
Add_Replace_Trim(_x, TValue1.v, _p, update);
|
||||||
{
|
Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update);
|
||||||
_x[_x.Count - 1] = TValue1.v;
|
Add_Replace_Trim(_y, TValue2.v, _p, update);
|
||||||
_xx[_xx.Count - 1] = TValue1.v * TValue1.v;
|
Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update);
|
||||||
_y[_y.Count - 1] = TValue2.v;
|
Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
|
||||||
_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 _sumx = _x.Sum();
|
||||||
for (int i = 0; i < _x.Count; i++) { _sumx += _x[i]; }
|
double _sumxx = _xx.Sum();
|
||||||
double _sumxx = 0;
|
double _sumy = _y.Sum();
|
||||||
for (int i = 0; i < _xx.Count; i++) { _sumxx += _xx[i]; }
|
double _sumyy = _yy.Sum();
|
||||||
double _sumy = 0;
|
double _sumxy = _xy.Sum();
|
||||||
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 _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
|
||||||
double _cor = (_div != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_div) : 0.0;
|
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);
|
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); }
|
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>
|
||||||
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,5 +1,6 @@
|
|||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
/* <summary>
|
/* <summary>
|
||||||
KURT: Kurtosis of population
|
KURT: Kurtosis of population
|
||||||
@@ -23,9 +24,9 @@ Sources:
|
|||||||
|
|
||||||
</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;
|
this._logbase = logbase;
|
||||||
if (base._data.Count > 0) { base.Add(base._data); }
|
if (base._data.Count > 0) { base.Add(base._data); }
|
||||||
@@ -35,22 +36,16 @@ public class KURT_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 _n = this._buffer.Count;
|
double _n = this._buffer.Count;
|
||||||
|
double _avg = _buffer.Average();
|
||||||
double _avg = 0;
|
|
||||||
for (int i = 0; i < this._buffer.Count; i++) { _avg += this._buffer[i]; }
|
|
||||||
_avg /= _n;
|
|
||||||
|
|
||||||
double _s2 = 0;
|
double _s2 = 0;
|
||||||
double _s4 = 0;
|
double _s4 = 0;
|
||||||
for (int i = 0; i < this._buffer.Count; i++)
|
for (int i = 0; i < this._buffer.Count; i++)
|
||||||
{
|
{
|
||||||
_s2 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
_s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg);
|
||||||
_s4 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
_s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _Vx = _s2 / (_n - 1);
|
double _Vx = _s2 / (_n - 1);
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,5 +1,6 @@
|
|||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
using System;
|
using System;
|
||||||
|
using static System.Net.Mime.MediaTypeNames;
|
||||||
|
|
||||||
/* <summary>
|
/* <summary>
|
||||||
MED - Median value
|
MED - Median value
|
||||||
@@ -20,9 +21,9 @@ Sources:
|
|||||||
|
|
||||||
</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); }
|
||||||
}
|
}
|
||||||
@@ -30,9 +31,7 @@ public class MED_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); }
|
|
||||||
|
|
||||||
System.Collections.Generic.List<double> _s = new(this._buffer);
|
System.Collections.Generic.List<double> _s = new(this._buffer);
|
||||||
_s.Sort();
|
_s.Sort();
|
||||||
@@ -40,8 +39,6 @@ public class MED_Series : Single_TSeries_Indicator
|
|||||||
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
|
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
|
||||||
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
|
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
|
||||||
|
|
||||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med);
|
base.Add((TValue.t, _med), update, _NaN);
|
||||||
|
|
||||||
base.Add(result, update);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,48 +20,44 @@ TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma
|
|||||||
|
|
||||||
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;
|
|
||||||
_sigma = sigma;
|
|
||||||
_weight = new double[period];
|
|
||||||
|
|
||||||
if (this._data.Count > 0) { base.Add(this._data); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
|
||||||
{
|
|
||||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
|
||||||
else { this._buffer.Add(TValue.v); }
|
|
||||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
|
||||||
|
|
||||||
if (this._buffer.Count <= _p) { calc_weights(); }
|
|
||||||
|
|
||||||
double _weightedSum = 0;
|
|
||||||
for (int i = 0; i < this._buffer.Count; i++) { _weightedSum += _weight[i] * _buffer[i]; }
|
|
||||||
double _alma = _weightedSum / _norm;
|
|
||||||
|
|
||||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _alma);
|
|
||||||
base.Add(ret, update);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calc_weights()
|
|
||||||
{
|
|
||||||
int _len = this._buffer.Count;
|
|
||||||
_norm = 0;
|
|
||||||
double _m = _offset * (_len - 1);
|
|
||||||
double _s = _len / _sigma;
|
|
||||||
for (int i = 0; i < _len; i++)
|
|
||||||
{
|
{
|
||||||
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
|
_offset = offset;
|
||||||
_weight[i] = _wt;
|
_sigma = sigma;
|
||||||
_norm += _wt;
|
_weight = new double[period];
|
||||||
|
|
||||||
|
if (this._data.Count > 0) { base.Add(this._data); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||||
|
{
|
||||||
|
Add_Replace_Trim(_buffer, TValue.v, _p, update);
|
||||||
|
|
||||||
|
if (this._buffer.Count <= _p)
|
||||||
|
{
|
||||||
|
int _len = this._buffer.Count;
|
||||||
|
_norm = 0;
|
||||||
|
double _m = _offset * (_len - 1);
|
||||||
|
double _s = _len / _sigma;
|
||||||
|
for (int i = 0; i < _len; i++)
|
||||||
|
{
|
||||||
|
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
|
||||||
|
_weight[i] = _wt;
|
||||||
|
_norm += _wt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double _weightedSum = 0;
|
||||||
|
for (int i = 0; i < this._buffer.Count; i++)
|
||||||
|
{ _weightedSum += _weight[i] * _buffer[i]; }
|
||||||
|
double _alma = _weightedSum / _norm;
|
||||||
|
|
||||||
|
base.Add((TValue.t, _alma), update, _NaN);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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,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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ public class PandasTA : IDisposable
|
|||||||
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()
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,7 @@ public class PandasTA : IDisposable
|
|||||||
[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));
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,15 @@ 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 OBV()
|
||||||
|
{
|
||||||
|
OBV_Series QL = new(bars);
|
||||||
|
var pta = df.ta.obv(close: df.close, volume: df.volume);
|
||||||
|
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
void ATR()
|
void ATR()
|
||||||
{
|
{
|
||||||
ATR_Series QL = new(bars, period);
|
ATR_Series QL = new(bars, period);
|
||||||
@@ -149,21 +157,21 @@ public class PandasTA : IDisposable
|
|||||||
[Fact]
|
[Fact]
|
||||||
void TRIMA()
|
void TRIMA()
|
||||||
{
|
{
|
||||||
//TODO: return length to variable length (period) when Pandas-TA fixes trima
|
// TODO: return length to variable length (period) when Pandas-TA fixes trima
|
||||||
TRIMA_Series QL = new(bars.Close, 11);
|
TRIMA_Series QL = new(bars.Close, 11);
|
||||||
var pta = df.ta.trima(close: df.close, length: 11);
|
var pta = df.ta.trima(close: df.close, length: 11);
|
||||||
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
|
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
void KAMA()
|
void KAMA()
|
||||||
{
|
{
|
||||||
KAMA_Series QL = new(bars.Close, period);
|
KAMA_Series QL = new(bars.Close, period);
|
||||||
var pta = df.ta.kama(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 HMA()
|
void HMA()
|
||||||
{
|
{
|
||||||
HMA_Series QL = new(bars.Close, period, false);
|
HMA_Series QL = new(bars.Close, period, false);
|
||||||
@@ -220,9 +228,9 @@ public class PandasTA : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[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));
|
||||||
}
|
}
|
||||||
@@ -268,9 +276,9 @@ public class PandasTA : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,16 @@ public class Skender_Stock
|
|||||||
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]
|
|
||||||
|
[Fact]
|
||||||
|
public void MAMA() {
|
||||||
|
MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
|
||||||
|
var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
|
||||||
|
|
||||||
|
Assert.Equal(Math.Round((double)SK.Last().Mama!, 6), Math.Round(QL.Last().v, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
public void MAD()
|
public void MAD()
|
||||||
{
|
{
|
||||||
MAD_Series QL = new(bars.Close, period, false);
|
MAD_Series QL = new(bars.Close, period, false);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public class TA_LIB
|
|||||||
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[] TALIB2;
|
||||||
private readonly double[] inopen;
|
private readonly double[] inopen;
|
||||||
private readonly double[] inhigh;
|
private readonly double[] inhigh;
|
||||||
private readonly double[] inlow;
|
private readonly double[] inlow;
|
||||||
@@ -21,6 +22,7 @@ public class TA_LIB
|
|||||||
bars = new(5000);
|
bars = new(5000);
|
||||||
period = rnd.Next(28) + 3;
|
period = rnd.Next(28) + 3;
|
||||||
TALIB = new double[bars.Count];
|
TALIB = new double[bars.Count];
|
||||||
|
TALIB2 = new double[bars.Count];
|
||||||
inopen = bars.Open.v.ToArray();
|
inopen = bars.Open.v.ToArray();
|
||||||
inhigh = bars.High.v.ToArray();
|
inhigh = bars.High.v.ToArray();
|
||||||
inlow = bars.Low.v.ToArray();
|
inlow = bars.Low.v.ToArray();
|
||||||
@@ -130,7 +132,16 @@ public class TA_LIB
|
|||||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.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 MAMA() {
|
||||||
|
MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05);
|
||||||
|
Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05);
|
||||||
|
|
||||||
|
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
public void TRIMA()
|
public void TRIMA()
|
||||||
{
|
{
|
||||||
TRIMA_Series QL = new(bars.Close, period, false);
|
TRIMA_Series QL = new(bars.Close, period, false);
|
||||||
@@ -315,4 +326,5 @@ public class TA_LIB
|
|||||||
|
|
||||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -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 ||
|
||||||
|
|||||||
Reference in New Issue
Block a user