TR and ATR

This commit is contained in:
Miha
2022-04-19 22:34:42 -07:00
parent 50ed6f6504
commit 509b6dec02
41 changed files with 488 additions and 236 deletions
+8 -9
View File
@@ -15,7 +15,7 @@
{
"data": {
"text/html": [
"<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>QuantLib, 1.0.7</span></li><li><span>TALib.NETCore, 0.4.4</span></li></ul></div></div>"
"<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>QuanTAlib, 0.1.10-beta</span></li><li><span>TALib.NETCore, 0.4.4</span></li></ul></div></div>"
]
},
"metadata": {},
@@ -24,7 +24,7 @@
],
"source": [
"#r \"nuget: TALib.NETCore, 0.4.4\" \n",
"#r \"nuget:QuanTAlib\" \n",
"#r \"nuget: QuanTAlib, 0.1.10-beta\" \n",
"\n",
"using QuanTAlib;\n",
"using TALib;\n"
@@ -43,13 +43,12 @@
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\">1394</div>"
]
},
"metadata": {},
"output_type": "display_data"
"ename": "Error",
"evalue": "(1,1): error CS0246: The type or namespace name 'YAHOO_Feed' could not be found (are you missing a using directive or an assembly reference?)",
"output_type": "error",
"traceback": [
"(1,1): error CS0246: The type or namespace name 'YAHOO_Feed' could not be found (are you missing a using directive or an assembly reference?)"
]
}
],
"source": [
+2 -1
View File
@@ -42,7 +42,8 @@
| AFIRMA - Autoregressive Finite Impulse Response Moving Average |||||
| ALMA - Arnaud Legoux Moving Average |||✔️|✔️|
| ARIMA - Autoregressive Integrated Moving Average |||||
| ATR - Average True Range ||✔️|✔️|✔️|
| ATR - Average True Range |✔️|✔️|✔️|✔️|
| ATRP - Average True Range Percent |✔️||✔️||
| DEMA - Double EMA |✔️|✔️|✔️|✔️|
| EMA - Exponential Moving Average |✔️|✔️|✔️|✔️|
| EPMA - Endpoint Moving Average |||✔️||
+9 -2
View File
@@ -1,6 +1,13 @@
// ADD - adding TSeries+TSeries together, or TSeries+double, or double+TSeries
using System;
namespace QuanTAlib;
using System;
/* <summary>
ADD - adding TSeries+TSeries together, or TSeries+double, or double+TSeries
Remarks:
Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator.
</summary> */
public class ADD_Series : Pair_TSeries_Indicator
{
@@ -1,6 +1,18 @@
namespace QuanTAlib;
using System;
/* <summary>
Abstract classes with all scaffolding required to build indicators.
All abstracts support period, NaN, and all permutations of Add() methods.
Indicator classess need to implement:
- Chaining constructor (Abstract's constructor executes first)
- Default Add(value) class
- optional Add(series) bulk insert class (for optimization of historical analysis)
Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
</summary> */
public abstract class Single_TSeries_Indicator : TSeries
{
protected readonly int _p;
@@ -124,8 +136,9 @@ public abstract class Single_TBars_Indicator : TSeries
protected readonly TBars _bars;
// Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
protected Single_TBars_Indicator(TBars source, bool useNaN)
protected Single_TBars_Indicator(TBars source, int period, bool useNaN)
{
this._p = period;
this._bars = source;
this._NaN = useNaN;
this._bars.Close.Pub += this.Sub;
+8 -2
View File
@@ -1,6 +1,12 @@
// DIV - divide TSeries/TSeries , or TSeries/double, or double/TSeries
using System;
namespace QuanTAlib;
using System;
/* <summary>
DIV - divide TSeries/TSeries , or TSeries/double, or double/TSeries
Remarks:
Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator.
</summary> */
public class DIV_Series : Pair_TSeries_Indicator
{
@@ -1,20 +1,18 @@
namespace QuanTAlib;
/*
MAX - Maximum value in the given period in the series.
If period = 0 => period = full length of the series
*/
using System;
using System.Collections.Generic;
/* <summary>
MAX - Maximum value in the given period in the series.
If period = 0 => period = full length of the series
</summary> */
public class MAX_Series : Single_TSeries_Indicator
{
public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
{
if (base._data.Count > 0) { base.Add(base._data); }
}
private readonly List<double> _buffer = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
public override void Add((DateTime t, double v) d, bool update)
{
@@ -24,7 +22,7 @@ public class MAX_Series : Single_TSeries_Indicator
double _max = d.v;
for (int i = 0; i < this._buffer.Count; i++)
{ _max = this._buffer[i] > _max ? this._buffer[i] : _max; }
{ _max = (this._buffer[i] > _max) ? this._buffer[i] : _max; }
var result = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _max);
@@ -1,12 +1,10 @@
/*
MIN - Minimum value in the given period in the series.
If period = 0 => period = full length of the series
*/
using System;
namespace QuanTAlib;
using System;
/* <summary>
MIN - Minimum value in the given period in the series.
If period = 0 => period = full length of the series
</summary> */
public class MIN_Series : Single_TSeries_Indicator
{
+6 -2
View File
@@ -1,6 +1,10 @@
// MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries
using System;
namespace QuanTAlib;
using System;
/* <summary>
MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries
</summary> */
public class MUL_Series : Pair_TSeries_Indicator
{
+12 -4
View File
@@ -1,20 +1,28 @@
using System;
namespace QuanTAlib;
using System;
/* <summary>
Random Bars generator - used for testing, validation and fun
Returns 'bars' number of candles that follow common market movement.
volatility defines how 'jumpy' is the series of
startvalue defines beginning closing price that then guides the rest of series
</summary> */
public class RND_Feed : TBars
{
public RND_Feed(int days, double volatility = 0.05, double startvalue = 100.0)
public RND_Feed(int bars, double volatility = 0.05, double startvalue = 100.0)
{
Random rnd = new();
double c = startvalue;
for (int i = 0; i < days; i++)
for (int i = 0; i < bars; i++)
{
double o = Math.Round(c + c * (volatility * 0.1 * rnd.NextDouble() - 0.005), 2);
double h = Math.Round(o + c * volatility * rnd.NextDouble(), 2);
double l = Math.Round(o - c * volatility * rnd.NextDouble(), 2);
c = Math.Round(l + (h - l) * rnd.NextDouble(), 2);
double v = Math.Round(1000 * rnd.NextDouble(), 2);
this.Add(DateTime.Today.AddDays(i - days), o, h, l, c, v);
this.Add(DateTime.Today.AddDays(i - bars), o, h, l, c, v);
}
}
}
+7 -2
View File
@@ -1,6 +1,11 @@
// SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries
using System;
namespace QuanTAlib;
using System;
/* <summary>
SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries
</summary> */
public class SUB_Series : Pair_TSeries_Indicator
{
+9 -1
View File
@@ -1,7 +1,15 @@
namespace QuanTAlib;
using System;
/* <summary>
TBars class - includes all series for common data used in indicators and other calculations.
Has a bit limited overloading and casting (compared to TSeries)
Includes Select(int) method to simplify choosing the most optimal data source for indicators
Includes the most basic pricing calcs: HL2, OC2, OHL3, HLC3, OHLC4, HLCC4
(it is 'cheaper' to calculate them once during data capture than each time during data analysis)
</summary> */
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)>
{
private readonly TSeries _open = new();
+38
View File
@@ -0,0 +1,38 @@
namespace QuanTAlib;
using System;
/* <summary>
TR: True Range
True Range was introduced by J. Welles Wilder in his book New Concepts in Technical Trading Systems.
It measures the daily range plus any gap from the closing price of the preceding day.
Calculation:
d1 = ABS(High - Low)
d2 = ABS(High - Previous close)
d3 = ABS(Previous close - Low)
TR = MAX(d1,d2,d3)
Sources:
https://www.macroption.com/true-range/
</summary> */
public class TR_Series : Single_TBars_Indicator
{
private double _cm1 = double.NaN;
public TR_Series(TBars source, bool useNaN = false) : base(source, period:0, useNaN:useNaN) {
if (this._bars.Count > 0) { base.Add(this._bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TValue, bool update = false)
{
if (_cm1 is double.NaN) { _cm1 = TValue.c; }
double d1 = Math.Abs(TValue.h - TValue.l);
double d2 = Math.Abs(_cm1 - TValue.h);
double d3 = Math.Abs(_cm1 - TValue.l);
var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : Math.Max(d1,Math.Max(d2,d3)) );
base.Add(ret, update);
_cm1 = TValue.c;
}
}
+11 -1
View File
@@ -1,8 +1,18 @@
namespace QuanTAlib;
using System;
using System.Linq;
/* <summary>
TSeries is the cornerstone of all QuanTAlib classess.
TSeries is a single List of tuples (time, value) and contains several operators, casts, overloads
and other helpers that simplify usage of library.
Think of TSeries as an equivalent of Numpy array.
- includes Length property (to mimic array's method)
- includes publishing and subscribing methods that attach to events
- uses Linq only for two transmutations - needs to be refactored out eventually (for speed)
</summary> */
public class TSeries : System.Collections.Generic.List<(DateTime t, double v)>
{
// when asked for a (t,v) tuple, return the last (t,v) on the List
+64
View File
@@ -0,0 +1,64 @@
namespace QuanTAlib;
using System;
/* <summary>
ATR: wildeR Moving Average
The average true range (ATR) is a price volatility indicator
showing the average price variation of assets within a given time period.
Sources:
https://en.wikipedia.org/wiki/Average_true_range
https://www.tradingview.com/wiki/Average_True_Range_(ATR)
https://www.investopedia.com/terms/a/atr.asp
</summary> */
public class ATR_Series : Single_TBars_Indicator
{
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema, _lastcm1;
private double _cm1 = double.NaN;
public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
{
this._k = 1.0 / (double)(this._p);
this._k1m = 1.0 - this._k;
this._lastema = this._lastlastema = double.NaN;
if (_bars.Count > 0) { base.Add(_bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update) {
this._lastema = this._lastlastema;
this._cm1 = this._lastcm1;
}
if (_cm1 is double.NaN) { _cm1 = TBar.c; }
double d1 = Math.Abs(TBar.h - TBar.l);
double d2 = Math.Abs(_cm1 - TBar.h);
double d3 = Math.Abs(_cm1 - TBar.l);
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
_lastcm1 = _cm1;
_cm1 = TBar.c;
double _ema = 0;
if (this.Count < this._p)
{
if (update) { _buffer[_buffer.Count - 1] = d.v; }
else { _buffer.Add(d.v); }
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
_ema /= this._buffer.Count;
}
else { _ema = d.v * _k + _lastema * _k1m; }
this._lastlastema = this._lastema;
this._lastema = _ema;
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _ema);
base.Add(ret, update);
}
}
+63
View File
@@ -0,0 +1,63 @@
namespace QuanTAlib;
using System;
/* <summary>
ATRP: Average True Range Percent
Average True Range Percent is (ATR/Close Price)*100.
This normalizes so it can be compared to other stocks.
Sources:
https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
</summary> */
public class ATRP_Series : Single_TBars_Indicator
{
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema, _lastcm1;
private double _cm1 = double.NaN;
public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
{
this._k = 1.0 / (double)(this._p);
this._k1m = 1.0 - this._k;
this._lastema = this._lastlastema = double.NaN;
if (_bars.Count > 0) { base.Add(_bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update) {
this._lastema = this._lastlastema;
this._cm1 = this._lastcm1;
}
if (_cm1 is double.NaN) { _cm1 = TBar.c; }
double d1 = Math.Abs(TBar.h - TBar.l);
double d2 = Math.Abs(_cm1 - TBar.h);
double d3 = Math.Abs(_cm1 - TBar.l);
(DateTime t, double v)d = (TBar.t, Math.Max(d1,Math.Max(d2,d3))); //TR value for RMA below
_lastcm1 = _cm1;
_cm1 = TBar.c;
double _ema = 0;
if (this.Count < this._p)
{
if (update) { _buffer[_buffer.Count - 1] = d.v; }
else { _buffer.Add(d.v); }
if (_buffer.Count > this._p) { _buffer.RemoveAt(0); }
for (int i = 0; i < _buffer.Count; i++) { _ema += _buffer[i]; }
_ema /= this._buffer.Count;
}
else { _ema = d.v * _k + _lastema * _k1m; }
this._lastlastema = this._lastema;
this._lastema = _ema;
double _atrp = 100 * (_ema / TBar.c);
var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
base.Add(ret, update);
}
}
@@ -1,8 +1,9 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
DEMA: Double Exponential Moving Average
DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
@@ -11,13 +12,12 @@ Remark:
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
DEMA = 2 * ema1 - ema2
**/
using System;
using System.Collections.Generic;
</summary> */
public class DEMA_Series : Single_TSeries_Indicator
{
private readonly List<double> _buffer = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema1, _lastlastema1;
private double _lastema2, _lastlastema2;
@@ -1,26 +1,27 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
EMA: Exponential Moving Average
EMA needs very short history buffer and calculates the EMA value using just the
previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
EMA needs very short history buffer and calculates the EMA value using just the
previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
Issues:
There is no consensus what the first EMA value should be - a zero, a first
datapoint, or an average of the initial Period bars. All three starting methods
converge within 20+ bars to the same moving average. Most implementations (including this one)
use SMA() for the first Period bars as a seeding value for EMA.
**/
datapoint, or an average of the initial Period bars. All three starting methods
converge within 20+ bars to the same moving average. Most implementations (including this one)
use SMA() for the first Period bars as a seeding value for EMA.
</summary> */
using System;
using System.Collections.Generic;
public class EMA_Series : Single_TSeries_Indicator
{
private readonly List<double> _buffer = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema;
@@ -1,16 +1,17 @@
using System;
namespace QuanTAlib;
namespace QuanTAlib;
using System;
/**
/* <summary>
HEMA: Hull-EMA Moving Average
Modified HUll Moving Average; instead of using WMA (Weighted MA) for a
calculation, HEMA uses EMA for Hull's formula:
Modified HUll Moving Average; instead of using WMA (Weighted MA) for acalculation,
HEMA uses EMA for Hull's formula:
EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
EMA2 = EMA(n) of price - where k = 3/(n+1)
Raw HMA = (2 * EMA1) - EMA2
EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
**/
</summary> */
public class HEMA_Series : Single_TSeries_Indicator
{
@@ -1,19 +1,21 @@
using System;
namespace QuanTAlib;
namespace QuanTAlib;
using System;
/**
/* <summary>
HMA: Hull Moving Average
Developed by Alan Hull, an extremely fast and smooth moving average; almost
eliminates lag altogether and manages to improve smoothing at the same time.
Developed by Alan Hull, an extremely fast and smooth moving average; almost
eliminates lag altogether and manages to improve smoothing at the same time.
Sources:
https://alanhull.com/hull-moving-average
https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
WMA1 = WMA(n/2) of price
WMA2 = WMA(n) of price
Raw HMA = (2 * WMA1) - WMA2
HMA = WMA(sqrt(n)) of Raw HMA
**/
</summary> */
public class HMA_Series : TSeries
{
@@ -1,11 +1,11 @@
using System;
namespace QuanTAlib;
namespace QuanTAlib;
using System;
/**
/* <summary>
JMA: Jurik Moving Average
Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
underlying activity. It has extremely low lag, is very smooth and is responsive
to market gaps.
Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
underlying activity. It has extremely low lag, is very smooth and is responsive
to market gaps.
Sources:
https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
@@ -13,10 +13,12 @@ Sources:
Issues:
Real JMA algorithm is not published and this formula is derived through
deduction and reverse analysis of JMA behavior. It is really close, but not
exact - published JMA tests against JMA.CSV fail with small deviation. The
original algo is slightly different, yet this approximation is close enough.
**/
deduction and reverse analysis of JMA behavior. It is really close, but not
exact - published JMA tests against JMA.CSV fail with small deviation. The
original algo is slightly different, yet this approximation is close enough.
</summary> */
public class JMA_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List<double> vbuffer10;
@@ -1,12 +1,13 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
RMA: wildeR Moving Average
J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
set as 1/period, giving less weight to the new data compared to EMA.
J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
set as 1/period, giving less weight to the new data compared to EMA. Sources:
Sources:
https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
https://www.incrediblecharts.com/indicators/wilder_moving_average.php
@@ -15,13 +16,11 @@ Issues:
pandas.ewm().mean() and returns incorrect first (period) of bars compared to
published formula. This implementation passess the validation test in Wilder's book.
**/
</summary> */
using System;
using System.Collections.Generic;
public class RMA_Series : Single_TSeries_Indicator
{
private readonly List<double> _buffer = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema, _lastlastema;
@@ -1,17 +1,20 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
SMA: Simple Moving Average
The weights are equally distributed across the period, resulting in a mean() of
the data within the period/
The weights are equally distributed across the period, resulting in a mean() of
the data within the period/
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
https://stats.stackexchange.com/a/24739
Remark:
This calc doesn't use LINQ or SUM() or any of iterative methods.
**/
This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
</summary> */
public class SMA_Series : Single_TSeries_Indicator
{
@@ -1,8 +1,9 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
TEMA: Triple Exponential Moving Average
TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
@@ -12,13 +13,12 @@ Remark:
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
TEMA = 3 * (ema1 - ema2) + ema3
**/
using System;
using System.Collections.Generic;
</summary> */
public class TEMA_Series : Single_TSeries_Indicator
{
private readonly List<double> _buffer = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
private readonly double _k, _k1m;
private double _lastema1, _lastlastema1;
private double _lastema2, _lastlastema2;
@@ -1,14 +1,16 @@
namespace QuanTAlib;
using System;
/**
/* <summary>
WMA: (linearly) Weighted Moving Average
The weights are linearly decreasing over the period and the most recent data has
the heaviest weight.
The weights are linearly decreasing over the period and the most recent data has
the heaviest weight.
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
**/
</summary> */
public class WMA_Series : Single_TSeries_Indicator
{
@@ -1,22 +1,23 @@
using System;
namespace QuanTAlib;
namespace QuanTAlib;
using System;
/**
/* <summary>
ZLEMA: Zero Lag Exponential Moving Average
The Zero lag exponential moving average (ZLEMA) indicator was created by John
Ehlers and Ric Way.
The Zero lag exponential moving average (ZLEMA) indicator was created by John
Ehlers and Ric Way.
The formula for a given N-Day period and for a given Data series is:
Lag = (Period-1)/2
Ema Data = {Data+(Data-Data(Lag days ago))
ZLEMA = EMA (EmaData,Period)
Lag = (Period-1)/2
Ema Data = {Data+(Data-Data(Lag days ago))
ZLEMA = EMA (EmaData,Period)
The idea is do a regular exponential moving average (EMA) calculation but on a
de-lagged data instead of doing it on the regular data. Data is de-lagged by
removing the data from "lag" days ago thus removing (or attempting to remove)
the cumulative lag effect of the moving average.
**/
Remark:
The idea is do a regular exponential moving average (EMA) calculation but on a
de-lagged data instead of doing it on the regular data. Data is de-lagged by
removing the data from "lag" days ago thus removing (or attempting to remove)
the cumulative lag effect of the moving average.
</summary> */
public class ZLEMA_Series : Single_TSeries_Indicator
{
+1 -1
View File
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>0.1.10-beta</Version>
<Version>0.1.11</Version>
<releaseNotes></releaseNotes>
<Title>QuanTAlib</Title>
<Product>Library of Technical Indicators for .NET</Product>
+8 -9
View File
@@ -1,18 +1,17 @@
/**
BIAS: Rate of change between the source and a moving average.
namespace QuanTAlib;
using System;
Bias is a statistical term which means a systematic deviation from the actual value.
/* <summary>
BIAS: Rate of change between the source and a moving average.
Bias is a statistical term which means a systematic deviation from the actual value.
BIAS = (close - SMA) / SMA
BIAS = (close - SMA) / SMA
= (close / SMA) - 1
Sources:
https://en.wikipedia.org/wiki/Bias_of_an_estimator
https://en.wikipedia.org/wiki/Bias_of_an_estimator
**/
using System;
namespace QuanTAlib;
</summary> */
public class BIAS_Series : Single_TSeries_Indicator
{
+8 -7
View File
@@ -1,8 +1,10 @@
/**
ENTP: Entropy
namespace QuanTAlib;
using System;
Introduced by Claude Shannon in 1948, entropy measures the unpredictability
of the data, or equivalently, of its average information.
/* <summary>
ENTP: Entropy
Introduced by Claude Shannon in 1948, entropy measures the unpredictability
of the data, or equivalently, of its average information.
Calculation:
P = close / Σ(close)
@@ -12,9 +14,8 @@ Sources:
https://en.wikipedia.org/wiki/Entropy_(information_theory)
https://math.stackexchange.com/questions/3428693/how-to-calculate-entropy-from-a-set-of-correlated-samples
**/
namespace QuanTAlib;
using System;
</summary> */
public class ENTP_Series : Single_TSeries_Indicator
{
public ENTP_Series(TSeries source, int period, double logbase = 2.0, bool useNaN = false) : base(source, period, useNaN)
+5 -8
View File
@@ -1,6 +1,8 @@
/**
KURT: Kurtosis of population
namespace QuanTAlib;
using System;
/* <summary>
KURT: Kurtosis of population
Kurtosis characterizes the relative peakedness or flatness of a distribution
compared with the normal distribution. Positive kurtosis indicates a relatively
peaked distribution. Negative kurtosis indicates a relatively flat distribution.
@@ -19,12 +21,7 @@ Sources:
https://en.wikipedia.org/wiki/Kurtosis
https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
**/
using System;
namespace QuanTAlib;
// https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faq-whats-with-the-different-formulas-for-kurtosis/
</summary> */
public class KURT_Series : Single_TSeries_Indicator
{
+7 -8
View File
@@ -1,8 +1,10 @@
/**
MAD: Mean Absolute Deviation
namespace QuanTAlib;
using System;
Also known as AAD - Average Absolute Deviation, to differentiate it from Median Absolute Deviation
MAD defines the degree of variation across the series.
/* <summary>
MAD: Mean Absolute Deviation
Also known as AAD - Average Absolute Deviation, to differentiate it from Median Absolute Deviation
MAD defines the degree of variation across the series.
Calculation:
MAD = Σ(|close-SMA|) / period
@@ -10,10 +12,7 @@ Calculation:
Sources:
https://en.wikipedia.org/wiki/Average_absolute_deviation
**/
using System;
namespace QuanTAlib;
</summary> */
public class MAD_Series : Single_TSeries_Indicator
{
+9 -9
View File
@@ -1,7 +1,9 @@
/**
MAPE: Mean Absolute Percentage Error
namespace QuanTAlib;
using System;
Measures the size of the error in percentage terms
/* <summary>
MAPE: Mean Absolute Percentage Error
Measures the size of the error in percentage terms
Calculation:
MAPE = Σ(|close SMA| / |close|) / n
@@ -9,13 +11,11 @@ Calculation:
Sources:
https://en.wikipedia.org/wiki/Mean_absolute_percentage_error
Remark: returns infinity if any of observations is 0.
Use SMAPE or WMAPE instead to avoid division-by-zero in MAPE
Remark:
returns infinity if any of observations is 0.
Use SMAPE or WMAPE instead to avoid division-by-zero in MAPE
**/
using System;
namespace QuanTAlib;
</summary> */
public class MAPE_Series : Single_TSeries_Indicator
{
+13 -14
View File
@@ -1,25 +1,24 @@
/*
namespace QuanTAlib;
using System;
/* <summary>
MED - Median value
Median of numbers is the middlemost value of the given set of numbers.
It separates the higher half and the lower half of a given data sample.
At least half of the observations are smaller than or equal to median
and at least half of the observations are greater than or equal to the median.
Median of numbers is the middlemost value of the given set of numbers.
It separates the higher half and the lower half of a given data sample.
At least half of the observations are smaller than or equal to median
and at least half of the observations are greater than or equal to the median.
If the number of values is odd, the middlemost observation of the sorted
list is the median of the given data. If the number of values is even,
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
If the number of values is odd, the middlemost observation of the sorted
list is the median of the given data. If the number of values is even,
median is the average of (n/2)th and [(n/2) + 1]th values of the sorted list.
If period = 0 => period is max
If period = 0 => period is max
Sources:
https://corporatefinanceinstitute.com/resources/knowledge/other/median/
https://en.wikipedia.org/wiki/Median
*/
using System;
namespace QuanTAlib;
</summary> */
public class MED_Series : Single_TSeries_Indicator
{
+6 -9
View File
@@ -1,17 +1,14 @@
/**
MSE: Mean Square Error
namespace QuanTAlib;
using System;
Defined as a Mean (Average) of the Square of the difference between actual and estimated values.
/* <summary>
MSE: Mean Square Error
Defined as a Mean (Average) of the Square of the difference between actual and estimated values.
Sources:
https://en.wikipedia.org/wiki/Mean_squared_error
Remark:
**/
using System;
namespace QuanTAlib;
</summary> */
public class MSE_Series : Single_TSeries_Indicator
{
+7 -8
View File
@@ -1,8 +1,10 @@
/**
PSDEV: Population Standard Deviation
namespace QuanTAlib;
using System;
Population Standard Deviation is the square root of the biased variance, also knons as
Uncorrected Sample Standard Deviation
/* <summary>
PSDEV: Population Standard Deviation
Population Standard Deviation is the square root of the biased variance, also knons as
Uncorrected Sample Standard Deviation
Sources:
https://en.wikipedia.org/wiki/Standard_deviation#Uncorrected_sample_standard_deviation
@@ -11,10 +13,7 @@ Remark:
PSDEV (Population Standard Deviation) is also known as a biased/uncorrected Standard Deviation.
For unbiased version that uses Bessel's correction, use SDEV instead.
**/
using System;
namespace QuanTAlib;
</summary> */
public class PSDEV_Series : Single_TSeries_Indicator
{
+6 -7
View File
@@ -1,7 +1,9 @@
/**
PVAR: Population Variance
namespace QuanTAlib;
using System;
Population variance....
/* <summary>
PVAR: Population Variance
Population variance without Bessel's correction
Sources:
https://en.wikipedia.org/wiki/Variance
@@ -11,10 +13,7 @@ Remark:
PVAR (Population Variance) is also known as a biased Sample Variance. For unbiased
sample variance use SVAR instead.
**/
using System;
namespace QuanTAlib;
</summary> */
public class PVAR_Series : Single_TSeries_Indicator
{
+6 -8
View File
@@ -1,21 +1,19 @@
/**
SDEV: (Corrected) Sample Standard Deviation
namespace QuanTAlib;
using System;
Sample Standard Deviaton uses Bessel's correction to correct the bias in the variance.
/* <summary>
SDEV: (Corrected) Sample Standard Deviation
Sample Standard Deviaton uses Bessel's correction to correct the bias in the variance.
Sources:
https://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation
Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
Remark:
SSDEV (Sample Standard Deviation) is also known as a unbiased/corrected Standard Deviation.
For a population/biased/uncorrected Standard Deviation, use PSDEV instead
**/
using System;
namespace QuanTAlib;
</summary> */
public class SDEV_Series : Single_TSeries_Indicator
{
+6 -7
View File
@@ -1,15 +1,14 @@
/**
SMAPE: Symmetric Mean Absolute Percentage Error
namespace QuanTAlib;
using System;
Measures the size of the error in percentage terms
/* <summary>
SMAPE: Symmetric Mean Absolute Percentage Error
Measures the size of the error in percentage terms
Sources:
https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error
**/
using System;
namespace QuanTAlib;
</summary> */
public class SMAPE_Series : Single_TSeries_Indicator
{
+6 -7
View File
@@ -1,7 +1,9 @@
/**
VAR: Sample Variance
namespace QuanTAlib;
using System;
Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
/* <summary>
VAR: Sample Variance
Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
Sources:
https://en.wikipedia.org/wiki/Variance
@@ -11,10 +13,7 @@ Remark:
VAR is also known as the Unbiased Sample Variance, while PVAR (Population Variance) is known as
the Biased Sample Variance.
**/
using System;
namespace QuanTAlib;
</summary> */
public class VAR_Series : Single_TSeries_Indicator
{
+6 -7
View File
@@ -1,15 +1,14 @@
/**
WMAPE: Weighted Mean Absolute Percentage Error
namespace QuanTAlib;
using System;
Measures the size of the error in percentage terms
/* <summary>
WMAPE: Weighted Mean Absolute Percentage Error
Measures the size of the error in percentage terms
Sources:
https://en.wikipedia.org/wiki/WMAPE
**/
using System;
namespace QuanTAlib;
</summary> */
public class WMAPE_Series : Single_TSeries_Indicator
{
+18
View File
@@ -90,4 +90,22 @@ public class Skender_Stock
Assert.Equal(Math.Round((double)SK.Last().Mape!, 8), Math.Round(QL.Last().v, 8));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetAtr(this.period);
Assert.Equal(Math.Round((double)SK.Last().Atr!, 8), Math.Round(QL.Last().v, 8));
}
[Fact]
public void ATRP()
{
ATRP_Series QL = new(this.bars, this.period, false);
var SK = this.quotes.GetAtr(this.period);
Assert.Equal(Math.Round((double)SK.Last().Atrp!, 8), Math.Round(QL.Last().v, 8));
}
}
+25 -9
View File
@@ -10,14 +10,22 @@ public class TA_LIB
private readonly Random rnd = new();
private readonly int period;
private readonly double[] TALIB;
private readonly double[] input;
private readonly double[] inopen;
private readonly double[] inhigh;
private readonly double[] inlow;
private readonly double[] inclose;
private readonly double[] involume;
public TA_LIB()
{
this.bars = new(1000);
this.period = this.rnd.Next(28) + 3;
this.TALIB = new double[this.bars.Count];
this.input = this.bars.Close.v.ToArray();
this.inopen = this.bars.Open.v.ToArray();
this.inhigh = this.bars.High.v.ToArray();
this.inlow = this.bars.Low.v.ToArray();
this.inclose = this.bars.Close.v.ToArray();
this.involume = this.bars.Volume.v.ToArray();
}
/////////////////////////////////////////
@@ -26,7 +34,7 @@ public class TA_LIB
public void SMA()
{
SMA_Series QL = new(this.bars.Close, this.period, false);
Core.Sma(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Sma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -35,7 +43,7 @@ public class TA_LIB
public void EMA()
{
EMA_Series QL = new(this.bars.Close, this.period, false);
Core.Ema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Ema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -44,7 +52,7 @@ public class TA_LIB
public void WMA()
{
WMA_Series QL = new(this.bars.Close, this.period, false);
Core.Wma(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Wma(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -53,7 +61,7 @@ public class TA_LIB
public void DEMA()
{
DEMA_Series QL = new(this.bars.Close, this.period, false);
Core.Dema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Dema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -62,7 +70,7 @@ public class TA_LIB
public void TEMA()
{
TEMA_Series QL = new(this.bars.Close, this.period, false);
Core.Tema(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Tema(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -71,7 +79,7 @@ public class TA_LIB
public void MAX()
{
MAX_Series QL = new(this.bars.Close, this.period, false);
Core.Max(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Max(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
@@ -80,9 +88,17 @@ public class TA_LIB
public void MIN()
{
MIN_Series QL = new(this.bars.Close, this.period, false);
Core.Min(this.input, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Core.Min(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
[Fact]
public void ATR()
{
ATR_Series QL = new(this.bars, this.period, false);
Core.Atr(this.inhigh, this.inlow, this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period);
Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8));
}
}