GitVersion

GitVersion
This commit is contained in:
Miha Kralj
2022-11-12 20:06:54 -08:00
parent 97fb428147
commit 59ca5c2395
80 changed files with 4237 additions and 4257 deletions
+42 -42
View File
@@ -1,43 +1,43 @@
namespace QuanTAlib;
using System;
/* <summary>
ADL: Chaikin Accumulation/Distribution Line
ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
3. ADL = Previous ADL + Current Period's Money Flow Volume
Sources:
https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
</summary> */
public class ADL_Series : Single_TBars_Indicator
{
private double _lastadl, _lastlastadl;
public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
{
this._lastadl = this._lastlastadl = 0;
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)
{
if (update)
{ this._lastadl = this._lastlastadl; }
double _mfm = ((TBar.c - TBar.l) - (TBar.h - TBar.c)) / (TBar.h - TBar.l);
double _mfv = _mfm * TBar.v;
double _adl = this._lastadl + _mfv;
this._lastlastadl = this._lastadl;
this._lastadl = _adl;
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl);
base.Add(ret, update);
}
namespace QuanTAlib;
using System;
/* <summary>
ADL: Chaikin Accumulation/Distribution Line
ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
3. ADL = Previous ADL + Current Period's Money Flow Volume
Sources:
https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
</summary> */
public class ADL_Series : Single_TBars_Indicator
{
private double _lastadl, _lastlastadl;
public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
{
this._lastadl = this._lastlastadl = 0;
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)
{
if (update)
{ this._lastadl = this._lastlastadl; }
double _mfm = ((TBar.c - TBar.l) - (TBar.h - TBar.c)) / (TBar.h - TBar.l);
double _mfv = _mfm * TBar.v;
double _adl = this._lastadl + _mfv;
this._lastlastadl = this._lastadl;
this._lastadl = _adl;
var ret = (TBar.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _adl);
base.Add(ret, update);
}
}
+44 -44
View File
@@ -1,45 +1,45 @@
namespace QuanTAlib;
using System;
/* <summary>
ADO: Chaikin Accumulation/Distribution Oscillator
ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
and fast (3-day) EMA(ADL):
Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
Sources:
https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
</summary> */
public class ADOSC_Series : Single_TBars_Indicator
{
private readonly ADL_Series _TSadl;
private readonly EMA_Series _TSslow;
private readonly EMA_Series _TSfast;
private readonly SUB_Series _TSado;
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
{
_TSadl = new(source: source, useNaN: false);
_TSslow = new(source: _TSadl, period: 10, useNaN: false);
_TSfast = new(source: _TSadl, period: 3, useNaN: false);
_TSado = new(_TSfast, _TSslow);
if (source.Count > 0)
{ base.Add(_TSado); }
Console.WriteLine(base.Count);
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update)
{ _TSadl.Add(TBar, true); }
double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
var result = (TBar.t, _ado);
base.Add(result, update);
}
namespace QuanTAlib;
using System;
/* <summary>
ADO: Chaikin Accumulation/Distribution Oscillator
ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
and fast (3-day) EMA(ADL):
Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
Sources:
https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
</summary> */
public class ADOSC_Series : Single_TBars_Indicator
{
private readonly ADL_Series _TSadl;
private readonly EMA_Series _TSslow;
private readonly EMA_Series _TSfast;
private readonly SUB_Series _TSado;
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
{
_TSadl = new(source: source, useNaN: false);
_TSslow = new(source: _TSadl, period: 10, useNaN: false);
_TSfast = new(source: _TSadl, period: 3, useNaN: false);
_TSado = new(_TSfast, _TSslow);
if (source.Count > 0)
{ base.Add(_TSado); }
Console.WriteLine(base.Count);
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update)
{ _TSadl.Add(TBar, true); }
double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
var result = (TBar.t, _ado);
base.Add(result, update);
}
}
+62 -62
View File
@@ -1,63 +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)
{
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);
}
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)
{
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);
}
}
+62 -62
View File
@@ -1,63 +1,63 @@
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 (this._bars.Count > 0) { base.Add(this._bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update) {
this._lastema = this._lastlastema;
this._cm1 = this._lastcm1;
}
if (this._cm1 is double.NaN) { this._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);
}
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 (this._bars.Count > 0) { base.Add(this._bars); }
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update) {
this._lastema = this._lastlastema;
this._cm1 = this._lastcm1;
}
if (this._cm1 is double.NaN) { this._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);
}
}
+72 -72
View File
@@ -1,73 +1,73 @@
namespace QuanTAlib;
using System;
/* <summary>
BBANDS: Bollinger Bands®
Price channels created by John Bollinger, depict volatility as standard deviation boundary
line range from a moving average of price. The bands automatically widen when volatility
increases and contract when volatility decreases. Their dynamic nature allows them to be
used on different securities with the standard settings.
Mid Band = simple moving average (SMA)
Upper Band = SMA + (standard deviation of price x multiplier)
Lower Band = SMA - (standard deviation of price x multiplier)
Bandwidth = Width of the channel: (Upper-Lower)/SMA
%B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
Z-Score = number of standard deviations of the data point from SMA
Sources:
https://www.investopedia.com/terms/b/bollingerbands.asp
https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
Note:
Bollinger Bands® is a registered trademark of John A. Bollinger.
</summary> */
public class BBANDS_Series : Single_TSeries_Indicator
{
public SMA_Series Mid { get; }
public ADD_Series Upper { get; }
public SUB_Series Lower { get; }
public DIV_Series PercentB { get; }
public DIV_Series Bandwidth { get; }
public DIV_Series Zscore { get; }
private readonly SDEV_Series _sdev;
private readonly MUL_Series _mulsdev;
private readonly SUB_Series _pbdnd;
private readonly SUB_Series _pbdvr;
private readonly SUB_Series _zdnd;
public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
: base(source, period: 0, useNaN)
{
this.Mid = new(source: source, period: period, useNaN: useNaN);
_sdev = new(source, period, useNaN: useNaN);
_mulsdev = new(_sdev, multiplier);
this.Upper = new(Mid, _mulsdev);
this.Lower = new(Mid, _mulsdev);
_pbdnd = new(source, Lower);
_pbdvr = new(Upper, Lower);
this.PercentB = new(_pbdnd, _pbdvr);
this.Bandwidth = new(_pbdvr, Mid);
_zdnd = new(source, Mid);
this.Zscore = new(_zdnd, _sdev);
if (source.Count > 0)
{ base.Add(this.Bandwidth); }
}
public override void Add((System.DateTime t, double v) TValue, bool update)
{
double _bbandwidth;
if (update)
{ _sdev.Add(TValue, true); }
_bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
var result = (TValue.t, _bbandwidth);
base.Add(result, update);
}
namespace QuanTAlib;
using System;
/* <summary>
BBANDS: Bollinger Bands®
Price channels created by John Bollinger, depict volatility as standard deviation boundary
line range from a moving average of price. The bands automatically widen when volatility
increases and contract when volatility decreases. Their dynamic nature allows them to be
used on different securities with the standard settings.
Mid Band = simple moving average (SMA)
Upper Band = SMA + (standard deviation of price x multiplier)
Lower Band = SMA - (standard deviation of price x multiplier)
Bandwidth = Width of the channel: (Upper-Lower)/SMA
%B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
Z-Score = number of standard deviations of the data point from SMA
Sources:
https://www.investopedia.com/terms/b/bollingerbands.asp
https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
Note:
Bollinger Bands® is a registered trademark of John A. Bollinger.
</summary> */
public class BBANDS_Series : Single_TSeries_Indicator
{
public SMA_Series Mid { get; }
public ADD_Series Upper { get; }
public SUB_Series Lower { get; }
public DIV_Series PercentB { get; }
public DIV_Series Bandwidth { get; }
public DIV_Series Zscore { get; }
private readonly SDEV_Series _sdev;
private readonly MUL_Series _mulsdev;
private readonly SUB_Series _pbdnd;
private readonly SUB_Series _pbdvr;
private readonly SUB_Series _zdnd;
public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
: base(source, period: 0, useNaN)
{
this.Mid = new(source: source, period: period, useNaN: useNaN);
_sdev = new(source, period, useNaN: useNaN);
_mulsdev = new(_sdev, multiplier);
this.Upper = new(Mid, _mulsdev);
this.Lower = new(Mid, _mulsdev);
_pbdnd = new(source, Lower);
_pbdvr = new(Upper, Lower);
this.PercentB = new(_pbdnd, _pbdvr);
this.Bandwidth = new(_pbdvr, Mid);
_zdnd = new(source, Mid);
this.Zscore = new(_zdnd, _sdev);
if (source.Count > 0)
{ base.Add(this.Bandwidth); }
}
public override void Add((System.DateTime t, double v) TValue, bool update)
{
double _bbandwidth;
if (update)
{ _sdev.Add(TValue, true); }
_bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
var result = (TValue.t, _bbandwidth);
base.Add(result, update);
}
}
+72 -72
View File
@@ -1,73 +1,73 @@
namespace QuanTAlib;
using System;
/* <summary>
RSI: Relative Strength Index
Created by J. Welles Wilder, the Relative Strength Index measures strength
of the winning/losing streak over N lookback periods on a scale of 0 to 100,
to depict overbought and oversold conditions.
Sources:
https://www.investopedia.com/terms/r/rsi.asp
</summary> */
public class RSI_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List<double> _gain = new();
private readonly System.Collections.Generic.List<double> _loss = new();
private double _avgGain;
private double _avgLoss;
private double _lastValue;
private double _lastlastValue;
public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
{ if (source.Count > 0) { base.Add(source); } }
public override void Add((System.DateTime t, double v) TValue, bool update)
{
int i = this.Count;
double _rsi = 0;
if (update) { _lastValue = _lastlastValue; }
if (i == 0) { _lastValue = TValue.v; }
double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
if (update) { _gain[_gain.Count - 1] = _gainval; } else { _gain.Add(_gainval); }
if (_gain.Count > this._p) { _gain.RemoveAt(0); }
double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
if (update) { _loss[_loss.Count - 1] = _lossval; } else { _loss.Add(_lossval); }
if (_loss.Count > this._p) { _loss.RemoveAt(0); }
_lastlastValue = _lastValue;
_lastValue = TValue.v;
// calculate RSI
if (i > _p)
{
_avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
_avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
if (_avgLoss > 0) {
double rs = _avgGain / _avgLoss;
_rsi = 100 - (100 / (1 + rs));
}
else { _rsi = 100; }
}
// initialize average gain
else
{
double _sumGain = 0;
for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
double _sumLoss = 0;
for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
_avgGain = _sumGain / _gain.Count;
_avgLoss = _sumLoss / _loss.Count;
_rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
}
var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
base.Add(result, update);
}
namespace QuanTAlib;
using System;
/* <summary>
RSI: Relative Strength Index
Created by J. Welles Wilder, the Relative Strength Index measures strength
of the winning/losing streak over N lookback periods on a scale of 0 to 100,
to depict overbought and oversold conditions.
Sources:
https://www.investopedia.com/terms/r/rsi.asp
</summary> */
public class RSI_Series : Single_TSeries_Indicator
{
private readonly System.Collections.Generic.List<double> _gain = new();
private readonly System.Collections.Generic.List<double> _loss = new();
private double _avgGain;
private double _avgLoss;
private double _lastValue;
private double _lastlastValue;
public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
{ if (source.Count > 0) { base.Add(source); } }
public override void Add((System.DateTime t, double v) TValue, bool update)
{
int i = this.Count;
double _rsi = 0;
if (update) { _lastValue = _lastlastValue; }
if (i == 0) { _lastValue = TValue.v; }
double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
if (update) { _gain[_gain.Count - 1] = _gainval; } else { _gain.Add(_gainval); }
if (_gain.Count > this._p) { _gain.RemoveAt(0); }
double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
if (update) { _loss[_loss.Count - 1] = _lossval; } else { _loss.Add(_lossval); }
if (_loss.Count > this._p) { _loss.RemoveAt(0); }
_lastlastValue = _lastValue;
_lastValue = TValue.v;
// calculate RSI
if (i > _p)
{
_avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
_avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
if (_avgLoss > 0) {
double rs = _avgGain / _avgLoss;
_rsi = 100 - (100 / (1 + rs));
}
else { _rsi = 100; }
}
// initialize average gain
else
{
double _sumGain = 0;
for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
double _sumLoss = 0;
for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
_avgGain = _sumGain / _gain.Count;
_avgLoss = _sumLoss / _loss.Count;
_rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
}
var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
base.Add(result, update);
}
}