diff --git a/.gitignore b/.gitignore
index 9e8f3128..2c6aac33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,356 +1,356 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-.vscode/
-*.deps.json
-.Sandbox/
-.sonarlint/
-.DS_Store
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-dotCover.Output.dcvr
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+.vscode/
+*.deps.json
+.Sandbox/
+.sonarlint/
+.DS_Store
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+dotCover.Output.dcvr
diff --git a/Source/Basics/Abstracts.cs b/Source/Basics/Abstracts.cs
index fc79b46f..ee3c91df 100644
--- a/Source/Basics/Abstracts.cs
+++ b/Source/Basics/Abstracts.cs
@@ -2,13 +2,13 @@
using System;
/*
Abstract classes with all scaffolding required to build indicators.
- All abstracts support period, NaN, and all permutations of Add() methods.
+ All abstracts support period, NaN, and all permutations of Add() methods.
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.
+ 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.
@@ -42,11 +42,24 @@ public abstract class Single_TSeries_Indicator : TSeries
public abstract class Pair_TSeries_Indicator : TSeries
{
+ protected readonly int _p;
+ protected readonly bool _NaN;
protected readonly TSeries _d1;
protected readonly TSeries _d2;
protected readonly double _dd1, _dd2;
// Chainable Constructors - add them at the end of primary constructors if needed
+ protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN)
+ {
+ this._p = period;
+ this._NaN = useNaN;
+ this._d1 = source1;
+ this._d2 = source2;
+ this._dd1 = double.NaN;
+ this._dd2 = double.NaN;
+ this._d1.Pub += this.Sub;
+ this._d2.Pub += this.Sub;
+ }
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
{
this._d1 = source1;
diff --git a/Source/Feeds/Yahoo_Feed.cs b/Source/Feeds/Yahoo_Feed.cs
index 75b7c53d..5e3f7e2c 100644
--- a/Source/Feeds/Yahoo_Feed.cs
+++ b/Source/Feeds/Yahoo_Feed.cs
@@ -1,47 +1,47 @@
-namespace QuanTAlib;
-using System;
-using System.Text.Json;
-
-/*
-Yahoo Finance - Free API feed to collect daily market quotes
- Parameters:
- Symbol: stock symbol (default: "IBM")
- Period: number of days of collected history (default: 252)
- Usage:
- Yahoo_Feed ticker = new("MSFT", 20)
-
- */
-
-public class Yahoo_Feed : TBars
-{
- public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
- string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
- Symbol+"?interval=1d&period1="+
- (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+
- (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
- System.Net.Http.HttpClient client = new();
- var msg = client.GetStringAsync(requestUrl).Result;
- var jresult = JsonSerializer.Deserialize(msg).RootElement;
-
- jresult.TryGetProperty("chart",out JsonElement json);
- json.TryGetProperty("result",out json);
- json[0].TryGetProperty("timestamp",out JsonElement datetime);
- json[0].TryGetProperty("indicators",out json);
- json.TryGetProperty("quote",out json);
- json[0].TryGetProperty("open",out JsonElement open);
- json[0].TryGetProperty("high",out JsonElement high);
- json[0].TryGetProperty("low",out JsonElement low);
- json[0].TryGetProperty("close",out JsonElement close);
- json[0].TryGetProperty("volume",out JsonElement volume);
-
- for (int i=0; i
+Yahoo Finance - Free API feed to collect daily market quotes
+ Parameters:
+ Symbol: stock symbol (default: "IBM")
+ Period: number of days of collected history (default: 252)
+ Usage:
+ Yahoo_Feed ticker = new("MSFT", 20)
+
+ */
+
+public class Yahoo_Feed : TBars
+{
+ public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
+ string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
+ Symbol+"?interval=1d&period1="+
+ (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+
+ (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
+ System.Net.Http.HttpClient client = new();
+ var msg = client.GetStringAsync(requestUrl).Result;
+ var jresult = JsonSerializer.Deserialize(msg).RootElement;
+
+ jresult.TryGetProperty("chart",out JsonElement json);
+ json.TryGetProperty("result",out json);
+ json[0].TryGetProperty("timestamp",out JsonElement datetime);
+ json[0].TryGetProperty("indicators",out json);
+ json.TryGetProperty("quote",out json);
+ json[0].TryGetProperty("open",out JsonElement open);
+ json[0].TryGetProperty("high",out JsonElement high);
+ json[0].TryGetProperty("low",out JsonElement low);
+ json[0].TryGetProperty("close",out JsonElement close);
+ json[0].TryGetProperty("volume",out JsonElement volume);
+
+ for (int i=0; i
+CORR: Pearson's Correlation Coefficient
+ PCC is a measure of linear correlation between two sets of data.
+ It is the ratio between the covariance of two variables and the product of
+ their standard deviations; it is essentially a normalized measurement of
+ the covariance, such that the result always has a value between −1 and 1.
+
+Sources:
+ https://en.wikipedia.org/wiki/Pearson_correlation_coefficient
+
+ */
+
+public class CORR_Series : Pair_TSeries_Indicator
+{
+ public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
+ {
+ if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
+ }
+
+ private readonly System.Collections.Generic.List _x = new();
+ private readonly System.Collections.Generic.List _xx = new();
+ private readonly System.Collections.Generic.List _y = new();
+ private readonly System.Collections.Generic.List _yy = new();
+ private readonly System.Collections.Generic.List _xy = new();
+
+ public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
+ {
+ if (update)
+ {
+ _x[_x.Count - 1] = TValue1.v;
+ _xx[_xx.Count - 1] = TValue1.v * TValue1.v;
+ _y[_y.Count - 1] = TValue2.v;
+ _y[_yy.Count - 1] = TValue2.v * TValue2.v;
+ _xy[_xy.Count - 1] = TValue1.v * TValue2.v;
+ }
+ else
+ {
+ _x.Add(TValue1.v);
+ _xx.Add(TValue1.v * TValue1.v);
+ _y.Add(TValue2.v);
+ _yy.Add(TValue2.v * TValue2.v);
+ _xy.Add(TValue1.v * TValue2.v);
+ }
+ if (_x.Count > this._p) { _x.RemoveAt(0); }
+ if (_xx.Count > this._p) { _xx.RemoveAt(0); }
+ if (_y.Count > this._p) { _y.RemoveAt(0); }
+ if (_yy.Count > this._p) { _yy.RemoveAt(0); }
+ if (_xy.Count > this._p) { _xy.RemoveAt(0); }
+
+ double _sumx = 0;
+ for (int i = 0; i < _x.Count; i++) { _sumx += _x[i]; }
+ double _sumxx = 0;
+ for (int i = 0; i < _xx.Count; i++) { _sumxx += _xx[i]; }
+ double _sumy = 0;
+ for (int i = 0; i < _y.Count; i++) { _sumy += _y[i]; }
+ double _sumyy = 0;
+ for (int i = 0; i < _yy.Count; i++) { _sumyy += _yy[i]; }
+ double _sumxy = 0;
+ for (int i = 0; i < _xy.Count; i++) { _sumxy += _xy[i]; }
+
+ double _div = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
+ double _cor = (_div != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_div) : 0.0;
+
+ var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor);
+ if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
+ }
+}
\ No newline at end of file
diff --git a/Source/Statistics/LINREG_Series.cs b/Source/Statistics/LINREG_Series.cs
index eb5a0cbf..44e1bb2c 100644
--- a/Source/Statistics/LINREG_Series.cs
+++ b/Source/Statistics/LINREG_Series.cs
@@ -1,93 +1,93 @@
-namespace QuanTAlib;
-using System;
-
-/*
-LINREG: Linear Regression (using Least Square Method)
- Linear Regression provides a slope of a straight line that is the best approximation of the given set of data.
- The method of least squares is a standard approach in linear regression analysis to approximate the solution
- by minimizing the sum of the squares of the residuals made in the results of each individual equation.
-
-Additional outputs provided by LINREG:
- .Intercept - y-intercept point of the best fit line
- .RSquared - R-Squared (R²), Coefficient of Determination
- .StdDev - Standard Deviation of data over given periods
-
- y = Slope * x + Intercept
-
-Sources:
- https://en.wikipedia.org/wiki/Least_squares
-
- */
-
-public class LINREG_Series : Single_TSeries_Indicator
-{
- public readonly TSeries Intercept = new();
- public readonly TSeries RSquared = new();
- public readonly TSeries StdDev = new();
- private readonly System.Collections.Generic.List _buffer = new();
-
- public LINREG_Series(TSeries source, int period, bool useNaN = false)
- : base(source, period, useNaN)
- {
- 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); }
-
- int _len = this._buffer.Count;
-
- // get averages for period
- double sumX = 0;
- double sumY = 0;
-
- for (int p = 0; p < _len; p++)
- {
- sumX += this.Count - _len + 2 + p;
- sumY += _buffer[p];
- }
- double avgX = sumX / _len;
- double avgY = sumY / _len;
-
- // least squares method
- double sumSqX = 0;
- double sumSqY = 0;
- double sumSqXY = 0;
-
- for (int p = 0; p < _len; p++)
- {
- double devX = this.Count - _len + 2 + p - avgX;
- double devY = _buffer[p] - avgY;
-
- sumSqX += devX * devX;
- sumSqY += devY * devY;
- sumSqXY += devX * devY;
- }
-
- double _slope = sumSqXY / sumSqX;
- double _intercept = avgY - (_slope * avgX);
-
- // calculate Standard Deviation and R-Squared
- double stdDevX = Math.Sqrt(sumSqX / _len);
- double stdDevY = Math.Sqrt(sumSqY / _len);
- double _StdDev = stdDevY;
-
- double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0;
- double _RSquared = arrr * arrr;
-
- var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope);
- base.Add(ret, update);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
- Intercept.Add(ret, update);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _StdDev);
- StdDev.Add(ret, update);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _RSquared);
- RSquared.Add(ret, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+LINREG: Linear Regression (using Least Square Method)
+ Linear Regression provides a slope of a straight line that is the best approximation of the given set of data.
+ The method of least squares is a standard approach in linear regression analysis to approximate the solution
+ by minimizing the sum of the squares of the residuals made in the results of each individual equation.
+
+Additional outputs provided by LINREG:
+ .Intercept - y-intercept point of the best fit line
+ .RSquared - R-Squared (R²), Coefficient of Determination
+ .StdDev - Standard Deviation of data over given periods
+
+ y = Slope * x + Intercept
+
+Sources:
+ https://en.wikipedia.org/wiki/Least_squares
+
+ */
+
+public class LINREG_Series : Single_TSeries_Indicator
+{
+ public readonly TSeries Intercept = new();
+ public readonly TSeries RSquared = new();
+ public readonly TSeries StdDev = new();
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public LINREG_Series(TSeries source, int period, bool useNaN = false)
+ : base(source, period, useNaN)
+ {
+ 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); }
+
+ int _len = this._buffer.Count;
+
+ // get averages for period
+ double sumX = 0;
+ double sumY = 0;
+
+ for (int p = 0; p < _len; p++)
+ {
+ sumX += this.Count - _len + 2 + p;
+ sumY += _buffer[p];
+ }
+ double avgX = sumX / _len;
+ double avgY = sumY / _len;
+
+ // least squares method
+ double sumSqX = 0;
+ double sumSqY = 0;
+ double sumSqXY = 0;
+
+ for (int p = 0; p < _len; p++)
+ {
+ double devX = this.Count - _len + 2 + p - avgX;
+ double devY = _buffer[p] - avgY;
+
+ sumSqX += devX * devX;
+ sumSqY += devY * devY;
+ sumSqXY += devX * devY;
+ }
+
+ double _slope = sumSqXY / sumSqX;
+ double _intercept = avgY - (_slope * avgX);
+
+ // calculate Standard Deviation and R-Squared
+ double stdDevX = Math.Sqrt(sumSqX / _len);
+ double stdDevY = Math.Sqrt(sumSqY / _len);
+ double _StdDev = stdDevY;
+
+ double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0;
+ double _RSquared = arrr * arrr;
+
+ var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope);
+ base.Add(ret, update);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
+ Intercept.Add(ret, update);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _StdDev);
+ StdDev.Add(ret, update);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _RSquared);
+ RSquared.Add(ret, update);
+ }
}
\ No newline at end of file
diff --git a/Source/Statistics/ZSCORE_Series.cs b/Source/Statistics/ZSCORE_Series.cs
index 5b6865eb..73034315 100644
--- a/Source/Statistics/ZSCORE_Series.cs
+++ b/Source/Statistics/ZSCORE_Series.cs
@@ -1,51 +1,51 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ZSCORE: number of standard deviations from SMA
- Z-score describes a value's relationship to the mean of a series, as measured in
- terms of standard deviations from the mean. If a Z-score is 0, it indicates that
- the data point's score is identical to the mean score. A Z-score of 1.0 would
- indicate a value that is one standard deviation from the mean. Z-scores may be
- positive or negative, with a positive value indicating the score is above the
- mean and a negative score indicating it is below the mean.
-
-Sources:
- https://en.wikipedia.org/wiki/Z-score
- https://www.investopedia.com/terms/z/zscore.asp
-
-Calculation:
- std = std * STDEV(close, length)
- mean = SMA(close, length)
- ZSCORE = (close - mean) / std
-
- */
-
-public class ZSCORE_Series : Single_TSeries_Indicator
-{
- public ZSCORE_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 _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;
- double _psdev = Math.Sqrt(_pvar);
- double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev;
-
- var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _zscore);
- base.Add(result, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+ZSCORE: number of standard deviations from SMA
+ Z-score describes a value's relationship to the mean of a series, as measured in
+ terms of standard deviations from the mean. If a Z-score is 0, it indicates that
+ the data point's score is identical to the mean score. A Z-score of 1.0 would
+ indicate a value that is one standard deviation from the mean. Z-scores may be
+ positive or negative, with a positive value indicating the score is above the
+ mean and a negative score indicating it is below the mean.
+
+Sources:
+ https://en.wikipedia.org/wiki/Z-score
+ https://www.investopedia.com/terms/z/zscore.asp
+
+Calculation:
+ std = std * STDEV(close, length)
+ mean = SMA(close, length)
+ ZSCORE = (close - mean) / std
+
+ */
+
+public class ZSCORE_Series : Single_TSeries_Indicator
+{
+ public ZSCORE_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 _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;
+ double _psdev = Math.Sqrt(_pvar);
+ double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev;
+
+ var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _zscore);
+ base.Add(result, update);
+ }
}
\ No newline at end of file
diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs
index 2f895e1f..c2976b00 100644
--- a/Tests/Validations/Skender_Stock.cs
+++ b/Tests/Validations/Skender_Stock.cs
@@ -5,296 +5,305 @@ 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 quotes;
-
- public Skender_Stock()
- {
- bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
- period = rnd.Next(28) + 3;
- quotes = bars.Select(
- q => new Quote
- {
- Date = q.t,
- Open = (decimal)q.o,
- High = (decimal)q.h,
- Low = (decimal)q.l,
- Close = (decimal)q.c,
- Volume = (decimal)q.v
- });
- }
-
- [Fact]
- public void SMA()
- {
- SMA_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetSma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void EMA()
- {
- EMA_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetEma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
- }
- [Fact]
- public void WMA()
- {
- WMA_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetWma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void DEMA()
- {
- DEMA_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetDema(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void TEMA()
- {
- TEMA_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetTema(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void MAD()
- {
- MAD_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetSmaAnalysis(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void MSE()
- {
- MSE_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetSmaAnalysis(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void MAPE()
- {
- MAPE_Series QL = new(bars.Close, period, false);
- var SK = quotes.GetSmaAnalysis(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void ATR()
- {
- ATR_Series QL = new(bars, period, false);
- var SK = quotes.GetAtr(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void OBV()
- {
- OBV_Series QL = new(bars, period, false);
- var SK = quotes.GetObv(period);
-
- // adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
- Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5),
- Math.Round(QL.Last().v, 5));
- }
-
- [Fact]
- public void ADL()
- {
- ADL_Series QL = new(bars, false);
- var SK = quotes.GetAdl();
-
- Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
- }
-
- [Fact]
- public void CCI()
- {
- CCI_Series QL = new(bars, period, false);
- var SK = quotes.GetCci(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void ATRP()
- {
- ATRP_Series QL = new(bars, period, false);
- var SK = quotes.GetAtr(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void KAMA()
- {
- KAMA_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetKama(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void HMA()
- {
- HMA_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetHma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void SMMA()
- {
- SMMA_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetSmma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void MACD()
- {
- MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
- var SK = quotes.GetMacd(12, 26, 9);
-
- Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
- }
-
- [Fact]
- public void BBANDS()
- {
- BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
- var SK = quotes.GetBollingerBands(period, 2.0);
-
- Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
- }
-
- [Fact]
- public void RSI()
- {
- RSI_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetRsi(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void ALMA()
- {
- ALMA_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetAlma(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void SDEV()
- {
- SDEV_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetStdDev(period);
-
- Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void ZSCORE()
- {
- ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetStdDev(period);
-
- Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void LINREG()
- {
- LINREG_Series QL = new(bars.Close, period, useNaN: false);
- var SK = quotes.GetSlope(period);
-
- Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
- Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
- }
-
- [Fact]
- public void TR()
- {
- TR_Series QL = new(bars, useNaN: false);
- var SK = quotes.GetTr();
-
- Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void HL2()
- {
- TSeries QL = bars.HL2;
- var SK = quotes.GetBaseQuote(CandlePart.HL2);
-
- Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void OC2()
- {
- TSeries QL = bars.OC2;
- var SK = quotes.GetBaseQuote(CandlePart.OC2);
-
- Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void HLC3()
- {
- TSeries QL = bars.HLC3;
- var SK = quotes.GetBaseQuote(CandlePart.HLC3);
-
- Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void OHL3()
- {
- TSeries QL = bars.OHL3;
- var SK = quotes.GetBaseQuote(CandlePart.OHL3);
-
- Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
- }
-
- [Fact]
- public void OHLC4()
- {
- TSeries QL = bars.OHLC4;
- var SK = quotes.GetBaseQuote(CandlePart.OHLC4);
-
- Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
- }
+{
+ private readonly GBM_Feed bars;
+ private readonly Random rnd = new();
+ private readonly int period;
+ private readonly IEnumerable quotes;
+
+ public Skender_Stock()
+ {
+ bars = new(Bars: 5000, Volatility: 0.7, Drift: 0.0);
+ period = rnd.Next(28) + 3;
+ quotes = bars.Select(
+ q => new Quote
+ {
+ Date = q.t,
+ Open = (decimal)q.o,
+ High = (decimal)q.h,
+ Low = (decimal)q.l,
+ Close = (decimal)q.c,
+ Volume = (decimal)q.v
+ });
+ }
+
+ [Fact]
+ public void SMA()
+ {
+ SMA_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetSma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void EMA()
+ {
+ EMA_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetEma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Ema!, 6), Math.Round(QL.Last().v, 6));
+ }
+ [Fact]
+ public void WMA()
+ {
+ WMA_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetWma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Wma!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void DEMA()
+ {
+ DEMA_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetDema(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Dema!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void TEMA()
+ {
+ TEMA_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetTema(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Tema!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void MAD()
+ {
+ MAD_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetSmaAnalysis(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Mad!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void MSE()
+ {
+ MSE_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetSmaAnalysis(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Mse!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void MAPE()
+ {
+ MAPE_Series QL = new(bars.Close, period, false);
+ var SK = quotes.GetSmaAnalysis(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Mape!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void CORR()
+ {
+ CORR_Series QL = new(bars.High, bars.Low, period, false);
+ var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Correlation!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void ATR()
+ {
+ ATR_Series QL = new(bars, period, false);
+ var SK = quotes.GetAtr(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Atr!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void OBV()
+ {
+ OBV_Series QL = new(bars, period, false);
+ var SK = quotes.GetObv(period);
+
+ // adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
+ Assert.Equal(Math.Round(SK.Last().Obv! + (double)quotes.First().Volume!, 5),
+ Math.Round(QL.Last().v, 5));
+ }
+
+ [Fact]
+ public void ADL()
+ {
+ ADL_Series QL = new(bars, false);
+ var SK = quotes.GetAdl();
+
+ Assert.Equal(Math.Round(SK.Last().Adl!, 5), Math.Round(QL.Last().v, 5));
+ }
+
+ [Fact]
+ public void CCI()
+ {
+ CCI_Series QL = new(bars, period, false);
+ var SK = quotes.GetCci(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Cci!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void ATRP()
+ {
+ ATRP_Series QL = new(bars, period, false);
+ var SK = quotes.GetAtr(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Atrp!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void KAMA()
+ {
+ KAMA_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetKama(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Kama!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void HMA()
+ {
+ HMA_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetHma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Hma!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void SMMA()
+ {
+ SMMA_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetSmma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Smma!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void MACD()
+ {
+ MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
+ var SK = quotes.GetMacd(12, 26, 9);
+
+ Assert.Equal(Math.Round((double)SK.Last().Macd!, 6), Math.Round(QL.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().Signal!, 6), Math.Round(QL.Signal.Last().v, 6));
+ }
+
+ [Fact]
+ public void BBANDS()
+ {
+ BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
+ var SK = quotes.GetBollingerBands(period, 2.0);
+
+ Assert.Equal(Math.Round((double)SK.Last().Sma!, 6), Math.Round(QL.Mid.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().UpperBand!, 6), Math.Round(QL.Upper.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().LowerBand!, 6), Math.Round(QL.Lower.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().Width!, 6), Math.Round(QL.Bandwidth.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().PercentB!, 6), Math.Round(QL.PercentB.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Zscore.Last().v, 6));
+ }
+
+ [Fact]
+ public void RSI()
+ {
+ RSI_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetRsi(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void ALMA()
+ {
+ ALMA_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetAlma(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Alma!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void SDEV()
+ {
+ SDEV_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetStdDev(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void ZSCORE()
+ {
+ ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetStdDev(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().ZScore!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void LINREG()
+ {
+ LINREG_Series QL = new(bars.Close, period, useNaN: false);
+ var SK = quotes.GetSlope(period);
+
+ Assert.Equal(Math.Round((double)SK.Last().Slope!, 6), Math.Round(QL.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().Intercept!, 6), Math.Round(QL.Intercept.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().RSquared!, 6), Math.Round(QL.RSquared.Last().v, 6));
+ Assert.Equal(Math.Round((double)SK.Last().StdDev!, 6), Math.Round(QL.StdDev.Last().v, 6));
+ }
+
+ [Fact]
+ public void TR()
+ {
+ TR_Series QL = new(bars, useNaN: false);
+ var SK = quotes.GetTr();
+
+ Assert.Equal(Math.Round((double)SK.Last().Tr!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void HL2()
+ {
+ TSeries QL = bars.HL2;
+ var SK = quotes.GetBaseQuote(CandlePart.HL2);
+
+ Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void OC2()
+ {
+ TSeries QL = bars.OC2;
+ var SK = quotes.GetBaseQuote(CandlePart.OC2);
+
+ Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void HLC3()
+ {
+ TSeries QL = bars.HLC3;
+ var SK = quotes.GetBaseQuote(CandlePart.HLC3);
+
+ Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void OHL3()
+ {
+ TSeries QL = bars.OHL3;
+ var SK = quotes.GetBaseQuote(CandlePart.OHL3);
+
+ Assert.Equal(Math.Round(SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
+ }
+
+ [Fact]
+ public void OHLC4()
+ {
+ TSeries QL = bars.OHLC4;
+ var SK = quotes.GetBaseQuote(CandlePart.OHLC4);
+
+ Assert.Equal(Math.Round((double)SK.Last().Value!, 6), Math.Round(QL.Last().v, 6));
+ }
}
diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs
index f9489107..caac9335 100644
--- a/Tests/Validations/TA_LIB.cs
+++ b/Tests/Validations/TA_LIB.cs
@@ -5,305 +5,314 @@ 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 VAR()
- {
- VAR_Series QL = new(bars.Close, period, false);
- Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
-
- Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 5, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 5));
- }
-
- [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));
- }
+{
+ private readonly GBM_Feed bars;
+ private readonly Random rnd = new();
+ private readonly int period;
+ private readonly double[] TALIB;
+ private readonly double[] inopen;
+ private readonly double[] inhigh;
+ private readonly double[] inlow;
+ private readonly double[] inclose;
+ private readonly double[] involume;
+
+ public TA_LIB()
+ {
+ bars = new(5000);
+ period = rnd.Next(28) + 3;
+ TALIB = new double[bars.Count];
+ inopen = bars.Open.v.ToArray();
+ inhigh = bars.High.v.ToArray();
+ inlow = bars.Low.v.ToArray();
+ inclose = bars.Close.v.ToArray();
+ involume = bars.Volume.v.ToArray();
+ }
+
+ /////////////////////////////////////////
+
+ [Fact]
+ public void ADD()
+ {
+ ADD_Series QL = new(bars.Open, bars.Close);
+ Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void SUB()
+ {
+ SUB_Series QL = new(bars.Open, bars.Close);
+ Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void MUL()
+ {
+ MUL_Series QL = new(bars.Open, bars.Close);
+ Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void DIV()
+ {
+ DIV_Series QL = new(bars.Open, bars.Close);
+ Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void CORR()
+ {
+ CORR_Series QL = new(bars.Open, bars.Close, period);
+ Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void SDEV()
+ {
+ SDEV_Series QL = new(bars.Close, period, false);
+ Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void SMA()
+ {
+ SMA_Series QL = new(bars.Close, period, false);
+ Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void SUM()
+ {
+ SUM_Series QL = new(bars.Close, period, false);
+ Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+ [Fact]
+ public void MIDPRICE()
+ {
+ MIDPRICE_Series QL = new(bars, period, false);
+ Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero));
+ }
+
+
+ [Fact]
+ public void VAR()
+ {
+ VAR_Series QL = new(bars.Close, period, false);
+ Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
+
+ Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 5, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 5));
+ }
+
+ [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));
+ }
}
diff --git a/docs/readme.md b/docs/readme.md
index 2db4cd98..eff2c21c 100644
--- a/docs/readme.md
+++ b/docs/readme.md
@@ -55,7 +55,7 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
|||||
| **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
| ⭐ BIAS - Bias | `BIAS_Series` ||| bias |
-| ⛔ CORREL - Pearson's Correlation Coefficient || CORREL | GetCorrelation ||
+| ⭐ CORR - Pearson's Correlation Coefficient | `CORR_Series` | CORREL | GetCorrelation ||
| ⛔ COVAR - Covariance ||| GetCorrelation ||
| ⭐ ENTP - Entropy | `ENTP_Series` ||| entropy |
| ⭐ KURT - Kurtosis | `KURT_Series` ||| kurtosis |
@@ -72,7 +72,7 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett
| ⭐ SVAR - Sample Variance | `SVAR_Series` ||| variance |
| ⛔ QUANTILE - Quantile |||| quantile |
| ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` ||||
-| ⭐ ZSCORE - Number of standard deviations from mean | ZSCORE_Series || GetStdDev | zscore |
+| ⭐ ZSCORE - Number of standard deviations from mean | `ZSCORE_Series` || GetStdDev | zscore |
||||||
| **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** |
| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average |||||