mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-21 03:58:04 +00:00
Update RSI_Series to check for period != 0 before calculating RSI
This commit is contained in:
@@ -19,7 +19,7 @@ public class ATRP_Series : Single_TBars_Indicator {
|
||||
|
||||
public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) {
|
||||
_period = period;
|
||||
_k = 1.0 / (double)(_p);
|
||||
_k = 1.0 / (double)(_period);
|
||||
_lastatr = _lastlastatr = _cm1 = _lastcm1 = _sum = _oldsum = 0;
|
||||
if (this._bars.Count > 0) { base.Add(this._bars); }
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
CMO: Chande Momentum Oscillator
|
||||
Chande Momentum Oscillator (also known as CMO indicator) was developed by Tushar S. Chande
|
||||
CMO is similar to other momentum oscillators (e.g. RSI or Stochastics). Alike RSI oscillator,
|
||||
the CMO values move in the range from -100 to +100 points and its aim is to detect the
|
||||
overbought and oversold market conditions. CMO calculates the price momentum on both the up
|
||||
days as well as the down days. The CMO calculation is based on non-smoothed price values
|
||||
meaning that it can reach its extremes more frequently and the short-time swings are more visible.
|
||||
|
||||
Sources:
|
||||
https://www.technicalindicators.net/indicators-technical-analysis/144-cmo-chande-momentum-oscillator
|
||||
|
||||
</summary> */
|
||||
|
||||
public class CMO_Series : Single_TSeries_Indicator {
|
||||
private readonly System.Collections.Generic.List<double> _buff_up = new();
|
||||
private readonly System.Collections.Generic.List<double> _buff_dn = new();
|
||||
private double _plast_value, _last_value;
|
||||
|
||||
public CMO_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update) {
|
||||
if (this.Count == 0) { _plast_value = _last_value = TValue.v; }
|
||||
if (update) {_last_value = _plast_value;} else {_plast_value = _last_value;}
|
||||
|
||||
Add_Replace_Trim(_buff_up, (TValue.v > _last_value) ? TValue.v-_last_value : 0, _p, update);
|
||||
Add_Replace_Trim(_buff_dn, (TValue.v < _last_value) ? _last_value-TValue.v : 0, _p, update);
|
||||
_last_value = TValue.v;
|
||||
|
||||
double _cmo_up = 0;
|
||||
double _cmo_dn = 0;
|
||||
for (int i = 0; i < Math.Min(_buff_up.Count, _buff_dn.Count); i++) {
|
||||
_cmo_up += _buff_up[i];
|
||||
_cmo_dn += _buff_dn[i];
|
||||
}
|
||||
|
||||
double _cmo = 100 * (_cmo_up - _cmo_dn) / (_cmo_up + _cmo_dn);
|
||||
if (_cmo_up + _cmo_dn == 0) {_cmo = 0;}
|
||||
base.Add((TValue.t, _cmo), update, _NaN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
OBV: On-Balance Volume
|
||||
On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
|
||||
changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
|
||||
Granville's New Key to Stock Market Profits.
|
||||
|
||||
| +volume; if close > close[previous]
|
||||
OBV = OBV[previous] + | 0; if close = close[previous]
|
||||
| -volume; if close < close[previous]
|
||||
|
||||
Sources:
|
||||
https://www.investopedia.com/terms/o/onbalancevolume.asp
|
||||
https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
|
||||
https://www.motivewave.com/studies/on_balance_volume.htm
|
||||
|
||||
Note:
|
||||
There is no consensus on what is the first OBV value in the series:
|
||||
- TA-LIB uses the first volume: OBV[0] = volume[0]
|
||||
- Skender stock library uses 0: OBV[0] = 0
|
||||
|
||||
</summary> */
|
||||
|
||||
public class OBV_Series : Single_TBars_Indicator
|
||||
{
|
||||
private double _lastobv, _lastlastobv;
|
||||
private double _lastclose, _lastlastclose;
|
||||
public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
|
||||
{
|
||||
this._lastobv = this._lastlastobv = 0;
|
||||
this._lastclose = this._lastlastclose = 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._lastobv = this._lastlastobv;
|
||||
this._lastclose = this._lastlastclose;
|
||||
}
|
||||
|
||||
double _obv = this._lastobv;
|
||||
if (TBar.c > this._lastclose) { _obv += TBar.v; }
|
||||
if (TBar.c < this._lastclose) { _obv -= TBar.v; }
|
||||
|
||||
this._lastlastobv = this._lastobv;
|
||||
this._lastobv = _obv;
|
||||
|
||||
this._lastlastclose = this._lastclose;
|
||||
this._lastclose = TBar.c;
|
||||
|
||||
var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
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, _avgLoss, _lastValue;
|
||||
private double _avgGain_o, _avgLoss_o, _lastValue_o;
|
||||
private int i;
|
||||
|
||||
public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN) {
|
||||
i = 0;
|
||||
if (source.Count > 0) { base.Add(source); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update) {
|
||||
double _rsi = 0;
|
||||
if (update) {
|
||||
_lastValue = _lastValue_o;
|
||||
_avgGain = _avgGain_o;
|
||||
_avgLoss = _avgLoss_o;
|
||||
}
|
||||
else {
|
||||
_lastValue_o = _lastValue;
|
||||
_avgGain_o = _avgGain;
|
||||
_avgLoss_o = _avgLoss;
|
||||
}
|
||||
|
||||
if (i == 0) { _lastValue = TValue.v; }
|
||||
|
||||
double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
|
||||
Add_Replace_Trim(_gain, _gainval, _p, update);
|
||||
double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
|
||||
Add_Replace_Trim(_loss, _lossval, _p, update);
|
||||
_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;
|
||||
}
|
||||
|
||||
if (!update) { i++; }
|
||||
var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
|
||||
base.Add(result, update);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user