mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-14 16:48:04 +00:00
Merge branch 'dev' into main
This commit is contained in:
@@ -30,6 +30,8 @@ jobs:
|
||||
with:
|
||||
java-version: 1.11
|
||||
|
||||
- name: Install GitVersion
|
||||
run: dotnet tool install GitVersion.Tool --global
|
||||
- name: Install JetBrains
|
||||
run: dotnet tool install JetBrains.dotCover.GlobalTool --global
|
||||
- name: Install Sonar Scanner
|
||||
@@ -78,14 +80,14 @@ jobs:
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
coverage-reports: ./coveragereport.xml
|
||||
|
||||
- name: Release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "latest"
|
||||
prerelease: true
|
||||
title: "Latest Build"
|
||||
files: /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll
|
||||
# - name: Release
|
||||
# uses: marvinpinto/action-automatic-releases@latest
|
||||
# with:
|
||||
# repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
# automatic_release_tag: "latest"
|
||||
# prerelease: true
|
||||
# title: "Latest Build"
|
||||
# files: /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll
|
||||
|
||||
- name: Authenticate to Github packages source
|
||||
run: dotnet nuget add source
|
||||
@@ -95,14 +97,12 @@ jobs:
|
||||
--name github "https://nuget.pkg.github.com/mihakralj/index.json"
|
||||
|
||||
- name: Push package to github
|
||||
if: ${{ github.ref == 'refs/heads/dev' }}
|
||||
run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
|
||||
--api-key ${{ secrets.GITHUB_TOKEN }}
|
||||
--source https://nuget.pkg.github.com/mihakralj/index.json
|
||||
--skip-duplicate
|
||||
--no-symbols
|
||||
|
||||
- name: Push package to nuget.org
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Push package to nuget.org
|
||||
run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
|
||||
--api-key ${{ secrets.NUGET_DEPLOY_KEY_QUANTLIB }}
|
||||
--source https://api.nuget.org/v3/index.json
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
next-version: 0.1.19
|
||||
minor-version-bump-message: \+semver:\s?(feature|new)
|
||||
branches:
|
||||
main:
|
||||
regex: ^main$
|
||||
is-release-branch: true
|
||||
prevent-increment-of-merged-branch-version: true
|
||||
mode: ContinuousDelivery
|
||||
tag: ''
|
||||
increment: Patch
|
||||
develop:
|
||||
regex: ^dev(elop)?(ment)?$
|
||||
is-release-branch: false
|
||||
mode: ContinuousDelivery
|
||||
tag: 'nightly'
|
||||
increment: Inherit
|
||||
update-build-number: true
|
||||
@@ -5,42 +5,22 @@ VisualStudioVersion = 17.2.32210.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuanTAlib", "Source\QuanTAlib.csproj", "{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quantower", "Quantower\Quantower.csproj", "{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Release|x64.ActiveCfg = Release|x64
|
||||
{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}.Release|x64.Build.0 = Release|x64
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Debug|x64.ActiveCfg = Release|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Debug|x64.Build.0 = Release|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Release|x64.ActiveCfg = Release|x64
|
||||
{5096AEA1-81BC-46E7-9F2B-B408AFAA850C}.Release|x64.Build.0 = Release|x64
|
||||
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|x64.Build.0 = Debug|x64
|
||||
{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|x64.ActiveCfg = Release|x64
|
||||
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class SDEV_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]
|
||||
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
|
||||
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
|
||||
private int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private SDEV_Series indicator;
|
||||
///////
|
||||
|
||||
public SDEV_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "SDEV - Standard Deviation";
|
||||
this.Description = "SDEV description";
|
||||
this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName =
|
||||
"SDEV (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: bars.Select(this.DataSource),
|
||||
period: this.Period, useNaN: true);
|
||||
}
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar ||
|
||||
args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
|
||||
this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
|
||||
this.GetPrice(PriceType.Close),
|
||||
this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class SDEV_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]
|
||||
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
|
||||
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
|
||||
private int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private SDEV_Series indicator;
|
||||
///////
|
||||
|
||||
public SDEV_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "SDEV - Standard Deviation";
|
||||
this.Description = "SDEV description";
|
||||
this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName =
|
||||
"SDEV (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: bars.Select(this.DataSource),
|
||||
period: this.Period, useNaN: true);
|
||||
}
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar ||
|
||||
args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
|
||||
this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
|
||||
this.GetPrice(PriceType.Close),
|
||||
this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class VAR_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]
|
||||
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
|
||||
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
|
||||
private int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private VAR_Series indicator;
|
||||
///////
|
||||
|
||||
public VAR_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "VAR - Variance";
|
||||
this.Description = "VAR description";
|
||||
this.AddLineSeries("VAR", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName =
|
||||
"VAR (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: bars.Select(this.DataSource),
|
||||
period: this.Period, useNaN: true);
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar ||
|
||||
args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
|
||||
this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
|
||||
this.GetPrice(PriceType.Close),
|
||||
this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class VAR_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]
|
||||
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
|
||||
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
|
||||
private int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private VAR_Series indicator;
|
||||
///////
|
||||
|
||||
public VAR_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "VAR - Variance";
|
||||
this.Description = "VAR description";
|
||||
this.AddLineSeries("VAR", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName =
|
||||
"VAR (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: bars.Select(this.DataSource),
|
||||
period: this.Period, useNaN: true);
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar ||
|
||||
args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
|
||||
this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
|
||||
this.GetPrice(PriceType.Close),
|
||||
this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
namespace QuanTAlib;
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
public class WMAPE_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private readonly int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]{
|
||||
"Open", 0,
|
||||
"High", 1,
|
||||
"Low", 2,
|
||||
"Close", 3,
|
||||
"HL2", 4,
|
||||
"OC2", 5,
|
||||
"OHL3", 6,
|
||||
"HLC3", 7,
|
||||
"OHLC4", 8,
|
||||
"Weighted (HLCC4)", 9
|
||||
})]
|
||||
private readonly int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private QuanTAlib.WMAPE_Series indicator;
|
||||
///////
|
||||
|
||||
public WMAPE_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "WMAPE - Weighted Mean Absolute Percentage Error";
|
||||
this.Description = "WMAPE description";
|
||||
this.AddLineSeries("WMAPE", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName = "WMAPE (" + QuanTAlib.TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: this.bars.Select(this.DataSource), period: this.Period, useNaN: true);
|
||||
}
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
public class WMAPE_chart : Indicator
|
||||
{
|
||||
#region Parameters
|
||||
|
||||
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
|
||||
private readonly int Period = 10;
|
||||
|
||||
[InputParameter("Data source", 1, variants: new object[]{
|
||||
"Open", 0,
|
||||
"High", 1,
|
||||
"Low", 2,
|
||||
"Close", 3,
|
||||
"HL2", 4,
|
||||
"OC2", 5,
|
||||
"OHL3", 6,
|
||||
"HLC3", 7,
|
||||
"OHLC4", 8,
|
||||
"Weighted (HLCC4)", 9
|
||||
})]
|
||||
private readonly int DataSource = 8;
|
||||
|
||||
#endregion Parameters
|
||||
|
||||
private TBars bars;
|
||||
|
||||
///////dotnet
|
||||
private QuanTAlib.WMAPE_Series indicator;
|
||||
///////
|
||||
|
||||
public WMAPE_chart()
|
||||
{
|
||||
this.SeparateWindow = true;
|
||||
this.Name = "WMAPE - Weighted Mean Absolute Percentage Error";
|
||||
this.Description = "WMAPE description";
|
||||
this.AddLineSeries("WMAPE", Color.RoyalBlue, 3, LineStyle.Solid);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
this.bars = new();
|
||||
this.ShortName = "WMAPE (" + QuanTAlib.TBars.SelectStr(this.DataSource) + ", " + this.Period + ")";
|
||||
this.indicator = new(source: this.bars.Select(this.DataSource), period: this.Period, useNaN: true);
|
||||
}
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
|
||||
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
|
||||
double result = this.indicator[this.indicator.Count - 1].v;
|
||||
|
||||
this.SetValue(result, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+135
-135
@@ -1,135 +1,135 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
/* <summary>
|
||||
Abstract classes with all scaffolding required to build indicators.
|
||||
All abstracts support period, NaN, and all permutations of Add() methods.
|
||||
Indicator classess need to implement:
|
||||
- Chaining constructor (Abstract's constructor executes first)
|
||||
- Default Add(value) class
|
||||
- optional Add(series) bulk insert class (for optimization of historical analysis)
|
||||
|
||||
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
|
||||
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
|
||||
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
|
||||
|
||||
</summary> */
|
||||
public abstract class Single_TSeries_Indicator : TSeries
|
||||
{
|
||||
protected readonly int _p;
|
||||
protected readonly bool _NaN;
|
||||
protected readonly TSeries _data;
|
||||
|
||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
||||
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN)
|
||||
{
|
||||
this._data = source;
|
||||
this._p = period;
|
||||
this._NaN = useNaN;
|
||||
this._data.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add() method to add/update a single item at the end of the list
|
||||
public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
|
||||
|
||||
// potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
|
||||
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }}
|
||||
|
||||
public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
|
||||
public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
|
||||
public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
|
||||
}
|
||||
|
||||
public abstract class Pair_TSeries_Indicator : TSeries
|
||||
{
|
||||
protected readonly TSeries _d1;
|
||||
protected readonly TSeries _d2;
|
||||
protected readonly double _dd1, _dd2;
|
||||
|
||||
// Chainable Constructors - add them at the end of primary constructors if needed
|
||||
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
|
||||
{
|
||||
this._d1 = source1;
|
||||
this._d2 = source2;
|
||||
this._dd1 = double.NaN;
|
||||
this._dd2 = double.NaN;
|
||||
this._d1.Pub += this.Sub;
|
||||
this._d2.Pub += this.Sub;
|
||||
}
|
||||
protected Pair_TSeries_Indicator(TSeries source1, double dd2)
|
||||
{
|
||||
this._d1 = source1;
|
||||
this._d2 = new();
|
||||
this._dd1 = double.NaN;
|
||||
this._dd2 = dd2;
|
||||
this._d1.Pub += this.Sub;
|
||||
}
|
||||
protected Pair_TSeries_Indicator(double dd1, TSeries source2)
|
||||
{
|
||||
this._d1 = new();
|
||||
this._d2 = source2;
|
||||
this._dd1 = dd1;
|
||||
this._dd2 = double.NaN;
|
||||
this._d2.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
|
||||
public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) => base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
|
||||
|
||||
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
|
||||
public virtual void Add(TSeries d1, TSeries d2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); }}
|
||||
public virtual void Add(TSeries d1, double dd2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }}
|
||||
public virtual void Add(double dd1, TSeries d2) { for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }}
|
||||
|
||||
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
|
||||
|
||||
public void Add(bool update)
|
||||
{
|
||||
if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN))
|
||||
{
|
||||
// (Series, Series)
|
||||
if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count))
|
||||
{ this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); }
|
||||
}
|
||||
else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN))
|
||||
{
|
||||
// (Series, Double)
|
||||
this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update);
|
||||
}
|
||||
else
|
||||
{
|
||||
// (Double, Series)
|
||||
this.Add(TValue1: (this._d2[this._d2.Count - 1].t, this._dd1), TValue2: this._d2[this._d2.Count - 1], update: update);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add() => this.Add(update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
|
||||
}
|
||||
|
||||
public abstract class Single_TBars_Indicator : TSeries
|
||||
{
|
||||
protected readonly int _p;
|
||||
protected readonly bool _NaN;
|
||||
protected readonly TBars _bars;
|
||||
|
||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
||||
protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
|
||||
{
|
||||
this._p = period;
|
||||
this._bars = source;
|
||||
this._NaN = useNaN;
|
||||
this._bars.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add() method to add/update a single item at the end of the list
|
||||
public virtual void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update);
|
||||
|
||||
// potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo)
|
||||
public virtual void Add(TBars bars) { for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); }}
|
||||
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }}
|
||||
public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar) => this.Add(TBar: TBar, update: false);
|
||||
public void Add(bool update) => this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
|
||||
public void Add() => this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
/* <summary>
|
||||
Abstract classes with all scaffolding required to build indicators.
|
||||
All abstracts support period, NaN, and all permutations of Add() methods.
|
||||
Indicator classess need to implement:
|
||||
- Chaining constructor (Abstract's constructor executes first)
|
||||
- Default Add(value) class
|
||||
- optional Add(series) bulk insert class (for optimization of historical analysis)
|
||||
|
||||
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
|
||||
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
|
||||
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
|
||||
|
||||
</summary> */
|
||||
public abstract class Single_TSeries_Indicator : TSeries
|
||||
{
|
||||
protected readonly int _p;
|
||||
protected readonly bool _NaN;
|
||||
protected readonly TSeries _data;
|
||||
|
||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
||||
protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN)
|
||||
{
|
||||
this._data = source;
|
||||
this._p = period;
|
||||
this._NaN = useNaN;
|
||||
this._data.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add() method to add/update a single item at the end of the list
|
||||
public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
|
||||
|
||||
// potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
|
||||
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }}
|
||||
|
||||
public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
|
||||
public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
|
||||
public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
|
||||
}
|
||||
|
||||
public abstract class Pair_TSeries_Indicator : TSeries
|
||||
{
|
||||
protected readonly TSeries _d1;
|
||||
protected readonly TSeries _d2;
|
||||
protected readonly double _dd1, _dd2;
|
||||
|
||||
// Chainable Constructors - add them at the end of primary constructors if needed
|
||||
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
|
||||
{
|
||||
this._d1 = source1;
|
||||
this._d2 = source2;
|
||||
this._dd1 = double.NaN;
|
||||
this._dd2 = double.NaN;
|
||||
this._d1.Pub += this.Sub;
|
||||
this._d2.Pub += this.Sub;
|
||||
}
|
||||
protected Pair_TSeries_Indicator(TSeries source1, double dd2)
|
||||
{
|
||||
this._d1 = source1;
|
||||
this._d2 = new();
|
||||
this._dd1 = double.NaN;
|
||||
this._dd2 = dd2;
|
||||
this._d1.Pub += this.Sub;
|
||||
}
|
||||
protected Pair_TSeries_Indicator(double dd1, TSeries source2)
|
||||
{
|
||||
this._d1 = new();
|
||||
this._d2 = source2;
|
||||
this._dd1 = dd1;
|
||||
this._dd2 = double.NaN;
|
||||
this._d2.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
|
||||
public virtual void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) => base.Add(TValue: (TValue1.t, 0), update: update); // default inserts zeros
|
||||
|
||||
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
|
||||
public virtual void Add(TSeries d1, TSeries d2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], d2[i], update: false); }}
|
||||
public virtual void Add(TSeries d1, double dd2) { for (int i = 0; i < d1.Count; i++) { this.Add(d1[i], (d1[i].t, dd2), update: false); }}
|
||||
public virtual void Add(double dd1, TSeries d2) { for (int i = 0; i < d2.Count; i++) { this.Add((d2[i].t, dd1), d2[i], update: false); }}
|
||||
|
||||
public void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2) => this.Add(TValue1, TValue2, update: false);
|
||||
|
||||
public void Add(bool update)
|
||||
{
|
||||
if ((this._dd1 is double.NaN) && (this._dd2 is double.NaN))
|
||||
{
|
||||
// (Series, Series)
|
||||
if (update || (this._d1.Count > this.Count && this._d2.Count > this.Count))
|
||||
{ this.Add(this._d1[this._d1.Count - 1], this._d2[this._d2.Count - 1], update); }
|
||||
}
|
||||
else if ((this._dd2 is not double.NaN) && (this._dd1 is double.NaN))
|
||||
{
|
||||
// (Series, Double)
|
||||
this.Add(TValue1: this._d1[this._d1.Count - 1], TValue2: (this._d1[this._d1.Count - 1].t, this._dd2), update: update);
|
||||
}
|
||||
else
|
||||
{
|
||||
// (Double, Series)
|
||||
this.Add(TValue1: (this._d2[this._d2.Count - 1].t, this._dd1), TValue2: this._d2[this._d2.Count - 1], update: update);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add() => this.Add(update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(e.update);
|
||||
}
|
||||
|
||||
public abstract class Single_TBars_Indicator : TSeries
|
||||
{
|
||||
protected readonly int _p;
|
||||
protected readonly bool _NaN;
|
||||
protected readonly TBars _bars;
|
||||
|
||||
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
|
||||
protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
|
||||
{
|
||||
this._p = period;
|
||||
this._bars = source;
|
||||
this._NaN = useNaN;
|
||||
this._bars.Pub += this.Sub;
|
||||
}
|
||||
|
||||
// overridable Add() method to add/update a single item at the end of the list
|
||||
public virtual void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar, bool update) => base.Add((TBar.t, 0.0), update);
|
||||
|
||||
// potentially overridable Add() method for the whole bars or series (could be replaced with faster bulk algo)
|
||||
public virtual void Add(TBars bars) { for (int i = 0; i < bars.Count; i++) { this.Add(TBar: bars[i], update: false); }}
|
||||
public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { base.Add(TValue: data[i], update: false); }}
|
||||
public void Add((System.DateTime t, double o, double h, double l, double c, double v) TBar) => this.Add(TBar: TBar, update: false);
|
||||
public void Add(bool update) => this.Add(TBar: this._bars[this._bars.Count - 1], update: update);
|
||||
public void Add() => this.Add(TBar: this._bars[this._bars.Count - 1], update: false);
|
||||
public new void Sub(object source, TSeriesEventArgs e) => this.Add(TBar: this._bars[this._bars.Count - 1], update: e.update);
|
||||
}
|
||||
|
||||
+33
-33
@@ -1,34 +1,34 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MAX - Maximum value in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
</summary> */
|
||||
|
||||
public class MAX_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _max = TValue.v;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
//_max = (this._buffer[i] > _max) ? this._buffer[i] : _max;
|
||||
_max = Math.Max(this._buffer[i], _max);
|
||||
}
|
||||
|
||||
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MAX - Maximum value in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
</summary> */
|
||||
|
||||
public class MAX_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _max = TValue.v;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
//_max = (this._buffer[i] > _max) ? this._buffer[i] : _max;
|
||||
_max = Math.Max(this._buffer[i], _max);
|
||||
}
|
||||
|
||||
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MIDPOINT: Midpoint value (max+min)/2 in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
|
||||
Sources:
|
||||
https://thefaqblog.com/what-is-the-midpoint-in-statistics/
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MIDPOINT_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MIDPOINT_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0)
|
||||
{ base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{ this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{ this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0)
|
||||
{ this._buffer.RemoveAt(0); }
|
||||
|
||||
double _max = TValue.v;
|
||||
double _min = TValue.v;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
_max = Math.Max(this._buffer[i], _max);
|
||||
_min = Math.Min(this._buffer[i], _min);
|
||||
}
|
||||
double _mid = (_max + _min) * 0.5;
|
||||
|
||||
var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MIDPRICE_Series : Single_TBars_Indicator
|
||||
{
|
||||
public MIDPRICE_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._bars.Count > 0)
|
||||
{ base.Add(base._bars); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _bufferhi = new();
|
||||
private readonly System.Collections.Generic.List<double> _bufferlo = new();
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._bufferhi[this._bufferhi.Count - 1] = TBar.h;
|
||||
this._bufferlo[this._bufferlo.Count - 1] = TBar.l;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._bufferhi.Add(TBar.h);
|
||||
this._bufferlo.Add(TBar.l);
|
||||
}
|
||||
if (this._bufferhi.Count > this._p && this._p != 0)
|
||||
{ this._bufferhi.RemoveAt(0); }
|
||||
if (this._bufferlo.Count > this._p && this._p != 0)
|
||||
{ this._bufferlo.RemoveAt(0); }
|
||||
|
||||
double _max = TBar.h;
|
||||
double _min = TBar.l;
|
||||
for (int i = 0; i < this._bufferhi.Count; i++)
|
||||
{
|
||||
_max = Math.Max(this._bufferhi[i], _max);
|
||||
_min = Math.Min(this._bufferlo[i], _min);
|
||||
}
|
||||
double _mid = (_max + _min) * 0.5;
|
||||
|
||||
var result = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+33
-33
@@ -1,34 +1,34 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MIN - Minimum value in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
</summary> */
|
||||
|
||||
public class MIN_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MIN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _min = TValue.v;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
//_min = (this._buffer[i] < _min) ? this._buffer[i] : _min;
|
||||
_min = Math.Min(this._buffer[i], _min);
|
||||
}
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _min);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MIN - Minimum value in the given period in the series.
|
||||
If period = 0 => period = full length of the series
|
||||
</summary> */
|
||||
|
||||
public class MIN_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MIN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _min = TValue.v;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
//_min = (this._buffer[i] < _min) ? this._buffer[i] : _min;
|
||||
_min = Math.Min(this._buffer[i], _min);
|
||||
}
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _min);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SUM: Cumulative Sum (aka Running Total)
|
||||
SUM across a period provides a rolling sum of all values across the period.
|
||||
If SUM values would be divided with period, the output would be SMA()
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/CUSUM
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SUM_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SUM_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sum = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; }
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sum);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+132
-132
@@ -1,132 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TBars class - includes all series for common data used in indicators and other calculations.
|
||||
Has a bit limited overloading and casting (compared to TSeries)
|
||||
Includes Select(int) method to simplify choosing the most optimal data source for indicators
|
||||
Includes the most basic pricing calcs: HL2, OC2, OHL3, HLC3, OHLC4, HLCC4
|
||||
(it is 'cheaper' to calculate them once during data capture than each time during data analysis)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)>
|
||||
{
|
||||
private readonly TSeries _open = new();
|
||||
private readonly TSeries _high = new();
|
||||
private readonly TSeries _low = new();
|
||||
private readonly TSeries _close = new();
|
||||
private readonly TSeries _volume = new();
|
||||
private readonly TSeries _hl2 = new();
|
||||
private readonly TSeries _oc2 = new();
|
||||
private readonly TSeries _ohl3 = new();
|
||||
private readonly TSeries _hlc3 = new();
|
||||
private readonly TSeries _ohlc4 = new();
|
||||
private readonly TSeries _hlcc4 = new();
|
||||
|
||||
public TSeries Open => this._open;
|
||||
public TSeries High => this._high;
|
||||
public TSeries Low => this._low;
|
||||
public TSeries Close => this._close;
|
||||
public TSeries Volume => this._volume;
|
||||
public TSeries HL2 => this._hl2;
|
||||
public TSeries OC2 => this._oc2;
|
||||
public TSeries OHL3 => this._ohl3;
|
||||
public TSeries HLC3 => this._hlc3;
|
||||
public TSeries OHLC4 => this._ohlc4;
|
||||
public TSeries HLCC4 => this._hlcc4;
|
||||
|
||||
public TBars Tail(int count=10) {
|
||||
TBars outBars = new();
|
||||
if (count > this.Count) { count = this.Count; }
|
||||
for (int i = this.Count-count; i<this.Count; i++) { outBars.Add(this[i]); }
|
||||
return outBars;
|
||||
}
|
||||
public TSeries Select(int source)
|
||||
{
|
||||
return source switch
|
||||
{
|
||||
0 => _open,
|
||||
1 => _high,
|
||||
2 => _low,
|
||||
3 => _close,
|
||||
4 => _hl2,
|
||||
5 => _oc2,
|
||||
6 => _ohl3,
|
||||
7 => _hlc3,
|
||||
8 => _ohlc4,
|
||||
_ => _hlcc4,
|
||||
};
|
||||
}
|
||||
public static string SelectStr(int source)
|
||||
{
|
||||
return source switch
|
||||
{
|
||||
0 => "Open",
|
||||
1 => "High",
|
||||
2 => "Low",
|
||||
3 => "Close",
|
||||
4 => "HL2",
|
||||
5 => "OC2",
|
||||
6 => "OHL3",
|
||||
7 => "Typical",
|
||||
8 => "Mean",
|
||||
_ => "Weighted",
|
||||
};
|
||||
}
|
||||
|
||||
public void Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false)
|
||||
=> Add(i.t, i.o, i.h, i.l, i.c, i.v, update);
|
||||
|
||||
public void Add(DateTime t, decimal o, decimal h, decimal l, decimal c, decimal v, bool update = false)
|
||||
=> Add(t, (double)o, (double)h, (double)l, (double)c, (double)v, update);
|
||||
|
||||
public void Add(DateTime t, double o, double h, double l, double c, double v, bool update = false)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this[this.Count - 1] = (t, o, h, l, c, v);
|
||||
_open[_open.Count - 1] = (t, o);
|
||||
_high[_high.Count - 1] = (t, h);
|
||||
_low[_low.Count - 1] = (t, l);
|
||||
_close[_close.Count - 1] = (t, c);
|
||||
_volume[_volume.Count - 1] = (t, v);
|
||||
_hl2[_hl2.Count - 1] = (t, (h + l) * 0.5);
|
||||
_oc2[_oc2.Count - 1] = (t, (o + c) * 0.5);
|
||||
_ohl3[_ohl3.Count - 1] = (t, (o + h + l) * 0.333333333333333);
|
||||
_hlc3[_hlc3.Count - 1] = (t, (h + l + c) * 0.333333333333333);
|
||||
_ohlc4[_ohlc4.Count - 1] = (t, (o + h + l + c) * 0.25);
|
||||
_hlcc4[_hlcc4.Count - 1] = (t, (h + l + c + c) * 0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Add((t, o, h, l, c, v));
|
||||
_open.Add((t, o));
|
||||
_high.Add((t, h));
|
||||
_low.Add((t, l));
|
||||
_close.Add((t, c));
|
||||
_volume.Add((t, v));
|
||||
_hl2.Add((t, (h + l) * 0.5));
|
||||
_oc2.Add((t, (o + c) * 0.5));
|
||||
_ohl3.Add((t, (o + h + l) * 0.333333333333333));
|
||||
_hlc3.Add((t, (h + l + c) * 0.333333333333333));
|
||||
_ohlc4.Add((t, (o + h + l + c) * 0.25));
|
||||
_hlcc4.Add((t, (h + l + c + c) * 0.25));
|
||||
}
|
||||
this.OnEvent(update);
|
||||
}
|
||||
|
||||
// delegate used by event handler + event handler (Pub == publisher)
|
||||
public delegate
|
||||
void NewDataEventHandler(object source, TSeriesEventArgs args);
|
||||
public event NewDataEventHandler Pub;
|
||||
|
||||
// Broadcast handler - only to valid targets
|
||||
protected virtual void OnEvent(bool update = false)
|
||||
{
|
||||
if (Pub != null && Pub.Target != this)
|
||||
{
|
||||
Pub(this, new TSeriesEventArgs { update = update });
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TBars class - includes all series for common data used in indicators and other calculations.
|
||||
Has a bit limited overloading and casting (compared to TSeries)
|
||||
Includes Select(int) method to simplify choosing the most optimal data source for indicators
|
||||
Includes the most basic pricing calcs: HL2, OC2, OHL3, HLC3, OHLC4, HLCC4
|
||||
(it is 'cheaper' to calculate them once during data capture than each time during data analysis)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)>
|
||||
{
|
||||
private readonly TSeries _open = new();
|
||||
private readonly TSeries _high = new();
|
||||
private readonly TSeries _low = new();
|
||||
private readonly TSeries _close = new();
|
||||
private readonly TSeries _volume = new();
|
||||
private readonly TSeries _hl2 = new();
|
||||
private readonly TSeries _oc2 = new();
|
||||
private readonly TSeries _ohl3 = new();
|
||||
private readonly TSeries _hlc3 = new();
|
||||
private readonly TSeries _ohlc4 = new();
|
||||
private readonly TSeries _hlcc4 = new();
|
||||
|
||||
public TSeries Open => this._open;
|
||||
public TSeries High => this._high;
|
||||
public TSeries Low => this._low;
|
||||
public TSeries Close => this._close;
|
||||
public TSeries Volume => this._volume;
|
||||
public TSeries HL2 => this._hl2;
|
||||
public TSeries OC2 => this._oc2;
|
||||
public TSeries OHL3 => this._ohl3;
|
||||
public TSeries HLC3 => this._hlc3;
|
||||
public TSeries OHLC4 => this._ohlc4;
|
||||
public TSeries HLCC4 => this._hlcc4;
|
||||
|
||||
public TBars Tail(int count=10) {
|
||||
TBars outBars = new();
|
||||
if (count > this.Count) { count = this.Count; }
|
||||
for (int i = this.Count-count; i<this.Count; i++) { outBars.Add(this[i]); }
|
||||
return outBars;
|
||||
}
|
||||
public TSeries Select(int source)
|
||||
{
|
||||
return source switch
|
||||
{
|
||||
0 => _open,
|
||||
1 => _high,
|
||||
2 => _low,
|
||||
3 => _close,
|
||||
4 => _hl2,
|
||||
5 => _oc2,
|
||||
6 => _ohl3,
|
||||
7 => _hlc3,
|
||||
8 => _ohlc4,
|
||||
_ => _hlcc4,
|
||||
};
|
||||
}
|
||||
public static string SelectStr(int source)
|
||||
{
|
||||
return source switch
|
||||
{
|
||||
0 => "Open",
|
||||
1 => "High",
|
||||
2 => "Low",
|
||||
3 => "Close",
|
||||
4 => "HL2",
|
||||
5 => "OC2",
|
||||
6 => "OHL3",
|
||||
7 => "Typical",
|
||||
8 => "Mean",
|
||||
_ => "Weighted",
|
||||
};
|
||||
}
|
||||
|
||||
public void Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false)
|
||||
=> Add(i.t, i.o, i.h, i.l, i.c, i.v, update);
|
||||
|
||||
public void Add(DateTime t, decimal o, decimal h, decimal l, decimal c, decimal v, bool update = false)
|
||||
=> Add(t, (double)o, (double)h, (double)l, (double)c, (double)v, update);
|
||||
|
||||
public void Add(DateTime t, double o, double h, double l, double c, double v, bool update = false)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this[this.Count - 1] = (t, o, h, l, c, v);
|
||||
_open[_open.Count - 1] = (t, o);
|
||||
_high[_high.Count - 1] = (t, h);
|
||||
_low[_low.Count - 1] = (t, l);
|
||||
_close[_close.Count - 1] = (t, c);
|
||||
_volume[_volume.Count - 1] = (t, v);
|
||||
_hl2[_hl2.Count - 1] = (t, (h + l) * 0.5);
|
||||
_oc2[_oc2.Count - 1] = (t, (o + c) * 0.5);
|
||||
_ohl3[_ohl3.Count - 1] = (t, (o + h + l) * 0.333333333333333);
|
||||
_hlc3[_hlc3.Count - 1] = (t, (h + l + c) * 0.333333333333333);
|
||||
_ohlc4[_ohlc4.Count - 1] = (t, (o + h + l + c) * 0.25);
|
||||
_hlcc4[_hlcc4.Count - 1] = (t, (h + l + c + c) * 0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Add((t, o, h, l, c, v));
|
||||
_open.Add((t, o));
|
||||
_high.Add((t, h));
|
||||
_low.Add((t, l));
|
||||
_close.Add((t, c));
|
||||
_volume.Add((t, v));
|
||||
_hl2.Add((t, (h + l) * 0.5));
|
||||
_oc2.Add((t, (o + c) * 0.5));
|
||||
_ohl3.Add((t, (o + h + l) * 0.333333333333333));
|
||||
_hlc3.Add((t, (h + l + c) * 0.333333333333333));
|
||||
_ohlc4.Add((t, (o + h + l + c) * 0.25));
|
||||
_hlcc4.Add((t, (h + l + c + c) * 0.25));
|
||||
}
|
||||
this.OnEvent(update);
|
||||
}
|
||||
|
||||
// delegate used by event handler + event handler (Pub == publisher)
|
||||
public delegate
|
||||
void NewDataEventHandler(object source, TSeriesEventArgs args);
|
||||
public event NewDataEventHandler Pub;
|
||||
|
||||
// Broadcast handler - only to valid targets
|
||||
protected virtual void OnEvent(bool update = false)
|
||||
{
|
||||
if (Pub != null && Pub.Target != this)
|
||||
{
|
||||
Pub(this, new TSeriesEventArgs { update = update });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-27
@@ -1,28 +1,28 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
Random Bars generator - used for testing, validation and fun
|
||||
Returns 'bars' number of candles that follow common market movement.
|
||||
volatility defines how 'jumpy' is the series of
|
||||
startvalue defines beginning closing price that then guides the rest of series
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RND_Feed : TBars
|
||||
{
|
||||
public RND_Feed(int bars, double volatility = 0.05, double startvalue = 100.0)
|
||||
{
|
||||
Random rnd = new();
|
||||
double c = startvalue;
|
||||
for (int i = 0; i < bars; i++)
|
||||
{
|
||||
double o = Math.Round(c + (c * (((volatility * 0.1) * rnd.NextDouble()) - 0.005)), 2);
|
||||
double h = Math.Round(o + (c * volatility * rnd.NextDouble()), 2);
|
||||
double l = Math.Round(o - (c * volatility * rnd.NextDouble()), 2);
|
||||
c = Math.Round(l + ((h - l) * rnd.NextDouble()), 2);
|
||||
double v = Math.Round(1000 * rnd.NextDouble(), 2);
|
||||
this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
Random Bars generator - used for testing, validation and fun
|
||||
Returns 'bars' number of candles that follow common market movement.
|
||||
volatility defines how 'jumpy' is the series of
|
||||
startvalue defines beginning closing price that then guides the rest of series
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RND_Feed : TBars
|
||||
{
|
||||
public RND_Feed(int bars, double volatility = 0.05, double startvalue = 100.0)
|
||||
{
|
||||
Random rnd = new();
|
||||
double c = startvalue;
|
||||
for (int i = 0; i < bars; i++)
|
||||
{
|
||||
double o = Math.Round(c + (c * (((volatility * 0.1) * rnd.NextDouble()) - 0.005)), 2);
|
||||
double h = Math.Round(o + (c * volatility * rnd.NextDouble()), 2);
|
||||
double l = Math.Round(o - (c * volatility * rnd.NextDouble()), 2);
|
||||
c = Math.Round(l + ((h - l) * rnd.NextDouble()), 2);
|
||||
double v = Math.Round(1000 * rnd.NextDouble(), 2);
|
||||
this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
CCI: Commodity Channel Index
|
||||
Commodity Channel Index is a momentum oscillator used to primarily identify overbought
|
||||
and oversold levels relative to a mean. CCI measures the current price level relative
|
||||
to an average price level over a given period of time:
|
||||
- CCI is relatively high when prices are far above their average.
|
||||
- CCI is relatively low when prices are far below their average.
|
||||
Using this method, CCI can be used to identify overbought and oversold levels.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/c/commoditychannelindex.asp
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cci
|
||||
|
||||
</summary> */
|
||||
|
||||
public class CCI_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _tp = new();
|
||||
|
||||
public CCI_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
|
||||
if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); }
|
||||
if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
|
||||
|
||||
// average TP over _tp buffer
|
||||
double _avgTp = 0;
|
||||
for (int i = 0; i < this._tp.Count; i++) { _avgTp+=this._tp[i]; }
|
||||
_avgTp /= this._tp.Count;
|
||||
|
||||
// average Deviation over _tp buffer
|
||||
double _avgDv = 0;
|
||||
for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
|
||||
_avgDv /= this._tp.Count;
|
||||
|
||||
double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv);
|
||||
|
||||
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _cci);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
CCI: Commodity Channel Index
|
||||
Commodity Channel Index is a momentum oscillator used to primarily identify overbought
|
||||
and oversold levels relative to a mean. CCI measures the current price level relative
|
||||
to an average price level over a given period of time:
|
||||
- CCI is relatively high when prices are far above their average.
|
||||
- CCI is relatively low when prices are far below their average.
|
||||
Using this method, CCI can be used to identify overbought and oversold levels.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/c/commoditychannelindex.asp
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cci
|
||||
|
||||
</summary> */
|
||||
|
||||
public class CCI_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _tp = new();
|
||||
|
||||
public CCI_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
|
||||
if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); }
|
||||
if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
|
||||
|
||||
// average TP over _tp buffer
|
||||
double _avgTp = 0;
|
||||
for (int i = 0; i < this._tp.Count; i++) { _avgTp+=this._tp[i]; }
|
||||
_avgTp /= this._tp.Count;
|
||||
|
||||
// average Deviation over _tp buffer
|
||||
double _avgDv = 0;
|
||||
for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
|
||||
_avgDv /= this._tp.Count;
|
||||
|
||||
double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv);
|
||||
|
||||
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _cci);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+72
-71
@@ -1,72 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version>0.1.18</Version>
|
||||
<releaseNotes>
|
||||
</releaseNotes>
|
||||
<Title>QuanTAlib</Title>
|
||||
<Product>Library of Technical Indicators for .NET</Product>
|
||||
<Description>Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis</Description>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/mihakralj/QuanTAlib</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<Authors>Miha Kralj</Authors>
|
||||
<Copyright>Miha Kralj</Copyright>
|
||||
<PackageReadmeFile>readme.md</PackageReadmeFile>
|
||||
<TargetFrameworks>net7.0;net6.0;netstandard2.0</TargetFrameworks>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<RootNamespace>QuanTAlib</RootNamespace>
|
||||
<AssemblyName>QuanTAlib</AssemblyName>
|
||||
<IsPublishable>True</IsPublishable>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
|
||||
<DebugType>embedded</DebugType>
|
||||
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<PackageTags>
|
||||
Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
|
||||
AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
|
||||
Quantitative;Historical;Quotes;
|
||||
</PackageTags>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<PackageLicenseFile></PackageLicenseFile>
|
||||
<SynchReleaseVersion>false</SynchReleaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<WarningLevel>7</WarningLevel>
|
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
|
||||
<PlatformTarget>anycpu</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DebugType></DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<WarningLevel>7</WarningLevel>
|
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
|
||||
<PlatformTarget>anycpu</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageIcon>QuanTAlib2.png</PackageIcon>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\Docs\readme.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
<None Include="..\.github\QuanTAlib2.png">
|
||||
<Pack>True</Pack>
|
||||
<Visible>False</Visible>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.6" />
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Title>QuanTAlib</Title>
|
||||
<Product>Library of Technical Indicators for .NET</Product>
|
||||
<Description>Quantitative Technical Analysis library for both real-time (streaming) and historical data analysis</Description>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/mihakralj/QuanTAlib</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<Authors>Miha Kralj</Authors>
|
||||
<Copyright>Miha Kralj</Copyright>
|
||||
<PackageReadmeFile>readme.md</PackageReadmeFile>
|
||||
<TargetFrameworks>net7.0;</TargetFrameworks>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<RootNamespace>QuanTAlib</RootNamespace>
|
||||
<AssemblyName>QuanTAlib</AssemblyName>
|
||||
<IsPublishable>True</IsPublishable>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
|
||||
<DebugType>embedded</DebugType>
|
||||
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<PackageTags>
|
||||
Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
|
||||
AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
|
||||
Quantitative;Historical;Quotes;
|
||||
</PackageTags>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<PackageLicenseFile></PackageLicenseFile>
|
||||
<SynchReleaseVersion>false</SynchReleaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<WarningLevel>7</WarningLevel>
|
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
|
||||
<PlatformTarget>anycpu</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DebugType></DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<WarningLevel>7</WarningLevel>
|
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
|
||||
<PlatformTarget>anycpu</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageIcon>QuanTAlib2.png</PackageIcon>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\Docs\readme.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
<None Include="..\.github\QuanTAlib2.png">
|
||||
<Pack>True</Pack>
|
||||
<Visible>False</Visible>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.0" />
|
||||
<PackageReference Include="GitVersion.MsBuild" Version="5.11.1">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,62 +1,62 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
KURT: Kurtosis of population
|
||||
Kurtosis characterizes the relative peakedness or flatness of a distribution
|
||||
compared with the normal distribution. Positive kurtosis indicates a relatively
|
||||
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
|
||||
|
||||
The normal curve is called Mesokurtic curve. If the curve of a distribution is
|
||||
more outlier prone (or heavier-tailed) than a normal or mesokurtic curve then
|
||||
it is referred to as a Leptokurtic curve. If a curve is less outlier prone (or
|
||||
lighter-tailed) than a normal curve, it is called as a platykurtic curve.
|
||||
|
||||
Calculation:
|
||||
sum4 = Σ(close-SMA)^4
|
||||
sum2 = (Σ(close-SMA)^2)^2
|
||||
KURT = length * (sum4/sum2)
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Kurtosis
|
||||
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KURT_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public KURT_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._logbase = logbase;
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
protected double _logbase;
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _n = this._buffer.Count;
|
||||
|
||||
double _avg = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _avg += this._buffer[i]; }
|
||||
_avg /= _n;
|
||||
|
||||
double _s2 = 0;
|
||||
double _s4 = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
_s2 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
||||
_s4 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
||||
}
|
||||
|
||||
double _Vx = _s2 / (_n - 1);
|
||||
double _kurt = (_n > 3) ? ((((_n * (_n + 1)) / (((_n - 1) * (_n - 2)) * (_n - 3))) * (_s4 / (_Vx * _Vx))) - (3 * (((_n - 1) * (_n - 1)) / ((_n - 2) * (_n - 3))))) : Double.NaN;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
KURT: Kurtosis of population
|
||||
Kurtosis characterizes the relative peakedness or flatness of a distribution
|
||||
compared with the normal distribution. Positive kurtosis indicates a relatively
|
||||
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
|
||||
|
||||
The normal curve is called Mesokurtic curve. If the curve of a distribution is
|
||||
more outlier prone (or heavier-tailed) than a normal or mesokurtic curve then
|
||||
it is referred to as a Leptokurtic curve. If a curve is less outlier prone (or
|
||||
lighter-tailed) than a normal curve, it is called as a platykurtic curve.
|
||||
|
||||
Calculation:
|
||||
sum4 = Σ(close-SMA)^4
|
||||
sum2 = (Σ(close-SMA)^2)^2
|
||||
KURT = length * (sum4/sum2)
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Kurtosis
|
||||
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KURT_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public KURT_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._logbase = logbase;
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
protected double _logbase;
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _n = this._buffer.Count;
|
||||
|
||||
double _avg = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _avg += this._buffer[i]; }
|
||||
_avg /= _n;
|
||||
|
||||
double _s2 = 0;
|
||||
double _s4 = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{
|
||||
_s2 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
||||
_s4 += (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg) * (this._buffer[i] - _avg);
|
||||
}
|
||||
|
||||
double _Vx = _s2 / (_n - 1);
|
||||
double _kurt = (_n > 3) ? ((((_n * (_n + 1)) / (((_n - 1) * (_n - 2)) * (_n - 3))) * (_s4 / (_Vx * _Vx))) - (3 * (((_n - 1) * (_n - 1)) / ((_n - 2) * (_n - 3))))) : Double.NaN;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? Double.NaN : _kurt);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,47 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MED - Median value
|
||||
Median of numbers is the middlemost value of the given set of numbers.
|
||||
It separates the higher half and the lower half of a given data sample.
|
||||
At least half of the observations are smaller than or equal to median
|
||||
and at least half of the observations are greater than or equal to the median.
|
||||
|
||||
If the number of values is odd, the middlemost observation of the sorted
|
||||
list is the median of the given data. If the number of values is even,
|
||||
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
|
||||
|
||||
If period = 0 => period is max
|
||||
|
||||
Sources:
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
|
||||
https://en.wikipedia.org/wiki/Median
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MED_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MED_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
System.Collections.Generic.List<double> _s = new(this._buffer);
|
||||
_s.Sort();
|
||||
int _p1 = _s.Count / 2;
|
||||
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
|
||||
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MED - Median value
|
||||
Median of numbers is the middlemost value of the given set of numbers.
|
||||
It separates the higher half and the lower half of a given data sample.
|
||||
At least half of the observations are smaller than or equal to median
|
||||
and at least half of the observations are greater than or equal to the median.
|
||||
|
||||
If the number of values is odd, the middlemost observation of the sorted
|
||||
list is the median of the given data. If the number of values is even,
|
||||
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
|
||||
|
||||
If period = 0 => period is max
|
||||
|
||||
Sources:
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
|
||||
https://en.wikipedia.org/wiki/Median
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MED_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public MED_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
System.Collections.Generic.List<double> _s = new(this._buffer);
|
||||
_s.Sort();
|
||||
int _p1 = _s.Count / 2;
|
||||
int _p2 = Math.Max(0, (_s.Count / 2) - 1);
|
||||
double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _med);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SVAR: Sample Variance
|
||||
Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Variance
|
||||
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
|
||||
|
||||
Remark:
|
||||
SVAR is also known as the Unbiased Sample Variance, while VAR (Population Variance) is known as
|
||||
the Biased Sample Variance.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SVAR_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SVAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
double _svar = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
|
||||
_svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _svar);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SVAR: Sample Variance
|
||||
Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Variance
|
||||
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
|
||||
|
||||
Remark:
|
||||
SVAR is also known as the Unbiased Sample Variance, while VAR (Population Variance) is known as
|
||||
the Biased Sample Variance.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SVAR_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SVAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
double _svar = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
|
||||
_svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _svar);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,43 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
VAR: Population Variance
|
||||
Population variance without Bessel's correction
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Variance
|
||||
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
|
||||
|
||||
Remark:
|
||||
VAR (Population Variance) is also known as a biased Sample Variance. For unbiased
|
||||
sample variance use SVAR instead.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class VAR_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public VAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
double _pvar = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
|
||||
_pvar /= this._buffer.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _pvar);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
VAR: Population Variance
|
||||
Population variance without Bessel's correction
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Variance
|
||||
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
|
||||
|
||||
Remark:
|
||||
VAR (Population Variance) is also known as a biased Sample Variance. For unbiased
|
||||
sample variance use SVAR instead.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class VAR_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public VAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
double _pvar = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
|
||||
_pvar /= this._buffer.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _pvar);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,67 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ALMA: Arnaud Legoux Moving Average
|
||||
The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
|
||||
can be shifted from 0 to 1. This allows regulating the smoothness and high
|
||||
sensitivity of the indicator. Sigma is another parameter that is responsible for
|
||||
the shape of the curve coefficients. This moving average reduces lag of the data
|
||||
in conjunction with smoothing to reduce noise.
|
||||
|
||||
|
||||
Sources:
|
||||
https://phemex.com/academy/what-is-arnaud-legoux-moving-averages
|
||||
https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ALMA_Series : Single_TSeries_Indicator
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ALMA: Arnaud Legoux Moving Average
|
||||
The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
|
||||
can be shifted from 0 to 1. This allows regulating the smoothness and high
|
||||
sensitivity of the indicator. Sigma is another parameter that is responsible for
|
||||
the shape of the curve coefficients. This moving average reduces lag of the data
|
||||
in conjunction with smoothing to reduce noise.
|
||||
|
||||
|
||||
Sources:
|
||||
https://phemex.com/academy/what-is-arnaud-legoux-moving-averages
|
||||
https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
|
||||
|
||||
TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ALMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double[] _weight;
|
||||
private double _norm;
|
||||
private readonly double _offset, _sigma;
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double[] _weight;
|
||||
private double _norm;
|
||||
private readonly double _offset, _sigma;
|
||||
|
||||
public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
|
||||
: base(source, period, useNaN)
|
||||
public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
|
||||
: base(source, period, useNaN)
|
||||
{
|
||||
_offset = offset;
|
||||
_sigma = sigma;
|
||||
_weight = new double[period];
|
||||
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
if (this._buffer.Count <= _p) { calc_weights(); }
|
||||
|
||||
double _weightedSum = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _weightedSum += _weight[i] * _buffer[i]; }
|
||||
double _alma = _weightedSum / _norm;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _alma);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
|
||||
private void calc_weights()
|
||||
{
|
||||
int _len = this._buffer.Count;
|
||||
_norm = 0;
|
||||
double _m = _offset * (_len - 1);
|
||||
double _s = _len / _sigma;
|
||||
for (int i = 0; i < _len; i++)
|
||||
{
|
||||
_offset = offset;
|
||||
_sigma = sigma;
|
||||
_weight = new double[period];
|
||||
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
|
||||
_weight[i] = _wt;
|
||||
_norm += _wt;
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else { this._buffer.Add(TValue.v); }
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
if (this._buffer.Count <= _p) { calc_weights(); }
|
||||
|
||||
double _weightedSum = 0;
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _weightedSum += _weight[i] * _buffer[i]; }
|
||||
double _alma = _weightedSum / _norm;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _alma);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
|
||||
private void calc_weights()
|
||||
{
|
||||
int _len = this._buffer.Count;
|
||||
_norm = 0;
|
||||
double _m = _offset * (_len - 1);
|
||||
double _s = _len / _sigma;
|
||||
for (int i = 0; i < _len; i++)
|
||||
{
|
||||
double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
|
||||
_weight[i] = _wt;
|
||||
_norm += _wt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
DEMA: Double Exponential Moving Average
|
||||
DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
|
||||
|
||||
Remark:
|
||||
ema1 = EMA(close, length)
|
||||
ema2 = EMA(ema1, length)
|
||||
DEMA = 2 * ema1 - ema2
|
||||
|
||||
</summary> */
|
||||
|
||||
public class DEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
|
||||
public DEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
}
|
||||
|
||||
double _ema1, _ema2;
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
_ema1 = _ema2 = _sma;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
|
||||
_ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
|
||||
}
|
||||
|
||||
double _dema = (2 * _ema1) - _ema2;
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _dema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
DEMA: Double Exponential Moving Average
|
||||
DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
|
||||
|
||||
Remark:
|
||||
ema1 = EMA(close, length)
|
||||
ema2 = EMA(ema1, length)
|
||||
DEMA = 2 * ema1 - ema2
|
||||
|
||||
</summary> */
|
||||
|
||||
public class DEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
|
||||
public DEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
}
|
||||
|
||||
double _ema1, _ema2;
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
_ema1 = _ema2 = _sma;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
|
||||
_ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
|
||||
}
|
||||
|
||||
double _dema = (2 * _ema1) - _ema2;
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _dema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
|
||||
+63
-63
@@ -1,64 +1,64 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
EMA: Exponential Moving Average
|
||||
EMA needs very short history buffer and calculates the EMA value using just the
|
||||
previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
|
||||
|
||||
Sources:
|
||||
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
|
||||
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
|
||||
https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
|
||||
|
||||
Issues:
|
||||
There is no consensus what the first EMA value should be - a zero, a first
|
||||
datapoint, or an average of the initial Period bars. All three starting methods
|
||||
converge within 20+ bars to the same moving average. Most implementations (including this one)
|
||||
use SMA() for the first Period bars as a seeding value for EMA.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class EMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public EMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _ema = 0;
|
||||
if (update) { this._lastema = this._lastlastema; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(TValue.v);
|
||||
}
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _ema += this._buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (TValue.v * this._k) + (this._lastema * this._k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
EMA: Exponential Moving Average
|
||||
EMA needs very short history buffer and calculates the EMA value using just the
|
||||
previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
|
||||
|
||||
Sources:
|
||||
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
|
||||
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
|
||||
https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
|
||||
|
||||
Issues:
|
||||
There is no consensus what the first EMA value should be - a zero, a first
|
||||
datapoint, or an average of the initial Period bars. All three starting methods
|
||||
converge within 20+ bars to the same moving average. Most implementations (including this one)
|
||||
use SMA() for the first Period bars as a seeding value for EMA.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class EMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public EMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _ema = 0;
|
||||
if (update) { this._lastema = this._lastlastema; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(TValue.v);
|
||||
}
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _ema += this._buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (TValue.v * this._k) + (this._lastema * this._k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,65 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
HEMA: Hull-EMA Moving Average
|
||||
Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation,
|
||||
HEMA uses EMA for Hull's formula:
|
||||
|
||||
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
|
||||
EMA2 = EMA(n) of price - where k = 3/(n+1)
|
||||
Raw HMA = (2 * EMA1) - EMA2
|
||||
EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class HEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public HEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k1 = 4 / ((period * 0.5) + 1);
|
||||
this._k2 = 3 / (double)(period + 1);
|
||||
this._k3 = 2 / (Math.Sqrt(period) + 1);
|
||||
this._lastema1 = this._lastlastema1 = double.NaN;
|
||||
this._lastema2 = this._lastlastema2 = double.NaN;
|
||||
this._lastema3 = this._lastlastema3 = double.NaN;
|
||||
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly double _k1, _k2, _k3;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
private double _lastema3, _lastlastema3;
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
this._lastema3 = this._lastlastema3;
|
||||
}
|
||||
double _ema1 = System.Double.IsNaN(this._lastema1)
|
||||
? TValue.v
|
||||
: TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
|
||||
double _ema2 = System.Double.IsNaN(this._lastema2)
|
||||
? TValue.v
|
||||
: TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
|
||||
|
||||
double _rawhema = (2 * _ema1) - _ema2;
|
||||
double _ema3 = System.Double.IsNaN(this._lastema3)
|
||||
? _rawhema
|
||||
: _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
|
||||
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastlastema3 = this._lastema3;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
this._lastema3 = _ema3;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ema3);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
HEMA: Hull-EMA Moving Average
|
||||
Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation,
|
||||
HEMA uses EMA for Hull's formula:
|
||||
|
||||
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
|
||||
EMA2 = EMA(n) of price - where k = 3/(n+1)
|
||||
Raw HMA = (2 * EMA1) - EMA2
|
||||
EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class HEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public HEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k1 = 4 / ((period * 0.5) + 1);
|
||||
this._k2 = 3 / (double)(period + 1);
|
||||
this._k3 = 2 / (Math.Sqrt(period) + 1);
|
||||
this._lastema1 = this._lastlastema1 = double.NaN;
|
||||
this._lastema2 = this._lastlastema2 = double.NaN;
|
||||
this._lastema3 = this._lastlastema3 = double.NaN;
|
||||
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly double _k1, _k2, _k3;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
private double _lastema3, _lastlastema3;
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
this._lastema3 = this._lastlastema3;
|
||||
}
|
||||
double _ema1 = System.Double.IsNaN(this._lastema1)
|
||||
? TValue.v
|
||||
: TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
|
||||
double _ema2 = System.Double.IsNaN(this._lastema2)
|
||||
? TValue.v
|
||||
: TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
|
||||
|
||||
double _rawhema = (2 * _ema1) - _ema2;
|
||||
double _ema3 = System.Double.IsNaN(this._lastema3)
|
||||
? _rawhema
|
||||
: _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
|
||||
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastlastema3 = this._lastema3;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
this._lastema3 = _ema3;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ema3);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+120
-120
@@ -1,120 +1,120 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
HMA: Hull Moving Average
|
||||
Developed by Alan Hull, an extremely fast and smooth moving average; almost
|
||||
eliminates lag altogether and manages to improve smoothing at the same time.
|
||||
|
||||
Sources:
|
||||
https://alanhull.com/hull-moving-average
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
|
||||
|
||||
WMA1 = WMA(n/2) of price
|
||||
WMA2 = WMA(n) of price
|
||||
Raw HMA = (2 * WMA1) - WMA2
|
||||
HMA = WMA(sqrt(n)) of Raw HMA
|
||||
|
||||
</summary> */
|
||||
|
||||
public class HMA_Series : TSeries
|
||||
{
|
||||
private readonly int _p;
|
||||
private readonly bool _NaN;
|
||||
private readonly TSeries _data;
|
||||
private double _wma1, _wma2;
|
||||
private readonly System.Collections.Generic.List<double> _buf1 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buf2 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buf3 = new();
|
||||
private readonly System.Collections.Generic.List<double> _weights = new();
|
||||
|
||||
public HMA_Series(TSeries source, int period, bool useNaN = false)
|
||||
{
|
||||
this._p = period;
|
||||
this._data = source;
|
||||
this._NaN = useNaN;
|
||||
for (int i = 0; i < this._p; i++)
|
||||
{
|
||||
this._weights.Add(i + 1);
|
||||
}
|
||||
|
||||
source.Pub += this.Sub;
|
||||
if (source.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
this.Add(source[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
public new void Add((System.DateTime t, double v) data, bool update = false)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._buf1[this._buf1.Count - 1] = data.v;
|
||||
this._buf2[this._buf2.Count - 1] = data.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._buf1.Add(data.v);
|
||||
this._buf2.Add(data.v);
|
||||
}
|
||||
if (this._buf1.Count > (int)((double)this._p / 2))
|
||||
{
|
||||
this._buf1.RemoveAt(0);
|
||||
}
|
||||
if (this._buf2.Count > this._p)
|
||||
{
|
||||
this._buf2.RemoveAt(0);
|
||||
}
|
||||
|
||||
this._wma1 = 0;
|
||||
for (int i = 0; i < this._buf1.Count; i++)
|
||||
{
|
||||
this._wma1 += this._buf1[i] * this._weights[i];
|
||||
}
|
||||
|
||||
this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
|
||||
|
||||
this._wma2 = 0;
|
||||
for (int i = 0; i < this._buf2.Count; i++)
|
||||
{
|
||||
this._wma2 += this._buf2[i] * this._weights[i];
|
||||
}
|
||||
|
||||
this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
|
||||
|
||||
if (update)
|
||||
{
|
||||
this._buf3[this._buf3.Count - 1] = 2 * this._wma1 - this._wma2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._buf3.Add(2 * this._wma1 - this._wma2);
|
||||
}
|
||||
if (this._buf3.Count > (int)Math.Sqrt(this._p))
|
||||
{
|
||||
this._buf3.RemoveAt(0);
|
||||
}
|
||||
|
||||
double _hma = 0;
|
||||
for (int i = 0; i < this._buf3.Count; i++)
|
||||
{
|
||||
_hma += this._buf3[i] * this._weights[i];
|
||||
}
|
||||
|
||||
_hma /= (this._buf3.Count * (this._buf3.Count + 1)) * 0.5;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(data.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _hma);
|
||||
base.Add(result, update);
|
||||
}
|
||||
public void Add(bool update = false)
|
||||
{
|
||||
this.Add(this._data[this._data.Count - 1], update);
|
||||
}
|
||||
public new void Sub(object source, TSeriesEventArgs e)
|
||||
{
|
||||
this.Add(this._data[this._data.Count - 1], e.update);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
HMA: Hull Moving Average
|
||||
Developed by Alan Hull, an extremely fast and smooth moving average; almost
|
||||
eliminates lag altogether and manages to improve smoothing at the same time.
|
||||
|
||||
Sources:
|
||||
https://alanhull.com/hull-moving-average
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
|
||||
|
||||
WMA1 = WMA(n/2) of price
|
||||
WMA2 = WMA(n) of price
|
||||
Raw HMA = (2 * WMA1) - WMA2
|
||||
HMA = WMA(sqrt(n)) of Raw HMA
|
||||
|
||||
</summary> */
|
||||
|
||||
public class HMA_Series : TSeries
|
||||
{
|
||||
private readonly int _p;
|
||||
private readonly bool _NaN;
|
||||
private readonly TSeries _data;
|
||||
private double _wma1, _wma2;
|
||||
private readonly System.Collections.Generic.List<double> _buf1 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buf2 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buf3 = new();
|
||||
private readonly System.Collections.Generic.List<double> _weights = new();
|
||||
|
||||
public HMA_Series(TSeries source, int period, bool useNaN = false)
|
||||
{
|
||||
this._p = period;
|
||||
this._data = source;
|
||||
this._NaN = useNaN;
|
||||
for (int i = 0; i < this._p; i++)
|
||||
{
|
||||
this._weights.Add(i + 1);
|
||||
}
|
||||
|
||||
source.Pub += this.Sub;
|
||||
if (source.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
this.Add(source[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
public new void Add((System.DateTime t, double v) data, bool update = false)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._buf1[this._buf1.Count - 1] = data.v;
|
||||
this._buf2[this._buf2.Count - 1] = data.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._buf1.Add(data.v);
|
||||
this._buf2.Add(data.v);
|
||||
}
|
||||
if (this._buf1.Count > (int)((double)this._p / 2))
|
||||
{
|
||||
this._buf1.RemoveAt(0);
|
||||
}
|
||||
if (this._buf2.Count > this._p)
|
||||
{
|
||||
this._buf2.RemoveAt(0);
|
||||
}
|
||||
|
||||
this._wma1 = 0;
|
||||
for (int i = 0; i < this._buf1.Count; i++)
|
||||
{
|
||||
this._wma1 += this._buf1[i] * this._weights[i];
|
||||
}
|
||||
|
||||
this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
|
||||
|
||||
this._wma2 = 0;
|
||||
for (int i = 0; i < this._buf2.Count; i++)
|
||||
{
|
||||
this._wma2 += this._buf2[i] * this._weights[i];
|
||||
}
|
||||
|
||||
this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
|
||||
|
||||
if (update)
|
||||
{
|
||||
this._buf3[this._buf3.Count - 1] = 2 * this._wma1 - this._wma2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._buf3.Add(2 * this._wma1 - this._wma2);
|
||||
}
|
||||
if (this._buf3.Count > (int)Math.Sqrt(this._p))
|
||||
{
|
||||
this._buf3.RemoveAt(0);
|
||||
}
|
||||
|
||||
double _hma = 0;
|
||||
for (int i = 0; i < this._buf3.Count; i++)
|
||||
{
|
||||
_hma += this._buf3[i] * this._weights[i];
|
||||
}
|
||||
|
||||
_hma /= (this._buf3.Count * (this._buf3.Count + 1)) * 0.5;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(data.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _hma);
|
||||
base.Add(result, update);
|
||||
}
|
||||
public void Add(bool update = false)
|
||||
{
|
||||
this.Add(this._data[this._data.Count - 1], update);
|
||||
}
|
||||
public new void Sub(object source, TSeriesEventArgs e)
|
||||
{
|
||||
this.Add(this._data[this._data.Count - 1], e.update);
|
||||
}
|
||||
}
|
||||
|
||||
+160
-160
@@ -1,161 +1,161 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
JMA: Jurik Moving Average
|
||||
Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
|
||||
underlying activity. It has extremely low lag, is very smooth and is responsive
|
||||
to market gaps.
|
||||
|
||||
Sources:
|
||||
https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
|
||||
https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/
|
||||
|
||||
Issues:
|
||||
Real JMA algorithm is not published and this formula is derived through
|
||||
deduction and reverse analysis of JMA behavior. It is really close, but not
|
||||
exact - published JMA tests against JMA.CSV fail with small deviation. The
|
||||
original algo is slightly different, yet this approximation is close enough.
|
||||
|
||||
</summary>
|
||||
TODO: buggy - rework
|
||||
*/
|
||||
|
||||
public class JMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> vbuffer10;
|
||||
private readonly System.Collections.Generic.List<double> vsum65;
|
||||
|
||||
private double prev_ma1, prev_det0, prev_det1, prev_jma, bsmax, bsmin;
|
||||
private double o_prev_ma1, o_prev_det0, o_prev_det1, o_prev_jma, o_bsmax, o_bsmin;
|
||||
|
||||
private readonly double pr, pow1, len2, beta, rvolty;
|
||||
|
||||
public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this.vbuffer10 = new();
|
||||
this.vsum65 = new();
|
||||
|
||||
// constants
|
||||
this.pr = (phase < -100) ? 0.5 : (phase > 100) ? 2.5 : (phase * 0.01) + 1.5;
|
||||
double len1 = Math.Max((Math.Log(Math.Sqrt(0.5 * (_p - 1))) / Math.Log(2.0)) + 2.0, 0);
|
||||
this.pow1 = Math.Max(len1 - 2, 0.5);
|
||||
this.rvolty = Math.Exp((1 / this.pow1) * Math.Log(len1));
|
||||
this.len2 = Math.Sqrt(0.5 * (_p - 1)) * len1;
|
||||
this.beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (this.Count == 0)
|
||||
{
|
||||
this.prev_ma1 = this.prev_jma = TValue.v;
|
||||
this.bsmax = this.bsmin = this.prev_det0 = this.prev_det1 = 0;
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
this.prev_jma = this.o_prev_jma;
|
||||
this.prev_ma1 = this.o_prev_ma1;
|
||||
this.prev_det0 = this.o_prev_det0;
|
||||
this.prev_det1 = this.o_prev_det1;
|
||||
this.bsmax = this.o_bsmax;
|
||||
this.bsmin = this.o_bsmin;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.o_prev_jma = this.prev_jma;
|
||||
this.o_prev_ma1 = this.prev_ma1;
|
||||
this.o_prev_det0 = this.prev_det0;
|
||||
this.o_prev_det1 = this.prev_det1;
|
||||
this.o_bsmax = this.bsmax;
|
||||
this.o_bsmin = this.bsmin;
|
||||
}
|
||||
|
||||
double hprice = TValue.v;
|
||||
double lprice = TValue.v;
|
||||
for (int i = 0; i <= Math.Min(9, this._data.Count - 1); i++)
|
||||
{
|
||||
var _item = this._data[this._data.Count - 1 - i].v;
|
||||
hprice = (_item > hprice) ? _item : hprice;
|
||||
lprice = (_item < lprice) ? _item : lprice;
|
||||
}
|
||||
double del1 = hprice - this.bsmax;
|
||||
double del2 = lprice - this.bsmin;
|
||||
|
||||
double volty = (Math.Abs(del1) != Math.Abs(del2))
|
||||
? Math.Max(Math.Abs(del1), Math.Abs(del2))
|
||||
: 0;
|
||||
if (update)
|
||||
{
|
||||
this.vbuffer10[this.vbuffer10.Count - 1] = volty;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vbuffer10.Add(volty);
|
||||
}
|
||||
if (this.vbuffer10.Count > 10)
|
||||
{
|
||||
this.vbuffer10.RemoveAt(0);
|
||||
}
|
||||
|
||||
double prevvsum =
|
||||
(this.vsum65.Count > 0) ? this.vsum65[this.vsum65.Count - 1] : 0;
|
||||
double vsumitem = prevvsum + 0.1 * (volty - this.vbuffer10[0]);
|
||||
if (update)
|
||||
{
|
||||
this.vsum65[this.vsum65.Count - 1] = vsumitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vsum65.Add(vsumitem);
|
||||
}
|
||||
if (this.vsum65.Count > 65)
|
||||
{
|
||||
this.vsum65.RemoveAt(0);
|
||||
}
|
||||
|
||||
double avolty = 0;
|
||||
for (int i = 0; i < this.vsum65.Count; i++)
|
||||
{
|
||||
avolty += this.vsum65[i];
|
||||
}
|
||||
|
||||
avolty /= this.vsum65.Count;
|
||||
double dvolty = (avolty > 0) ? volty / avolty : 0;
|
||||
dvolty = Math.Max((dvolty > this.rvolty) ? this.rvolty : dvolty, 1.0);
|
||||
|
||||
double pow2 = Math.Exp(this.pow1 * Math.Log(dvolty));
|
||||
double kv =
|
||||
Math.Exp(Math.Sqrt(pow2) * Math.Log(this.len2 / (this.len2 + 1)));
|
||||
|
||||
this.bsmax = (del1 > 0) ? hprice : hprice - (kv * del1);
|
||||
this.bsmin = (del2 < 0) ? lprice : lprice - (kv * del2);
|
||||
|
||||
// adaptive EMA dynamic factor
|
||||
double pow = Math.Pow(dvolty, this.pow1);
|
||||
double alpha = Math.Pow(this.beta, pow);
|
||||
|
||||
// 1st stage - preliminary smoothing by adaptive EMA
|
||||
double ma1 = TValue.v * (1 - alpha) + this.prev_ma1 * alpha;
|
||||
this.prev_ma1 = ma1;
|
||||
|
||||
// 2nd stage - one more preliminary smoothing by Kalman filter
|
||||
double det0 = (TValue.v - ma1) * (1 - this.beta) + this.prev_det0 * this.beta;
|
||||
this.prev_det0 = det0;
|
||||
double ma2 = ma1 + (this.pr * det0);
|
||||
|
||||
// 3rd stage - final smoothing by Jurik adaptive filter
|
||||
double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) +
|
||||
(this.prev_det1 * alpha * alpha);
|
||||
this.prev_det1 = det1;
|
||||
var jma = this.prev_jma + det1;
|
||||
this.prev_jma = jma;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma);
|
||||
base.Add(result, update);
|
||||
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
JMA: Jurik Moving Average
|
||||
Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
|
||||
underlying activity. It has extremely low lag, is very smooth and is responsive
|
||||
to market gaps.
|
||||
|
||||
Sources:
|
||||
https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
|
||||
https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/
|
||||
|
||||
Issues:
|
||||
Real JMA algorithm is not published and this formula is derived through
|
||||
deduction and reverse analysis of JMA behavior. It is really close, but not
|
||||
exact - published JMA tests against JMA.CSV fail with small deviation. The
|
||||
original algo is slightly different, yet this approximation is close enough.
|
||||
|
||||
</summary>
|
||||
TODO: buggy - rework
|
||||
*/
|
||||
|
||||
public class JMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> vbuffer10;
|
||||
private readonly System.Collections.Generic.List<double> vsum65;
|
||||
|
||||
private double prev_ma1, prev_det0, prev_det1, prev_jma, bsmax, bsmin;
|
||||
private double o_prev_ma1, o_prev_det0, o_prev_det1, o_prev_jma, o_bsmax, o_bsmin;
|
||||
|
||||
private readonly double pr, pow1, len2, beta, rvolty;
|
||||
|
||||
public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this.vbuffer10 = new();
|
||||
this.vsum65 = new();
|
||||
|
||||
// constants
|
||||
this.pr = (phase < -100) ? 0.5 : (phase > 100) ? 2.5 : (phase * 0.01) + 1.5;
|
||||
double len1 = Math.Max((Math.Log(Math.Sqrt(0.5 * (_p - 1))) / Math.Log(2.0)) + 2.0, 0);
|
||||
this.pow1 = Math.Max(len1 - 2, 0.5);
|
||||
this.rvolty = Math.Exp((1 / this.pow1) * Math.Log(len1));
|
||||
this.len2 = Math.Sqrt(0.5 * (_p - 1)) * len1;
|
||||
this.beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (this.Count == 0)
|
||||
{
|
||||
this.prev_ma1 = this.prev_jma = TValue.v;
|
||||
this.bsmax = this.bsmin = this.prev_det0 = this.prev_det1 = 0;
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
this.prev_jma = this.o_prev_jma;
|
||||
this.prev_ma1 = this.o_prev_ma1;
|
||||
this.prev_det0 = this.o_prev_det0;
|
||||
this.prev_det1 = this.o_prev_det1;
|
||||
this.bsmax = this.o_bsmax;
|
||||
this.bsmin = this.o_bsmin;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.o_prev_jma = this.prev_jma;
|
||||
this.o_prev_ma1 = this.prev_ma1;
|
||||
this.o_prev_det0 = this.prev_det0;
|
||||
this.o_prev_det1 = this.prev_det1;
|
||||
this.o_bsmax = this.bsmax;
|
||||
this.o_bsmin = this.bsmin;
|
||||
}
|
||||
|
||||
double hprice = TValue.v;
|
||||
double lprice = TValue.v;
|
||||
for (int i = 0; i <= Math.Min(9, this._data.Count - 1); i++)
|
||||
{
|
||||
var _item = this._data[this._data.Count - 1 - i].v;
|
||||
hprice = (_item > hprice) ? _item : hprice;
|
||||
lprice = (_item < lprice) ? _item : lprice;
|
||||
}
|
||||
double del1 = hprice - this.bsmax;
|
||||
double del2 = lprice - this.bsmin;
|
||||
|
||||
double volty = (Math.Abs(del1) != Math.Abs(del2))
|
||||
? Math.Max(Math.Abs(del1), Math.Abs(del2))
|
||||
: 0;
|
||||
if (update)
|
||||
{
|
||||
this.vbuffer10[this.vbuffer10.Count - 1] = volty;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vbuffer10.Add(volty);
|
||||
}
|
||||
if (this.vbuffer10.Count > 10)
|
||||
{
|
||||
this.vbuffer10.RemoveAt(0);
|
||||
}
|
||||
|
||||
double prevvsum =
|
||||
(this.vsum65.Count > 0) ? this.vsum65[this.vsum65.Count - 1] : 0;
|
||||
double vsumitem = prevvsum + 0.1 * (volty - this.vbuffer10[0]);
|
||||
if (update)
|
||||
{
|
||||
this.vsum65[this.vsum65.Count - 1] = vsumitem;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vsum65.Add(vsumitem);
|
||||
}
|
||||
if (this.vsum65.Count > 65)
|
||||
{
|
||||
this.vsum65.RemoveAt(0);
|
||||
}
|
||||
|
||||
double avolty = 0;
|
||||
for (int i = 0; i < this.vsum65.Count; i++)
|
||||
{
|
||||
avolty += this.vsum65[i];
|
||||
}
|
||||
|
||||
avolty /= this.vsum65.Count;
|
||||
double dvolty = (avolty > 0) ? volty / avolty : 0;
|
||||
dvolty = Math.Max((dvolty > this.rvolty) ? this.rvolty : dvolty, 1.0);
|
||||
|
||||
double pow2 = Math.Exp(this.pow1 * Math.Log(dvolty));
|
||||
double kv =
|
||||
Math.Exp(Math.Sqrt(pow2) * Math.Log(this.len2 / (this.len2 + 1)));
|
||||
|
||||
this.bsmax = (del1 > 0) ? hprice : hprice - (kv * del1);
|
||||
this.bsmin = (del2 < 0) ? lprice : lprice - (kv * del2);
|
||||
|
||||
// adaptive EMA dynamic factor
|
||||
double pow = Math.Pow(dvolty, this.pow1);
|
||||
double alpha = Math.Pow(this.beta, pow);
|
||||
|
||||
// 1st stage - preliminary smoothing by adaptive EMA
|
||||
double ma1 = TValue.v * (1 - alpha) + this.prev_ma1 * alpha;
|
||||
this.prev_ma1 = ma1;
|
||||
|
||||
// 2nd stage - one more preliminary smoothing by Kalman filter
|
||||
double det0 = (TValue.v - ma1) * (1 - this.beta) + this.prev_det0 * this.beta;
|
||||
this.prev_det0 = det0;
|
||||
double ma2 = ma1 + (this.pr * det0);
|
||||
|
||||
// 3rd stage - final smoothing by Jurik adaptive filter
|
||||
double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) +
|
||||
(this.prev_det1 * alpha * alpha);
|
||||
this.prev_det1 = det1;
|
||||
var jma = this.prev_jma + det1;
|
||||
this.prev_jma = jma;
|
||||
|
||||
(System.DateTime t, double v) result =
|
||||
(TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma);
|
||||
base.Add(result, update);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,65 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
KAMA: Kaufman's Adaptive Moving Average
|
||||
Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
|
||||
Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
|
||||
it was not until the popular book titled "Trading Systems and Methods" that it was made widely
|
||||
available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
|
||||
Moving Average, considers market volatility apart from price fluctuations.
|
||||
|
||||
KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
|
||||
|
||||
Sources:
|
||||
https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
|
||||
https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
|
||||
|
||||
Remark:
|
||||
If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
|
||||
Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
|
||||
slightly different results for the first 50 bars - and then converges with the other one.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KAMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly double _scFast, _scSlow;
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private double _lastkama = double.NaN;
|
||||
private double _lastlastkama;
|
||||
|
||||
public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
|
||||
_scFast = 2.0 / (fast+1);
|
||||
_scSlow = 2.0 / (slow+1);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update){
|
||||
_buffer[_buffer.Count - 1] = TValue.v;
|
||||
this._lastkama = this._lastlastkama;
|
||||
} else {
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
|
||||
double _kama = 0;
|
||||
if (this.Count < this._p) {
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _kama += this._buffer[i]; }
|
||||
_kama /= this._buffer.Count;
|
||||
} else {
|
||||
double _change = Math.Abs(_buffer[_buffer.Count - 1] - _buffer[(_buffer.Count > _p + 1) ? 1 : 0]);
|
||||
double _sumpv = 0;
|
||||
for (int i = 1; i < _buffer.Count; i++)
|
||||
{ _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); }
|
||||
double _er = (_sumpv == 0) ? 0 : _change / _sumpv;
|
||||
double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
|
||||
_kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
|
||||
}
|
||||
_lastlastkama = _lastkama;
|
||||
_lastkama = _kama;
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
KAMA: Kaufman's Adaptive Moving Average
|
||||
Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
|
||||
Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
|
||||
it was not until the popular book titled "Trading Systems and Methods" that it was made widely
|
||||
available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
|
||||
Moving Average, considers market volatility apart from price fluctuations.
|
||||
|
||||
KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
|
||||
|
||||
Sources:
|
||||
https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
|
||||
https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
|
||||
|
||||
Remark:
|
||||
If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
|
||||
Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
|
||||
slightly different results for the first 50 bars - and then converges with the other one.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class KAMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly double _scFast, _scSlow;
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private double _lastkama = double.NaN;
|
||||
private double _lastlastkama;
|
||||
|
||||
public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
|
||||
_scFast = 2.0 / (fast+1);
|
||||
_scSlow = 2.0 / (slow+1);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update){
|
||||
_buffer[_buffer.Count - 1] = TValue.v;
|
||||
this._lastkama = this._lastlastkama;
|
||||
} else {
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
|
||||
double _kama = 0;
|
||||
if (this.Count < this._p) {
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _kama += this._buffer[i]; }
|
||||
_kama /= this._buffer.Count;
|
||||
} else {
|
||||
double _change = Math.Abs(_buffer[_buffer.Count - 1] - _buffer[(_buffer.Count > _p + 1) ? 1 : 0]);
|
||||
double _sumpv = 0;
|
||||
for (int i = 1; i < _buffer.Count; i++)
|
||||
{ _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); }
|
||||
double _er = (_sumpv == 0) ? 0 : _change / _sumpv;
|
||||
double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
|
||||
_kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
|
||||
}
|
||||
_lastlastkama = _lastkama;
|
||||
_lastkama = _kama;
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _kama);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,46 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MACD: Moving Average Convergence/Divergence
|
||||
Moving average convergence divergence (MACD) is a trend-following momentum
|
||||
indicator that shows the relationship between two moving averages of a series.
|
||||
The MACD is calculated by subtracting the 26-period exponential moving average (EMA)
|
||||
from the 12-period EMA. MACD Signal is 9-day EMA of MACD.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/m/macd.asp
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/macd
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MACD_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly EMA_Series _TSslow;
|
||||
private readonly EMA_Series _TSfast;
|
||||
private readonly SUB_Series _TSmacd;
|
||||
public EMA_Series Signal { get; }
|
||||
|
||||
public MACD_Series(TSeries source, int slow = 26, int fast = 12, int signal = 9, bool useNaN = false)
|
||||
: base(source, period: 0, useNaN)
|
||||
{
|
||||
_TSslow = new(source: source, period: slow, useNaN: false);
|
||||
_TSfast = new(source: source, period: fast, useNaN: false);
|
||||
_TSmacd = new(_TSfast, _TSslow);
|
||||
this.Signal = new(source: _TSmacd, period: signal, useNaN: useNaN);
|
||||
|
||||
if (source.Count > 0) { base.Add(_TSmacd); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _macd;
|
||||
if (update)
|
||||
{
|
||||
_TSslow.Add(TValue, true);
|
||||
_TSfast.Add(TValue, true);
|
||||
}
|
||||
_macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
|
||||
var result = (TValue.t, _macd);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
MACD: Moving Average Convergence/Divergence
|
||||
Moving average convergence divergence (MACD) is a trend-following momentum
|
||||
indicator that shows the relationship between two moving averages of a series.
|
||||
The MACD is calculated by subtracting the 26-period exponential moving average (EMA)
|
||||
from the 12-period EMA. MACD Signal is 9-day EMA of MACD.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/m/macd.asp
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/macd
|
||||
|
||||
</summary> */
|
||||
|
||||
public class MACD_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly EMA_Series _TSslow;
|
||||
private readonly EMA_Series _TSfast;
|
||||
private readonly SUB_Series _TSmacd;
|
||||
public EMA_Series Signal { get; }
|
||||
|
||||
public MACD_Series(TSeries source, int slow = 26, int fast = 12, int signal = 9, bool useNaN = false)
|
||||
: base(source, period: 0, useNaN)
|
||||
{
|
||||
_TSslow = new(source: source, period: slow, useNaN: false);
|
||||
_TSfast = new(source: source, period: fast, useNaN: false);
|
||||
_TSmacd = new(_TSfast, _TSslow);
|
||||
this.Signal = new(source: _TSmacd, period: signal, useNaN: useNaN);
|
||||
|
||||
if (source.Count > 0) { base.Add(_TSmacd); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _macd;
|
||||
if (update)
|
||||
{
|
||||
_TSslow.Add(TValue, true);
|
||||
_TSfast.Add(TValue, true);
|
||||
}
|
||||
_macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
|
||||
var result = (TValue.t, _macd);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+62
-62
@@ -1,63 +1,63 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
RMA: wildeR Moving Average
|
||||
J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
|
||||
set as 1/period, giving less weight to the new data compared to EMA.
|
||||
|
||||
Sources:
|
||||
https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
|
||||
https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
|
||||
https://www.incrediblecharts.com/indicators/wilder_moving_average.php
|
||||
|
||||
Issues:
|
||||
Pandas-TA library calculates RMA using straight Exponential Weighted Mean:
|
||||
pandas.ewm().mean() and returns incorrect first (period) of bars compared to
|
||||
published formula. This implementation passess the validation test in Wilder's book.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public RMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _ema = 0;
|
||||
if (update) { this._lastema = this._lastlastema; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (TValue.v * _k) + (_lastema * _k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
RMA: wildeR Moving Average
|
||||
J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
|
||||
set as 1/period, giving less weight to the new data compared to EMA.
|
||||
|
||||
Sources:
|
||||
https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
|
||||
https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
|
||||
https://www.incrediblecharts.com/indicators/wilder_moving_average.php
|
||||
|
||||
Issues:
|
||||
Pandas-TA library calculates RMA using straight Exponential Weighted Mean:
|
||||
pandas.ewm().mean() and returns incorrect first (period) of bars compared to
|
||||
published formula. This implementation passess the validation test in Wilder's book.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public RMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _ema = 0;
|
||||
if (update) { this._lastema = this._lastlastema; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (TValue.v * _k) + (_lastema * _k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
+41
-41
@@ -1,41 +1,41 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SMA: Simple Moving Average
|
||||
The weights are equally distributed across the period, resulting in a mean() of
|
||||
the data within the period/
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
|
||||
https://stats.stackexchange.com/a/24739
|
||||
|
||||
Remark:
|
||||
This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
|
||||
implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sma);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SMA: Simple Moving Average
|
||||
The weights are equally distributed across the period, resulting in a mean() of
|
||||
the data within the period/
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
|
||||
https://stats.stackexchange.com/a/24739
|
||||
|
||||
Remark:
|
||||
This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
|
||||
implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sma);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SMMA: Smoothed Moving Average
|
||||
The Smoothed Moving Average (SMMA) is a combination of a SMA and an EMA. It gives the recent prices
|
||||
an equal weighting as the historic prices as it takes all available price data into account.
|
||||
The main advantage of a smoothed moving average is that it removes short-term fluctuations.
|
||||
|
||||
SMMA(i) = (SMMA-1*(N-1) + CLOSE (i)) / N
|
||||
|
||||
Sources:
|
||||
https://blog.earn2trade.com/smoothed-moving-average
|
||||
https://guide.traderevolution.com/traderevolution/mobile-applications/phone/android/technical-indicators/moving-averages/smma-smoothed-moving-average
|
||||
https://www.chartmill.com/documentation/technical-analysis-indicators/217-MOVING-AVERAGES-%7C-The-Smoothed-Moving-Average-%28SMMA%29
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SMMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private double _lastsmma, _lastlastsmma;
|
||||
|
||||
public SMMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._lastsmma = this._lastlastsmma = double.NaN;
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _smma = 0;
|
||||
if (update) { this._lastsmma = this._lastlastsmma; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(TValue.v);
|
||||
}
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _smma += this._buffer[i]; }
|
||||
_smma /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_smma = ((_lastsmma * (_p-1)) + TValue.v) / _p ;
|
||||
}
|
||||
|
||||
this._lastlastsmma = this._lastsmma;
|
||||
this._lastsmma = _smma;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _smma);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
SMMA: Smoothed Moving Average
|
||||
The Smoothed Moving Average (SMMA) is a combination of a SMA and an EMA. It gives the recent prices
|
||||
an equal weighting as the historic prices as it takes all available price data into account.
|
||||
The main advantage of a smoothed moving average is that it removes short-term fluctuations.
|
||||
|
||||
SMMA(i) = (SMMA-1*(N-1) + CLOSE (i)) / N
|
||||
|
||||
Sources:
|
||||
https://blog.earn2trade.com/smoothed-moving-average
|
||||
https://guide.traderevolution.com/traderevolution/mobile-applications/phone/android/technical-indicators/moving-averages/smma-smoothed-moving-average
|
||||
https://www.chartmill.com/documentation/technical-analysis-indicators/217-MOVING-AVERAGES-%7C-The-Smoothed-Moving-Average-%28SMMA%29
|
||||
|
||||
</summary> */
|
||||
|
||||
public class SMMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private double _lastsmma, _lastlastsmma;
|
||||
|
||||
public SMMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._lastsmma = this._lastlastsmma = double.NaN;
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _smma = 0;
|
||||
if (update) { this._lastsmma = this._lastlastsmma; }
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(TValue.v);
|
||||
}
|
||||
if (this._buffer.Count > this._p) { this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++) { _smma += this._buffer[i]; }
|
||||
_smma /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_smma = ((_lastsmma * (_p-1)) + TValue.v) / _p ;
|
||||
}
|
||||
|
||||
this._lastlastsmma = this._lastsmma;
|
||||
this._lastsmma = _smma;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _smma);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,78 +1,78 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TEMA: Triple Exponential Moving Average
|
||||
TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
|
||||
|
||||
Remark:
|
||||
ema1 = EMA(close, length)
|
||||
ema2 = EMA(ema1, length)
|
||||
ema3 = EMA(ema2, length)
|
||||
TEMA = 3 * (ema1 - ema2) + ema3
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
private double _lastema3, _lastlastema3;
|
||||
|
||||
public TEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
this._lastema3 = this._lastlastema3;
|
||||
}
|
||||
|
||||
double _ema1, _ema2, _ema3;
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
_ema1 = _ema2 = _ema3 = _sma;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
|
||||
_ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
|
||||
_ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
|
||||
}
|
||||
|
||||
double _tema = (3 * (_ema1 - _ema2)) + _ema3;
|
||||
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastlastema3 = this._lastema3;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
this._lastema3 = _ema3;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _tema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TEMA: Triple Exponential Moving Average
|
||||
TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
|
||||
|
||||
Remark:
|
||||
ema1 = EMA(close, length)
|
||||
ema2 = EMA(ema1, length)
|
||||
ema3 = EMA(ema2, length)
|
||||
TEMA = 3 * (ema1 - ema2) + ema3
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema1, _lastlastema1;
|
||||
private double _lastema2, _lastlastema2;
|
||||
private double _lastema3, _lastlastema3;
|
||||
|
||||
public TEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
if (_data.Count > 0) { base.Add(_data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastema1 = this._lastlastema1;
|
||||
this._lastema2 = this._lastlastema2;
|
||||
this._lastema3 = this._lastlastema3;
|
||||
}
|
||||
|
||||
double _ema1, _ema2, _ema3;
|
||||
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else
|
||||
{
|
||||
_buffer.Add(TValue.v);
|
||||
}
|
||||
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _sma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; }
|
||||
_sma /= this._buffer.Count;
|
||||
_ema1 = _ema2 = _ema3 = _sma;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
|
||||
_ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
|
||||
_ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
|
||||
}
|
||||
|
||||
double _tema = (3 * (_ema1 - _ema2)) + _ema3;
|
||||
|
||||
this._lastlastema1 = this._lastema1;
|
||||
this._lastlastema2 = this._lastema2;
|
||||
this._lastlastema3 = this._lastema3;
|
||||
this._lastema1 = _ema1;
|
||||
this._lastema2 = _ema2;
|
||||
this._lastema3 = _ema3;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _tema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TRIMA: Triangular Moving Average
|
||||
A weighted moving average where the shape of the weights are triangular and the greatest
|
||||
weight is in the middle of the period,
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
|
||||
|
||||
Remark:
|
||||
trima = sma(sma(signal, n/2), n/2)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TRIMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer1 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buffer2 = new();
|
||||
private readonly int _p1a, _p1b;
|
||||
|
||||
public TRIMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
_p1a = (int) Math.Floor((period * 0.5) + 1);
|
||||
_p1b = (int) Math.Ceiling(0.5 * period);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
|
||||
if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
|
||||
|
||||
double _sma1 = 0;
|
||||
for (int i = 0; i < _buffer1.Count; i++) { _sma1 += _buffer1[i]; }
|
||||
_sma1 /= this._buffer1.Count;
|
||||
|
||||
if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
|
||||
if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
|
||||
|
||||
double _trima = 0;
|
||||
for (int i = 0; i < _buffer2.Count; i++) { _trima += _buffer2[i]; }
|
||||
_trima /= this._buffer2.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _trima);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
TRIMA: Triangular Moving Average
|
||||
A weighted moving average where the shape of the weights are triangular and the greatest
|
||||
weight is in the middle of the period,
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
|
||||
|
||||
Remark:
|
||||
trima = sma(sma(signal, n/2), n/2)
|
||||
|
||||
</summary> */
|
||||
|
||||
public class TRIMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer1 = new();
|
||||
private readonly System.Collections.Generic.List<double> _buffer2 = new();
|
||||
private readonly int _p1a, _p1b;
|
||||
|
||||
public TRIMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
_p1a = (int) Math.Floor((period * 0.5) + 1);
|
||||
_p1b = (int) Math.Ceiling(0.5 * period);
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
|
||||
if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
|
||||
|
||||
double _sma1 = 0;
|
||||
for (int i = 0; i < _buffer1.Count; i++) { _sma1 += _buffer1[i]; }
|
||||
_sma1 /= this._buffer1.Count;
|
||||
|
||||
if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
|
||||
if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
|
||||
|
||||
double _trima = 0;
|
||||
for (int i = 0; i < _buffer2.Count; i++) { _trima += _buffer2[i]; }
|
||||
_trima /= this._buffer2.Count;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _trima);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+38
-38
@@ -1,39 +1,39 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
WMA: (linearly) Weighted Moving Average
|
||||
The weights are linearly decreasing over the period and the most recent data has
|
||||
the heaviest weight.
|
||||
|
||||
Sources:
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
|
||||
https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
|
||||
|
||||
</summary> */
|
||||
|
||||
public class WMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public WMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
for (int i = 0; i < this._p; i++) { this._weights.Add(i + 1); }
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly System.Collections.Generic.List<double> _weights = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _wma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
|
||||
_wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _wma);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
WMA: (linearly) Weighted Moving Average
|
||||
The weights are linearly decreasing over the period and the most recent data has
|
||||
the heaviest weight.
|
||||
|
||||
Sources:
|
||||
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
|
||||
https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
|
||||
|
||||
</summary> */
|
||||
|
||||
public class WMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public WMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
for (int i = 0; i < this._p; i++) { this._weights.Add(i + 1); }
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly System.Collections.Generic.List<double> _weights = new();
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
|
||||
else { _buffer.Add(TValue.v); }
|
||||
if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
|
||||
|
||||
double _wma = 0;
|
||||
for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
|
||||
_wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5;
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _wma);
|
||||
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +1,72 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ZLEMA: Zero Lag Exponential Moving Average
|
||||
The Zero lag exponential moving average (ZLEMA) indicator was created by John
|
||||
Ehlers and Ric Way.
|
||||
|
||||
The formula for a given N-Day period and for a given Data series is:
|
||||
Lag = (Period-1)/2
|
||||
Ema Data = {Data+(Data-Data(Lag days ago))
|
||||
ZLEMA = EMA (EmaData,Period)
|
||||
|
||||
Remark:
|
||||
The idea is do a regular exponential moving average (EMA) calculation but on a
|
||||
de-lagged data instead of doing it on the regular data. Data is de-lagged by
|
||||
removing the data from "lag" days ago thus removing (or attempting to remove)
|
||||
the cumulative lag effect of the moving average.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ZLEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public ZLEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (base._data.Count > 0)
|
||||
{ base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
int _lag = (int)((_p-1) * 0.5);
|
||||
_lag = (this.Count-_lag < 0) ? 0 : this.Count-_lag;
|
||||
double _zl = TValue.v + (TValue.v - _data[_lag].v);
|
||||
|
||||
double _ema = 0;
|
||||
if (update)
|
||||
{ this._lastema = this._lastlastema; }
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update)
|
||||
{ this._buffer[this._buffer.Count - 1] = _zl; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(_zl);
|
||||
}
|
||||
if (this._buffer.Count > this._p)
|
||||
{ this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{ _ema += this._buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (_zl * this._k) + (this._lastema * this._k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ZLEMA: Zero Lag Exponential Moving Average
|
||||
The Zero lag exponential moving average (ZLEMA) indicator was created by John
|
||||
Ehlers and Ric Way.
|
||||
|
||||
The formula for a given N-Day period and for a given Data series is:
|
||||
Lag = (Period-1)/2
|
||||
Ema Data = {Data+(Data-Data(Lag days ago))
|
||||
ZLEMA = EMA (EmaData,Period)
|
||||
|
||||
Remark:
|
||||
The idea is do a regular exponential moving average (EMA) calculation but on a
|
||||
de-lagged data instead of doing it on the regular data. Data is de-lagged by
|
||||
removing the data from "lag" days ago thus removing (or attempting to remove)
|
||||
the cumulative lag effect of the moving average.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ZLEMA_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema;
|
||||
|
||||
public ZLEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 2.0 / (this._p + 1);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (base._data.Count > 0)
|
||||
{ base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
int _lag = (int)((_p-1) * 0.5);
|
||||
_lag = (this.Count-_lag < 0) ? 0 : this.Count-_lag;
|
||||
double _zl = TValue.v + (TValue.v - _data[_lag].v);
|
||||
|
||||
double _ema = 0;
|
||||
if (update)
|
||||
{ this._lastema = this._lastlastema; }
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update)
|
||||
{ this._buffer[this._buffer.Count - 1] = _zl; }
|
||||
else
|
||||
{
|
||||
this._buffer.Add(_zl);
|
||||
}
|
||||
if (this._buffer.Count > this._p)
|
||||
{ this._buffer.RemoveAt(0); }
|
||||
|
||||
for (int i = 0; i < this._buffer.Count; i++)
|
||||
{ _ema += this._buffer[i]; }
|
||||
_ema /= this._buffer.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ema = (_zl * this._k) + (this._lastema * this._k1m);
|
||||
}
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,43 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ADL: Chaikin Accumulation/Distribution Line
|
||||
ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
|
||||
|
||||
1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
|
||||
2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
|
||||
3. ADL = Previous ADL + Current Period's Money Flow Volume
|
||||
|
||||
Sources:
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ADL_Series : Single_TBars_Indicator
|
||||
{
|
||||
private double _lastadl, _lastlastadl;
|
||||
|
||||
public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
|
||||
{
|
||||
this._lastadl = this._lastlastadl = 0;
|
||||
if (_bars.Count > 0)
|
||||
{ base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{ this._lastadl = this._lastlastadl; }
|
||||
|
||||
double _mfm = ((TBar.c - TBar.l) - (TBar.h - TBar.c)) / (TBar.h - TBar.l);
|
||||
double _mfv = _mfm * TBar.v;
|
||||
double _adl = this._lastadl + _mfv;
|
||||
|
||||
this._lastlastadl = this._lastadl;
|
||||
this._lastadl = _adl;
|
||||
|
||||
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ADL: Chaikin Accumulation/Distribution Line
|
||||
ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
|
||||
|
||||
1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
|
||||
2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
|
||||
3. ADL = Previous ADL + Current Period's Money Flow Volume
|
||||
|
||||
Sources:
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ADL_Series : Single_TBars_Indicator
|
||||
{
|
||||
private double _lastadl, _lastlastadl;
|
||||
|
||||
public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
|
||||
{
|
||||
this._lastadl = this._lastlastadl = 0;
|
||||
if (_bars.Count > 0)
|
||||
{ base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{ this._lastadl = this._lastlastadl; }
|
||||
|
||||
double _mfm = ((TBar.c - TBar.l) - (TBar.h - TBar.c)) / (TBar.h - TBar.l);
|
||||
double _mfv = _mfm * TBar.v;
|
||||
double _adl = this._lastadl + _mfv;
|
||||
|
||||
this._lastlastadl = this._lastadl;
|
||||
this._lastadl = _adl;
|
||||
|
||||
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,45 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ADO: Chaikin Accumulation/Distribution Oscillator
|
||||
ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
|
||||
and fast (3-day) EMA(ADL):
|
||||
|
||||
Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
|
||||
|
||||
Sources:
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ADOSC_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly ADL_Series _TSadl;
|
||||
|
||||
private readonly EMA_Series _TSslow;
|
||||
private readonly EMA_Series _TSfast;
|
||||
private readonly SUB_Series _TSado;
|
||||
|
||||
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
|
||||
{
|
||||
_TSadl = new(source: source, useNaN: false);
|
||||
_TSslow = new(source: _TSadl, period: 10, useNaN: false);
|
||||
_TSfast = new(source: _TSadl, period: 3, useNaN: false);
|
||||
_TSado = new(_TSfast, _TSslow);
|
||||
|
||||
if (source.Count > 0)
|
||||
{ base.Add(_TSado); }
|
||||
Console.WriteLine(base.Count);
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{ _TSadl.Add(TBar, true); }
|
||||
|
||||
double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
|
||||
var result = (TBar.t, _ado);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ADO: Chaikin Accumulation/Distribution Oscillator
|
||||
ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
|
||||
and fast (3-day) EMA(ADL):
|
||||
|
||||
Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
|
||||
|
||||
Sources:
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ADOSC_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly ADL_Series _TSadl;
|
||||
|
||||
private readonly EMA_Series _TSslow;
|
||||
private readonly EMA_Series _TSfast;
|
||||
private readonly SUB_Series _TSado;
|
||||
|
||||
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
|
||||
{
|
||||
_TSadl = new(source: source, useNaN: false);
|
||||
_TSslow = new(source: _TSadl, period: 10, useNaN: false);
|
||||
_TSfast = new(source: _TSadl, period: 3, useNaN: false);
|
||||
_TSado = new(_TSfast, _TSslow);
|
||||
|
||||
if (source.Count > 0)
|
||||
{ base.Add(_TSado); }
|
||||
Console.WriteLine(base.Count);
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{ _TSadl.Add(TBar, true); }
|
||||
|
||||
double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
|
||||
var result = (TBar.t, _ado);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,63 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ATRP: Average True Range Percent
|
||||
Average True Range Percent is (ATR/Close Price)*100.
|
||||
This normalizes so it can be compared to other stocks.
|
||||
|
||||
Sources:
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ATRP_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema, _lastcm1;
|
||||
private double _cm1 = double.NaN;
|
||||
|
||||
public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update) {
|
||||
this._lastema = this._lastlastema;
|
||||
this._cm1 = this._lastcm1;
|
||||
}
|
||||
|
||||
if (_cm1 is double.NaN) { _cm1 = TBar.c; }
|
||||
double d1 = Math.Abs(TBar.h - TBar.l);
|
||||
double d2 = Math.Abs(_cm1 - TBar.h);
|
||||
double d3 = Math.Abs(_cm1 - TBar.l);
|
||||
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
|
||||
_lastcm1 = _cm1;
|
||||
_cm1 = TBar.c;
|
||||
|
||||
double _ema = 0;
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = d.v; }
|
||||
else { _buffer.Add(d.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 { _ema = (d.v * _k) + (_lastema * _k1m); }
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
double _atrp = 100 * (_ema / TBar.c);
|
||||
|
||||
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ATRP: Average True Range Percent
|
||||
Average True Range Percent is (ATR/Close Price)*100.
|
||||
This normalizes so it can be compared to other stocks.
|
||||
|
||||
Sources:
|
||||
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ATRP_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema, _lastcm1;
|
||||
private double _cm1 = double.NaN;
|
||||
|
||||
public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update) {
|
||||
this._lastema = this._lastlastema;
|
||||
this._cm1 = this._lastcm1;
|
||||
}
|
||||
|
||||
if (_cm1 is double.NaN) { _cm1 = TBar.c; }
|
||||
double d1 = Math.Abs(TBar.h - TBar.l);
|
||||
double d2 = Math.Abs(_cm1 - TBar.h);
|
||||
double d3 = Math.Abs(_cm1 - TBar.l);
|
||||
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
|
||||
_lastcm1 = _cm1;
|
||||
_cm1 = TBar.c;
|
||||
|
||||
double _ema = 0;
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = d.v; }
|
||||
else { _buffer.Add(d.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 { _ema = (d.v * _k) + (_lastema * _k1m); }
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
double _atrp = 100 * (_ema / TBar.c);
|
||||
|
||||
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,63 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ATR: wildeR Moving Average
|
||||
The average true range (ATR) is a price volatility indicator
|
||||
showing the average price variation of assets within a given time period.
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Average_true_range
|
||||
https://www.tradingview.com/wiki/Average_True_Range_(ATR)
|
||||
https://www.investopedia.com/terms/a/atr.asp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ATR_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema, _lastcm1;
|
||||
private double _cm1 = double.NaN;
|
||||
|
||||
public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (this._bars.Count > 0) { base.Add(this._bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update) {
|
||||
this._lastema = this._lastlastema;
|
||||
this._cm1 = this._lastcm1;
|
||||
}
|
||||
|
||||
if (this._cm1 is double.NaN) { this._cm1 = TBar.c; }
|
||||
double d1 = Math.Abs(TBar.h - TBar.l);
|
||||
double d2 = Math.Abs(_cm1 - TBar.h);
|
||||
double d3 = Math.Abs(_cm1 - TBar.l);
|
||||
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
|
||||
_lastcm1 = _cm1;
|
||||
_cm1 = TBar.c;
|
||||
|
||||
double _ema = 0;
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = d.v; }
|
||||
else { _buffer.Add(d.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 { _ema = (d.v * _k) + (_lastema * _k1m); }
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
ATR: wildeR Moving Average
|
||||
The average true range (ATR) is a price volatility indicator
|
||||
showing the average price variation of assets within a given time period.
|
||||
|
||||
Sources:
|
||||
https://en.wikipedia.org/wiki/Average_true_range
|
||||
https://www.tradingview.com/wiki/Average_True_Range_(ATR)
|
||||
https://www.investopedia.com/terms/a/atr.asp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class ATR_Series : Single_TBars_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _buffer = new();
|
||||
private readonly double _k, _k1m;
|
||||
private double _lastema, _lastlastema, _lastcm1;
|
||||
private double _cm1 = double.NaN;
|
||||
|
||||
public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
|
||||
{
|
||||
this._k = 1.0 / (double)(this._p);
|
||||
this._k1m = 1.0 - this._k;
|
||||
this._lastema = this._lastlastema = double.NaN;
|
||||
if (this._bars.Count > 0) { base.Add(this._bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update) {
|
||||
this._lastema = this._lastlastema;
|
||||
this._cm1 = this._lastcm1;
|
||||
}
|
||||
|
||||
if (this._cm1 is double.NaN) { this._cm1 = TBar.c; }
|
||||
double d1 = Math.Abs(TBar.h - TBar.l);
|
||||
double d2 = Math.Abs(_cm1 - TBar.h);
|
||||
double d3 = Math.Abs(_cm1 - TBar.l);
|
||||
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
|
||||
_lastcm1 = _cm1;
|
||||
_cm1 = TBar.c;
|
||||
|
||||
double _ema = 0;
|
||||
if (this.Count < this._p)
|
||||
{
|
||||
if (update) { _buffer[_buffer.Count - 1] = d.v; }
|
||||
else { _buffer.Add(d.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 { _ema = (d.v * _k) + (_lastema * _k1m); }
|
||||
|
||||
this._lastlastema = this._lastema;
|
||||
this._lastema = _ema;
|
||||
|
||||
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
|
||||
base.Add(ret, update);
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,73 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
BBANDS: Bollinger Bands®
|
||||
Price channels created by John Bollinger, depict volatility as standard deviation boundary
|
||||
line range from a moving average of price. The bands automatically widen when volatility
|
||||
increases and contract when volatility decreases. Their dynamic nature allows them to be
|
||||
used on different securities with the standard settings.
|
||||
|
||||
Mid Band = simple moving average (SMA)
|
||||
Upper Band = SMA + (standard deviation of price x multiplier)
|
||||
Lower Band = SMA - (standard deviation of price x multiplier)
|
||||
Bandwidth = Width of the channel: (Upper-Lower)/SMA
|
||||
%B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
|
||||
Z-Score = number of standard deviations of the data point from SMA
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/b/bollingerbands.asp
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
|
||||
|
||||
Note:
|
||||
Bollinger Bands® is a registered trademark of John A. Bollinger.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class BBANDS_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SMA_Series Mid { get; }
|
||||
public ADD_Series Upper { get; }
|
||||
public SUB_Series Lower { get; }
|
||||
public DIV_Series PercentB { get; }
|
||||
public DIV_Series Bandwidth { get; }
|
||||
public DIV_Series Zscore { get; }
|
||||
|
||||
private readonly SDEV_Series _sdev;
|
||||
private readonly MUL_Series _mulsdev;
|
||||
private readonly SUB_Series _pbdnd;
|
||||
private readonly SUB_Series _pbdvr;
|
||||
private readonly SUB_Series _zdnd;
|
||||
|
||||
public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
|
||||
: base(source, period: 0, useNaN)
|
||||
{
|
||||
this.Mid = new(source: source, period: period, useNaN: useNaN);
|
||||
|
||||
_sdev = new(source, period, useNaN: useNaN);
|
||||
_mulsdev = new(_sdev, multiplier);
|
||||
this.Upper = new(Mid, _mulsdev);
|
||||
this.Lower = new(Mid, _mulsdev);
|
||||
|
||||
_pbdnd = new(source, Lower);
|
||||
_pbdvr = new(Upper, Lower);
|
||||
|
||||
this.PercentB = new(_pbdnd, _pbdvr);
|
||||
this.Bandwidth = new(_pbdvr, Mid);
|
||||
|
||||
_zdnd = new(source, Mid);
|
||||
this.Zscore = new(_zdnd, _sdev);
|
||||
|
||||
if (source.Count > 0)
|
||||
{ base.Add(this.Bandwidth); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _bbandwidth;
|
||||
if (update)
|
||||
{ _sdev.Add(TValue, true); }
|
||||
_bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
|
||||
var result = (TValue.t, _bbandwidth);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
BBANDS: Bollinger Bands®
|
||||
Price channels created by John Bollinger, depict volatility as standard deviation boundary
|
||||
line range from a moving average of price. The bands automatically widen when volatility
|
||||
increases and contract when volatility decreases. Their dynamic nature allows them to be
|
||||
used on different securities with the standard settings.
|
||||
|
||||
Mid Band = simple moving average (SMA)
|
||||
Upper Band = SMA + (standard deviation of price x multiplier)
|
||||
Lower Band = SMA - (standard deviation of price x multiplier)
|
||||
Bandwidth = Width of the channel: (Upper-Lower)/SMA
|
||||
%B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
|
||||
Z-Score = number of standard deviations of the data point from SMA
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/b/bollingerbands.asp
|
||||
https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
|
||||
|
||||
Note:
|
||||
Bollinger Bands® is a registered trademark of John A. Bollinger.
|
||||
|
||||
</summary> */
|
||||
|
||||
public class BBANDS_Series : Single_TSeries_Indicator
|
||||
{
|
||||
public SMA_Series Mid { get; }
|
||||
public ADD_Series Upper { get; }
|
||||
public SUB_Series Lower { get; }
|
||||
public DIV_Series PercentB { get; }
|
||||
public DIV_Series Bandwidth { get; }
|
||||
public DIV_Series Zscore { get; }
|
||||
|
||||
private readonly SDEV_Series _sdev;
|
||||
private readonly MUL_Series _mulsdev;
|
||||
private readonly SUB_Series _pbdnd;
|
||||
private readonly SUB_Series _pbdvr;
|
||||
private readonly SUB_Series _zdnd;
|
||||
|
||||
public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
|
||||
: base(source, period: 0, useNaN)
|
||||
{
|
||||
this.Mid = new(source: source, period: period, useNaN: useNaN);
|
||||
|
||||
_sdev = new(source, period, useNaN: useNaN);
|
||||
_mulsdev = new(_sdev, multiplier);
|
||||
this.Upper = new(Mid, _mulsdev);
|
||||
this.Lower = new(Mid, _mulsdev);
|
||||
|
||||
_pbdnd = new(source, Lower);
|
||||
_pbdvr = new(Upper, Lower);
|
||||
|
||||
this.PercentB = new(_pbdnd, _pbdvr);
|
||||
this.Bandwidth = new(_pbdvr, Mid);
|
||||
|
||||
_zdnd = new(source, Mid);
|
||||
this.Zscore = new(_zdnd, _sdev);
|
||||
|
||||
if (source.Count > 0)
|
||||
{ base.Add(this.Bandwidth); }
|
||||
}
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
double _bbandwidth;
|
||||
if (update)
|
||||
{ _sdev.Add(TValue, true); }
|
||||
_bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
|
||||
var result = (TValue.t, _bbandwidth);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,73 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
RSI: Relative Strength Index
|
||||
Created by J. Welles Wilder, the Relative Strength Index measures strength
|
||||
of the winning/losing streak over N lookback periods on a scale of 0 to 100,
|
||||
to depict overbought and oversold conditions.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/r/rsi.asp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RSI_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _gain = new();
|
||||
private readonly System.Collections.Generic.List<double> _loss = new();
|
||||
private double _avgGain;
|
||||
private double _avgLoss;
|
||||
private double _lastValue;
|
||||
private double _lastlastValue;
|
||||
|
||||
public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{ if (source.Count > 0) { base.Add(source); } }
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
int i = this.Count;
|
||||
double _rsi = 0;
|
||||
if (update) { _lastValue = _lastlastValue; }
|
||||
if (i == 0) { _lastValue = TValue.v; }
|
||||
|
||||
double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
|
||||
if (update) { _gain[_gain.Count - 1] = _gainval; } else { _gain.Add(_gainval); }
|
||||
if (_gain.Count > this._p) { _gain.RemoveAt(0); }
|
||||
|
||||
double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
|
||||
if (update) { _loss[_loss.Count - 1] = _lossval; } else { _loss.Add(_lossval); }
|
||||
if (_loss.Count > this._p) { _loss.RemoveAt(0); }
|
||||
|
||||
_lastlastValue = _lastValue;
|
||||
_lastValue = TValue.v;
|
||||
|
||||
// calculate RSI
|
||||
if (i > _p)
|
||||
{
|
||||
_avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
|
||||
_avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
|
||||
if (_avgLoss > 0) {
|
||||
double rs = _avgGain / _avgLoss;
|
||||
_rsi = 100 - (100 / (1 + rs));
|
||||
}
|
||||
else { _rsi = 100; }
|
||||
}
|
||||
// initialize average gain
|
||||
else
|
||||
{
|
||||
double _sumGain = 0;
|
||||
for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
|
||||
double _sumLoss = 0;
|
||||
for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
|
||||
|
||||
_avgGain = _sumGain / _gain.Count;
|
||||
_avgLoss = _sumLoss / _loss.Count;
|
||||
|
||||
_rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
|
||||
}
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
|
||||
base.Add(result, update);
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
RSI: Relative Strength Index
|
||||
Created by J. Welles Wilder, the Relative Strength Index measures strength
|
||||
of the winning/losing streak over N lookback periods on a scale of 0 to 100,
|
||||
to depict overbought and oversold conditions.
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/r/rsi.asp
|
||||
|
||||
</summary> */
|
||||
|
||||
public class RSI_Series : Single_TSeries_Indicator
|
||||
{
|
||||
private readonly System.Collections.Generic.List<double> _gain = new();
|
||||
private readonly System.Collections.Generic.List<double> _loss = new();
|
||||
private double _avgGain;
|
||||
private double _avgLoss;
|
||||
private double _lastValue;
|
||||
private double _lastlastValue;
|
||||
|
||||
public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{ if (source.Count > 0) { base.Add(source); } }
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update)
|
||||
{
|
||||
int i = this.Count;
|
||||
double _rsi = 0;
|
||||
if (update) { _lastValue = _lastlastValue; }
|
||||
if (i == 0) { _lastValue = TValue.v; }
|
||||
|
||||
double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
|
||||
if (update) { _gain[_gain.Count - 1] = _gainval; } else { _gain.Add(_gainval); }
|
||||
if (_gain.Count > this._p) { _gain.RemoveAt(0); }
|
||||
|
||||
double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
|
||||
if (update) { _loss[_loss.Count - 1] = _lossval; } else { _loss.Add(_lossval); }
|
||||
if (_loss.Count > this._p) { _loss.RemoveAt(0); }
|
||||
|
||||
_lastlastValue = _lastValue;
|
||||
_lastValue = TValue.v;
|
||||
|
||||
// calculate RSI
|
||||
if (i > _p)
|
||||
{
|
||||
_avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
|
||||
_avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
|
||||
if (_avgLoss > 0) {
|
||||
double rs = _avgGain / _avgLoss;
|
||||
_rsi = 100 - (100 / (1 + rs));
|
||||
}
|
||||
else { _rsi = 100; }
|
||||
}
|
||||
// initialize average gain
|
||||
else
|
||||
{
|
||||
double _sumGain = 0;
|
||||
for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
|
||||
double _sumLoss = 0;
|
||||
for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
|
||||
|
||||
_avgGain = _sumGain / _gain.Count;
|
||||
_avgLoss = _sumLoss / _loss.Count;
|
||||
|
||||
_rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
|
||||
}
|
||||
|
||||
var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
+62
-62
@@ -1,62 +1,62 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
OBV: On-Balance Volume
|
||||
On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
|
||||
changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
|
||||
Granville's New Key to Stock Market Profits.
|
||||
|
||||
| +volume; if close > close[previous]
|
||||
OBV = OBV[previous] + | 0; if close = close[previous]
|
||||
| -volume; if close < close[previous]
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/o/onbalancevolume.asp
|
||||
https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
|
||||
https://www.motivewave.com/studies/on_balance_volume.htm
|
||||
|
||||
Note:
|
||||
There is no consensus on what is the first OBV value in the series:
|
||||
- TA-LIB uses the first volume: OBV[0] = volume[0]
|
||||
- Skender stock library uses 0: OBV[0] = 0
|
||||
|
||||
</summary> */
|
||||
|
||||
public class OBV_Series : Single_TBars_Indicator
|
||||
{
|
||||
private double _lastobv, _lastlastobv;
|
||||
private double _lastclose, _lastlastclose;
|
||||
public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{
|
||||
this._lastobv = this._lastlastobv = 0;
|
||||
this._lastclose = this._lastlastclose = 0;
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastobv = this._lastlastobv;
|
||||
this._lastclose = this._lastlastclose;
|
||||
}
|
||||
|
||||
double _obv = this._lastobv;
|
||||
if (TBar.c > this._lastclose) { _obv += TBar.v; }
|
||||
if (TBar.c < this._lastclose) { _obv -= TBar.v; }
|
||||
|
||||
// Unclear what the first value in OBV series is - currently set to volume[0]
|
||||
// if (this.Count == 0) { _obv = 0; }
|
||||
|
||||
this._lastlastobv = this._lastobv;
|
||||
this._lastobv = _obv;
|
||||
|
||||
this._lastlastclose = this._lastclose;
|
||||
this._lastclose = TBar.c;
|
||||
|
||||
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
OBV: On-Balance Volume
|
||||
On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
|
||||
changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
|
||||
Granville's New Key to Stock Market Profits.
|
||||
|
||||
| +volume; if close > close[previous]
|
||||
OBV = OBV[previous] + | 0; if close = close[previous]
|
||||
| -volume; if close < close[previous]
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/o/onbalancevolume.asp
|
||||
https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
|
||||
https://www.motivewave.com/studies/on_balance_volume.htm
|
||||
|
||||
Note:
|
||||
There is no consensus on what is the first OBV value in the series:
|
||||
- TA-LIB uses the first volume: OBV[0] = volume[0]
|
||||
- Skender stock library uses 0: OBV[0] = 0
|
||||
|
||||
</summary> */
|
||||
|
||||
public class OBV_Series : Single_TBars_Indicator
|
||||
{
|
||||
private double _lastobv, _lastlastobv;
|
||||
private double _lastclose, _lastlastclose;
|
||||
public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{
|
||||
this._lastobv = this._lastlastobv = 0;
|
||||
this._lastclose = this._lastlastclose = 0;
|
||||
if (_bars.Count > 0) { base.Add(_bars); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
|
||||
{
|
||||
if (update)
|
||||
{
|
||||
this._lastobv = this._lastlastobv;
|
||||
this._lastclose = this._lastlastclose;
|
||||
}
|
||||
|
||||
double _obv = this._lastobv;
|
||||
if (TBar.c > this._lastclose) { _obv += TBar.v; }
|
||||
if (TBar.c < this._lastclose) { _obv -= TBar.v; }
|
||||
|
||||
// Unclear what the first value in OBV series is - currently set to volume[0]
|
||||
// if (this.Count == 0) { _obv = 0; }
|
||||
|
||||
this._lastlastobv = this._lastobv;
|
||||
this._lastobv = _obv;
|
||||
|
||||
this._lastlastclose = this._lastclose;
|
||||
this._lastclose = TBar.c;
|
||||
|
||||
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class Abstract_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Single_Add_variations()
|
||||
{
|
||||
TSeries s = new() { 1,2,3,4,5 };
|
||||
SMA_Series a = new(s, 3)
|
||||
{
|
||||
{ (DateTime.Today, 10), true }
|
||||
};
|
||||
Assert.Equal(s.Length, a.Length);
|
||||
a.Add(true);
|
||||
Assert.Equal(s.Length, a.Length);
|
||||
a.Add();
|
||||
Assert.Equal(s.Length+1, a.Length);
|
||||
}
|
||||
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class Abstract_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Single_Add_variations()
|
||||
{
|
||||
TSeries s = new() { 1,2,3,4,5 };
|
||||
SMA_Series a = new(s, 3)
|
||||
{
|
||||
{ (DateTime.Today, 10), true }
|
||||
};
|
||||
Assert.Equal(s.Length, a.Length);
|
||||
a.Add(true);
|
||||
Assert.Equal(s.Length, a.Length);
|
||||
a.Add();
|
||||
Assert.Equal(s.Length+1, a.Length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+112
-112
@@ -1,112 +1,112 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class TBars_Test
|
||||
{
|
||||
[Fact]
|
||||
public void InsertingTuple()
|
||||
{
|
||||
TBars s = new() { (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue, c: Double.NegativeInfinity, v: Double.PositiveInfinity) };
|
||||
var tup = (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue,
|
||||
c: Double.NegativeInfinity, v: Double.PositiveInfinity);
|
||||
Assert.Equal(tup, s[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Casting_Parameters()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false }
|
||||
};
|
||||
Assert.Equal(0.1, s[^1].o);
|
||||
Assert.Equal(1.1, s[^1].h);
|
||||
Assert.Equal(2.1, s[^1].l);
|
||||
Assert.Equal(3.1, s[^1].c);
|
||||
Assert.Equal(4.1, s[^1].v);
|
||||
Assert.Equal(DateTime.Today, s[^1].t);
|
||||
Assert.Single(s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Updating_Value()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 }
|
||||
};
|
||||
s.Add(DateTime.Today, 1.0, 1.0, 1.0, 1.0, 1.0, update: false);
|
||||
s.Add(DateTime.Today, 0.0, 0.0, 0.0, 0.0, 0.0, update: true);
|
||||
Assert.Equal(0.0, s[^1].o);
|
||||
Assert.Equal(0.0, s[^1].h);
|
||||
Assert.Equal(0.0, s[^1].l);
|
||||
Assert.Equal(0.0, s[^1].c);
|
||||
Assert.Equal(0.0, s[^1].v);
|
||||
Assert.Equal(2, s.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void Extracting_TSeries()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 },
|
||||
{ DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1 }
|
||||
};
|
||||
|
||||
TSeries t = s.Open;
|
||||
Assert.Equal(t.t, s.Open.t);
|
||||
Assert.Equal(t.v, s.Open.v);
|
||||
|
||||
t = s.High;
|
||||
Assert.Equal(t.t, s.High.t);
|
||||
Assert.Equal(t.v, s.High.v);
|
||||
|
||||
t = s.Low;
|
||||
Assert.Equal(t.t, s.Low.t);
|
||||
Assert.Equal(t.v, s.Low.v);
|
||||
|
||||
t = s.Close;
|
||||
Assert.Equal(t.t, s.Close.t);
|
||||
Assert.Equal(t.v, s.Close.v);
|
||||
|
||||
t = s.Volume;
|
||||
Assert.Equal(t.t, s.Volume.t);
|
||||
Assert.Equal(t.v, s.Volume.v);
|
||||
|
||||
t = s.HL2;
|
||||
Assert.Equal(t.t, s.HL2.t);
|
||||
Assert.Equal(t.v, s.HL2.v);
|
||||
|
||||
t = s.OC2;
|
||||
Assert.Equal(t.t, s.OC2.t);
|
||||
Assert.Equal(t.v, s.OC2.v);
|
||||
|
||||
t = s.OHL3;
|
||||
Assert.Equal(t.t, s.OHL3.t);
|
||||
Assert.Equal(t.v, s.OHL3.v);
|
||||
|
||||
t = s.HLC3;
|
||||
Assert.Equal(t.t, s.HLC3.t);
|
||||
Assert.Equal(t.v, s.HLC3.v);
|
||||
|
||||
t = s.OHLC4;
|
||||
Assert.Equal(t.t, s.OHLC4.t);
|
||||
Assert.Equal(t.v, s.OHLC4.v);
|
||||
|
||||
t = s.HLCC4;
|
||||
Assert.Equal(t.t, s.HLCC4.t);
|
||||
Assert.Equal(t.v, s.HLCC4.v);
|
||||
}
|
||||
[Fact]
|
||||
public void Broadcasting_Events()
|
||||
{
|
||||
TBars s = new() { (DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1) };
|
||||
TSeries t = new();
|
||||
s.Close.Pub += t.Sub;
|
||||
s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false);
|
||||
Assert.Equal(s.Close.v, t.v);
|
||||
Assert.Equal(s.Close.Count, t.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class TBars_Test
|
||||
{
|
||||
[Fact]
|
||||
public void InsertingTuple()
|
||||
{
|
||||
TBars s = new() { (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue, c: Double.NegativeInfinity, v: Double.PositiveInfinity) };
|
||||
var tup = (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue,
|
||||
c: Double.NegativeInfinity, v: Double.PositiveInfinity);
|
||||
Assert.Equal(tup, s[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Casting_Parameters()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false }
|
||||
};
|
||||
Assert.Equal(0.1, s[^1].o);
|
||||
Assert.Equal(1.1, s[^1].h);
|
||||
Assert.Equal(2.1, s[^1].l);
|
||||
Assert.Equal(3.1, s[^1].c);
|
||||
Assert.Equal(4.1, s[^1].v);
|
||||
Assert.Equal(DateTime.Today, s[^1].t);
|
||||
Assert.Single(s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Updating_Value()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 }
|
||||
};
|
||||
s.Add(DateTime.Today, 1.0, 1.0, 1.0, 1.0, 1.0, update: false);
|
||||
s.Add(DateTime.Today, 0.0, 0.0, 0.0, 0.0, 0.0, update: true);
|
||||
Assert.Equal(0.0, s[^1].o);
|
||||
Assert.Equal(0.0, s[^1].h);
|
||||
Assert.Equal(0.0, s[^1].l);
|
||||
Assert.Equal(0.0, s[^1].c);
|
||||
Assert.Equal(0.0, s[^1].v);
|
||||
Assert.Equal(2, s.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void Extracting_TSeries()
|
||||
{
|
||||
TBars s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 },
|
||||
{ DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1 }
|
||||
};
|
||||
|
||||
TSeries t = s.Open;
|
||||
Assert.Equal(t.t, s.Open.t);
|
||||
Assert.Equal(t.v, s.Open.v);
|
||||
|
||||
t = s.High;
|
||||
Assert.Equal(t.t, s.High.t);
|
||||
Assert.Equal(t.v, s.High.v);
|
||||
|
||||
t = s.Low;
|
||||
Assert.Equal(t.t, s.Low.t);
|
||||
Assert.Equal(t.v, s.Low.v);
|
||||
|
||||
t = s.Close;
|
||||
Assert.Equal(t.t, s.Close.t);
|
||||
Assert.Equal(t.v, s.Close.v);
|
||||
|
||||
t = s.Volume;
|
||||
Assert.Equal(t.t, s.Volume.t);
|
||||
Assert.Equal(t.v, s.Volume.v);
|
||||
|
||||
t = s.HL2;
|
||||
Assert.Equal(t.t, s.HL2.t);
|
||||
Assert.Equal(t.v, s.HL2.v);
|
||||
|
||||
t = s.OC2;
|
||||
Assert.Equal(t.t, s.OC2.t);
|
||||
Assert.Equal(t.v, s.OC2.v);
|
||||
|
||||
t = s.OHL3;
|
||||
Assert.Equal(t.t, s.OHL3.t);
|
||||
Assert.Equal(t.v, s.OHL3.v);
|
||||
|
||||
t = s.HLC3;
|
||||
Assert.Equal(t.t, s.HLC3.t);
|
||||
Assert.Equal(t.v, s.HLC3.v);
|
||||
|
||||
t = s.OHLC4;
|
||||
Assert.Equal(t.t, s.OHLC4.t);
|
||||
Assert.Equal(t.v, s.OHLC4.v);
|
||||
|
||||
t = s.HLCC4;
|
||||
Assert.Equal(t.t, s.HLCC4.t);
|
||||
Assert.Equal(t.v, s.HLCC4.v);
|
||||
}
|
||||
[Fact]
|
||||
public void Broadcasting_Events()
|
||||
{
|
||||
TBars s = new() { (DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1) };
|
||||
TSeries t = new();
|
||||
s.Close.Pub += t.Sub;
|
||||
s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false);
|
||||
Assert.Equal(s.Close.v, t.v);
|
||||
Assert.Equal(s.Close.Count, t.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class TSeries_Test
|
||||
{
|
||||
[Fact]
|
||||
public void InsertingTuple()
|
||||
{
|
||||
TSeries s = new() { (t: DateTime.Today, v: double.Epsilon) };
|
||||
Assert.Equal((DateTime.Today, double.Epsilon), s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CastingTwoParameters()
|
||||
{
|
||||
TSeries s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.0 }
|
||||
};
|
||||
Assert.Equal(0.0, s[s.Count - 1].v);
|
||||
Assert.Equal(DateTime.Today, s[s.Count - 1].t);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CastingOneParameter()
|
||||
{
|
||||
TSeries s = new()
|
||||
{
|
||||
double.PositiveInfinity
|
||||
};
|
||||
Assert.Equal(double.PositiveInfinity, (double)s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdatingValue()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
s.Add(0.0, update: true);
|
||||
Assert.Equal(0.0, (double)s);
|
||||
Assert.Equal(5, s.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void ReflectingSeries()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
TSeries t = s;
|
||||
Assert.Equal(5, (double)t);
|
||||
Assert.Equal(5, t.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void BroadcastingEvents()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
TSeries t = new();
|
||||
s.Pub += t.Sub;
|
||||
s.Add(0.0, update: true);
|
||||
Assert.Equal(0.0, (double)t);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Basics;
|
||||
public class TSeries_Test
|
||||
{
|
||||
[Fact]
|
||||
public void InsertingTuple()
|
||||
{
|
||||
TSeries s = new() { (t: DateTime.Today, v: double.Epsilon) };
|
||||
Assert.Equal((DateTime.Today, double.Epsilon), s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CastingTwoParameters()
|
||||
{
|
||||
TSeries s = new()
|
||||
{
|
||||
{ DateTime.Today, 0.0 }
|
||||
};
|
||||
Assert.Equal(0.0, s[s.Count - 1].v);
|
||||
Assert.Equal(DateTime.Today, s[s.Count - 1].t);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CastingOneParameter()
|
||||
{
|
||||
TSeries s = new()
|
||||
{
|
||||
double.PositiveInfinity
|
||||
};
|
||||
Assert.Equal(double.PositiveInfinity, (double)s);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdatingValue()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
s.Add(0.0, update: true);
|
||||
Assert.Equal(0.0, (double)s);
|
||||
Assert.Equal(5, s.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void ReflectingSeries()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
TSeries t = s;
|
||||
Assert.Equal(5, (double)t);
|
||||
Assert.Equal(5, t.Count);
|
||||
}
|
||||
[Fact]
|
||||
public void BroadcastingEvents()
|
||||
{
|
||||
TSeries s = new() { 1, 2, 3, 4, 5 };
|
||||
TSeries t = new();
|
||||
s.Pub += t.Sub;
|
||||
s.Add(0.0, update: true);
|
||||
Assert.Equal(0.0, (double)t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class ALMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ALMA_Series c = new(a, 4);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(10, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ALMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class ALMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ALMA_Series c = new(a, 4);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(10, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ALMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class BBANDS_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
BBANDS_Series c = new(a, 4,2.5);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
BBANDS_Series c = new(a, 4, 2.5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class BBANDS_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
BBANDS_Series c = new(a, 4,2.5);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
BBANDS_Series c = new(a, 4, 2.5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
Assert.Equal(a.Count, c.Mid.Count);
|
||||
Assert.Equal(a.Count, c.Upper.Count);
|
||||
Assert.Equal(a.Count, c.Lower.Count);
|
||||
Assert.Equal(a.Count, c.PercentB.Count);
|
||||
Assert.Equal(a.Count, c.Zscore.Count);
|
||||
Assert.Equal(a.Count, c.Bandwidth.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class DEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
DEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
DEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class DEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
DEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
DEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class EMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
EMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
EMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class EMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
EMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
EMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class HEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
HEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
HEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class HEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
HEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
HEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class HMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
HMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
HMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class HMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
HMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
HMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class JMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
JMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
JMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class JMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
JMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
JMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class KAMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
KAMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
KAMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class KAMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
KAMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
KAMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class MACD_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MACD_Series c = new(a, 26,12,9);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MACD_Series c = new(a, 26,12,9);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class MACD_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MACD_Series c = new(a, 26,12,9);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MACD_Series c = new(a, 26,12,9);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class RMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
RMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
RMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class RMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
RMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
RMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class RSI_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
RSI_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
RSI_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class RSI_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
RSI_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
RSI_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class SMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class SMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class SMMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class SMMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class TEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
TEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
TEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class TEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
TEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
TEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class WMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
WMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
WMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class WMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
WMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
WMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class ZLEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ZLEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ZLEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class ZLEMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ZLEMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ZLEMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class BIAS_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
BIAS_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
BIAS_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class BIAS_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
BIAS_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
BIAS_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class KURT_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
KURT_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
KURT_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class KURT_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
KURT_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
KURT_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class ENTP_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ENTP_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ENTP_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class ENTP_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
ENTP_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
ENTP_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class LINREG_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
LINREG_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
LINREG_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class LINREG_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
LINREG_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
LINREG_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAD_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAD_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAD_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAD_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAD_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAD_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAX_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAX_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAX_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MAX_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MAX_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MAX_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MED_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MED_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MED_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MED_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MED_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MED_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MIN_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MIN_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MIN_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MIN_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MIN_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MIN_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MSE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MSE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MSE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class MSE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
MSE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
MSE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class PSDEV_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SDEV_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SDEV_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class PSDEV_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SDEV_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SDEV_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class PVAR_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class PVAR_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class SDEV_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SSDEV_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SSDEV_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class SDEV_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SSDEV_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SSDEV_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class SMAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class SMAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class VAR_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class VAR_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
SVAR_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class WMAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
WMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
WMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Statistics;
|
||||
public class WMAPE_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
WMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
WMAPE_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-25
@@ -5,46 +5,32 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>1701;1702;MSB3270</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<NoWarn>1701;1702;MSB3270</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<NoWarn>1701;1702;MSB3270</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NoWarn>1701;1702;MSB3270</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Python.Included" Version="3.10.0-preview5" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.dotCover.CommandLineTools" Version="2022.3.0-eap07">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0-preview-20221003-04" />
|
||||
<PackageReference Include="Python.Included" Version="3.10.0-preview5" />
|
||||
<PackageReference Include="TALib.NETCore" Version="0.4.4" />
|
||||
<PackageReference Include="Skender.Stock.Indicators" Version="2.4.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="pythonnet" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Source\QuanTAlib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Python.Included" />
|
||||
<None Remove="pythonnet" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
+148
-93
@@ -3,119 +3,174 @@ using System;
|
||||
using QuanTAlib;
|
||||
using Python.Runtime;
|
||||
using Python.Included;
|
||||
|
||||
namespace Validation;
|
||||
public class PandasTA
|
||||
|
||||
namespace Validations;
|
||||
public class PandasTA : IDisposable
|
||||
{
|
||||
private readonly RND_Feed bars;
|
||||
private readonly Random rnd = new();
|
||||
private readonly int period;
|
||||
private readonly dynamic ta;
|
||||
private readonly dynamic df;
|
||||
private GBM_Feed bars;
|
||||
private Random rnd = new();
|
||||
private int period;
|
||||
private string OStype;
|
||||
private dynamic np;
|
||||
private dynamic ta;
|
||||
private dynamic df;
|
||||
|
||||
public PandasTA()
|
||||
{
|
||||
this.bars = new(1000);
|
||||
this.period = this.rnd.Next(28) + 3;
|
||||
public PandasTA()
|
||||
{
|
||||
bars = new(5000);
|
||||
period = rnd.Next(28) + 3;
|
||||
|
||||
Runtime.PythonDLL = @"python310.dll";
|
||||
Installer.InstallPath = Path.GetFullPath(".");
|
||||
Installer.SetupPython().Wait();
|
||||
Installer.TryInstallPip();
|
||||
Installer.PipInstallModule("numpy");
|
||||
Installer.PipInstallModule("pandas");
|
||||
Installer.PipInstallModule("pandas-ta");
|
||||
PythonEngine.Initialize();
|
||||
this.ta = Py.Import("pandas_ta");
|
||||
this.df = this.ta.DataFrame(this.bars.Close.v);
|
||||
}
|
||||
// Checking the host OS and setting PythonDLL accordingly
|
||||
OStype = Environment.OSVersion.ToString();
|
||||
if (OStype == "Unix 13.1.0")
|
||||
OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib";
|
||||
else OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll";
|
||||
|
||||
~PandasTA()
|
||||
{
|
||||
PythonEngine.Shutdown();
|
||||
}
|
||||
/*
|
||||
[Fact]
|
||||
void SMA()
|
||||
{
|
||||
SMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.sma(close: this.df[0], length: this.period);
|
||||
Installer.InstallPath = Path.GetFullPath(".");
|
||||
Installer.SetupPython().Wait();
|
||||
Installer.TryInstallPip();
|
||||
//Installer.PipInstallModule("pandas-ta");
|
||||
Installer.PipInstallModule("git+https://github.com/twopirllc/pandas-ta@development");
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
Runtime.PythonDLL = OStype;
|
||||
PythonEngine.Initialize();
|
||||
np = Py.Import("numpy");
|
||||
ta = Py.Import("pandas_ta");
|
||||
|
||||
[Fact]
|
||||
void EMA()
|
||||
{
|
||||
EMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.ema(close: this.df[0], length: this.period);
|
||||
string[] cols = { "open", "high", "low", "close", "volume" };
|
||||
double[,] ary = new double[bars.Count, 5];
|
||||
for (int i = 0; i < bars.Count; i++)
|
||||
{
|
||||
ary[i, 0] = bars.Open[i].v;
|
||||
ary[i, 1] = bars.High[i].v;
|
||||
ary[i, 2] = bars.Low[i].v;
|
||||
ary[i, 3] = bars.Close[i].v;
|
||||
ary[i, 4] = bars.Volume[i].v;
|
||||
}
|
||||
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
PythonEngine.Shutdown();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void HL2()
|
||||
{
|
||||
var pta = df.ta.hl2(high: df.high, low: df.low);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(bars.HL2.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.tema(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void HLC3()
|
||||
{
|
||||
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(bars.HLC3.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
[Fact]
|
||||
void OHLC4()
|
||||
{
|
||||
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(bars.OHLC4.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void ENTP()
|
||||
{
|
||||
ENTP_Series QL = new(this.bars.Close, this.period, useNaN:false);
|
||||
var pta = this.ta.entropy(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void KAMA()
|
||||
{
|
||||
KAMA_Series QL = new(bars.Close, period);
|
||||
var pta = df.ta.kama(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
/*
|
||||
[Fact]
|
||||
void ALMA()
|
||||
{
|
||||
ALMA_Series QL = new(bars.Close, period: period, offset: 0.85, sigma: 6.0, false);
|
||||
var pta = df.ta.alma(close: df.close, length: period, distribution_offset: 0.85, sigma: 6.0);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
void HMA()
|
||||
{
|
||||
HMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.hma(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void WMA()
|
||||
{
|
||||
WMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.wma(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void SMA()
|
||||
{
|
||||
SMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.sma(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
[Fact]
|
||||
void EMA()
|
||||
{
|
||||
EMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.ema(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.dema(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.tema(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
[Fact]
|
||||
void ENTP()
|
||||
{
|
||||
ENTP_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var pta = df.ta.entropy(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void BIAS()
|
||||
{
|
||||
BIAS_Series QL = new(this.bars.Close, this.period, false);
|
||||
var pta = this.ta.bias(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void WMA()
|
||||
{
|
||||
WMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.wma(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
[Fact]
|
||||
void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.dema(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void KURT()
|
||||
{
|
||||
KURT_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var pta = this.ta.kurtosis(close: this.df[0], length: this.period);
|
||||
[Fact]
|
||||
void BIAS()
|
||||
{
|
||||
BIAS_Series QL = new(bars.Close, period, false);
|
||||
var pta = df.ta.bias(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
|
||||
}
|
||||
[Fact]
|
||||
void KURT()
|
||||
{
|
||||
KURT_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var pta = df.ta.kurtosis(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void MAD()
|
||||
{
|
||||
MAD_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var pta = this.ta.mad(close: this.df[0], length: this.period);
|
||||
|
||||
Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
*/
|
||||
[Fact]
|
||||
void MAD()
|
||||
{
|
||||
MAD_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var pta = df.ta.mad(close: df.close, length: period);
|
||||
Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7));
|
||||
}
|
||||
}
|
||||
+282
-282
@@ -1,282 +1,282 @@
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
using Skender.Stock.Indicators;
|
||||
using Xunit;
|
||||
|
||||
namespace Validation;
|
||||
public class Skender_Stock
|
||||
{
|
||||
private readonly GBM_Feed bars;
|
||||
private readonly Random rnd = new();
|
||||
private readonly int period;
|
||||
private readonly IEnumerable<Quote> quotes;
|
||||
|
||||
public Skender_Stock()
|
||||
{
|
||||
this.bars = new(Bars: 5000, Volatility:0.7, Drift:0.0);
|
||||
this.period = this.rnd.Next(28) + 3;
|
||||
this.quotes = this.bars.Select(
|
||||
q => new Quote
|
||||
{
|
||||
Date = q.t,
|
||||
Open = (decimal)q.o,
|
||||
High = (decimal)q.h,
|
||||
Low = (decimal)q.l,
|
||||
Close = (decimal)q.c,
|
||||
Volume = (decimal)q.v
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMA()
|
||||
{
|
||||
SMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetSma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EMA()
|
||||
{
|
||||
EMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetEma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
[Fact]
|
||||
public void WMA()
|
||||
{
|
||||
WMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetWma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetDema(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetTema(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAD()
|
||||
{
|
||||
MAD_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetSmaAnalysis(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAPE()
|
||||
{
|
||||
MAPE_Series QL = new(this.bars.Close, this.period, false);
|
||||
var SK = this.quotes.GetSmaAnalysis(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATR()
|
||||
{
|
||||
ATR_Series QL = new(this.bars, this.period, false);
|
||||
var SK = this.quotes.GetAtr(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OBV()
|
||||
{
|
||||
OBV_Series QL = new(this.bars, this.period, false);
|
||||
var SK = this.quotes.GetObv(this.period);
|
||||
|
||||
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
|
||||
Assert.Equal(Math.Round((double)SK.Last().Obv!, 6) + Math.Round((double)this.quotes.First().Volume!, 6),
|
||||
Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADL()
|
||||
{
|
||||
ADL_Series QL = new(this.bars, false);
|
||||
var SK = this.quotes.GetAdl();
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CCI()
|
||||
{
|
||||
CCI_Series QL = new(this.bars, this.period, false);
|
||||
var SK = this.quotes.GetCci(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATRP()
|
||||
{
|
||||
ATRP_Series QL = new(this.bars, this.period, false);
|
||||
var SK = this.quotes.GetAtr(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KAMA()
|
||||
{
|
||||
KAMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetKama(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HMA()
|
||||
{
|
||||
HMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetHma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMMA()
|
||||
{
|
||||
SMMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetSmma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MACD()
|
||||
{
|
||||
MACD_Series QL = new(this.bars.Close, 26,12,9, useNaN: false);
|
||||
var SK = this.quotes.GetMacd(12,26,9);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BBANDS()
|
||||
{
|
||||
BBANDS_Series QL = new(this.bars.Close, this.period, 2.0, useNaN: false);
|
||||
var SK = this.quotes.GetBollingerBands(this.period, 2.0);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RSI()
|
||||
{
|
||||
RSI_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetRsi(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ALMA()
|
||||
{
|
||||
ALMA_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetAlma(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SDEV()
|
||||
{
|
||||
SDEV_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetStdDev(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LINREG()
|
||||
{
|
||||
LINREG_Series QL = new(this.bars.Close, this.period, useNaN: false);
|
||||
var SK = this.quotes.GetSlope(this.period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TR()
|
||||
{
|
||||
TR_Series QL = new(this.bars, useNaN: false);
|
||||
var SK = this.quotes.GetTr();
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HL2()
|
||||
{
|
||||
TSeries QL = this.bars.HL2;
|
||||
var SK = this.quotes.GetBaseQuote(CandlePart.HL2);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OC2()
|
||||
{
|
||||
TSeries QL = this.bars.OC2;
|
||||
var SK = this.quotes.GetBaseQuote(CandlePart.OC2);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLC3()
|
||||
{
|
||||
TSeries QL = this.bars.HLC3;
|
||||
var SK = this.quotes.GetBaseQuote(CandlePart.HLC3);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHL3()
|
||||
{
|
||||
TSeries QL = this.bars.OHL3;
|
||||
var SK = this.quotes.GetBaseQuote(CandlePart.OHL3);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHLC4()
|
||||
{
|
||||
TSeries QL = this.bars.OHLC4;
|
||||
var SK = this.quotes.GetBaseQuote(CandlePart.OHLC4);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
using Skender.Stock.Indicators;
|
||||
using Xunit;
|
||||
|
||||
namespace Validations;
|
||||
public class Skender_Stock
|
||||
{
|
||||
private readonly GBM_Feed bars;
|
||||
private readonly Random rnd = new();
|
||||
private readonly int period;
|
||||
private readonly IEnumerable<Quote> quotes;
|
||||
|
||||
public Skender_Stock()
|
||||
{
|
||||
bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
|
||||
period = rnd.Next(28) + 3;
|
||||
quotes = bars.Select(
|
||||
q => new Quote
|
||||
{
|
||||
Date = q.t,
|
||||
Open = (decimal)q.o,
|
||||
High = (decimal)q.h,
|
||||
Low = (decimal)q.l,
|
||||
Close = (decimal)q.c,
|
||||
Volume = (decimal)q.v
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMA()
|
||||
{
|
||||
SMA_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetSma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EMA()
|
||||
{
|
||||
EMA_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetEma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
[Fact]
|
||||
public void WMA()
|
||||
{
|
||||
WMA_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetWma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetDema(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetTema(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAD()
|
||||
{
|
||||
MAD_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetSmaAnalysis(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAPE()
|
||||
{
|
||||
MAPE_Series QL = new(bars.Close, period, false);
|
||||
var SK = quotes.GetSmaAnalysis(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATR()
|
||||
{
|
||||
ATR_Series QL = new(bars, period, false);
|
||||
var SK = quotes.GetAtr(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OBV()
|
||||
{
|
||||
OBV_Series QL = new(bars, period, false);
|
||||
var SK = quotes.GetObv(period);
|
||||
|
||||
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
|
||||
Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5),
|
||||
Math.Round(QL.Last().v, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADL()
|
||||
{
|
||||
ADL_Series QL = new(bars, false);
|
||||
var SK = quotes.GetAdl();
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CCI()
|
||||
{
|
||||
CCI_Series QL = new(bars, period, false);
|
||||
var SK = quotes.GetCci(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATRP()
|
||||
{
|
||||
ATRP_Series QL = new(bars, period, false);
|
||||
var SK = quotes.GetAtr(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KAMA()
|
||||
{
|
||||
KAMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetKama(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HMA()
|
||||
{
|
||||
HMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetHma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMMA()
|
||||
{
|
||||
SMMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetSmma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MACD()
|
||||
{
|
||||
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
|
||||
var SK = quotes.GetMacd(12, 26, 9);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BBANDS()
|
||||
{
|
||||
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
|
||||
var SK = quotes.GetBollingerBands(period, 2.0);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RSI()
|
||||
{
|
||||
RSI_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetRsi(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ALMA()
|
||||
{
|
||||
ALMA_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetAlma(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SDEV()
|
||||
{
|
||||
SDEV_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetStdDev(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LINREG()
|
||||
{
|
||||
LINREG_Series QL = new(bars.Close, period, useNaN: false);
|
||||
var SK = quotes.GetSlope(period);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
|
||||
Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TR()
|
||||
{
|
||||
TR_Series QL = new(bars, useNaN: false);
|
||||
var SK = quotes.GetTr();
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HL2()
|
||||
{
|
||||
TSeries QL = bars.HL2;
|
||||
var SK = quotes.GetBaseQuote(CandlePart.HL2);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OC2()
|
||||
{
|
||||
TSeries QL = bars.OC2;
|
||||
var SK = quotes.GetBaseQuote(CandlePart.OC2);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLC3()
|
||||
{
|
||||
TSeries QL = bars.HLC3;
|
||||
var SK = quotes.GetBaseQuote(CandlePart.HLC3);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHL3()
|
||||
{
|
||||
TSeries QL = bars.OHL3;
|
||||
var SK = quotes.GetBaseQuote(CandlePart.OHL3);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHLC4()
|
||||
{
|
||||
TSeries QL = bars.OHLC4;
|
||||
var SK = quotes.GetBaseQuote(CandlePart.OHLC4);
|
||||
|
||||
Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
|
||||
}
|
||||
}
|
||||
|
||||
+299
-272
@@ -1,272 +1,299 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using TALib;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Validation;
|
||||
public class TA_LIB
|
||||
{
|
||||
private readonly GBM_Feed bars;
|
||||
private readonly Random rnd = new();
|
||||
private readonly int period;
|
||||
private readonly double[] TALIB;
|
||||
private readonly double[] inopen;
|
||||
private readonly double[] inhigh;
|
||||
private readonly double[] inlow;
|
||||
private readonly double[] inclose;
|
||||
private readonly double[] involume;
|
||||
|
||||
public TA_LIB()
|
||||
{
|
||||
this.bars = new(5000);
|
||||
this.period = this.rnd.Next(28) + 3;
|
||||
this.TALIB = new double[this.bars.Count];
|
||||
this.inopen = this.bars.Open.v.ToArray();
|
||||
this.inhigh = this.bars.High.v.ToArray();
|
||||
this.inlow = this.bars.Low.v.ToArray();
|
||||
this.inclose = this.bars.Close.v.ToArray();
|
||||
this.involume = this.bars.Volume.v.ToArray();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
[Fact]
|
||||
public void ADD()
|
||||
{
|
||||
ADD_Series QL = new(this.bars.Open, this.bars.Close);
|
||||
Core.Add(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SUB()
|
||||
{
|
||||
SUB_Series QL = new(this.bars.Open, this.bars.Close);
|
||||
Core.Sub(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MUL()
|
||||
{
|
||||
MUL_Series QL = new(this.bars.Open, this.bars.Close);
|
||||
Core.Mult(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DIV()
|
||||
{
|
||||
DIV_Series QL = new(this.bars.Open, this.bars.Close);
|
||||
Core.Div(this.inopen, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SDEV()
|
||||
{
|
||||
SDEV_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.StdDev(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMA()
|
||||
{
|
||||
SMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Sma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TRIMA()
|
||||
{
|
||||
TRIMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Trima(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EMA()
|
||||
{
|
||||
EMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Ema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WMA()
|
||||
{
|
||||
WMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Wma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Dema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Tema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAX()
|
||||
{
|
||||
MAX_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Max(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MIN()
|
||||
{
|
||||
MIN_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Min(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADL()
|
||||
{
|
||||
ADL_Series QL = new(this.bars, false);
|
||||
Core.Ad(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OBV()
|
||||
{
|
||||
OBV_Series QL = new(this.bars, this.period, false);
|
||||
Core.Obv(this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADOSC()
|
||||
{
|
||||
ADOSC_Series QL = new(this.bars, false);
|
||||
Core.AdOsc(this.inhigh, this.inlow, this.inclose, this.involume, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATR()
|
||||
{
|
||||
ATR_Series QL = new(this.bars, this.period, false);
|
||||
Core.Atr(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CCI()
|
||||
{
|
||||
CCI_Series QL = new(this.bars, this.period, false);
|
||||
Core.Cci(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RSI()
|
||||
{
|
||||
RSI_Series QL = new(this.bars.Close, this.period, false);
|
||||
Core.Rsi(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TR()
|
||||
{
|
||||
TR_Series QL = new(this.bars, false);
|
||||
Core.TRange(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MACD()
|
||||
{
|
||||
double[] macdSignal = new double[this.bars.Count];
|
||||
double[] macdHist = new double[this.bars.Count];
|
||||
MACD_Series QL = new(this.bars.Close, slow: 26, fast: 12, signal: 9, false);
|
||||
Core.Macd(this.inclose, 0, this.bars.Count - 1, outMacd: this.TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BBANDS()
|
||||
{
|
||||
double[] outMiddle = new double[this.bars.Count];
|
||||
double[] outUpper = new double[this.bars.Count];
|
||||
double[] outLower = new double[this.bars.Count];
|
||||
BBANDS_Series QL = new(this.bars.Close, period:26, multiplier:2.0, false);
|
||||
Core.Bbands(this.inclose, 0, this.bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod:26, optInNbDevUp:2.0, optInNbDevDn:2.0);
|
||||
Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Upper.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Mid.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Lower.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HL2()
|
||||
{
|
||||
TSeries QL = this.bars.HL2;
|
||||
Core.MedPrice(this.inhigh, this.inlow, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLC3()
|
||||
{
|
||||
TSeries QL = this.bars.HLC3;
|
||||
Core.TypPrice(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHLC4()
|
||||
{
|
||||
TSeries QL = this.bars.OHLC4;
|
||||
Core.AvgPrice(this.inopen, this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLCC4()
|
||||
{
|
||||
TSeries QL = this.bars.HLCC4;
|
||||
Core.WclPrice( this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
using System;
|
||||
using TALib;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace Validations;
|
||||
public class TA_LIB
|
||||
{
|
||||
private readonly GBM_Feed bars;
|
||||
private readonly Random rnd = new();
|
||||
private readonly int period;
|
||||
private readonly double[] TALIB;
|
||||
private readonly double[] inopen;
|
||||
private readonly double[] inhigh;
|
||||
private readonly double[] inlow;
|
||||
private readonly double[] inclose;
|
||||
private readonly double[] involume;
|
||||
|
||||
public TA_LIB()
|
||||
{
|
||||
bars = new(5000);
|
||||
period = rnd.Next(28) + 3;
|
||||
TALIB = new double[bars.Count];
|
||||
inopen = bars.Open.v.ToArray();
|
||||
inhigh = bars.High.v.ToArray();
|
||||
inlow = bars.Low.v.ToArray();
|
||||
inclose = bars.Close.v.ToArray();
|
||||
involume = bars.Volume.v.ToArray();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
[Fact]
|
||||
public void ADD()
|
||||
{
|
||||
ADD_Series QL = new(bars.Open, bars.Close);
|
||||
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SUB()
|
||||
{
|
||||
SUB_Series QL = new(bars.Open, bars.Close);
|
||||
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MUL()
|
||||
{
|
||||
MUL_Series QL = new(bars.Open, bars.Close);
|
||||
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DIV()
|
||||
{
|
||||
DIV_Series QL = new(bars.Open, bars.Close);
|
||||
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SDEV()
|
||||
{
|
||||
SDEV_Series QL = new(bars.Close, period, false);
|
||||
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SMA()
|
||||
{
|
||||
SMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SUM()
|
||||
{
|
||||
SUM_Series QL = new(bars.Close, period, false);
|
||||
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MIDPRICE()
|
||||
{
|
||||
MIDPRICE_Series QL = new(bars, period, false);
|
||||
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MIDPOINT()
|
||||
{
|
||||
MIDPOINT_Series QL = new(bars.Close, period, false);
|
||||
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TRIMA()
|
||||
{
|
||||
TRIMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EMA()
|
||||
{
|
||||
EMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WMA()
|
||||
{
|
||||
WMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DEMA()
|
||||
{
|
||||
DEMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TEMA()
|
||||
{
|
||||
TEMA_Series QL = new(bars.Close, period, false);
|
||||
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MAX()
|
||||
{
|
||||
MAX_Series QL = new(bars.Close, period, false);
|
||||
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MIN()
|
||||
{
|
||||
MIN_Series QL = new(bars.Close, period, false);
|
||||
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADL()
|
||||
{
|
||||
ADL_Series QL = new(bars, false);
|
||||
Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OBV()
|
||||
{
|
||||
OBV_Series QL = new(bars, period, false);
|
||||
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ADOSC()
|
||||
{
|
||||
ADOSC_Series QL = new(bars, false);
|
||||
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATR()
|
||||
{
|
||||
ATR_Series QL = new(bars, period, false);
|
||||
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CCI()
|
||||
{
|
||||
CCI_Series QL = new(bars, period, false);
|
||||
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RSI()
|
||||
{
|
||||
RSI_Series QL = new(bars.Close, period, false);
|
||||
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TR()
|
||||
{
|
||||
TR_Series QL = new(bars, false);
|
||||
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MACD()
|
||||
{
|
||||
double[] macdSignal = new double[bars.Count];
|
||||
double[] macdHist = new double[bars.Count];
|
||||
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
|
||||
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _);
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(macdSignal[macdSignal.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Signal.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BBANDS()
|
||||
{
|
||||
double[] outMiddle = new double[bars.Count];
|
||||
double[] outUpper = new double[bars.Count];
|
||||
double[] outLower = new double[bars.Count];
|
||||
BBANDS_Series QL = new(bars.Close, period: 26, multiplier: 2.0, false);
|
||||
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: 26, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
|
||||
Assert.Equal(Math.Round(outUpper[outUpper.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Upper.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(outMiddle[outMiddle.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Mid.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
Assert.Equal(Math.Round(outLower[outLower.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Lower.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HL2()
|
||||
{
|
||||
TSeries QL = bars.HL2;
|
||||
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLC3()
|
||||
{
|
||||
TSeries QL = bars.HLC3;
|
||||
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OHLC4()
|
||||
{
|
||||
TSeries QL = bars.OHLC4;
|
||||
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HLCC4()
|
||||
{
|
||||
TSeries QL = bars.HLCC4;
|
||||
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
|
||||
|
||||
Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
}
|
||||
|
||||
+16
-15
File diff suppressed because one or more lines are too long
+4
-4
@@ -43,11 +43,11 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
||||
| ✔️ OHL3 - (Open+High+Low)/3 | `.OHL3` |||
|
||||
| ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE |️ GetBaseQuote |
|
||||
| ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE ||
|
||||
| ⭐ MIDPOINT - Midpoint value | `MIDPOINT_Series` | MIDPOINT ||
|
||||
| ⭐ MIDPRICE - Midpoint price | `MIDPRICE_Series` | MIDPRICE ||
|
||||
| ⭐ MAX - Max value | `MAX_Series` | MAX ||
|
||||
| ⭐ MIN - Min value | `MIN_Series` | MIN ||
|
||||
| ⛔ MID - Midpoint value || MIDPOINT ||
|
||||
| ⛔ MIDP - Midpoint price || MIDPRICE ||
|
||||
| ⛔ SUM - Summation || SUM ||
|
||||
| ⭐ SUM - Summation | `SUM_Series` | SUM ||
|
||||
| ⭐ ADD - Addition | `ADD_Series` | ADD ||
|
||||
| ⭐ SUB - Subtraction | `SUB_Series` | SUB ||
|
||||
| ⭐ MUL - Multiplication | `MUL_Series` | MUL ||
|
||||
@@ -181,7 +181,7 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|
||||
| ⛔ AOBV - Archer On-Balance Volume ||||
|
||||
| ⛔ CMF - Chaikin Money Flow ||||
|
||||
| ⛔ EOM - Ease of Movement ||||
|
||||
| ⭐ OBV - On-Balance Volume | `OBV_Series` | OBV | GetObv |
|
||||
| ⭐ OBV - On-Balance Volume | ` OBV_Series` | OBV | GetObv |
|
||||
| ⛔ PRS - Price Relative Strength |||
|
||||
| ⛔ PVOL - Price-Volume ||||
|
||||
| ⛔ PVO - Percentage Volume Oscillator ||||
|
||||
|
||||
Reference in New Issue
Block a user