dotcover

s1

.sln

s1

s1

s2

s3

s4

s5

s1

s2

x

x2

x3

x4

x5

x6

x1

sonarcube cleanup1

sonarcube cleanup2

sonarcube cleanup 3

fixes

q

q

q

q

q

q

q

q

q1

q2

q

q1

codacy 1
This commit is contained in:
Miha Kralj
2024-09-23 22:08:40 -07:00
parent 846429eccf
commit 58d72c06ca
244 changed files with 621 additions and 14397 deletions
-1
View File
@@ -1 +0,0 @@
-5
View File
@@ -1,5 +0,0 @@
# ALMA: Arnaud Legoux Moving Average
period = 10
![Alt text](./img/ALMA_chart.svg)
-5
View File
@@ -1,5 +0,0 @@
# DEMA: Double Exponential Moving Average
period = 10
![Alt text](./img/DEMA_chart.svg)
-5
View File
@@ -1,5 +0,0 @@
# DWMA: Double Weighted Moving Average
period = 10
![Alt text](./img/DWMA_chart.svg)
-50
View File
@@ -1,50 +0,0 @@
# EMA: Exponential Moving Average
Also known as exponentially weighted moving average, as it places greater weight on the most recent data points.
EMA reacts more agressively to recent data changes and calculates the current value using just the previous EMA value and current data point. The weight applied to the new value is typically $k = 2 / (period-1)$
## Calculation
EMA is a rolling calculation requiring only one historical data point to calculate the current value and is denoted as ${EMA}_{p}{(data)}$ where $p$ represents the period and $data$ represents the list of data points.
Some implementations of EMA calculate a seeding value of $EMA$ as a ${SMA}_{p}$ when $n < period$ - and start the $EMA$ calculation only after the warm-up period. QuanTAlib offers an option to enable/disable SMA warm-up.
$$
EMA_n = \left\{ \begin{array}{cl}
\frac{1}{p}\left( data_{n}-data_{n-p}\right)+SMA_{n-1} & : \ n \leq period \\
{k}\times ({data_{n}} - EMA_{n-1}) + EMA_{n-1} & : \ n > period
\end{array} \right.
$$
## Behavior
![Alt text](./img/EMA_chart.svg)
## Reference Calculation
period = 5
```
TSeries data = new() {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29};
EMA_Series ema = new(data, 5, useNaN: false);
EMA_Series ema_nan = new(data, 5, useNaN: true);
for (int i=0; i< data.Count; i++)
Console.WriteLine($"{i}\t{data[i].v,7:f2}\t{ema_nan[i].v,7:f3}\t{ema[i].v,7:f3}");
```
| #| Input | **QuanTAlib** | _TA-LIB_ | _Skender_ | _Pandas-TA_ | _Tulip_ |
|--|:--:|:--:|:--:|:--:|:--:|:--:|
|0| 81.59| **81.590**| _NaN_| _NaN_| _NaN_| _NaN_|
|1| 81.06| **81.840**| _NaN_| _NaN_| _NaN_| _NaN_|
|2| 82.87| **81.840**| _NaN_| _NaN_| _NaN_| _NaN_|
|3| 83.00| **82.130**| _NaN_| _NaN_| _NaN_| _NaN_|
|4| 83.61| **82.426**| _82.426_| _82.426_| _82.426_| _82.426_|
|5| 83.15| **82.667**| _82.667_| _82.667_| _82.667_|_82.667_|
|6| 82.84| **82.725**| _82.725_| _82.725_| _82.725_|_82.725_|
|7| 83.99| **83.147**| _83.147_| _83.147_| _83.147_|_83.147_|
|8| 84.55| **83.614**| _83.614_| _83.614_| _83.614_|_83.614_|
|9| 84.36| **83.863**| _83.863_| _83.863_| _83.863_|_83.863_|
|10| 85.53| **84.419**| _84.419_| _84.419_| _84.419_|_84.419_|
|11| 86.54| **85.126**| _85.126_| _85.126_| _85.126_|_85.126_|
|12| 86.89| **85.714**| _85.714_| _85.714_| _85.714_|_85.714_|
|13| 87.77| **86.399**| _86.399_| _86.399_| _86.399_|_86.399_|
|14| 87.29| **86.696**| _86.696_| _86.696_| _86.696_|_86.696_|
## References
- https://en.wikipedia.org/wiki/Exponential_smoothing
-4
View File
@@ -1,4 +0,0 @@
# FMA: Fibonacci Moving Average
period = 6
![Alt text](./img/FMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# HEMA: Hull-Exponential Moving Average
period = 10
![Alt text](./img/HEMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# HMA: Hull Moving Average
period = 10
![Alt text](./img/HMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# HWMA: Holt-Winter Moving Average
nA = 0.5; nB = 0.3; nC = 0.01;
![Alt text](./img/HWMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# JMA: Jurik Moving Average
period = 10
![Alt text](./img/JMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# KAMA: Kaufman's Adaptive Moving Average
period = 10
![Alt text](./img/KAMA_chart.svg)
-4
View File
@@ -1,4 +0,0 @@
# MAMA: MESA Adaptive Moving Average
period = 10
![Alt text](./img/MAMA_chart.svg)
-40
View File
@@ -1,40 +0,0 @@
### 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|
-5
View File
@@ -1,5 +0,0 @@
# RMA: wildeR Moving Average
period = 10
![Alt text](./img/RMA_chart.svg)
-57
View File
@@ -1,57 +0,0 @@
# SMA: Simple Moving Average
SMA is is an arithmetic moving average where the weights in SMA are **equally** distributed across the given period, resulting in a mean() of the data within the period.
## Calculation
SMA is a rolling calculation that is looking backwards from the position ${n}$ and is denoted as ${SMA}_{p}{(data)}$ where $p$ represents the period and $data$ represents the list of data points:
$$
SMA_p{(data)} = \frac{1}{p}\sum_{i=n-p+1}^{n} data_i
$$
When calculating the value of the next $SMA_{p,next}$ while knowing previous SMA values, SMA calculation can be reduced to:
$$
SMA_{p,next} = SMA_{p,prev}+\frac{1}{p}\left( data_{n+1}-data_{n+1-p}\right)
$$
## Implementation
`TSeries SMA_Series (TSeries source, int period = 0, bool useNaN = false)`
- SMA_Series returns TSeries list
- `source`: input of type TSeries; SMA_Series automatically subscribes to events of new data added to the source
- `period`: optional size of a lookback window; if set to 0, SMA calculates cumulative average across the whole source
- `useNaN`: if set to _true_, SMA_Series will hide values within the initial period with NaN (for compatibility with other libraries)
## Behavior
![Alt text](./img/SMA_chart.svg)
## Reference Calculation & Validation
period = 5
```
TSeries data = new() {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29};
SMA_Series sma = new(data, 5, useNaN: false);
```
| #| Input | **QuanTAlib** | _TA-LIB_ | _Skender_ | _Pandas-TA_ | _Tulip_ |
|--|:--:|:--:|:--:|:--:|:--:|:--:|
| 0| 212.80|**212.80**| _NaN_| _NaN_| _NaN_| _NaN_|
| 1| 214.06|**213.43**| _NaN_| _NaN_| _NaN_| _NaN_|
| 2| 213.89|**213.58**| _NaN_| _NaN_| _NaN_| _NaN_|
| 3| 214.66|**213.85**| _NaN_| _NaN_| _NaN_| _NaN_|
| 4| 213.95|**213.87**| _213.87_| _213.87_| _213.87_| _213.87_|
| 5| 213.95|**214.10**| _214.10_| _214.10_| _214.10_| _214.10_|
| 6| 214.55|**214.20**| _214.20_| _214.20_| _214.20_| _214.20_|
| 7| 214.02|**214.23**| _214.23_| _214.23_| _214.23_| _214.23_|
| 8| 214.51|**214.20**| _214.20_| _214.20_| _214.20_| _214.20_|
| 9| 213.75|**214.16**| _214.16_| _214.16_| _214.16_| _214.16_|
|10| 214.22|**214.21**| _214.21_| _214.21_| _214.21_| _214.21_|
|11| 213.43|**213.99**| _213.99_| _213.99_| _213.99_| _213.99_|
|12| 214.21|**214.02**| _214.02_| _214.02_| _214.02_| _214.02_|
|13| 213.66|**213.85**| _213.85_| _213.85_| _213.85_| _213.85_|
|14| 215.03|**214.11**| _214.11_| _214.11_| _214.11_| _214.11_|
|15| 216.89|**214.64**| _214.64_| _214.64_| _214.64_| _214.64_|
|16| 216.66|**215.29**| _215.29_| _215.29_| _215.29_| _215.29_|
## References
- https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average
- Kaufman, Perry J. (2013) Trading Systems and Methods
- Murphy, J. (1999) Technical Analysis of the Financial Markets
-5
View File
@@ -1,5 +0,0 @@
# SMMA: Smoothed Moving Average
period = 10
![Alt text](./img/SMMA_chart.svg)
-5
View File
@@ -1,5 +0,0 @@
# T3: Tillson T3 Moving Average
period = 10
![Alt text](./img/T3_chart.svg)
-5
View File
@@ -1,5 +0,0 @@
# TEMA: Triple Exponential Moving Average
period = 10
![Alt text](./img/TEMA_chart.svg)
-5
View File
@@ -1,5 +0,0 @@
# TRIMA: Triangular Moving Average
period = 10
![Alt text](./img/TRIMA_chart.svg)
File diff suppressed because one or more lines are too long
-49
View File
@@ -1,49 +0,0 @@
# WMA: Weighted Moving Average
period = 10
![Alt text](./img/WMA_chart.svg)
WMA is linearly weighted moving Average where the weights are linearly decreasing over the _period_ and the most recent data has the heaviest weight.
## Calculation
WMA is a rolling calculation that is looking backwards from the position ${n}$ and is denoted as ${WMA}_{p}{(data)}$ where $p$ represents the period, $w$ represents the assigned weight and $data$ represents the list of data points:
$$
WMA_p{(data)} = \frac{1}{\sum w }\sum_{i=n-p+1}^{n} w_i data_i
$$
Weights $w$ are linearly increasing from $1$ to $p$. For example, the weights $w$ for a $p=5$ would be {1, 2, 3, 4, 5}
## Reference Calculation
period = 5
```
TSeries data = new() {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29};
WMA_Series wma = new(data, 5, useNaN: false);
WMA_Series wma_nan = new(data, 5, useNaN: true);
for (int i=0; i< data.Count; i++)
Console.WriteLine($"{i}\t{data[i].v,7:f2}\t{wma_nan[i].v,7:f3}\t{wma[i].v,7:f3}");
```
|#|input|wma_NaN|wma|
|--|:--:|:--:|:--:|
|0| 81.59| NaN| 81.590|
|1| 81.06| NaN| 81.237|
|2| 82.87| NaN| 82.053|
|3| 83.00| NaN| 82.432|
|4| 83.61| 82.825| 82.825|
|5| 83.15| 83.066| 83.066|
|6| 82.84| 83.100| 83.100|
|7| 83.99| 83.399| 83.399|
|8| 84.55| 83.809| 83.809|
|9| 84.36| 84.053| 84.053|
|10| 85.53| 84.637| 84.637|
|11| 86.54| 85.399| 85.399|
|12| 86.89| 86.031| 86.031|
|13| 87.77| 86.763| 86.763|
|14| 87.29| 87.121| 87.121|
## References
- https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average
- Kaufman, Perry J. (2013) Trading Systems and Methods
- Murphy, J. (1999) Technical Analysis of the Financial Markets
-5
View File
@@ -1,5 +0,0 @@
# ZLEMA: Zero-lag Exponential Moving Average
period = 10
![Alt text](./img/ZLEMA_chart.svg)
-24
View File
@@ -1,24 +0,0 @@
* [Home](/)
* [FAQ - Frequently asked questions answered](QA.md)
* [List of all Indicators](indicators.md "Indicators coverage")
* [SMA - Simple Moving Average](SMA.md)
* [EMA - Exponential Moving Average](EMA.md)
* [WMA - Weighted Moving Average](WMA.md)
* [T3 - Tillson T3 Exponential MA](T3.md)
* [SMMA - Smoothed Moving Average](SMMA.md)
* [TRIMA - Triangular Moving Average](TRIMA.md)
* [DWMA - Double Weighted Moving Average](DWMA.md)
* [FMA - Fibonacci Moving Average](FMA.md)
* [DEMA - Double Exponential MA](DEMA.md)
* [TEMA - Triple Exponential MA](TEMA.md)
* [ALMA - Arnaud Legoux Moving Average](ALMA.md)
* [HMA - Hull Moving Average](HMA.md)
* [HEMA - Hull/Exponential Moving Average](HEMA.md)
* [HWMA - Holt-Winter Moving Average](HWMA.md)
* [MAMA - MESA Adaptive Moving Average](MAMA.md)
* [KAMA - Kaufman Adaptive Moving Average](KAMA.md)
* [ZLEMA - Zero-Lag Exponential MA](ZLEMA.md)
* [JMA - Jurik Moving Average](JMA.md)
-445
View File
@@ -1,445 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Quick Start\n",
"\n",
"In order to use this .NET Interactive Notebook and play along with QuanTAlib (outside of making your own app or plugging QuanTAlib into Quantower platform), you will need:\n",
"\n",
"- Installed <a href=\"https://code.visualstudio.com/\" target=\"_blank\">Visual Studio Code</a>\n",
"- Installed <a href=\"https://dotnet.microsoft.com/download/dotnet/6.0\" target=\"_blank\">.NET 6 SDK</a>\n",
"- Installed <a href=\"https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode\" target=\"_blank\">.NET Interactive Notebooks</a> extension\n",
"\n",
"**For impatient**, here is a simple example of calculating three moving averages - SMA(data), EMA(SMA(data)) and WMA(EMA(SMA(data))) from 10 days of AAPL stock data using QuanTAlib:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div><div></div><div></div><div></div></div>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"index\t data\t\t sma(data)\t ema(sma(data))\t wma(ema(sma(data)))\n",
"0\t 2023-03-27\t 158.28\t\t 158.28\t\t NaN\n",
"1\t 2023-03-28\t 157.97\t\t 158.12\t\t NaN\n",
"2\t 2023-03-29\t 158.90\t\t 158.38\t\t NaN\n",
"3\t 2023-03-30\t 159.77\t\t 158.73\t\t NaN\n",
"4\t 2023-03-31\t 160.79\t\t 159.14\t\t 158.69\n",
"5\t 2023-04-03\t 162.37\t\t 160.22\t\t 159.25\n",
"6\t 2023-04-04\t 163.97\t\t 161.47\t\t 160.10\n",
"7\t 2023-04-05\t 164.56\t\t 162.50\t\t 161.07\n",
"8\t 2023-04-06\t 165.02\t\t 163.34\t\t 162.04\n"
]
}
],
"source": [
"#r \"nuget:QuanTAlib;\"\n",
"using QuanTAlib;\n",
"\n",
"Yahoo_Feed aapl = new(\"AAPL\", 10);\n",
"TSeries data = aapl.Close;\n",
"SMA_Series sma = new(source: data, period: 5, useNaN: false);\n",
"EMA_Series ema = new(sma, period: 5); // by default, indicators expose all data, no NaN values\n",
"WMA_Series wma = new(ema, 5, useNaN: true); // for the final calculation we can hide early data with NaNs\n",
"\n",
"Console.Write($\"index\\t data\\t\\t sma(data)\\t ema(sma(data))\\t wma(ema(sma(data)))\\n\");\n",
"for (int i=0; i<aapl.Count; i++)\n",
" Console.Write($\"{i}\\t {data[i].t:yyyy-MM-dd}\\t {sma[i].v:f2}\\t\\t {ema[i].v:f2}\\t\\t {wma[i].v:f2}\\n\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Understanding QuanTAlib data model\n",
"\n",
"QuanTAlib expects that every data item is a tuple (TimeDate t, double v) and TSeries is a list of (t,v) tuples. There are several helpers built into the TSeries class to simplify adding elements:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 12:00:00 AM, 105.3)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 00:00:00Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>105.3</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>1</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 2:34:48 PM, 293.1)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>293.1</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>2</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 2:34:48 PM, 0)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>0</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>3</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/4/2023 2:34:48 PM, 10)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-04 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>10</pre></div></td></tr></tbody></table></div></details></td></tr></tbody></table><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"var item1 = (DateTime.Today, 105.3); // (DateTime, Value) tuple\n",
"double item2 = 293.1; // a simple double\n",
"\n",
"TSeries data = new();\n",
"data.Add(item1); // adding tuple variable\n",
"data.Add(item2); // QuanTAlib stamps the (double) with current time\n",
"data.Add(0); // directly adding a number (stamped with current time)\n",
"data.Add((DateTime.Now.AddDays(-3), 10)); // adding a tuple with timestamp 3 days ago\n",
"\n",
"data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"TSeries list can display only values (without timestamps) or only timestamps (without values) by using `.v` or `.t` properties"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 105.3, 293.1, 0, 10 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"data.v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The last element on the list can be accessed by .Last() or by [^1] - and using `.t` (time) and `.v` (value) properties. Also, casting a TSeries into (double) will return the value of the last element"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>10</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"bool IsTheSame = data.Last().v == data[^1].v;\n",
"double lastvalue = data;\n",
"\n",
"lastvalue"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All indicators are just modified TSeries classes; they get all required input during class construction (source of the datafeed, period...) and they automatically subscribe to events of the datafeed. Whenever datafeed gets a new value, indicator will calculate its own value. Indicators are also event publishers, so other indicators can subscribe to their results, chaining indicators together:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ Infinity, 0.6666666666666666, 0.3333333333333333, 0.2, 0.14285714285714285, 0.1111111111111111, 0.09090909090909091, 0.07692307692307693, 0.06666666666666667, 0.058823529411764705, 0.25 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"TSeries t1 = new() {0,1,2,3,4,5,6,7,8,9}; // t1 is loaded with data and activated as a publisher\n",
"EMA_Series t2 = new(t1, 3); // t2 will auto-load all history of t1 and wait for events from t1\n",
"ADD_Series t3 = new(t1, t2); // t3 is an ADDition of t1 and t2 - will also load history and wait for t2 events\n",
"DIV_Series t4 = new(1, t3); // t4 is calculating 1/t3 - and waiting for t3 events\n",
"\n",
"TSeries t5 = new(); // a wild indicator appeared! And it is empty!\n",
"t4.Pub += t5.Sub; // let us add a manual subscription to events coming from t4 - t5 is now listening to t4\n",
"t1.Add(0); // we add one new value to t1 - and trigger the full cascade of calculation! t5 is now full!\n",
"\n",
"t5.v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MACD compounded indicator\n",
"\n",
"With QuanTAlib we can chain indicators together, creating complex compounded indicators. For example, we can create Moving Average Convergence/Divergence (MACD) indicators by chaining all required operations in a sequence:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.000974358974349343, -0.03456027049873228, -0.13792617985566447, -0.4729486712049916, -0.825402881197467, -0.8902360596814031, -0.9360607784903126, -0.7333381872239422 ... (79 more) ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Yahoo_Feed aapl = new(\"AAPL\", 100);\n",
"TSeries close = aapl.Close; // close will get data from history\n",
"EMA_Series slow = new(close,26); // slow gets data from slow through pub-sub eventing\n",
"EMA_Series fast = new(close,12); // fast gets data from slow (via eventing)\n",
"SUB_Series macd = new(fast,slow); // macd is a SUBtraction: fast-slow\n",
"EMA_Series signal = new(macd,9); // signal is EMA of macd\n",
"SUB_Series histogram = new(macd, signal); // histogram is SUBtraction macd-signal\n",
"\n",
"histogram.v\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [
"C#",
"c#"
],
"languageName": "C#",
"name": "csharp"
},
{
"aliases": [],
"languageName": "KQL",
"name": "kql"
},
{
"aliases": [
"frontend"
],
"name": "vscode"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 151 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 151 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 KiB

-34
View File
@@ -1,34 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
homepage: 'readme.md',
loadSidebar: true,
subMaxLevel: 1,
name: '',
repo: '',
latex: {
inlineMath : [['$', '$'], ['\\(', '\\)']], // default
displayMath : [['$$', '$$']], // default
}
};
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<!-- LaTeX display engine -->
<script src="//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<!-- docsify-latex plugin -->
<script src="//cdn.jsdelivr.net/npm/docsify-latex@0"></script>
</body>
</html>
-175
View File
@@ -1,175 +0,0 @@
# Coverage
⭐= Calculation is validated against several TA libraries
✔️= Validation tests passed
❌= Issue
|**BASIC TRANSFORMS**|**QuanTAlib**|**TA-LIB**|**Skender**|**Pandas TA**|**Tulip**|
|--|:--:|:--:|:--:|:--:|:--:|
|OC2 - (Open+Close)/2| `.OC2`||✔️CandlePart.OC2||
|⭐HL2 - Median Price|`.HL2`|✔️MEDPRICE|✔️CandlePart.HL2|✔️hl2|✔️medprice|
|⭐HLC3 - Typical Price|`.HLC3`|✔️TYPPRICE|✔️CandlePart.HLC3|✔️hlc3|✔️typprice|
|OHL3 - (Open+High+Low)/3|`.OHL3`||✔️CandlePart.OHL3||
|⭐OHLC4 - Average Price|`.OHLC4`|✔️AVGPRICE|️✔️CandlePart.OHLC4|✔️ohlc4|✔️avgprice|
|HLCC4 - Weighted Price|`.HLCC4`|✔️WCLPRICE|||✔️wcprice|
|MIDPOINT - Midpoint value|`MIDPOINT_Series`|✔️MIDPOINT||midpoint|
|MIDPRICE - Midpoint price|`MIDPRICE_Series`|✔️MIDPRICE||midprice|
|MAX - Max value|`MAX_Series`|✔️MAX|||✔️max|
|MIN - Min value|`MIN_Series`|✔️MIN|||✔️min|
|SUM - Summation|`SUM_Series`|✔️SUM|||✔️sum|
|ADD - Addition|`ADD_Series`|✔️ADD|||✔️add|
|SUB - Subtraction|`SUB_Series`|✔️SUB|||✔️sub|
|MUL - Multiplication|`MUL_Series`|✔️MUL|||✔️mul|
|DIV - Division|`DIV_Series`|✔️DIV|||✔️div|
|||||
|**STATISTICS & NUMERICAL ANALYSIS**|
||||||
|BIAS - Bias|`BIAS_Series`|||✔️bias|
|CORR - Pearson's Correlation Coefficient|`CORR_Series`|✔️CORREL|✔️GetCorrelation||
|COVAR - Covariance|`COVAR_Series`||✔️GetCorrelation||
|DECAY - Linear Decay|`DECAY_Series`|||decay|✔️decay|
|EDECAY - Exponential Decay|`DECAY_Series`|||decay|✔️edecay|
|ENTROPY - Entropy|`ENTROPY_Series`|||entropy||
|KURTOSIS - Kurtosis|`KURT_Series`|||✔️kurtosis|
|SLOPE - Slope of Linear Regression|`SLOPE_Series`||✔️GetSlope||✔️linregslope|
|MAD - Mean Absolute Deviation|`MAD_Series`||✔️GetSmaAnalysis|✔️mad|
|MAE - Mean Absolute Error|`MAE_Series`||||
|MAPE - Mean Absolute Percent Error|`MAPE_Series`||✔️GetSmaAnalysis||
|MEDIAN - Median value|`MEDIAN_Series`|||✔️median|
|MSE - Mean Squared Error|`MSE_Series`||✔️GetSmaAnalysis||
|SKEW - Skewness||||skew|
|⭐SDEV - Standard Deviation (Volatility)|`SDEV_Series`|✔️STDDEV|✔️GetStdDev|✔️stdev|✔️stddev|
|SSDEV - Sample Standard Deviation|`SSDEV_Series`|||✔️stdev|
|SMAPE - Symmetric Mean Absolute Percent Error|`SMAPE_Series`||||
|VAR - Population Variance|`VAR_Series`|✔️VAR||✔️variance|✔️var|
|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|
||||||
|**TREND INDICATORS & AVERAGES**|
||||||
|AFIRMA - Autoregressive Finite Impulse Response Moving Average|||||
|ALMA - Arnaud Legoux Moving Average|`ALMA_Series`||✔️GetAlma|alma|
|DEMA - Double EMA Average|`DEMA_Series`|✔️DEMA|✔️GetDema|✔️dema|✔️dema|
|DWMA - Double WMA Average|`DWMA_Series`|||||
|⭐[EMA - Exponential Moving Average](EMA.md)|`EMA_Series`|✔️EMA|✔️GetEma|✔️ema|✔️ema|
|EPMA - Endpoint Moving Average|||GetEpma||
|FRAMA - Fractal Adaptive Moving Average|||||
|FMA - Fibonacci's Weighted Moving Average|`FMA_Series`|||fwma|
|HILO - Gann High-Low Activator||||hilo|
|HEMA - Hull/EMA Average|`HEMA_Series`||||
|Hilbert Transform Instantaneous Trendline||HT_TRENDLINE|GetHtTrendline||
|⭐HMA - Hull Moving Average|`HMA_Series`||✔️GetHma|✔️hma|✔️hma|
|HWMA - Holt-Winter Moving Average|`HWMA_Series`|||✔️hwma|
|JMA - Jurik Moving Average|`JMA_Series`|||jma||
|KAMA - Kaufman's Adaptive Moving Average|`KAMA_Series`|✔️KAMA|✔️GetKama|✔️kama|✔️kama|
|KDJ - KDJ Indicator (trend reversal)||||kdj|
|LSMA - Least Squares Moving Average|||GetEpma||
|⭐MACD - Moving Average Convergence/Divergence|`MACD_Series`|✔️MACD|✔️GetMacd|✔️macd|✔️macd|
|MAMA - MESA Adaptive Moving Average|`MAMA_Series`|✔️MAMA|✔️GetMama||
|MCGD - McGinley Dynamic||||mcgd|
|MMA - Modified Moving Average|||||
|PPMA - Pivot Point Moving Average|||||
|PWMA - Pascal's Weighted Moving Average||||pwma|
|⭐RMA - WildeR's Moving Average|`RMA_Series`|||✔️rma|✔️rma|
|SINWMA - Sine Weighted Moving Average||||sinwma|
|⭐[SMA - Simple Moving Average](SMA.md)|`SMA_Series`|✔️SMA|✔️GetSma|✔️sma|✔️sma|
|SMMA - Smoothed Moving Average|`SMMA_Series`||✔️GetSmma||
|SSF - Ehler's Super Smoother Filter||||ssf|
|SUPERTREND - Supertrend||||supertrend|
|SWMA - Symmetric Weighted Moving Average||||swma|
|T3 - Tillson T3 Moving Average|`T3_Series`|✔️T3|✔️GetT3|✔️t3||
|⭐TEMA - Triple EMA Average|`TEMA_Series`|✔️TEMA|✔️GetTema|✔️tema|✔️tema|
|⭐TRIMA - Triangular Moving Average|`TRIMA_Series`|✔️TRIMA||✔️trima|✔️trima|
|TSF - Time Series Forecast||TSF|||
|VIDYA - Variable Index Dynamic Average||||vidya|vidya|
|VORTEX - Vortex Indicator||||vortex|
|⭐WMA - Weighted Moving Average|`WMA_Series`|✔️WMA|✔️GetWma|✔️wma|✔️wma|
|ZLEMA - Zero Lag EMA Average|`ZLEMA_Series`|||✔️zlma|❌zlema|
||||||
|**VOLATILITY INDICATORS**|
||||||
|⭐ADL - Chaikin Accumulation Distribution Line|`ADL_Series`|✔️AD|✔️GetAdl|✔️ad|✔️ad|
|⭐ADOSC - Chaikin Accumulation Distribution Oscillator|`ADOSC_Series`|✔️ADOSC||✔️adosc|✔️adosc|
|⭐ATR - Average True Range|`ATR_Series`|✔️ATR|✔️GetAtr|✔️atr|✔️atr|
|ATRP - Average True Range Percent|`ATRP_Series`||✔️GetAtr||
|BETA - Beta coefficient||BETA|GetBeta||
|⭐BBANDS - Bollinger Bands®|`BBANDS_Series`|✔️BBANDS|✔️GetBollingerBands|✔️bbands|✔️bbands|
|CHAND - Chandelier Exit|||GetChandelier||
|CRSI - Connor RSI|||GetConnorsRsi||
|CVI - Chaikins Volatility|||||cvi|
|DON - Donchian Channels|||GetDonchian||
|FCB - Fractal Chaos Bands|||GetFcb||
|FISHER - Fisher Transform|||GetFcb||fisher|
|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|✔️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|✔️tr|
|UI - Ulcer Index|||||
|VSTOP - Volatility Stop|||||
||||||
|**MOMENTUM INDICATORS & OSCILLATORS**|
||||||
|AC - Acceleration Oscillator|||||
|ADX - Average Directional Movement Index||ADX|GetAdx||adx|
|ADXR - Average Directional Movement Index Rating||ADXR|GetAdx||adxr|
|AO - Awesome Oscillator|||GetAwesome||ao|
|APO - Absolute Price Oscillator||APO|||apo|
|AROON - Aroon oscillator||AROON|GetAroon||aroon|
|BOP - Balance of Power||BOP|GetBop||bop|
|CCI - Commodity Channel Index|`CCI_Series`|✔️CCI|✔️GetCci||❌cci|
|CFO - Chande Forcast Oscillator|||||
|CMO - Chande Momentum Oscillator|`CMO_Series`|❌CMO|✔️GetCmo|❌cmo|✔️cmo|
|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||
|FOSC - Forecast oscillator|||||fosc|
|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_Series`|✔️TRIX|✔️GetTrix|✔️trix|❌trix|
|TSI - True Strength Index|||||
|UO - Ultimate Oscillator||ULTOSC|GetUltimate||ultosc|
|WILLR - Larry Williams' %R||WILLR|GetWilliamsR||willr|
|WGAT - Williams Alligator|||||
||||||
|**VOLUME INDICATORS**|
||||||
|AOBV - Archer On-Balance Volume|||||
|CMF - Chaikin Money Flow|||||
|EOM - Ease of Movement|||||emv|
|KVO - Klinger Volume Oscilaltor|||||kvo|
|OBV - On-Balance Volume|`OBV_Series`|✔️OBV|✔️GetObv|✔️obv|❌obv|
|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|||||vwma|
-44
View File
@@ -1,44 +0,0 @@
# QuanTAlib - quantitative technical indicators for Quantower and other C#-based trading platorms
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=mihakralj_QuanTAlib&metric=ncloc)](https://sonarcloud.io/summary/overall?id=mihakralj_QuanTAlib)
[![Codacy grade](https://img.shields.io/codacy/grade/b1f9109222234c87bce45f1fd4c63aee?style=flat-square)](https://app.codacy.com/gh/mihakralj/QuanTAlib/dashboard)
[![codecov](https://codecov.io/gh/mihakralj/QuanTAlib/branch/main/graph/badge.svg?style=flat-square&token=YNMJRGKMTJ?style=flat-square)](https://codecov.io/gh/mihakralj/QuanTAlib)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=mihakralj_QuanTAlib&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=mihakralj_QuanTAlib)
[![CodeFactor](https://www.codefactor.io/repository/github/mihakralj/quantalib/badge/main)](https://www.codefactor.io/repository/github/mihakralj/quantalib/overview/main)
[![Nuget](https://img.shields.io/nuget/v/QuanTAlib?style=flat-square)](https://www.nuget.org/packages/QuanTAlib/)
![GitHub last commit](https://img.shields.io/github/last-commit/mihakralj/QuanTAlib)
[![Nuget](https://img.shields.io/nuget/dt/QuanTAlib?style=flat-square)](https://www.nuget.org/packages/QuanTAlib/)
[![GitHub watchers](https://img.shields.io/github/watchers/mihakralj/QuanTAlib?style=flat-square)](https://github.com/mihakralj/QuanTAlib/watchers)
[![.NET7.0](https://img.shields.io/badge/.NET-7.0%20%7C%206.0%20%7C%204.8-blue?style=flat-square)](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
**Quan**titative **TA** **lib**rary (QuanTAlib) is a C# library of classess and methods for quantitative technical analysis useful for analyzing quotes with [Quantower](https://www.quantower.com/) and other C#-based trading platforms.
**QuanTAlib** is written with some specific design criteria in mind - why there is '_yet another C# TA library_':
- Prioritize **real-time data analysis** (series can add new data and indicator doesn't have to re-calculate the whole history)
- **Allow updates** to the last quote and adjusting the calculation to the still-forming bar
- **Calculate early data right** - output data is as valid as mathematically possible from the first value onwards
![Alt text](./img/quotes.gif)
If not obvious, QuanTAlib is intended for developers, and it does not focus on sources of OHLCV quotes. There are some very basic data feeds available to use in the learning process: `RND_Feed` and `GBM_Feed` for random data, `Yahoo_Feed` and `Alphavantage_Feed` for a quick grab of daily data of US stock market.
See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/getting_started.ipynb) .NET interactive notebook to get a feel how library works. Developers can use QuanTAlib in [Polyglot Notebooks](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) or in console apps, but the best usage of the library is with C#-enabled trading platforms - see **QuanTower_Charts** folder for Quantower examples and check **Releases** for compiled Quantower DLL.
### Coverage
[List of all indicators - current and planned](indicators.md)
### Validation
QuanTAlib uses validation tests with four other TA 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/)
### Questions
[Some most common questions addressed](QA.md)