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 |||||