From 585bbdf1290918ab58ea3ef52537df62a17cd486 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Sun, 8 Jan 2023 19:28:45 -0800 Subject: [PATCH] minor updates --- Source/Feeds/GBM_Feed.cs | 1 + Source/QuanTAlib.csproj | 2 +- Tests/Validations/Trends/Pandas_TA.cs | 8 +++--- Tests/Validations/Trends/TA_LIB.cs | 6 ++-- docs/QA.md | 40 +++++++++++++++++++++++++++ docs/img/SMA_chart.svg | 2 +- docs/readme.md | 10 ++----- 7 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 docs/QA.md diff --git a/Source/Feeds/GBM_Feed.cs b/Source/Feeds/GBM_Feed.cs index e83e6b46..e0ca22dc 100644 --- a/Source/Feeds/GBM_Feed.cs +++ b/Source/Feeds/GBM_Feed.cs @@ -34,6 +34,7 @@ public class GBM_Feed : TBars } } + public void Add(bool update = false) {this.Add(DateTime.Now, update);} public void Add(DateTime timestamp, bool update = false) { double Open = GBM_value(seed, volatility*volatility, drift, precision); double Close = GBM_value(Open, volatility, drift, precision); diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj index 87a32a2e..90da774b 100644 --- a/Source/QuanTAlib.csproj +++ b/Source/QuanTAlib.csproj @@ -2,7 +2,7 @@ QuanTAlib - 0.1.25 + 0.1.26 Library of Technical Indicators for .NET Quantitative Technical Analysis library for real-time (streaming) data analysis git diff --git a/Tests/Validations/Trends/Pandas_TA.cs b/Tests/Validations/Trends/Pandas_TA.cs index 34b56c1b..82d472d0 100644 --- a/Tests/Validations/Trends/Pandas_TA.cs +++ b/Tests/Validations/Trends/Pandas_TA.cs @@ -65,7 +65,7 @@ public class PandasTA : IDisposable } } - + /* [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); @@ -122,7 +122,7 @@ public class PandasTA : IDisposable Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } - /* + [Fact] void CMO() { CMO_Series QL = new(bars.Close, period, false); @@ -133,7 +133,7 @@ public class PandasTA : IDisposable Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } - */ + [Fact] void DEMA() { DEMA_Series QL = new(bars.Close, period, false); var pta = df.ta.dema(close: df.close, length: period); @@ -428,5 +428,5 @@ public class PandasTA : IDisposable Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); } } - + */ } \ No newline at end of file diff --git a/Tests/Validations/Trends/TA_LIB.cs b/Tests/Validations/Trends/TA_LIB.cs index 2fe52686..891d7bd8 100644 --- a/Tests/Validations/Trends/TA_LIB.cs +++ b/Tests/Validations/Trends/TA_LIB.cs @@ -62,7 +62,7 @@ public class Ta_Lib { ADOSC_Series QL = new(bars, 3, 10, false); Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + for (int i = QL.Length - 1; i > skip*2; i--) { double QL_item = QL[i].v; double TA_item = TALIB[i - outBegIdx]; @@ -244,11 +244,11 @@ public class Ta_Lib { MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05); Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05); - for (int i = QL.Length - 1; i > skip * 15; i--) + for (int i = QL.Length - 1; i > skip * 10; i--) { double QL_item = QL[i].v; double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits-1), Math.Exp(-digits-1)); } } [Fact] diff --git a/docs/QA.md b/docs/QA.md new file mode 100644 index 00000000..3e56fcda --- /dev/null +++ b/docs/QA.md @@ -0,0 +1,40 @@ +### Is QuanTAlib fast? + +Well, _no_, but actually *yes*. QuanTAlib works on an additive principle, meaning that even when served a full list of quotes, QuanTAlib will process them one item at the time, rolling forward throug the given time series of data. +- If the last bar is still forming (parameter `update: true`), QuanTAlib can easily recalculates the last entry as often as needed without any need to recalculate the history. +- If a new bar is added to the input, QuanTAlib will process that one item (default parameter `update: false`) and add that one result to the List. No recalculation of the history needed. + +So, if you test QuanTAlib with small set of 500 historical bars and calculate EMA(20) on it, the performance of QuanTAlib will be dead last compared to all other TA libraries. + +But when the system uses 10,000 or historical bars, updates the current data at every new tick, and adds a new bar every minute, QuanTAlib has no rivals; all other libraries will need to re-calculate the full length of the indicator on each update/addition to the time series, while QuanTAlib will just update the last entry or add a single new value to the series. No back calculations are performed - ever. Longer the input data series and more updates/additions it gets, the greater advantage there is for QuanTAlib. + +### Are results of QuanTAlib valid? + +QuanTAlib includes battery of tests to compare its results with four well-known and reviewed Technical Analysis libraries to assure accuracy and validity of results: + +- [TA-LIB](https://www.ta-lib.org/function.html) +- [Skender Stock Indicators](https://dotnet.stockindicators.dev/) +- [Pandas-TA](https://twopirllc.github.io/pandas-ta/) +- [Tulip Indicators](https://tulipindicators.org/) + +Not all indicators are implemented by all libraries - and sometimes results of the four reference libraries disagree with each other. Indicators that return equivalent result set to **all four** libraries are marked with ⭐ on [the list of indicators](indicators.md) - these are indicators that can be trusted most. Each verified equivalency of results is marked with ✔️, and each discrepancy is marked with ❌. + +For each discrepancy the research was done to establish the reason and to select the implementation that is the most faithful to the original description of the indicator. + +_For example, CMO indicator was described by Tushar S. Chande in his book The New Technical Trader, where he includes the example of calculating 10-day CMO on a given data. QuanTAlib, Skender.NET and Tulip libraries can all replicate the results, while TA-LIB and Pandas-TA return something very different:_ + +| #| Input | **QuanTAlib** | TA-LIB | Skender | Pandas-TA | Tulip | +|--|:--:|:--:|:--:|:--:|:--:|:--:| +| 0| 101.03|**0.00**| NaN| NaN| NaN| NaN| +| 1| 101.03|**0.00**| NaN| NaN| NaN| NaN| +| 2| 101.12|**100.00**| NaN| NaN| NaN| NaN| +| 3| 101.97|**100.00**| NaN| NaN| NaN| NaN| +| 4| 102.78|**100.00**| NaN| NaN| NaN| NaN| +| 5| 103.00|**100.00**| NaN| NaN| NaN| NaN| +| 6| 102.97|**96.87**| NaN| NaN| NaN| NaN| +| 7| 103.06|**97.01**| NaN| NaN| NaN| NaN| +| 8| 102.94|**85.91**| NaN| NaN| NaN| NaN| +| 9| 102.72|**69.23**| NaN| NaN| NaN| NaN| +|10| 102.75|**69.62**| 69.62| 69.62| ~55.22~| 69.62| +|11| 102.91|**71.43**| ~71.62~| 71.43| ~60.09~| 71.43| +|12| 102.97|**71.08**| ~72.42~| 71.08| ~61.93~| 71.08| \ No newline at end of file diff --git a/docs/img/SMA_chart.svg b/docs/img/SMA_chart.svg index 543c137d..9de5db90 100644 --- a/docs/img/SMA_chart.svg +++ b/docs/img/SMA_chart.svg @@ -1 +1 @@ -020406000.20.40.60.81020406000.20.40.60.8102040600102030020406001020300204060−1−0.500.510204060−1−0.500.510204060−1−0.500.510204060−0.4−0.200.20.40204060−1−0.500.50204060−1−0.500.510204060−1−0.500.51020406000.51020406001020300204060−1010204060−1010204060170172174176178 \ No newline at end of file +020406000.20.40.60.81020406000.20.40.60.8102040600102030020406001020300204060−1−0.500.510204060−1−0.500.510204060−1−0.500.510204060−0.4−0.200.20.40204060−1−0.500.50204060−1−0.500.510204060−1−0.500.51020406000.51020406001020300204060−1010204060−1010204060170172174176178 \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md index 582856d4..226ee7b8 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -39,12 +39,6 @@ QuanTAlib uses validation tests with four other TA libraries to assure accuracy - [Pandas-TA](https://twopirllc.github.io/pandas-ta/) - [Tulip Indicators](https://tulipindicators.org/) -### Performance +### Questions -Is QuanTAlib fast? Well, _no_, but actually *yes*. QuanTAlib works on an additive principle, meaning that even when served a full list of quotes, QuanTAlib will process one item at the time, rolling forward throug time series of data. -- If the last bar is still forming (parameter `update: true`), QuanTAlib easily recalculates the last entry as often as needed without any need to recalculate the history. -- If a new bar is added to the input, QuanTAlib will process that one item (default parameter `update: false`) and add that one result to the List. No recalculation of the history needed. - -If you feed QuanTAlib 500 historical bars and calculate EMA(20) on it, the performance of QuanTAlib will be dead last compared to all other TA libraries. - -But when system uses 10,000 historical bars, does updates to the current/last bar every tick, and adds a new bar every minute, QuanTAlib has no rivals; all other libraries need to re-calculate the full length of the array on each update/addition to the time series. Longer the series and more updates/additions it gets, more advantage for QuanTAlib. \ No newline at end of file +[Some most common questions addressed](QA.md) \ No newline at end of file