diff --git a/.github/workflows/main_automation.yml b/.github/workflows/main_automation.yml index ca0c0815..f526ec77 100644 --- a/.github/workflows/main_automation.yml +++ b/.github/workflows/main_automation.yml @@ -103,6 +103,7 @@ jobs: --skip-duplicate - name: Push package to nuget.org + if: ${{ github.ref == 'refs/heads/main' }} run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg' --api-key ${{ secrets.NUGET_DEPLOY_KEY_QUANTLIB }} --source https://api.nuget.org/v3/index.json diff --git a/Source/Basics/MAX_Series.cs b/Source/Basics/MAX_Series.cs index 1f0af935..826aeb10 100644 --- a/Source/Basics/MAX_Series.cs +++ b/Source/Basics/MAX_Series.cs @@ -23,7 +23,6 @@ public class MAX_Series : Single_TSeries_Indicator double _max = TValue.v; for (int i = 0; i < this._buffer.Count; i++) { - //_max = (this._buffer[i] > _max) ? this._buffer[i] : _max; _max = Math.Max(this._buffer[i], _max); } diff --git a/Source/Basics/MIDPOINT_Series.cs b/Source/Basics/MIDPOINT_Series.cs index ea5bdd0a..91ddac5c 100644 --- a/Source/Basics/MIDPOINT_Series.cs +++ b/Source/Basics/MIDPOINT_Series.cs @@ -1,44 +1,44 @@ -namespace QuanTAlib; -using System; - -/* -MIDPOINT: Midpoint value (max+min)/2 in the given period in the series. - If period = 0 => period = full length of the series - -Sources: - https://thefaqblog.com/what-is-the-midpoint-in-statistics/ - - */ - -public class MIDPOINT_Series : Single_TSeries_Indicator -{ - public MIDPOINT_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) - { - if (base._data.Count > 0) - { base.Add(base._data); } - } - private readonly System.Collections.Generic.List _buffer = new(); - - public override void Add((DateTime t, double v) TValue, bool update) - { - if (update) - { this._buffer[this._buffer.Count - 1] = TValue.v; } - else - { this._buffer.Add(TValue.v); } - if (this._buffer.Count > this._p && this._p != 0) - { this._buffer.RemoveAt(0); } - - double _max = TValue.v; - double _min = TValue.v; - for (int i = 0; i < this._buffer.Count; i++) - { - _max = Math.Max(this._buffer[i], _max); - _min = Math.Min(this._buffer[i], _min); - } - double _mid = (_max + _min) * 0.5; - - var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); - - base.Add(result, update); - } +namespace QuanTAlib; +using System; + +/* +MIDPOINT: Midpoint value (max+min)/2 in the given period in the series. + If period = 0 => period = full length of the series + +Sources: + https://thefaqblog.com/what-is-the-midpoint-in-statistics/ + + */ + +public class MIDPOINT_Series : Single_TSeries_Indicator +{ + public MIDPOINT_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) + { + if (base._data.Count > 0) + { base.Add(base._data); } + } + private readonly System.Collections.Generic.List _buffer = new(); + + public override void Add((DateTime t, double v) TValue, bool update) + { + if (update) + { this._buffer[this._buffer.Count - 1] = TValue.v; } + else + { this._buffer.Add(TValue.v); } + if (this._buffer.Count > this._p && this._p != 0) + { this._buffer.RemoveAt(0); } + + double _max = TValue.v; + double _min = TValue.v; + for (int i = 0; i < this._buffer.Count; i++) + { + _max = Math.Max(this._buffer[i], _max); + _min = Math.Min(this._buffer[i], _min); + } + double _mid = (_max + _min) * 0.5; + + var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); + + base.Add(result, update); + } } \ No newline at end of file diff --git a/Source/Basics/MIDPRICE_Series.cs b/Source/Basics/MIDPRICE_Series.cs index f91a0f47..f49e1f1c 100644 --- a/Source/Basics/MIDPRICE_Series.cs +++ b/Source/Basics/MIDPRICE_Series.cs @@ -1,50 +1,50 @@ -namespace QuanTAlib; -using System; - -/* -MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series. - If period = 0 => period = full length of the series - - */ - -public class MIDPRICE_Series : Single_TBars_Indicator -{ - public MIDPRICE_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) - { - if (base._bars.Count > 0) - { base.Add(base._bars); } - } - private readonly System.Collections.Generic.List _bufferhi = new(); - private readonly System.Collections.Generic.List _bufferlo = new(); - - public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) - { - if (update) - { - this._bufferhi[this._bufferhi.Count - 1] = TBar.h; - this._bufferlo[this._bufferlo.Count - 1] = TBar.l; - } - else - { - this._bufferhi.Add(TBar.h); - this._bufferlo.Add(TBar.l); - } - if (this._bufferhi.Count > this._p && this._p != 0) - { this._bufferhi.RemoveAt(0); } - if (this._bufferlo.Count > this._p && this._p != 0) - { this._bufferlo.RemoveAt(0); } - - double _max = TBar.h; - double _min = TBar.l; - for (int i = 0; i < this._bufferhi.Count; i++) - { - _max = Math.Max(this._bufferhi[i], _max); - _min = Math.Min(this._bufferlo[i], _min); - } - double _mid = (_max + _min) * 0.5; - - var result = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); - - base.Add(result, update); - } +namespace QuanTAlib; +using System; + +/* +MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series. + If period = 0 => period = full length of the series + + */ + +public class MIDPRICE_Series : Single_TBars_Indicator +{ + public MIDPRICE_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) + { + if (base._bars.Count > 0) + { base.Add(base._bars); } + } + private readonly System.Collections.Generic.List _bufferhi = new(); + private readonly System.Collections.Generic.List _bufferlo = new(); + + public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) + { + if (update) + { + this._bufferhi[this._bufferhi.Count - 1] = TBar.h; + this._bufferlo[this._bufferlo.Count - 1] = TBar.l; + } + else + { + this._bufferhi.Add(TBar.h); + this._bufferlo.Add(TBar.l); + } + if (this._bufferhi.Count > this._p && this._p != 0) + { this._bufferhi.RemoveAt(0); } + if (this._bufferlo.Count > this._p && this._p != 0) + { this._bufferlo.RemoveAt(0); } + + double _max = TBar.h; + double _min = TBar.l; + for (int i = 0; i < this._bufferhi.Count; i++) + { + _max = Math.Max(this._bufferhi[i], _max); + _min = Math.Min(this._bufferlo[i], _min); + } + double _mid = (_max + _min) * 0.5; + + var result = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _mid); + + base.Add(result, update); + } } \ No newline at end of file diff --git a/Source/Basics/MIN_Series.cs b/Source/Basics/MIN_Series.cs index 889370e2..ceea135d 100644 --- a/Source/Basics/MIN_Series.cs +++ b/Source/Basics/MIN_Series.cs @@ -23,7 +23,6 @@ public class MIN_Series : Single_TSeries_Indicator double _min = TValue.v; for (int i = 0; i < this._buffer.Count; i++) { - //_min = (this._buffer[i] < _min) ? this._buffer[i] : _min; _min = Math.Min(this._buffer[i], _min); } diff --git a/Source/Basics/SUM_Series.cs b/Source/Basics/SUM_Series.cs index bb98134d..b3846737 100644 --- a/Source/Basics/SUM_Series.cs +++ b/Source/Basics/SUM_Series.cs @@ -1,35 +1,35 @@ -namespace QuanTAlib; -using System; - -/* -SUM: Cumulative Sum (aka Running Total) - SUM across a period provides a rolling sum of all values across the period. - If SUM values would be divided with period, the output would be SMA() - -Sources: - https://en.wikipedia.org/wiki/CUSUM - - */ - -public class SUM_Series : Single_TSeries_Indicator -{ - public SUM_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) - { - if (base._data.Count > 0) { base.Add(base._data); } - } - private readonly System.Collections.Generic.List _buffer = new(); - - public override void Add((System.DateTime t, double v) TValue, bool update) - { - if (update) { _buffer[_buffer.Count - 1] = TValue.v; } - else { _buffer.Add(TValue.v); } - if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); } - - double _sum = 0; - for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; } - - var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sum); - - base.Add(result, update); - } -} +namespace QuanTAlib; +using System; + +/* +SUM: Cumulative Sum (aka Running Total) + SUM across a period provides a rolling sum of all values across the period. + If SUM values would be divided with period, the output would be SMA() + +Sources: + https://en.wikipedia.org/wiki/CUSUM + + */ + +public class SUM_Series : Single_TSeries_Indicator +{ + public SUM_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) + { + if (base._data.Count > 0) { base.Add(base._data); } + } + private readonly System.Collections.Generic.List _buffer = new(); + + public override void Add((System.DateTime t, double v) TValue, bool update) + { + if (update) { _buffer[_buffer.Count - 1] = TValue.v; } + else { _buffer.Add(TValue.v); } + if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); } + + double _sum = 0; + for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; } + + var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sum); + + base.Add(result, update); + } +} diff --git a/Source/Feeds/Alphavantage_Feed.cs b/Source/Feeds/Alphavantage_Feed.cs index ab485dfb..96cdafdc 100644 --- a/Source/Feeds/Alphavantage_Feed.cs +++ b/Source/Feeds/Alphavantage_Feed.cs @@ -8,8 +8,6 @@ Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free) Parameters: Symbol: stock ("AAPL"), APIkey: unique Alphavantage API key - Usage: - Alphavantage_Feed ticker = new("MSFT", APIkey:"xxxxxxx"); */ @@ -47,9 +45,10 @@ public class Alphavantage_Feed : TBars case "3b. low (USD)": l = Convert.ToDouble(val.Value.ToString()); break; case "4. close": c = Convert.ToDouble(val.Value.ToString()); break; case "4b. close (USD)": c = Convert.ToDouble(val.Value.ToString()); break; - //case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break; + case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break; case "5. volume": v = Convert.ToDouble(val.Value.ToString()); break; case "6. volume": v = Convert.ToDouble(val.Value.ToString()); break; + default: o = 0; h = 0; l = 0; c = 0; v = 0; break; } } return (date, o, h, l, c, v); diff --git a/Source/Feeds/Yahoo_Feed.cs b/Source/Feeds/Yahoo_Feed.cs index b0c19183..5cbcdd86 100644 --- a/Source/Feeds/Yahoo_Feed.cs +++ b/Source/Feeds/Yahoo_Feed.cs @@ -8,16 +8,14 @@ Yahoo Finance - Free API feed to collect daily market quotes Symbol: stock symbol (default: "IBM") Period: number of days of collected history (default: 252) Usage: - Yahoo_Feed ticker = new("MSFT", 20); + Yahoo_Feed ticker = new("MSFT", 20) */ public class Yahoo_Feed : TBars { - private static string requestUrl; - public Yahoo_Feed(string Symbol = "IBM", int Period = 252) { - requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+ + 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(); diff --git a/Source/Statistics/LINREG_Series.cs b/Source/Statistics/LINREG_Series.cs index 9c7aeff0..eb5a0cbf 100644 --- a/Source/Statistics/LINREG_Series.cs +++ b/Source/Statistics/LINREG_Series.cs @@ -71,11 +71,11 @@ public class LINREG_Series : Single_TSeries_Indicator double _intercept = avgY - (_slope * avgX); // calculate Standard Deviation and R-Squared - double stdDevX = Math.Sqrt((double)sumSqX / _len); - double stdDevY = Math.Sqrt((double)sumSqY / _len); + double stdDevX = Math.Sqrt(sumSqX / _len); + double stdDevY = Math.Sqrt(sumSqY / _len); double _StdDev = stdDevY; - double arrr = (stdDevX * stdDevY != 0) ? (double)sumSqXY / (stdDevX * stdDevY) / _len : 0; + 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); diff --git a/Source/Volume/OBV_Series.cs b/Source/Volume/OBV_Series.cs index bc4bd3ee..c77570a8 100644 --- a/Source/Volume/OBV_Series.cs +++ b/Source/Volume/OBV_Series.cs @@ -47,9 +47,6 @@ public class OBV_Series : Single_TBars_Indicator if (TBar.c > this._lastclose) { _obv += TBar.v; } if (TBar.c < this._lastclose) { _obv -= TBar.v; } - // Unclear what the first value in OBV series is - currently set to volume[0] - // if (this.Count == 0) { _obv = 0; } - this._lastlastobv = this._lastobv; this._lastobv = _obv; diff --git a/Tests/Validations/Pandas_TA.cs b/Tests/Validations/Pandas_TA.cs index ce5224c8..5991fedf 100644 --- a/Tests/Validations/Pandas_TA.cs +++ b/Tests/Validations/Pandas_TA.cs @@ -7,10 +7,10 @@ using Python.Included; namespace Validations; public class PandasTA : IDisposable { - private GBM_Feed bars; - private Random rnd = new(); - private int period; - private string OStype; + private readonly GBM_Feed bars; + private readonly Random rnd = new(); + private readonly int period; + private readonly string OStype; private dynamic np; private dynamic ta; private dynamic df; @@ -23,14 +23,19 @@ public class PandasTA : IDisposable // Checking the host OS and setting PythonDLL accordingly OStype = Environment.OSVersion.ToString(); if (OStype == "Unix 13.1.0") - OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib"; - else OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; + { + OStype = @"/usr/local/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib"; + } + else + { + OStype = Path.GetFullPath(".") + @"\python-3.10.0-embed-amd64\python310.dll"; + } Installer.InstallPath = Path.GetFullPath("."); Installer.SetupPython().Wait(); Installer.TryInstallPip(); Installer.PipInstallModule("pandas-ta"); - //Installer.PipInstallModule("git+https://github.com/twopirllc/pandas-ta@development"); + //alternative: git+https://github.com/twopirllc/pandas-ta Runtime.PythonDLL = OStype; PythonEngine.Initialize(); @@ -74,35 +79,98 @@ public class PandasTA : IDisposable { var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(bars.OHLC4.Last().v, 7)); - } - - [Fact] + } + + [Fact] + void MEDIAN() + { + MED_Series QL = new(bars.Close, period); + var pta = df.ta.median(close: df.close, length: period); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void VARIANCE() + { + VAR_Series QL = new(bars.Close, period); + var pta = df.ta.variance(close: df.close, length: period, ddof:0); + Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5)); + } + + [Fact] + void SVARIANCE() + { + SVAR_Series QL = new(bars.Close, period); + var pta = df.ta.variance(close: df.close, length: period, ddof: 1); + Assert.Equal(Math.Round((double)pta.tail(1), 5), Math.Round(QL.Last().v, 5)); + } + + [Fact] + void ADL() + { + ADL_Series QL = new(bars); + var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void ADOSC() + { + ADOSC_Series QL = new(bars); + var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void TR() + { + TR_Series QL = new(bars); + var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void ATR() + { + ATR_Series QL = new(bars, period); + var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void RSI() + { + RSI_Series QL = new(bars.Close, period); + var pta = df.ta.rsi(close: df.close, length: period); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void TRIMA() + { + //TODO: return length to variable length (period) when Pandas-TA fixes trima + TRIMA_Series QL = new(bars.Close, 11); + var pta = df.ta.trima(close: df.close, length: 11); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] void KAMA() { KAMA_Series QL = new(bars.Close, period); var pta = df.ta.kama(close: df.close, length: period); Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - /* - [Fact] - void ALMA() - { - ALMA_Series QL = new(bars.Close, period: period, offset: 0.85, sigma: 6.0, false); - var pta = df.ta.alma(close: df.close, length: period, distribution_offset: 0.85, sigma: 6.0); - Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - */ - - [Fact] + } + + [Fact] void HMA() { HMA_Series QL = new(bars.Close, period, false); var pta = df.ta.hma(close: df.close, length: period); Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] + } + + [Fact] void SMA() { SMA_Series QL = new(bars.Close, period, false); @@ -140,9 +208,25 @@ public class PandasTA : IDisposable WMA_Series QL = new(bars.Close, period, false); var pta = df.ta.wma(close: df.close, length: period); Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] + } + + [Fact] + void RMA() + { + RMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.rma(close: df.close, length: period); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void ZLEMA() + { + ZLEMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.zlma(close: df.close, length: period); + Assert.Equal(Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] void DEMA() { DEMA_Series QL = new(bars.Close, period, false); diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs index d4914862..33664ee5 100644 --- a/Tests/Validations/Skender_Stock.cs +++ b/Tests/Validations/Skender_Stock.cs @@ -27,7 +27,7 @@ public class Skender_Stock }); } - [Fact] + [Fact] public void SMA() { SMA_Series QL = new(bars.Close, period, false); @@ -196,7 +196,7 @@ public class Skender_Stock Assert.Equal(Math.Round((double)SK.Last().Rsi!, 6), Math.Round(QL.Last().v, 6)); } - [Fact] + [Fact] public void ALMA() { ALMA_Series QL = new(bars.Close, period, useNaN: false); diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs index 84f92250..f9489107 100644 --- a/Tests/Validations/TA_LIB.cs +++ b/Tests/Validations/TA_LIB.cs @@ -102,6 +102,16 @@ public class TA_LIB Assert.Equal(Math.Round(TALIB[TALIB.Length - outBegIdx - 1], 6, MidpointRounding.AwayFromZero), Math.Round(QL.Last().v, 6, MidpointRounding.AwayFromZero)); } + + [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() { diff --git a/docs/crossovers.ipynb b/docs/crossovers.ipynb index 62f4583d..1a8821f6 100644 --- a/docs/crossovers.ipynb +++ b/docs/crossovers.ipynb @@ -1,149 +1,149 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "vscode": { - "languageId": "dotnet-interactive.csharp" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#r \"nuget: QuanTAlib;\"\n", - "#r \"nuget: Plotly.NET;\"\n", - "#r \"nuget: Plotly.NET.Interactive;\"\n", - "\n", - "using QuanTAlib;\n", - "using Plotly.NET;\n", - "using Plotly.NET.LayoutObjects;\n" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "vscode": { - "languageId": "dotnet-interactive.csharp" - } - }, - "outputs": [], - "source": [ - "String Sym = \"IBM\";\n", - "Alphavantage_Feed data = new(Symbol: Sym);\n", - "ZLEMA_Series calc1 = new(data.OHLC4,20);\n", - "HMA_Series calc2 = new(data.OHLC4,20);\n", - "HEMA_Series calc3 = new(data.OHLC4,20);" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "vscode": { - "languageId": "dotnet-interactive.csharp" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - " \r\n", - "\r\n", - "\n", - " \n", - " \n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "var layout = Layout.init( \n", - " PlotBGColor : Color.fromString(\"#1e1e1e\"),\n", - " PaperBGColor : Color.fromString(\"#1e1e1e\"),\n", - " Font:Font.init(Size:10, Color: Color.fromString(\"#ffffff\")));\n", - "\n", - "var yAxis = LinearAxis.init(\n", - " GridColor:Color.fromString(\"#252525\")); \n", - "\n", - "var candles = Chart2D.Chart.Candlestick(data.Open.v, data.High.v, data.Low.v, data.Close.v, data.Open.t, \"\");\n", - "var line1 = Chart2D.Chart.Line(calc1.t, calc1.v, false, calc1.GetType().Name).WithLineStyle(Width: 2, Color: Color.fromString(\"yellow\"));\n", - "var line2 = Chart2D.Chart.Line(calc2.t, calc2.v, false, calc2.GetType().Name).WithLineStyle(Width: 3, Color: Color.fromString(\"red\"));\n", - "var line3 = Chart2D.Chart.Line(calc3.t, calc3.v, false, calc3.GetType().Name).WithLineStyle(Width: 2, Color: Color.fromString(\"blue\"));\n", - "var chart = Chart.Combine(new []{candles, line1, line2, line3})\n", - " .WithSize(1200,600)\n", - " .WithMargin(Margin.init(30,10,40,30,1,false))\n", - " .WithXAxisRangeSlider(RangeSlider.init(Visible:false))\n", - " .WithYAxis(yAxis)\n", - " .WithXAxis(yAxis)\n", - " .WithTitle(Sym)\n", - " .WithLayout(layout);\n", - "\n", - "chart" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".NET (C#)", - "language": "C#", - "name": ".net-csharp" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/x-csharp", - "name": "C#", - "pygments_lexer": "csharp", - "version": "9.0" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "dotnet-interactive.csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget: QuanTAlib;\"\n", + "#r \"nuget: Plotly.NET;\"\n", + "#r \"nuget: Plotly.NET.Interactive;\"\n", + "\n", + "using QuanTAlib;\n", + "using Plotly.NET;\n", + "using Plotly.NET.LayoutObjects;\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "dotnet-interactive.csharp" + } + }, + "outputs": [], + "source": [ + "String Sym = \"IBM\";\n", + "Alphavantage_Feed data = new(Symbol: Sym);\n", + "ZLEMA_Series calc1 = new(data.OHLC4,20);\n", + "HMA_Series calc2 = new(data.OHLC4,20);\n", + "HEMA_Series calc3 = new(data.OHLC4,20);" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "vscode": { + "languageId": "dotnet-interactive.csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \r\n", + "\r\n", + "\n", + " \n", + " \n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "var layout = Layout.init( \n", + " PlotBGColor : Color.fromString(\"#1e1e1e\"),\n", + " PaperBGColor : Color.fromString(\"#1e1e1e\"),\n", + " Font:Font.init(Size:10, Color: Color.fromString(\"#ffffff\")));\n", + "\n", + "var yAxis = LinearAxis.init(\n", + " GridColor:Color.fromString(\"#252525\")); \n", + "\n", + "var candles = Chart2D.Chart.Candlestick(data.Open.v, data.High.v, data.Low.v, data.Close.v, data.Open.t, \"\");\n", + "var line1 = Chart2D.Chart.Line(calc1.t, calc1.v, false, calc1.GetType().Name).WithLineStyle(Width: 2, Color: Color.fromString(\"yellow\"));\n", + "var line2 = Chart2D.Chart.Line(calc2.t, calc2.v, false, calc2.GetType().Name).WithLineStyle(Width: 3, Color: Color.fromString(\"red\"));\n", + "var line3 = Chart2D.Chart.Line(calc3.t, calc3.v, false, calc3.GetType().Name).WithLineStyle(Width: 2, Color: Color.fromString(\"blue\"));\n", + "var chart = Chart.Combine(new []{candles, line1, line2, line3})\n", + " .WithSize(1200,600)\n", + " .WithMargin(Margin.init(30,10,40,30,1,false))\n", + " .WithXAxisRangeSlider(RangeSlider.init(Visible:false))\n", + " .WithYAxis(yAxis)\n", + " .WithXAxis(yAxis)\n", + " .WithTitle(Sym)\n", + " .WithLayout(layout);\n", + "\n", + "chart" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/x-csharp", + "name": "C#", + "pygments_lexer": "csharp", + "version": "9.0" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/readme.md b/docs/readme.md index c6d0e743..5bd1f513 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -35,158 +35,158 @@ See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/gett ⛔= Not implemented (yet) -| **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** | -|--|:--:|:--:|:--:| -| ✔️ OC2 - (Open+Close)/2 |️ `.OC2` || ️GetBaseQuote | -| ⭐ HL2 - Median Price | `.HL2` | MEDPRICE | ️GetBaseQuote | -| ⭐ HLC3 - Typical Price | `.HLC3` | TYPPRICE || -| ✔️ OHL3 - (Open+High+Low)/3 | `.OHL3` ||| -| ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE |️ GetBaseQuote | -| ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE || -| ⭐ MIDPOINT - Midpoint value | `MIDPOINT_Series` | MIDPOINT || -| ⭐ MIDPRICE - Midpoint price | `MIDPRICE_Series` | MIDPRICE || -| ⭐ MAX - Max value | `MAX_Series` | MAX || -| ⭐ MIN - Min value | `MIN_Series` | MIN || -| ⭐ SUM - Summation | `SUM_Series` | SUM || -| ⭐ ADD - Addition | `ADD_Series` | ADD || -| ⭐ SUB - Subtraction | `SUB_Series` | SUB || -| ⭐ MUL - Multiplication | `MUL_Series` | MUL || -| ⭐ DIV - Division | `DIV_Series` | DIV || +| **BASIC TRANSFORMS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +|--|:--:|:--:|:--:|:--:| +| ⭐ OC2 - (Open+Close)/2 |️ `.OC2` || CandlePart.OC2 || +| ⭐ HL2 - Median Price | `.HL2` | MEDPRICE | CandlePart.HL2 || +| ⭐ HLC3 - Typical Price | `.HLC3` | TYPPRICE | CandlePart.HLC3 || +| ⭐ OHL3 - (Open+High+Low)/3 | `.OHL3` || CandlePart.OHL3 || +| ⭐ OHLC4 - Average Price | `.OHLC4` | AVGPRICE |️ CandlePart.OHLC4 || +| ⭐ HLCC4 - Weighted Price | `.HLCC4` | WCLPRICE | CandlePart.HLCC4 || +| ⭐ MIDPOINT - Midpoint value | `MIDPOINT_Series` | MIDPOINT ||| +| ⭐ MIDPRICE - Midpoint price | `MIDPRICE_Series` | MIDPRICE ||| +| ⭐ MAX - Max value | `MAX_Series` | MAX ||| +| ⭐ MIN - Min value | `MIN_Series` | MIN ||| +| ⭐ SUM - Summation | `SUM_Series` | SUM ||| +| ⭐ ADD - Addition | `ADD_Series` | ADD ||| +| ⭐ SUB - Subtraction | `SUB_Series` | SUB ||| +| ⭐ MUL - Multiplication | `MUL_Series` | MUL ||| +| ⭐ DIV - Division | `DIV_Series` | DIV ||| ||||| -| **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** | -| ✔️ BIAS - Bias | `BIAS_Series` ||| -| ⛔ CORREL - Pearson's Correlation Coefficient || CORREL | GetCorrelation | -| ⛔ COVAR - Covariance ||| GetCorrelation | -| ✔️ ENTP - Entropy | `ENTP_Series` ||| -| ✔️ KURT - Kurtosis | `KURT_Series` ||| -| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope | -| ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma | -| ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma | -| ✔️ MED - Median value | `MED_Series` ||| -| ✔️ MSE - Mean Squared Error | `MSE_Series` || GetSma | -| ⛔ SKEW - Skewness |||| -| ⭐ SDEV - Standard Deviation (Volatility) | `SDEV_Series` | STDDEV || -| ✔️ SSDEV - Sample Standard Deviation | `SSDEV_Series` ||| -| ✔️ SMAPE - Symmetric Mean Absolute Percent Error | `SMAPE_Series` ||| -| ✔️ VAR - Population Variance | `VAR_Series` | VAR || -| ✔️ SVAR - Sample Variance | `SVAR_Series` ||| -| ⛔ QUANT - Quantile |||| -| ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` ||| -| ⛔ ZSCORE - Number of standard deviations from mean |||| -||||| -| **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** | -| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average |||| -| ⭐ ALMA - Arnaud Legoux Moving Average | `ALMA_Series` || GetAlma | -| ⛔ ARIMA - Autoregressive Integrated Moving Average |||| -| ⭐ DEMA - Double EMA Average | `DEMA_Series` | DEMA | GetDema | -| ⭐ EMA - Exponential Moving Average | `EMA_Series` || GetEma | -| ⛔ EPMA - Endpoint Moving Average ||| GetEpma | -| ⛔ FRAMA - Fractal Adaptive Moving Average |||| -| ⛔ FWMA - Fibonacci's Weighted Moving Average |||| -| ⛔ HILO - Gann High-Low Activator |||| -| ✔️ HEMA - Hull/EMA Average | `HEMA_Series` ||| -| ⛔ Hilbert Transform Instantaneous Trendline || HT_TRENDLINE | GetHtTrendline | -| ⭐ HMA - Hull Moving Average | `HMA_Series` || GetHma | -| ⛔ HWMA - Holt-Winter Moving Average |||| -| ✔️ JMA - Jurik Moving Average | `JMA_Series` ||| -| ⭐ KAMA - Kaufman's Adaptive Moving Average | `KAMA_Series` | KAMA | GetKama | -| ⛔ KDJ - KDJ Indicator (trend reversal) |||| -| ⛔ LSMA - Least Squares Moving Average |||| -| ⭐ MACD - Moving Average Convergence/Divergence | `MACD_Series` | MACD | GetMacd | -| ⛔ MAMA - MESA Adaptive Moving Average || MAMA | GetMama | -| ⛔ MCGD - McGinley Dynamic |||| -| ⛔ MMA - Modified Moving Average |||| -| ⛔ PPMA - Pivot Point Moving Average |||| -| ⛔ PWMA - Pascal's Weighted Moving Average |||| -| ✔️ RMA - WildeR's Moving Average | `RMA_Series` ||| -| ⛔ SINWMA - Sine Weighted Moving Average |||| -| ⭐ SMA - Simple Moving Average | `SMA_Series` | SMA | GetSma | -| ⭐ SMMA - Smoothed Moving Average | `SMMA_Series` ||| -| ⛔ SSF - Ehler's Super Smoother Filter |||| -| ⛔ SUP - Supertrend |||| -| ⛔ SWMA - Symmetric Weighted Moving Average |||| -| ⛔ T3 - Tillson T3 Moving Average || T3 | GetT3 | -| ⭐ TEMA - Triple EMA Average | `TEMA_Series` | TEMA | GetTema | -| ⭐ TRIMA - Triangular Moving Average | `TRIMA_Series` | TRIMA || -| ⛔ TSF - Time Series Forecast || TSF || -| ⛔ VIDYA - Variable Index Dynamic Average |||| -| ⛔ VOR - Vortex Indicator |||| -| ⭐ WMA - Weighted Moving Average | `WMA_Series` | WMA | GetWma | -| ✔️ ZLEMA - Zero Lag EMA Average | `ZLEMA_Series` ||| -||||| -| **VOLATILITY INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | -| ⭐ ADL - Chaikin Accumulation Distribution Line | `ADL_Series` | AD | GetAdl | -| ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | `ADOSC_Series` | ADOSC| GetAdl | -| ⭐ ATR - Average True Range | `ATR_Series` | ATR | GetAtr | -| ⭐ ATRP - Average True Range Percent | `ATRP_Series` || GetAtr | -| ⛔ BETA - Beta coefficient || BETA | GetBeta | -| ⭐ BBANDS - Bollinger Bands® | `BBANDS_Series` | BBANDS | GetBollingerBands | -| ⛔ CHAND - Chandelier Exit ||| GetChandelier | -| ⛔ CRSI - Connor RSI ||| GetConnorsRsi | -| ⛔ DON - Donchian Channels ||| GetDonchian | -| ⛔ FCB - Fractal Chaos Bands ||| GetFcb | -| ⛔ HV - Historical Volatility |||| -| ⛔ ICH - Ichimoku ||| GetIchimoku | -| ⛔ KEL - Keltner Channels ||| GetKeltner | -| ⛔ NATR - Normalized Average True Range || NATR | GetAtr | -| ⛔ CHN - Price Channel Indicator |||| -| ⭐ RSI - Relative Strength Index | `RSI_Series` | RSI | GetRsi | -| ⛔ SAR - Parabolic Stop and Reverse || SAR | GetParabolicSar | -| ⛔ SRSI - Stochastic RSI || STOCHRSI | GetStochRsi | -| ⛔ STARC - Starc Bands |||| -| ⭐ TR - True Range | `TR_Series` | TRANGE | GetTr | -| ⛔ UI - Ulcer Index |||| -| ⛔ VSTOP - Volatility Stop |||| -||||| -| **MOMENTUM INDICATORS & OSCILLATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | -| ⛔ AC - Acceleration Oscillator |||| -| ⛔ ADX - Average Directional Movement Index || ADX | GetAdx | -| ⛔ ADXR - Average Directional Movement Index Rating || ADXR | GetAdx | -| ⛔ AO - Awesome Oscillator ||| GetAwesome | -| ⛔ APO - Absolute Price Oscillator || APO || -| ⛔ AROON - Aroon oscillator || AROON | GetAroon | -| ⛔ BOP - Balance of Power || BOP | GetBop | -| ⭐ CCI - Commodity Channel Index | `CCI_Series` | CCI | GetCci | -| ⛔ CFO - Chande Forcast Oscillator |||| -| ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo | -| ⛔ COG - Center of Gravity |||| -| ⛔ COPPOCK - Coppock Curve |||| -| ⛔ CTI - Ehler's Correlation Trend Indicator |||| -| ⛔ DPO - Detrended Price Oscillator ||| GetDpo | -| ⛔ DMI - Directional Movement Index || DX | GetAdx | -| ⛔ EFI - Elder Ray's Force Index ||| GetElderRay | -| ⛔ GAT - Alligator oscillator ||| GetGator | -| ⛔ HURST - Hurst Exponent ||| GetHurst | -| ⛔ KRI - Kairi Relative Index |||| -| ⛔ KVO - Klinger Volume Oscillator |||| -| ⛔ MFI - Money Flow Index || MFI | GetMfi | -| ⛔ MOM - Momentum || MOM || -| ⛔ NVI - Negative Volume Index |||| -| ⛔ PO - Price Oscillator |||| -| ⛔ PPO - Percentage Price Oscillator || PPO || -| ⛔ PMO - Price Momentum Oscillator |||| -| ⛔ PVI - Positive Volume Index |||| -| ⛔ ROC - Rate of Change || MOM | GetRoc | -| ⛔ RVGI - Relative Vigor Index |||| -| ⛔ SMI - Stochastic Momentum Index |||| -| ⛔ STC - Schaff Trend Cycle |||| -| ⛔ STOCH - Stochastic Oscillator || STOCH | GetStoch | -| ⛔ TRIX - 1-day ROC of TEMA || TRIX | GetTrix | -| ⛔ TSI - True Strength Index |||| -| ⛔ UO - Ultimate Oscillator || ULTOSC | GetUltimate | -| ⛔ WILLR - Larry Williams' %R || WILLR | GetWilliamsR | -| ⛔ WGAT - Williams Alligator |||| -||||| -| **VOLUME INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | -| ⛔ AOBV - Archer On-Balance Volume |||| -| ⛔ CMF - Chaikin Money Flow |||| -| ⛔ EOM - Ease of Movement |||| -| ⭐ OBV - On-Balance Volume | ` OBV_Series` | OBV | GetObv | -| ⛔ PRS - Price Relative Strength ||| -| ⛔ PVOL - Price-Volume |||| -| ⛔ PVO - Percentage Volume Oscillator |||| -| ⛔ PVR - Price Volume Rank |||| -| ⛔ PVT - Price Volume Trend |||| -| ⛔ VP - Volume Profile |||| -| ⛔ VWAP - Volume Weighted Average Price |||| -| ⛔ VWMA - Volume Weighted Moving Average |||| +| **STATISTICS & NUMERICAL ANALYSIS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +| ⭐ BIAS - Bias | `BIAS_Series` ||| bias | +| ⛔ CORREL - Pearson's Correlation Coefficient || CORREL | GetCorrelation || +| ⛔ COVAR - Covariance ||| GetCorrelation || +| ⭐ ENTP - Entropy | `ENTP_Series` ||| entropy | +| ⭐ KURT - Kurtosis | `KURT_Series` ||| kurtosis | +| ⭐ LINREG - Linear Regression | `LINREG_Series` || GetSlope || +| ⭐ MAD - Mean Absolute Deviation | `MAD_Series` || GetSma | mad | +| ⭐ MAPE - Mean Absolute Percent Error | `MAPE_Series` || GetSma || +| ⭐ MED - Median value | `MED_Series` ||| median | +| ✔️ MSE - Mean Squared Error | `MSE_Series` || GetSma || +| ⛔ SKEW - Skewness ||||| +| ⭐ SDEV - Standard Deviation (Volatility) | `SDEV_Series` | STDDEV ||| +| ✔️ SSDEV - Sample Standard Deviation | `SSDEV_Series` |||| +| ✔️ SMAPE - Symmetric Mean Absolute Percent Error | `SMAPE_Series` |||| +| ⭐ VAR - Population Variance | `VAR_Series` | VAR || variance | +| ⭐ SVAR - Sample Variance | `SVAR_Series` ||| variance | +| ⛔ QUANT - Quantile ||||| +| ✔️ WMAPE - Weighted Mean Absolute Percent Error | `WMAPE_Series` |||| +| ⛔ ZSCORE - Number of standard deviations from mean ||||| +|||||| +| **TREND INDICATORS & AVERAGES** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +| ⛔ AFIRMA - Autoregressive Finite Impulse Response Moving Average ||||| +| ⭐ ALMA - Arnaud Legoux Moving Average | `ALMA_Series` || GetAlma || +| ⛔ ARIMA - Autoregressive Integrated Moving Average ||||| +| ⭐ DEMA - Double EMA Average | `DEMA_Series` | DEMA | GetDema | dema | +| ⭐ EMA - Exponential Moving Average | `EMA_Series` || GetEma | ema | +| ⛔ EPMA - Endpoint Moving Average ||| GetEpma || +| ⛔ FRAMA - Fractal Adaptive Moving Average ||||| +| ⛔ FWMA - Fibonacci's Weighted Moving Average ||||| +| ⛔ HILO - Gann High-Low Activator ||||| +| ✔️ HEMA - Hull/EMA Average | `HEMA_Series` |||| +| ⛔ Hilbert Transform Instantaneous Trendline || HT_TRENDLINE | GetHtTrendline || +| ⭐ HMA - Hull Moving Average | `HMA_Series` || GetHma | hma | +| ⛔ HWMA - Holt-Winter Moving Average ||||| +| ✔️ JMA - Jurik Moving Average | `JMA_Series` |||| +| ⭐ KAMA - Kaufman's Adaptive Moving Average | `KAMA_Series` | KAMA | GetKama | kama | +| ⛔ KDJ - KDJ Indicator (trend reversal) ||||| +| ⛔ LSMA - Least Squares Moving Average ||||| +| ⭐ MACD - Moving Average Convergence/Divergence | `MACD_Series` | MACD | GetMacd || +| ⛔ MAMA - MESA Adaptive Moving Average || MAMA | GetMama || +| ⛔ MCGD - McGinley Dynamic ||||| +| ⛔ MMA - Modified Moving Average ||||| +| ⛔ PPMA - Pivot Point Moving Average ||||| +| ⛔ PWMA - Pascal's Weighted Moving Average ||||| +| ⭐ RMA - WildeR's Moving Average | `RMA_Series` ||| rma | +| ⛔ SINWMA - Sine Weighted Moving Average ||||| +| ⭐ SMA - Simple Moving Average | `SMA_Series` | SMA | GetSma | sma | +| ⭐ SMMA - Smoothed Moving Average | `SMMA_Series` || GetSmma || +| ⛔ SSF - Ehler's Super Smoother Filter ||||| +| ⛔ SUP - Supertrend ||||| +| ⛔ SWMA - Symmetric Weighted Moving Average ||||| +| ⛔ T3 - Tillson T3 Moving Average || T3 | GetT3 || +| ⭐ TEMA - Triple EMA Average | `TEMA_Series` | TEMA | GetTema | tema | +| ⭐ TRIMA - Triangular Moving Average | `TRIMA_Series` | TRIMA ||| +| ⛔ TSF - Time Series Forecast || TSF ||| +| ⛔ VIDYA - Variable Index Dynamic Average ||||| +| ⛔ VOR - Vortex Indicator ||||| +| ⭐ WMA - Weighted Moving Average | `WMA_Series` | WMA | GetWma | wma | +| ⭐ ZLEMA - Zero Lag EMA Average | `ZLEMA_Series` ||| zlma | +|||||| +| **VOLATILITY INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +| ⭐ ADL - Chaikin Accumulation Distribution Line | `ADL_Series` | AD | GetAdl | ad | +| ⭐ ADOSC - Chaikin Accumulation Distribution Oscillator | `ADOSC_Series` | ADOSC| GetAdl | adosc | +| ⭐ ATR - Average True Range | `ATR_Series` | ATR | GetAtr | atr | +| ⭐ ATRP - Average True Range Percent | `ATRP_Series` || GetAtr || +| ⛔ BETA - Beta coefficient || BETA | GetBeta || +| ⭐ BBANDS - Bollinger Bands® | `BBANDS_Series` | BBANDS | GetBollingerBands || +| ⛔ CHAND - Chandelier Exit ||| GetChandelier || +| ⛔ CRSI - Connor RSI ||| GetConnorsRsi || +| ⛔ DON - Donchian Channels ||| GetDonchian || +| ⛔ FCB - Fractal Chaos Bands ||| GetFcb || +| ⛔ HV - Historical Volatility ||||| +| ⛔ ICH - Ichimoku ||| GetIchimoku || +| ⛔ KEL - Keltner Channels ||| GetKeltner || +| ⛔ NATR - Normalized Average True Range || NATR | GetAtr || +| ⛔ CHN - Price Channel Indicator ||||| +| ⭐ RSI - Relative Strength Index | `RSI_Series` | RSI | GetRsi | rsi | +| ⛔ SAR - Parabolic Stop and Reverse || SAR | GetParabolicSar || +| ⛔ SRSI - Stochastic RSI || STOCHRSI | GetStochRsi || +| ⛔ STARC - Starc Bands ||||| +| ⭐ TR - True Range | `TR_Series` | TRANGE | GetTr | true_range | +| ⛔ UI - Ulcer Index ||||| +| ⛔ VSTOP - Volatility Stop ||||| +|||||| +| **MOMENTUM INDICATORS & OSCILLATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +| ⛔ AC - Acceleration Oscillator ||||| +| ⛔ ADX - Average Directional Movement Index || ADX | GetAdx || +| ⛔ ADXR - Average Directional Movement Index Rating || ADXR | GetAdx || +| ⛔ AO - Awesome Oscillator ||| GetAwesome || +| ⛔ APO - Absolute Price Oscillator || APO ||| +| ⛔ AROON - Aroon oscillator || AROON | GetAroon || +| ⛔ BOP - Balance of Power || BOP | GetBop || +| ⭐ CCI - Commodity Channel Index | `CCI_Series` | CCI | GetCci || +| ⛔ CFO - Chande Forcast Oscillator ||||| +| ⛔ CMO - Chande Momentum Oscillator || CMO | GetCmo || +| ⛔ COG - Center of Gravity ||||| +| ⛔ COPPOCK - Coppock Curve ||||| +| ⛔ CTI - Ehler's Correlation Trend Indicator ||||| +| ⛔ DPO - Detrended Price Oscillator ||| GetDpo || +| ⛔ DMI - Directional Movement Index || DX | GetAdx || +| ⛔ EFI - Elder Ray's Force Index ||| GetElderRay || +| ⛔ GAT - Alligator oscillator ||| GetGator || +| ⛔ HURST - Hurst Exponent ||| GetHurst || +| ⛔ KRI - Kairi Relative Index ||||| +| ⛔ KVO - Klinger Volume Oscillator ||||| +| ⛔ MFI - Money Flow Index || MFI | GetMfi || +| ⛔ MOM - Momentum || MOM ||| +| ⛔ NVI - Negative Volume Index ||||| +| ⛔ PO - Price Oscillator ||||| +| ⛔ PPO - Percentage Price Oscillator || PPO ||| +| ⛔ PMO - Price Momentum Oscillator ||||| +| ⛔ PVI - Positive Volume Index ||||| +| ⛔ ROC - Rate of Change || MOM | GetRoc || +| ⛔ RVGI - Relative Vigor Index ||||| +| ⛔ SMI - Stochastic Momentum Index ||||| +| ⛔ STC - Schaff Trend Cycle ||||| +| ⛔ STOCH - Stochastic Oscillator || STOCH | GetStoch || +| ⛔ TRIX - 1-day ROC of TEMA || TRIX | GetTrix || +| ⛔ TSI - True Strength Index ||||| +| ⛔ UO - Ultimate Oscillator || ULTOSC | GetUltimate || +| ⛔ WILLR - Larry Williams' %R || WILLR | GetWilliamsR || +| ⛔ WGAT - Williams Alligator ||||| +|||||| +| **VOLUME INDICATORS** | **QuanTAlib** | **TA-LIB** | **Skender** | **Pandas TA** | +| ⛔ AOBV - Archer On-Balance Volume ||||| +| ⛔ CMF - Chaikin Money Flow ||||| +| ⛔ EOM - Ease of Movement ||||| +| ⭐ OBV - On-Balance Volume | `OBV_Series` | OBV | GetObv || +| ⛔ PRS - Price Relative Strength |||| +| ⛔ PVOL - Price-Volume ||||| +| ⛔ PVO - Percentage Volume Oscillator ||||| +| ⛔ PVR - Price Volume Rank ||||| +| ⛔ PVT - Price Volume Trend ||||| +| ⛔ VP - Volume Profile ||||| +| ⛔ VWAP - Volume Weighted Average Price ||||| +| ⛔ VWMA - Volume Weighted Moving Average |||||