namespace QuanTAlib; using System; using System.Collections.Generic; /* 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. */ public abstract class Single_TSeries_Indicator : TSeries { protected readonly int _p; protected readonly bool _NaN; protected readonly TSeries _data; // Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN) protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN) { this._data = source; this._p = period; this._NaN = useNaN; this._data.Pub += this.Sub; } // overridable Add() method to add/update a single item at the end of the list public virtual void Add((System.DateTime t, double v) TValue, bool update, bool useNaN) { var res = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : TValue.v); base.Add(res, update); } public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update); // potentially overridable Add() method for the whole series (could be replaced with faster bulk algo) public virtual void Add(TSeries data) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); }} public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false); public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update); public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false); public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update); protected static void Add_Replace(List l, double v, bool update) { if (update) { l[l.Count - 1] = v; } else { l.Add(v); } } protected static void Add_Replace_Trim(List l, double v, int p, bool update) { Add_Replace(l, v, update); if (l.Count > p && p!=0) { l.RemoveAt(0); } } }