Merge branch 'dev'

This commit is contained in:
Miha Kralj
2024-09-30 09:07:08 -07:00
95 changed files with 7982 additions and 2375 deletions
+71
View File
@@ -0,0 +1,71 @@
namespace QuanTAlib;
/// <summary>
/// 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.
/// </summary>
public abstract class AbstractBarBase : iTValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
public bool IsNew { get; set; }
public bool IsHot { get; set; }
public TBar Input { get; set; }
public String Name { get; set; } = "";
public int WarmupPeriod { get; set; }
public TValue Tick => new(Time, Value, IsNew, IsHot); // Stores the current value of indicator
public event ValueSignal Pub = delegate { }; // Publisher of generated values
protected int _index; //tracking the position of output
protected double _lastValidValue;
// other _internal vars defined here
protected AbstractBarBase()
{ //add parameters into constructor
}
public void Sub(object source, in TBarEventArgs args) => Calc(args.Bar);
public virtual void Init()
{
_index = 0;
_lastValidValue = 0;
}
public virtual TValue Calc(TBar input)
{
Input = input;
if (double.IsNaN(input.Close) || double.IsInfinity(input.Close))
{
return Process(new TValue(Time: input.Time, Value: GetLastValid(), IsNew: input.IsNew, IsHot: true));
}
this.Value = Calculation();
return Process(new TValue(Time: Input.Time, Value: this.Value, IsNew: Input.IsNew, IsHot: this.IsHot));
}
protected virtual double GetLastValid()
{
return this.Value;
}
protected abstract void ManageState(bool isNew);
protected abstract double Calculation();
/// <summary>
/// Processes the calculated value, updates the indicator's own state,
/// and publishes the result through an event.
/// </summary>
/// <param name="value">The calculated TValue to process.</param>
/// <returns>The processed TValue.</returns>
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;
}
}
+6 -12
View File
@@ -30,15 +30,11 @@ public readonly record struct TBar(DateTime Time, double Open, double High, doub
public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { }
// when TBar casts to double, it returns its Close
public static implicit operator double(TBar bar) => bar.Close;
public static implicit operator DateTime(TBar tv) => tv.Time;
// castings for sloppy people - a single double injected into a TBar, and a single TValue injected into a TBar
public TBar(double value) : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) { }
public TBar(TValue value) : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) { }
public static implicit operator double(TBar bar) => bar.Close;
public static implicit operator DateTime(TBar tv) => tv.Time;
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
}
@@ -70,11 +66,8 @@ public class TBarSeries : List<TBar>
public TBarSeries()
{
this.Name = "Bar";
Open = new();
High = new();
Low = new();
Close = new();
Volume = new();
(Open, High, Low, Close, Volume) = ([], [], [], [], []);
}
public TBarSeries(object source) : this()
{
@@ -84,7 +77,8 @@ public class TBarSeries : List<TBar>
public new virtual void Add(TBar bar)
{
if (bar.IsNew) { base.Add(bar); } else { this[^1] = bar; }
if (bar.IsNew || base.Count == 0) { base.Add(bar); }
else { this[^1] = bar; }
Pub?.Invoke(this, new TBarEventArgs(bar));
Open.Add(bar.Time, bar.Open, IsNew: bar.IsNew, IsHot: true);
+1 -1
View File
@@ -66,7 +66,7 @@ public class TSeries : List<TValue>
public new virtual void Add(TValue tick)
{
if (tick.IsNew) { base.Add(tick); }
if (tick.IsNew || base.Count==0) { base.Add(tick); }
else { this[^1] = tick; }
Pub?.Invoke(this, new ValueEventArgs(tick));
}