namespace QuanTAlib; /// /// Provides a base implementation for financial indicators in the QuanTAlib library. /// /// /// This abstract class implements the iTValue interface and defines common properties /// and methods used by inheriting indicator types. It handles the basic flow of /// receiving data, performing calculations, and publishing results. /// public abstract class AbstractBase : iTValue { public DateTime Time { get; set; } public double Value { get; set; } public bool IsNew { get; set; } public bool IsHot { get; set; } public TValue Input { get; set; } public String Name { get; set; } = ""; public int WarmupPeriod { get; set; } public TValue Tick => new(Time, Value, IsNew, IsHot); public event ValueSignal Pub = delegate { }; protected int _index; protected double _lastValidValue; protected AbstractBase() { // Add parameters into constructor if needed } /// /// Subscribes to a data source and triggers calculations on new data. /// /// The class publishing the data. /// The argument containing the new data point. public void Sub(object source, in ValueEventArgs args) => Calc(args.Tick); /// /// Initializes the indicator's state. /// public virtual void Init() { _index = 0; _lastValidValue = 0; } /// /// Calculates the indicator value based on the input. /// /// The input value for the calculation. /// A TValue representing the calculated indicator value. /// /// This method calls the specific Calculation() method where the actual implementation is. /// If the input value is NaN or infinity, it returns the last valid value instead. /// public virtual TValue Calc(TValue input) { Input = input; if (double.IsNaN(input.Value) || double.IsInfinity(input.Value)) { return Process(new TValue(input.Time, GetLastValid(), input.IsNew, input.IsHot)); } this.Value = Calculation(); return Process(new TValue(Time: Input.Time, Value: this.Value, IsNew: Input.IsNew, IsHot: this.IsHot)); } /// /// Retrieves the last valid calculated value. /// /// The last valid value of the indicator. protected virtual double GetLastValid() { return this.Value; } /// /// Manages the state of the indicator based on whether a new data point is being processed. /// /// Indicates whether the current input is a new data point. protected abstract void ManageState(bool isNew); /// /// Performs the actual calculation of the indicator value. /// /// The calculated indicator value. protected abstract double Calculation(); /// /// Processes the calculated value, updates the indicator's own state, /// and publishes the result through an event. /// /// The calculated TValue to process. /// The processed TValue. protected virtual TValue Process(TValue value) { this.Time = value.Time; this.Value = value.Value; this.IsNew = value.IsNew; this.IsHot = value.IsHot; Pub?.Invoke(this, new ValueEventArgs(value)); return value; } }