diff --git a/.editorconfig b/.editorconfig index 27ae0e75..b99bec2f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,4 +5,12 @@ root = true # Suppress S3776 (Cognitive Complexity) dotnet_diagnostic.S3776.severity = none # Suppress CA1416 (Platform Compatibility) -dotnet_diagnostic.CA1416.severity = none \ No newline at end of file +dotnet_diagnostic.CA1416.severity = none +dotnet_style_parentheses_in_control_flow_statements = always_for_clarity:suggestion +csharp_new_line_before_open_brace = none +csharp_new_line_before_else = false +csharp_new_line_before_catch = false +csharp_new_line_before_finally = false +csharp_new_line_before_members_in_object_initializers = false +csharp_new_line_before_members_in_anonymous_types = false +csharp_new_line_between_query_expression_clauses = false \ No newline at end of file diff --git a/.refactoring/base.cs b/.refactoring/base.cs index 7e61500b..883293e9 100644 --- a/.refactoring/base.cs +++ b/.refactoring/base.cs @@ -1,95 +1,237 @@ using System; -public readonly struct TValue { - public DateTime Timestamp { get; } - public double Value { get; } +public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) +{ + public DateTime Time { get; init; } = Time; + public double Value { get; init; } = Value; + public bool IsNew { get; init; } = IsNew; + public bool IsHot { get; init; } = IsHot; + + public TValue() : this(DateTime.UtcNow, 0) { } + public TValue(double value) : this(DateTime.UtcNow, value) { } + public TValue((DateTime time, double value) tuple) : this(tuple.time, tuple.value) { } - public TValue(DateTime timestamp, double value) { - Timestamp = timestamp; - Value = value; - } - public TValue() : this(DateTime.Now, 0) { } - public TValue(double value) : this(DateTime.Now, value) { } public static implicit operator double(TValue tv) => tv.Value; - public static implicit operator DateTime(TValue tv) => tv.Timestamp; - public static implicit operator TValue(double value) => new TValue(DateTime.Now, value); + public static implicit operator DateTime(TValue tv) => tv.Time; + public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value); + + public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: {Value:F2}]"; +} - public override string ToString() { - return $"[{Timestamp:yyyy-MM-dd HH:mm:ss}: {Value:F2}]"; +public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) +{ + public DateTime Time { get; init; } = Time; + public double Open { get; init; } = Open; + public double High { get; init; } = High; + public double Low { get; init; } = Low; + public double Close { get; init; } = Close; + public double Volume { get; init; } = Volume; + public bool IsNew { get; init; } = IsNew; + + public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { } + public TBar(double open, double high, double low, double close, double volume) : this(DateTime.UtcNow, open, high, low, close, volume) { } + public TBar((DateTime time, double open, double high, double low, double close, double volume) tuple) : this(tuple.time, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) { } + + 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}]"; +} + +///////////////////// +/// +///////////////////// + +public class GBM_Feed +{ + private readonly double _mu; + private readonly double _sigma; + private readonly Random _random; + private double _lastClose; + private double _lastHigh; + private double _lastLow; + + public GBM_Feed(double initialPrice, double mu, double sigma) + { + _lastClose = initialPrice; + _lastHigh = initialPrice; + _lastLow = initialPrice; + _mu = mu; + _sigma = sigma; + _random = Random.Shared; } - public override bool Equals(object obj) { - return obj is TValue other && Equals(in other); + public TBar Generate(bool IsNew = true) + { + DateTime time = DateTime.UtcNow; + double dt = 1.0 / 252; // Assuming daily steps in a trading year of 252 days + double drift = (_mu - 0.5 * _sigma * _sigma) * dt; + double diffusion = _sigma * Math.Sqrt(dt) * NormalRandom(); + double newClose = _lastClose * Math.Exp(drift + diffusion); + + double open = _lastClose; + double high = Math.Max(open, newClose) * (1 + _random.NextDouble() * 0.01); + double low = Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01); + double volume = 1000 + _random.NextDouble() * 1000; // Random volume between 1000 and 2000 + + if (!IsNew) + { + high = Math.Max(_lastHigh, high); + low = Math.Min(_lastLow, low); + } + else + { + _lastClose = newClose; + } + + _lastHigh = high; + _lastLow = low; + + return new TBar(time, open, high, low, newClose, volume, IsNew); } - public bool Equals(in TValue other) { - return Timestamp == other.Timestamp && Value == other.Value; - } - - public override int GetHashCode() { - return HashCode.Combine(Timestamp, Value); + private double NormalRandom() + { + // Box-Muller transform to generate standard normal random variable + double u1 = 1.0 - _random.NextDouble(); // Uniform(0,1] random doubles + double u2 = 1.0 - _random.NextDouble(); + return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); } } -public readonly struct TBar +/// +/// //////////////// +/// + +public class EMA { - public DateTime Timestamp { get; } - public double Open { get; } - public double High { get; } - public double Low { get; } - public double Close { get; } - public double Volume { get; } + private double lastEma, lastEmaCandidate, k; + private int period, i; + public TValue Value { get; private set; } + public bool IsHot { get; private set; } - public TBar(DateTime timestamp, double open, double high, double low, double close, double volume) - { - Timestamp = timestamp; - Open = open; - High = high; - Low = low; - Close = close; - Volume = volume; + public EMA(int period) { + Init(period); } - public override string ToString() + public void Init(int period) { - return $"[{Timestamp:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]"; + this.period = period; + this.k = 2.0 / (period + 1); + this.lastEma = this.lastEmaCandidate = double.NaN; + this.i = 0; } + public TValue Update(TValue input, bool IsNew = true) { + double ema; - public override bool Equals(object obj) - { - return obj is TBar other && Equals(in other); - } + if (double.IsNaN(lastEma)) { lastEma = input.Value; } - public bool Equals(in TBar other) - { - return Timestamp == other.Timestamp && - Open == other.Open && - High == other.High && - Low == other.Low && - Close == other.Close && - Volume == other.Volume; - } + if (IsNew) { + lastEma = lastEmaCandidate; + i++; + } - public override int GetHashCode() - { - return HashCode.Combine(Timestamp, Open, High, Low, Close, Volume); + double kk = (i= period; + Value = new TValue(input.Time, ema, IsNew, IsHot); + return Value; } } +///////////////// +/// - -public class EventArg : EventArgs +public class SMA { - public T Data { get; } - public bool IsClosed { get; } - public bool IsHot { get; } + private CircularBuffer buffer; + private int period; + private double sum; + public TValue Value { get; private set; } + public bool IsHot { get; private set; } - public EventArg(T data, bool isClosed, bool isHot) + public SMA(int period) { - Data = data; - IsClosed = isClosed; - IsHot = isHot; + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.buffer = new CircularBuffer(period); + this.sum = 0; + this.IsHot = false; + this.Value = default; + } + + public TValue Update(TValue input, bool IsNew = true) + { + if (IsNew) + { + if (buffer.Count == period) { + sum -= buffer[0]; + } + buffer.Add(input); + sum += input.Value; + } else { + if (buffer.Count > 0) { + sum -= buffer[buffer.Count - 1]; + sum += input.Value; + buffer[buffer.Count - 1] = input; + } else { + buffer.Add(input); + sum += input.Value; + } + } + + double sma = buffer.Count > 0 ? sum / buffer.Count : double.NaN; + IsHot = buffer.Count >= period; + Value = new TValue(input.Time, sma, IsNew, IsHot); + return Value; + } +} + +///////////////////// +/// +///////////////////// + + +public class CircularBuffer +{ + private double[] _buffer; + private int _start; + private int _size; + + public CircularBuffer(int capacity) { + _buffer = new double[capacity]; + _start = 0; + _size = 0; + } + + public int Capacity => _buffer.Length; + public int Count => _size; + + public void Add(double item) { + if (_size < Capacity) { + _buffer[(_start + _size) % Capacity] = item; + _size++; + } else { + _buffer[_start] = item; + _start = (_start + 1) % Capacity; + } + } + + public double this[int index] { + get { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + return _buffer[(_start + index) % Capacity]; + } + set { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + _buffer[(_start + index) % Capacity] = value; + } } } \ No newline at end of file diff --git a/.refactoring/test.dib b/.refactoring/test.dib index 7a0a681d..a55e8863 100644 --- a/.refactoring/test.dib +++ b/.refactoring/test.dib @@ -4,17 +4,34 @@ #!csharp -#load "./base.cs" +#r "..\v2\bin\Debug\calculations.dll" +using QuanTAlib; #!csharp TValue vv = new(10); display(vv.ToString()); +display(vv.IsHot); + +TBar bb = new(1,1,1,1,10); +display(bb.ToString()); +display(bb.IsNew); #!csharp -TBar bb = new(); -display(bb.ToString()); +int i=10; +SMA sma = new(i); +Console.WriteLine($"{"Close",10} {"SMA(" + i + ")",10}"); +for (int i = 0; i < 20; i++) +{ + TValue c =(double)i+1; + sma.Update(10000,true); + sma.Update(1,false); + sma.Update(-1000,false); + sma.Update(c,false); + + Console.WriteLine($"{i+1} {(double)c,10:F2} {(double)sma.Value,10:F2} {sma.Value.IsHot}"); +} #!csharp diff --git a/Calculations/Basics/ADD_Series.cs b/Calculations/Basics/ADD_Series.cs index 0588d216..6d0436fe 100644 --- a/Calculations/Basics/ADD_Series.cs +++ b/Calculations/Basics/ADD_Series.cs @@ -9,21 +9,24 @@ Remarks: */ -public class ADD_Series : Pair_TSeries_Indicator +public class ADD_Series : Pair_TSeries_Indicator { - public ADD_Series(TSeries d1, TSeries d2 ) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + public ADD_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } } - public ADD_Series(TSeries d1, double dd2 ) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + public ADD_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } } - public ADD_Series(double dd1, TSeries d2 ) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i=0; i< base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + public ADD_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } } - public override void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { - (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v+TValue2.v); + (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v + TValue2.v); if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } diff --git a/Calculations/Basics/CORR_Series.cs b/Calculations/Basics/CORR_Series.cs index f82d82de..8052b4e2 100644 --- a/Calculations/Basics/CORR_Series.cs +++ b/Calculations/Basics/CORR_Series.cs @@ -17,36 +17,36 @@ Sources: public class CORR_Series : Pair_TSeries_Indicator { - public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN) - { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } - } + public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + } - private readonly System.Collections.Generic.List _x = new(); - private readonly System.Collections.Generic.List _xx = new(); - private readonly System.Collections.Generic.List _y = new(); - private readonly System.Collections.Generic.List _yy = new(); - private readonly System.Collections.Generic.List _xy = new(); + private readonly System.Collections.Generic.List _x = new(); + private readonly System.Collections.Generic.List _xx = new(); + private readonly System.Collections.Generic.List _y = new(); + private readonly System.Collections.Generic.List _yy = new(); + private readonly System.Collections.Generic.List _xy = new(); - public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) - { - Add_Replace_Trim(_x, TValue1.v, _p, update); - Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update); - Add_Replace_Trim(_y, TValue2.v, _p, update); - Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update); - Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update); + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) + { + Add_Replace_Trim(_x, TValue1.v, _p, update); + Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update); + Add_Replace_Trim(_y, TValue2.v, _p, update); + Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update); + Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update); - double _sumx = _x.Sum(); - double _sumxx = _xx.Sum(); - double _sumy = _y.Sum(); - double _sumyy = _yy.Sum(); - double _sumxy = _xy.Sum(); + double _sumx = _x.Sum(); + double _sumxx = _xx.Sum(); + double _sumy = _y.Sum(); + double _sumyy = _yy.Sum(); + double _sumxy = _xy.Sum(); - double _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p); - double _cor = (_covar != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_covar) : 0.0; + double _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p); + double _cor = (_covar != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_covar) : 0.0; - var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor); - if (update) { base[base.Count - 1] = result; } else { base.Add(result); } + var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor); + if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } diff --git a/Calculations/Basics/COVAR_Series.cs b/Calculations/Basics/COVAR_Series.cs index 4d6891c6..7368689c 100644 --- a/Calculations/Basics/COVAR_Series.cs +++ b/Calculations/Basics/COVAR_Series.cs @@ -16,31 +16,33 @@ Sources: public class COVAR_Series : Pair_TSeries_Indicator { - public COVAR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN) - { - if (base._d1.Count > 0 && base._d2.Count > 0) { - for (int i = 0; i < base._d1.Count; i++) { - this.Add(base._d1[i], base._d2[i], false); - } - } - } + public COVAR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN) + { + if (base._d1.Count > 0 && base._d2.Count > 0) + { + for (int i = 0; i < base._d1.Count; i++) + { + this.Add(base._d1[i], base._d2[i], false); + } + } + } - private readonly System.Collections.Generic.List _x = new(); - private readonly System.Collections.Generic.List _y = new(); - private readonly System.Collections.Generic.List _xy = new(); + private readonly System.Collections.Generic.List _x = new(); + private readonly System.Collections.Generic.List _y = new(); + private readonly System.Collections.Generic.List _xy = new(); - public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) - { - BufferTrim(_x, TValue1.v, _p, update); - BufferTrim(_y, TValue2.v, _p, update); - BufferTrim(_xy, TValue1.v * TValue2.v, _p, update); + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) + { + BufferTrim(_x, TValue1.v, _p, update); + BufferTrim(_y, TValue2.v, _p, update); + BufferTrim(_xy, TValue1.v * TValue2.v, _p, update); - double _avgx = _x.Average(); - double _avgy = _y.Average(); - double _avgxy = _xy.Average(); - double _covar = _avgxy - (_avgx * _avgy); + double _avgx = _x.Average(); + double _avgy = _y.Average(); + double _avgxy = _xy.Average(); + double _covar = _avgxy - (_avgx * _avgy); - var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _covar); - if (update) { base[base.Count - 1] = result; } else { base.Add(result); } + var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _covar); + if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } diff --git a/Calculations/Basics/DIV_Series.cs b/Calculations/Basics/DIV_Series.cs index 16069917..962e4f6f 100644 --- a/Calculations/Basics/DIV_Series.cs +++ b/Calculations/Basics/DIV_Series.cs @@ -8,22 +8,25 @@ Remarks: Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator. */ -public class DIV_Series : Pair_TSeries_Indicator +public class DIV_Series : Pair_TSeries_Indicator { - public DIV_Series(TSeries d1, TSeries d2 ) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + public DIV_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } } - public DIV_Series(TSeries d1, double dd2 ) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + public DIV_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } } - public DIV_Series(double dd1, TSeries d2 ) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i=0; i< base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + public DIV_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } } - public override void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { - (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, - (TValue2.v is not 0) ? TValue1.v/TValue2.v : Double.PositiveInfinity); + (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, + (TValue2.v is not 0) ? TValue1.v / TValue2.v : Double.PositiveInfinity); if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } \ No newline at end of file diff --git a/Calculations/Basics/MUL_Series.cs b/Calculations/Basics/MUL_Series.cs index c1c573bd..b2bae613 100644 --- a/Calculations/Basics/MUL_Series.cs +++ b/Calculations/Basics/MUL_Series.cs @@ -6,22 +6,25 @@ MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries */ -public class MUL_Series : Pair_TSeries_Indicator +public class MUL_Series : Pair_TSeries_Indicator { - public MUL_Series(TSeries d1, TSeries d2 ) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + public MUL_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } } - public MUL_Series(TSeries d1, double dd2 ) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + public MUL_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } } - public MUL_Series(double dd1, TSeries d2 ) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i=0; i< base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + public MUL_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } } - public override void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { - (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, - TValue1.v*TValue2.v); + (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, + TValue1.v * TValue2.v); if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } \ No newline at end of file diff --git a/Calculations/Basics/SUB_Series.cs b/Calculations/Basics/SUB_Series.cs index 88511f81..e4333ec6 100644 --- a/Calculations/Basics/SUB_Series.cs +++ b/Calculations/Basics/SUB_Series.cs @@ -7,22 +7,25 @@ SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries */ -public class SUB_Series : Pair_TSeries_Indicator +public class SUB_Series : Pair_TSeries_Indicator { - public SUB_Series(TSeries d1, TSeries d2 ) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + public SUB_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } } - public SUB_Series(TSeries d1, double dd2 ) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i=0; i< base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + public SUB_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } } - public SUB_Series(double dd1, TSeries d2 ) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i=0; i< base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + public SUB_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } } - public override void Add((System.DateTime t, double v)TValue1, (System.DateTime t, double v)TValue2, bool update) + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { - (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, - TValue1.v-TValue2.v); + (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, + TValue1.v - TValue2.v); if (update) { base[base.Count - 1] = result; } else { base.Add(result); } } } \ No newline at end of file diff --git a/Calculations/ClassStructures/Pair_TSeries_Abstract.cs b/Calculations/ClassStructures/Pair_TSeries_Abstract.cs index 99ccfee6..682b1b87 100644 --- a/Calculations/ClassStructures/Pair_TSeries_Abstract.cs +++ b/Calculations/ClassStructures/Pair_TSeries_Abstract.cs @@ -16,117 +16,142 @@ Abstract classes with all scaffolding required to build indicators. */ -public abstract class Pair_TSeries_Indicator : TSeries { - protected readonly int _p; - protected readonly bool _NaN; - protected readonly TSeries _d1; - protected readonly TSeries _d2; - protected readonly double _dd1, _dd2; +public abstract class Pair_TSeries_Indicator : TSeries +{ + protected readonly int _p; + protected readonly bool _NaN; + protected readonly TSeries _d1; + protected readonly TSeries _d2; + protected readonly double _dd1, _dd2; - // Chainable Constructors - add them at the end of primary constructors if needed - protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN) { - _p = period; - _NaN = useNaN; - _d1 = source1; - _d2 = source2; - _dd1 = double.NaN; - _dd2 = double.NaN; - _d1.Pub += Sub; - _d2.Pub += Sub; - } + // Chainable Constructors - add them at the end of primary constructors if needed + protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN) + { + _p = period; + _NaN = useNaN; + _d1 = source1; + _d2 = source2; + _dd1 = double.NaN; + _dd2 = double.NaN; + _d1.Pub += Sub; + _d2.Pub += Sub; + } - protected Pair_TSeries_Indicator(TSeries source1, TSeries source2) { - _d1 = source1; - _d2 = source2; - _dd1 = double.NaN; - _dd2 = double.NaN; - _d1.Pub += Sub; - _d2.Pub += Sub; - } + protected Pair_TSeries_Indicator(TSeries source1, TSeries source2) + { + _d1 = source1; + _d2 = source2; + _dd1 = double.NaN; + _dd2 = double.NaN; + _d1.Pub += Sub; + _d2.Pub += Sub; + } - protected Pair_TSeries_Indicator(TSeries source1, double dd2) { - _d1 = source1; - _d2 = new TSeries(); - _dd1 = double.NaN; - _dd2 = dd2; - _d1.Pub += Sub; - } + protected Pair_TSeries_Indicator(TSeries source1, double dd2) + { + _d1 = source1; + _d2 = new TSeries(); + _dd1 = double.NaN; + _dd2 = dd2; + _d1.Pub += Sub; + } - protected Pair_TSeries_Indicator(double dd1, TSeries source2) { - _d1 = new TSeries(); - _d2 = source2; - _dd1 = dd1; - _dd2 = double.NaN; - _d2.Pub += Sub; - } + protected Pair_TSeries_Indicator(double dd1, TSeries source2) + { + _d1 = new TSeries(); + _d2 = source2; + _dd1 = dd1; + _dd2 = double.NaN; + _d2.Pub += Sub; + } - // overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list - public virtual void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2, bool update) { - base.Add((TValue1.t, 0), update); - // default inserts zeros - } + // overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list + public virtual void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2, bool update) + { + base.Add((TValue1.t, 0), update); + // default inserts zeros + } - // potentially overridable Add() bulk variations (could be replaced with faster bulk algos) - public virtual void Add(TSeries d1, TSeries d2) { - for (var i = 0; i < d1.Count; i++) { - Add(d1[i], d2[i], false); - } - } + // potentially overridable Add() bulk variations (could be replaced with faster bulk algos) + public virtual void Add(TSeries d1, TSeries d2) + { + for (var i = 0; i < d1.Count; i++) + { + Add(d1[i], d2[i], false); + } + } - public virtual void Add(TSeries d1, double dd2) { - for (var i = 0; i < d1.Count; i++) { - Add(d1[i], (d1[i].t, dd2), false); - } - } + public virtual void Add(TSeries d1, double dd2) + { + for (var i = 0; i < d1.Count; i++) + { + Add(d1[i], (d1[i].t, dd2), false); + } + } - public virtual void Add(double dd1, TSeries d2) { - for (var i = 0; i < d2.Count; i++) { - Add((d2[i].t, dd1), d2[i], false); - } - } + public virtual void Add(double dd1, TSeries d2) + { + for (var i = 0; i < d2.Count; i++) + { + Add((d2[i].t, dd1), d2[i], false); + } + } - public void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2) { - Add(TValue1, TValue2, false); - } + public void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2) + { + Add(TValue1, TValue2, false); + } - public void Add(bool update) { - if (_dd1 is double.NaN && _dd2 is double.NaN) { - // (Series, Series) - if (update || (_d1.Count > Count && _d2.Count > Count)) { - Add(_d1[_d1.Count - 1], _d2[_d2.Count - 1], update); - } - } - else if (_dd2 is not double.NaN && _dd1 is double.NaN) { - // (Series, Double) - Add(_d1[_d1.Count - 1], (_d1[_d1.Count - 1].t, _dd2), update); - } - else { - // (Double, Series) - Add((_d2[_d2.Count - 1].t, _dd1), _d2[_d2.Count - 1], update); - } - } + public void Add(bool update) + { + if (_dd1 is double.NaN && _dd2 is double.NaN) + { + // (Series, Series) + if (update || (_d1.Count > Count && _d2.Count > Count)) + { + Add(_d1[_d1.Count - 1], _d2[_d2.Count - 1], update); + } + } + else if (_dd2 is not double.NaN && _dd1 is double.NaN) + { + // (Series, Double) + Add(_d1[_d1.Count - 1], (_d1[_d1.Count - 1].t, _dd2), update); + } + else + { + // (Double, Series) + Add((_d2[_d2.Count - 1].t, _dd1), _d2[_d2.Count - 1], update); + } + } - public void Add() { - Add(false); - } + public void Add() + { + Add(false); + } - public new void Sub(object source, TSeriesEventArgs e) { - Add(e.update); - } + public new void Sub(object source, TSeriesEventArgs e) + { + Add(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(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); - } - } + 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); + } + } } diff --git a/Calculations/Feeds/Alphavantage_Feed.cs b/Calculations/Feeds/Alphavantage_Feed.cs index 5c9fc35f..f2bcc60e 100644 --- a/Calculations/Feeds/Alphavantage_Feed.cs +++ b/Calculations/Feeds/Alphavantage_Feed.cs @@ -13,7 +13,7 @@ Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free) */ public class Alphavantage_Feed : TBars { - public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1} + public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1 } public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo") { System.Net.Http.HttpClient client = new(); @@ -22,8 +22,8 @@ public class Alphavantage_Feed : TBars var msg = client.GetStringAsync(req).Result; var jres = JsonSerializer.Deserialize(msg).RootElement; jres.TryGetProperty("Time Series (Daily)", out JsonElement json); - - if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); } + + if (json.ValueKind == JsonValueKind.Undefined) { throw new InvalidOperationException("Stock symbol " + Symbol + " not found"); } foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); } base.Reverse(); } diff --git a/Calculations/Feeds/GBM_Feed.cs b/Calculations/Feeds/GBM_Feed.cs index a08568c1..c99a282f 100644 --- a/Calculations/Feeds/GBM_Feed.cs +++ b/Calculations/Feeds/GBM_Feed.cs @@ -23,41 +23,45 @@ public class GBM_Feed : TBars private double seed; readonly double drift, volatility; readonly int precision; - public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0, int Precision = 2) { + public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0, int Precision = 2) + { this.seed = Seed; - volatility = Volatility*0.01; - drift = Drift*0.01; + volatility = Volatility * 0.01; + drift = Drift * 0.01; precision = Precision; - for (int i = 0; i OCMin)? (2 * OCMin) - Low : Low; + double OCMin = Math.Min(Open, Close); + double Low = (GBM_value(seed, volatility * 0.5, 0, precision)); + Low = (Low > OCMin) ? (2 * OCMin) - Low : Low; - double Volume = GBM_value(seed*10, volatility*2, Drift:0, precision: 1); + double Volume = GBM_value(seed * 10, volatility * 2, Drift: 0, precision: 1); base.Add((timestamp, Open, High, Low, Close, Volume), update); seed = Close; } - private static double GBM_value(double Seed, double Volatility, double Drift, int precision) { + private static double GBM_value(double Seed, double Volatility, double Drift, int precision) + { Random rnd = new(); - double U1 = 1.0-rnd.NextDouble(); - double U2 = 1.0-rnd.NextDouble(); + double U1 = 1.0 - rnd.NextDouble(); + double U2 = 1.0 - rnd.NextDouble(); double Z = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); - return Math.Round(Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z)), digits: precision); + return Math.Round(Seed * Math.Exp(Drift - (Volatility * Volatility * 0.5) + (Volatility * Z)), digits: precision); } } \ No newline at end of file diff --git a/Calculations/Feeds/Yahoo_Feed.cs b/Calculations/Feeds/Yahoo_Feed.cs index 5b9029a1..1d87e97d 100644 --- a/Calculations/Feeds/Yahoo_Feed.cs +++ b/Calculations/Feeds/Yahoo_Feed.cs @@ -14,34 +14,36 @@ Yahoo Finance - Free API feed to collect daily market quotes */ public class Yahoo_Feed : TBars { - public Yahoo_Feed(string Symbol = "IBM", int Period = 252) { - Period = (int)(Period*1.45); - string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+ - Symbol+"?interval=1d&period1="+ - (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+ + public Yahoo_Feed(string Symbol = "IBM", int Period = 252) + { + Period = (int)(Period * 1.45); + string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/" + + Symbol + "?interval=1d&period1=" + + (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period + 1)).ToUnixTimeSeconds() + "&period2=" + (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); System.Net.Http.HttpClient client = new(); var msg = client.GetStringAsync(requestUrl).Result; var jresult = JsonSerializer.Deserialize(msg).RootElement; - jresult.TryGetProperty("chart",out JsonElement json); - json.TryGetProperty("result",out json); - json[0].TryGetProperty("timestamp",out JsonElement datetime); - json[0].TryGetProperty("indicators",out json); - json.TryGetProperty("quote",out json); - json[0].TryGetProperty("open",out JsonElement open); - json[0].TryGetProperty("high",out JsonElement high); - json[0].TryGetProperty("low",out JsonElement low); - json[0].TryGetProperty("close",out JsonElement close); - json[0].TryGetProperty("volume",out JsonElement volume); + jresult.TryGetProperty("chart", out JsonElement json); + json.TryGetProperty("result", out json); + json[0].TryGetProperty("timestamp", out JsonElement datetime); + json[0].TryGetProperty("indicators", out json); + json.TryGetProperty("quote", out json); + json[0].TryGetProperty("open", out JsonElement open); + json[0].TryGetProperty("high", out JsonElement high); + json[0].TryGetProperty("low", out JsonElement low); + json[0].TryGetProperty("close", out JsonElement close); + json[0].TryGetProperty("volume", out JsonElement volume); - for (int i=0; i */ -public class COMPARE_Series : Pair_TSeries_Indicator { +public class COMPARE_Series : Pair_TSeries_Indicator +{ - public COMPARE_Series(TSeries d1, TSeries d2) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } - } - public COMPARE_Series(TSeries d1, double dd2) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } - } - public COMPARE_Series(double dd1, TSeries d2) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } - } + public COMPARE_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + } + public COMPARE_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + } + public COMPARE_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + } - public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) + { - double val = TValue1.v > TValue2.v ? 1 : -1; - val = TValue1.v == TValue2.v ? 0 : val; - (System.DateTime t, double v) over = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v > TValue2.v ? 1 : val); - if (update) { base[^1] = over; } - else { base.Add(over); } + double val = TValue1.v > TValue2.v ? 1 : -1; + val = TValue1.v == TValue2.v ? 0 : val; + (System.DateTime t, double v) over = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v > TValue2.v ? 1 : val); + if (update) { base[^1] = over; } + else { base.Add(over); } - } + } } diff --git a/Calculations/Logic/CROSS_Series.cs b/Calculations/Logic/CROSS_Series.cs index 2c4cad1c..6d62a54c 100644 --- a/Calculations/Logic/CROSS_Series.cs +++ b/Calculations/Logic/CROSS_Series.cs @@ -9,36 +9,41 @@ Remarks: */ -public class CROSS_Series : Pair_TSeries_Indicator { - public TSeries Cross { get; set; } = new(); +public class CROSS_Series : Pair_TSeries_Indicator +{ + public TSeries Cross { get; set; } = new(); - private double _previous = double.NaN; - public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2) { - if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } - } - public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2) { - if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } - } - public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2) { - if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } - } + private double _previous = double.NaN; + public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2) + { + if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } } + } + public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2) + { + if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } } + } + public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2) + { + if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } } + } - public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) { + public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) + { - double val = TValue1.v > TValue2.v ? 1 : -1; - val = TValue1.v == TValue2.v ? 0 : val; - double over = TValue1.v > TValue2.v ? 1 : val; + double val = TValue1.v > TValue2.v ? 1 : -1; + val = TValue1.v == TValue2.v ? 0 : val; + double over = TValue1.v > TValue2.v ? 1 : val; - val = (_previous < over) ? 1 : -1; - val = ((_previous == over) || Double.IsNaN(this._previous) || (this._previous == 0)) ? 0 : val; - (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,val); + val = (_previous < over) ? 1 : -1; + val = ((_previous == over) || Double.IsNaN(this._previous) || (this._previous == 0)) ? 0 : val; + (System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, val); - this._previous = over; + this._previous = over; - if (update) { base[^1] = result; } - else { base.Add(result); } + if (update) { base[^1] = result; } + else { base.Add(result); } - } + } } diff --git a/Calculations/Logic/TOrders.cs b/Calculations/Logic/TOrders.cs index 04d5ffa3..1e122b2b 100644 --- a/Calculations/Logic/TOrders.cs +++ b/Calculations/Logic/TOrders.cs @@ -6,29 +6,33 @@ using System.Data; using System.Linq; -public enum OType { - NIL = 0, // No position - BTO = 1, // Buy to Open - STC = 2, // Sell to Close - STO = 3, // Sell to Open - BTC = 4, // Buy to Close - END = 5, // Exit the trade +public enum OType +{ + NIL = 0, // No position + BTO = 1, // Buy to Open + STC = 2, // Sell to Close + STO = 3, // Sell to Open + BTC = 4, // Buy to Close + END = 5, // Exit the trade } -public class TOrders : List<(DateTime t, OType o)> { +public class TOrders : List<(DateTime t, OType o)> +{ - public void Add((DateTime t, OType o) TOrder, bool update = false) - { - if (update) { this[^1] = TOrder; } - else { base.Add(TOrder); } - OnEvent(update); - } + public void Add((DateTime t, OType o) TOrder, bool update = false) + { + if (update) { this[^1] = TOrder; } + else { base.Add(TOrder); } + OnEvent(update); + } - protected virtual void OnEvent(bool update = false) { - Pub?.Invoke(this, new TSeriesEventArgs { update = update }); } - public delegate void NewDataEventHandler(object source, TSeriesEventArgs args); - public event NewDataEventHandler Pub; + protected virtual void OnEvent(bool update = false) + { + Pub?.Invoke(this, new TSeriesEventArgs { update = update }); + } + public delegate void NewDataEventHandler(object source, TSeriesEventArgs args); + public event NewDataEventHandler Pub; } \ No newline at end of file diff --git a/Calculations/_Updated/ADL_Series.cs b/Calculations/_Updated/ADL_Series.cs index 2222887e..d84c1cf6 100644 --- a/Calculations/_Updated/ADL_Series.cs +++ b/Calculations/_Updated/ADL_Series.cs @@ -15,55 +15,65 @@ Sources: */ -public class ADL_Series : TSeries { - protected readonly TBars _data; - private double _lastadl, _lastlastadl; +public class ADL_Series : TSeries +{ + protected readonly TBars _data; + private double _lastadl, _lastlastadl; - //core constructors - public ADL_Series() { - Name = $"ADL()"; - _lastadl = _lastlastadl = 0; - } - public ADL_Series(TBars source) { - _data = source; - Name = $"ADL({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _lastadl = _lastlastadl = 0; - _data.Pub += Sub; - Add(data: _data); - } + //core constructors + public ADL_Series() + { + Name = $"ADL()"; + _lastadl = _lastlastadl = 0; + } + public ADL_Series(TBars source) + { + _data = source; + Name = $"ADL({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _lastadl = _lastlastadl = 0; + _data.Pub += Sub; + Add(data: _data); + } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - if (update) { this._lastadl = this._lastlastadl; } - else { this._lastlastadl = this._lastadl; } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + if (update) { this._lastadl = this._lastlastadl; } + else { this._lastlastadl = this._lastadl; } - double _adl = 0; - double tmp = TBar.h - TBar.l; - if (tmp > 0.0) { - _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); - } - _lastadl = _adl; + double _adl = 0; + double tmp = TBar.h - TBar.l; + if (tmp > 0.0) + { + _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); + } + _lastadl = _adl; - var ret = (TBar.t, _adl); - return base.Add(ret, update); - } + var ret = (TBar.t, _adl); + return base.Add(ret, update); + } - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _lastadl = _lastlastadl = 0; - } + //reset calculation + public override void Reset() + { + _lastadl = _lastlastadl = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/ADOSC_Series.cs b/Calculations/_Updated/ADOSC_Series.cs index 4c943b07..bc5b4305 100644 --- a/Calculations/_Updated/ADOSC_Series.cs +++ b/Calculations/_Updated/ADOSC_Series.cs @@ -14,77 +14,87 @@ Sources: */ -public class ADOSC_Series : TSeries { - protected readonly TBars _data; - private readonly double _k1, _k2; - private double _lastema1, _lastlastema1, _lastema2, _lastlastema2; - private double _lastadl, _lastlastadl; +public class ADOSC_Series : TSeries +{ + protected readonly TBars _data; + private readonly double _k1, _k2; + private double _lastema1, _lastlastema1, _lastema2, _lastlastema2; + private double _lastadl, _lastlastadl; - //core constructors - public ADOSC_Series(int shortPeriod, int longPeriod, bool useNaN = false) { - Name = $"ADOSC()"; - _k1 = 2.0 / (shortPeriod + 1); - _k2 = 2.0 / (longPeriod + 1); - _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0; - } - public ADOSC_Series(TBars source, int shortPeriod, int longPeriod, bool useNaN = false) :this(shortPeriod, longPeriod, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _lastadl = _lastlastadl = 0; - _data.Pub += Sub; - Add(data: _data); - } + //core constructors + public ADOSC_Series(int shortPeriod, int longPeriod, bool useNaN = false) + { + Name = $"ADOSC()"; + _k1 = 2.0 / (shortPeriod + 1); + _k2 = 2.0 / (longPeriod + 1); + _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0; + } + public ADOSC_Series(TBars source, int shortPeriod, int longPeriod, bool useNaN = false) : this(shortPeriod, longPeriod, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _lastadl = _lastlastadl = 0; + _data.Pub += Sub; + Add(data: _data); + } - public ADOSC_Series() : this(shortPeriod: 3, longPeriod: 10, useNaN: false) {} + public ADOSC_Series() : this(shortPeriod: 3, longPeriod: 10, useNaN: false) { } - public ADOSC_Series(TBars source) : this(source, shortPeriod: 3, longPeriod:10, useNaN:false) { } + public ADOSC_Series(TBars source) : this(source, shortPeriod: 3, longPeriod: 10, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update= false) { + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { - if (update) { - _lastadl = _lastlastadl; - _lastema1 = _lastlastema1; - _lastema2 = _lastlastema2; - } + if (update) + { + _lastadl = _lastlastadl; + _lastema1 = _lastlastema1; + _lastema2 = _lastlastema2; + } - double _adl = 0; - double tmp = TBar.h - TBar.l; - if (tmp > 0.0) { _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); } - if (this.Count == 0) { _lastema1 = _lastema2 = _adl; } + double _adl = 0; + double tmp = TBar.h - TBar.l; + if (tmp > 0.0) { _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); } + if (this.Count == 0) { _lastema1 = _lastema2 = _adl; } - double _ema1 = (_adl - _lastema1) * _k1 + _lastema1; - double _ema2 = (_adl - _lastema2) * _k2 + _lastema2; + double _ema1 = (_adl - _lastema1) * _k1 + _lastema1; + double _ema2 = (_adl - _lastema2) * _k2 + _lastema2; - _lastlastadl = _lastadl; - _lastadl = _adl; - _lastlastema1 = _lastema1; - _lastema1 = _ema1; - _lastlastema2 = _lastema2; - _lastema2 = _ema2; + _lastlastadl = _lastadl; + _lastadl = _adl; + _lastlastema1 = _lastema1; + _lastema1 = _ema1; + _lastlastema2 = _lastema2; + _lastema2 = _ema2; - double _adosc = _ema1 - _ema2; - - var ret = (TBar.t, _adosc); - return base.Add(ret, update); - } + double _adosc = _ema1 - _ema2; - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + var ret = (TBar.t, _adosc); + return base.Add(ret, update); + } - //reset calculation - public override void Reset() { - _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0; - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/ALMA_Series.cs b/Calculations/_Updated/ALMA_Series.cs index e4c8c3de..a25ac7d5 100644 --- a/Calculations/_Updated/ALMA_Series.cs +++ b/Calculations/_Updated/ALMA_Series.cs @@ -19,96 +19,111 @@ Sources: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma) */ -public class ALMA_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class ALMA_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - private readonly System.Collections.Generic.List _buffer = new(); - private readonly System.Collections.Generic.List _weight; - private double _norm; - private readonly double _offset, _sigma; + private readonly System.Collections.Generic.List _buffer = new(); + private readonly System.Collections.Generic.List _weight; + private double _norm; + private readonly double _offset, _sigma; - //core constructors - public ALMA_Series(int period, double offset, double sigma, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"ALMA({period})"; - _offset = offset; - _sigma = sigma; - _weight = new(); - } - public ALMA_Series(TSeries source, int period, double offset, double sigma, bool useNaN) : this(period, offset, sigma, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + //core constructors + public ALMA_Series(int period, double offset, double sigma, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"ALMA({period})"; + _offset = offset; + _sigma = sigma; + _weight = new(); + } + public ALMA_Series(TSeries source, int period, double offset, double sigma, bool useNaN) : this(period, offset, sigma, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - public ALMA_Series() : this(period:0, offset:0.85, sigma:6.0, useNaN: false) { } - public ALMA_Series(int period) : this(period: period, offset:0.85, sigma:6.0, useNaN:false) { } - public ALMA_Series(TBars source) : this(source:source.Close, period:0, offset:0.85, sigma:6.0, useNaN:false) { } - public ALMA_Series(TBars source, int period) : this(source:source.Close, period:period, offset: 0.85, sigma: 6.0, useNaN: false) { } - public ALMA_Series(TBars source, int period, double offset, double sigma, bool useNaN) : this(source.Close, period:period, offset: offset, sigma: sigma, useNaN: false) { } - public ALMA_Series(TSeries source) : this(source, period:0, offset:0.85, sigma:6.0, useNaN:false) { } - public ALMA_Series(TSeries source, int period) : this(source:source, period:period, offset:0.85, sigma:6.0, useNaN:false) { } - public ALMA_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, offset: 0.85, sigma: 6.0, useNaN: useNaN) { } + public ALMA_Series() : this(period: 0, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(int period) : this(period: period, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(TBars source) : this(source: source.Close, period: 0, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(TBars source, int period) : this(source: source.Close, period: period, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(TBars source, int period, double offset, double sigma, bool useNaN) : this(source.Close, period: period, offset: offset, sigma: sigma, useNaN: false) { } + public ALMA_Series(TSeries source) : this(source, period: 0, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(TSeries source, int period) : this(source: source, period: period, offset: 0.85, sigma: 6.0, useNaN: false) { } + public ALMA_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, offset: 0.85, sigma: 6.0, useNaN: useNaN) { } - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, double.NaN), update); - } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, double.NaN), update); + } - BufferTrim(_buffer, TValue.v, _period, update); - if (_weight.Count < _buffer.Count) { - for (var i = 0; i < _buffer.Count - _weight.Count; i++) { - _weight.Add(0.0); - } - } - + BufferTrim(_buffer, TValue.v, _period, update); + if (_weight.Count < _buffer.Count) + { + for (var i = 0; i < _buffer.Count - _weight.Count; i++) + { + _weight.Add(0.0); + } + } - if (_buffer.Count <= _period || _period == 0) { - var _len = _buffer.Count; - _norm = 0; - var _m = _offset * (_len - 1); - var _s = _len / _sigma; - for (var i = 0; i < _len; i++) { - var _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s)); - _weight[i] = _wt; - _norm += _wt; - } - } - double _weightedSum = 0; - for (var i = 0; i < _buffer.Count; i++) { - _weightedSum += _weight[i] * _buffer[i]; - } + if (_buffer.Count <= _period || _period == 0) + { + var _len = _buffer.Count; + _norm = 0; + var _m = _offset * (_len - 1); + var _s = _len / _sigma; + for (var i = 0; i < _len; i++) + { + var _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s)); + _weight[i] = _wt; + _norm += _wt; + } + } - var _alma = _weightedSum / _norm; + double _weightedSum = 0; + for (var i = 0; i < _buffer.Count; i++) + { + _weightedSum += _weight[i] * _buffer[i]; + } - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _alma); - return base.Add(res, update); - } + var _alma = _weightedSum / _norm; - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } - //reset calculation - public override void Reset() { - _buffer.Clear(); - _weight.Clear(); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _alma); + return base.Add(res, update); + } + + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + _weight.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/ATRP_Series.cs b/Calculations/_Updated/ATRP_Series.cs index 7f4cf4c7..ee429ea0 100644 --- a/Calculations/_Updated/ATRP_Series.cs +++ b/Calculations/_Updated/ATRP_Series.cs @@ -12,76 +12,86 @@ Sources: */ -public class ATRP_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TBars _data; - private double _k; - private int _len; - private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum; +public class ATRP_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TBars _data; + private double _k; + private int _len; + private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum; - //core constructors - public ATRP_Series(int period, bool useNaN) { - _period = period; - _k = 1.0 / (double)(_period); - _NaN = useNaN; - _len = 0; - Name = $"ATRP({period})"; - } - public ATRP_Series(TBars source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(data: _data); - } - public ATRP_Series() : this(period: 1, useNaN: false) { } - public ATRP_Series(int period) : this(period: period, useNaN: false) { } - public ATRP_Series(TBars source) : this(source, period: 1, useNaN: false) { } - public ATRP_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public ATRP_Series(int period, bool useNaN) + { + _period = period; + _k = 1.0 / (double)(_period); + _NaN = useNaN; + _len = 0; + Name = $"ATRP({period})"; + } + public ATRP_Series(TBars source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(data: _data); + } + public ATRP_Series() : this(period: 1, useNaN: false) { } + public ATRP_Series(int period) : this(period: period, useNaN: false) { } + public ATRP_Series(TBars source) : this(source, period: 1, useNaN: false) { } + public ATRP_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } - else { - _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; - _k = (_period == 0) ? 1 / (double)_len : _k; - _len++; - } - - if (_len == 1) { _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))); - _cm1 = TBar.c; + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } + else + { + _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; + _k = (_period == 0) ? 1 / (double)_len : _k; + _len++; + } - double _atr = 0; - if (this.Count == 0) { _atr = d.v; } - else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } - else { _atr = _k * (d.v - _lastatr) + _lastatr; } - _lastatr = _atr; - double _atrp = 100 * (_atr / TBar.c); + if (_len == 1) { _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))); + _cm1 = TBar.c; - var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _atrp); - return base.Add(res, update); - } + double _atr = 0; + if (this.Count == 0) { _atr = d.v; } + else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } + else { _atr = _k * (d.v - _lastatr) + _lastatr; } + _lastatr = _atr; + double _atrp = 100 * (_atr / TBar.c); - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _atrp); + return base.Add(res, update); + } - //reset calculation - public override void Reset() { - _len = 0; - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/ATR_Series.cs b/Calculations/_Updated/ATR_Series.cs index be22668d..c09ce7b2 100644 --- a/Calculations/_Updated/ATR_Series.cs +++ b/Calculations/_Updated/ATR_Series.cs @@ -14,75 +14,85 @@ Sources: */ -public class ATR_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TBars _data; - private double _k; - private int _len; - private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum; +public class ATR_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TBars _data; + private double _k; + private int _len; + private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum; - //core constructors - public ATR_Series(int period, bool useNaN) { - _period = period; - _k = 1.0 / (double)(_period); - _NaN = useNaN; - _len = 0; - Name = $"ATR({period})"; - } - public ATR_Series(TBars source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(data: _data); - } - public ATR_Series() : this(period: 1, useNaN: false) { } - public ATR_Series(int period) : this(period: period, useNaN: false) { } - public ATR_Series(TBars source) : this(source, period: 1, useNaN: false) { } - public ATR_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public ATR_Series(int period, bool useNaN) + { + _period = period; + _k = 1.0 / (double)(_period); + _NaN = useNaN; + _len = 0; + Name = $"ATR({period})"; + } + public ATR_Series(TBars source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(data: _data); + } + public ATR_Series() : this(period: 1, useNaN: false) { } + public ATR_Series(int period) : this(period: period, useNaN: false) { } + public ATR_Series(TBars source) : this(source, period: 1, useNaN: false) { } + public ATR_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } - else { - _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; - _k = (_period == 0) ? 1 / (double)_len : _k; - _len++; - } - - if (_len == 1) { _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))); - _cm1 = TBar.c; + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } + else + { + _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; + _k = (_period == 0) ? 1 / (double)_len : _k; + _len++; + } - double _atr = 0; - if (this.Count == 0) { _atr = d.v; } - else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } - else { _atr = _k * (d.v - _lastatr) + _lastatr; } - _lastatr = _atr; - - var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _atr); - return base.Add(res, update); - } + if (_len == 1) { _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))); + _cm1 = TBar.c; - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + double _atr = 0; + if (this.Count == 0) { _atr = d.v; } + else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } + else { _atr = _k * (d.v - _lastatr) + _lastatr; } + _lastatr = _atr; - //reset calculation - public override void Reset() { - _len = 0; - } + var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _atr); + return base.Add(res, update); + } + + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/BBANDS_Series.cs b/Calculations/_Updated/BBANDS_Series.cs index 7cc5a3e0..e64398ff 100644 --- a/Calculations/_Updated/BBANDS_Series.cs +++ b/Calculations/_Updated/BBANDS_Series.cs @@ -26,87 +26,96 @@ Note: */ -public class BBANDS_Series : TSeries { - protected readonly int _period; - protected readonly double _multiplier; - protected readonly bool _NaN; - protected readonly TSeries _data; - public SMA_Series Mid { get; } - public TSeries Upper { get; } - public TSeries Lower { get; } - public TSeries PercentB { get; } - public TSeries Bandwidth { get; } - public TSeries Zscore { get; } - private readonly SDEV_Series _sdev; +public class BBANDS_Series : TSeries +{ + protected readonly int _period; + protected readonly double _multiplier; + protected readonly bool _NaN; + protected readonly TSeries _data; + public SMA_Series Mid { get; } + public TSeries Upper { get; } + public TSeries Lower { get; } + public TSeries PercentB { get; } + public TSeries Bandwidth { get; } + public TSeries Zscore { get; } + private readonly SDEV_Series _sdev; - //core constructors - public BBANDS_Series(int period, double multiplier, bool useNaN) { - _period = period; - _multiplier = multiplier; - _NaN = useNaN; - Name = $"BBANDS({period})"; - } - public BBANDS_Series(TSeries source, int period, double multiplier, bool useNaN) : this(period, multiplier, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - Upper = new("BB_Up"); - Lower = new("BB_Low"); - Bandwidth = new("BBandwidth"); - PercentB = new("%BBandwidth"); - Zscore = new("Zscore"); + //core constructors + public BBANDS_Series(int period, double multiplier, bool useNaN) + { + _period = period; + _multiplier = multiplier; + _NaN = useNaN; + Name = $"BBANDS({period})"; + } + public BBANDS_Series(TSeries source, int period, double multiplier, bool useNaN) : this(period, multiplier, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + Upper = new("BB_Up"); + Lower = new("BB_Low"); + Bandwidth = new("BBandwidth"); + PercentB = new("%BBandwidth"); + Zscore = new("Zscore"); - Mid = new(period, false); - _sdev = new(period, false); + Mid = new(period, false); + _sdev = new(period, false); - _data.Pub += Sub; - Add(_data); - } + _data.Pub += Sub; + Add(_data); + } - public BBANDS_Series() : this(period:0, multiplier: 2.0, useNaN: false) { } - public BBANDS_Series(int period) : this(period: period, multiplier: 2.0, useNaN:false) { } - public BBANDS_Series(TBars source) : this(source:source.Close, period:0, multiplier: 2.0, useNaN:false) { } - public BBANDS_Series(TBars source, int period) : this(source:source.Close, period:period, multiplier: 2.0, useNaN: false) { } - public BBANDS_Series(TBars source, int period, double multiplier, bool useNaN) : this(source.Close, period:period, multiplier:multiplier, useNaN: false) { } - public BBANDS_Series(TSeries source) : this(source, period:0, useNaN:false) { } - public BBANDS_Series(TSeries source, int period) : this(source:source, period:period, useNaN:false) { } - public BBANDS_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, multiplier: 2.0, useNaN: useNaN) { } + public BBANDS_Series() : this(period: 0, multiplier: 2.0, useNaN: false) { } + public BBANDS_Series(int period) : this(period: period, multiplier: 2.0, useNaN: false) { } + public BBANDS_Series(TBars source) : this(source: source.Close, period: 0, multiplier: 2.0, useNaN: false) { } + public BBANDS_Series(TBars source, int period) : this(source: source.Close, period: period, multiplier: 2.0, useNaN: false) { } + public BBANDS_Series(TBars source, int period, double multiplier, bool useNaN) : this(source.Close, period: period, multiplier: multiplier, useNaN: false) { } + public BBANDS_Series(TSeries source) : this(source, period: 0, useNaN: false) { } + public BBANDS_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + public BBANDS_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, multiplier: 2.0, useNaN: useNaN) { } - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update=false) { - var _mid = Mid.Add(TValue,update); - var _sd = this._sdev.Add(TValue, update); - var _upper = Upper.Add((TValue.t, _mid.v + _sd.v * _multiplier), update); - var _lower = Lower.Add((TValue.t, _mid.v - _sd.v * _multiplier), update); - double _pbdnd = TValue.v - _lower.v; - double _pbdvr = _upper.v - _lower.v; - PercentB.Add((TValue.t, _pbdnd/_pbdvr), update); - Zscore.Add((TValue.t, (TValue.v-_mid.v)/_sd.v), update); - Bandwidth.Add((TValue.t, _pbdvr / _mid.v), update); - - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _pbdvr / _mid.v); - return base.Add(res, update); - } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + var _mid = Mid.Add(TValue, update); + var _sd = this._sdev.Add(TValue, update); + var _upper = Upper.Add((TValue.t, _mid.v + _sd.v * _multiplier), update); + var _lower = Lower.Add((TValue.t, _mid.v - _sd.v * _multiplier), update); + double _pbdnd = TValue.v - _lower.v; + double _pbdvr = _upper.v - _lower.v; + PercentB.Add((TValue.t, _pbdnd / _pbdvr), update); + Zscore.Add((TValue.t, (TValue.v - _mid.v) / _sd.v), update); + Bandwidth.Add((TValue.t, _pbdvr / _mid.v), update); - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } - //reset calculation - public override void Reset() { - Mid.Clear(); - _sdev.Clear(); - Upper.Clear(); - Lower.Clear(); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _pbdvr / _mid.v); + return base.Add(res, update); + } + + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + //reset calculation + public override void Reset() + { + Mid.Clear(); + _sdev.Clear(); + Upper.Clear(); + Lower.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/BIAS_Series.cs b/Calculations/_Updated/BIAS_Series.cs index 0c859ee4..cf724bf3 100644 --- a/Calculations/_Updated/BIAS_Series.cs +++ b/Calculations/_Updated/BIAS_Series.cs @@ -13,60 +13,69 @@ Sources: */ -public class BIAS_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly SMA_Series _sma; +public class BIAS_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly SMA_Series _sma; - //core constructors - public BIAS_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"BIAS({period})"; - _sma = new(period, false); - } - public BIAS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public BIAS_Series() : this(period: 0, useNaN: false) { } - public BIAS_Series(int period) : this(period: period, useNaN: false) { } - public BIAS_Series(TBars source) : this(source.Close, 0, false) { } - public BIAS_Series(TBars source, int period) : this(source.Close, period, false) { } - public BIAS_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public BIAS_Series(TSeries source) : this(source, 0, false) { } - public BIAS_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public BIAS_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"BIAS({period})"; + _sma = new(period, false); + } + public BIAS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public BIAS_Series() : this(period: 0, useNaN: false) { } + public BIAS_Series(int period) : this(period: period, useNaN: false) { } + public BIAS_Series(TBars source) : this(source.Close, 0, false) { } + public BIAS_Series(TBars source, int period) : this(source.Close, period, false) { } + public BIAS_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public BIAS_Series(TSeries source) : this(source, 0, false) { } + public BIAS_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - var _s = _sma.Add(TValue,update); - double _bias = (TValue.v / ((_s.v!=0)?_s.v:1)) - 1; + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + var _s = _sma.Add(TValue, update); + double _bias = (TValue.v / ((_s.v != 0) ? _s.v : 1)) - 1; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _bias); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _bias); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _sma.Reset(); - } + //reset calculation + public override void Reset() + { + _sma.Reset(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/CCI_Series.cs b/Calculations/_Updated/CCI_Series.cs index 89efbc20..4886857b 100644 --- a/Calculations/_Updated/CCI_Series.cs +++ b/Calculations/_Updated/CCI_Series.cs @@ -18,69 +18,80 @@ Sources: */ -public class CCI_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TBars _data; - private readonly System.Collections.Generic.List _tp = new(); +public class CCI_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TBars _data; + private readonly System.Collections.Generic.List _tp = new(); - //core constructors - public CCI_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"CCI({period})"; - } - public CCI_Series(TBars source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(data: _data); - } - public CCI_Series() : this(period: 2, useNaN: false) { } - public CCI_Series(int period) : this(period: period, useNaN: false) { } - public CCI_Series(TBars source) : this(source, period: 2, useNaN: false) { } - public CCI_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public CCI_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"CCI({period})"; + } + public CCI_Series(TBars source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(data: _data); + } + public CCI_Series() : this(period: 2, useNaN: false) { } + public CCI_Series(int period) : this(period: period, useNaN: false) { } + public CCI_Series(TBars source) : this(source, period: 2, useNaN: false) { } + public CCI_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0; - if (update) { - this._tp[this._tp.Count - 1] = _tpItem; - } - else { - this._tp.Add(_tpItem); - } - if (this._tp.Count > this._period) { this._tp.RemoveAt(0); } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0; + if (update) + { + this._tp[this._tp.Count - 1] = _tpItem; + } + else + { + this._tp.Add(_tpItem); + } + if (this._tp.Count > this._period) { this._tp.RemoveAt(0); } - // average TP over _tp buffer - double _avgTp = _tp.Average(); + // average TP over _tp buffer + double _avgTp = _tp.Average(); - // average Deviation over _tp buffer - double _avgDv = 0; - for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); } - _avgDv /= this._tp.Count; + // average Deviation over _tp buffer + double _avgDv = 0; + for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); } + _avgDv /= this._tp.Count; - double _cci = (_avgDv == 0) ? 0 : (this._tp[this._tp.Count - 1] - _avgTp) / (0.015 * _avgDv); - var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _cci); - return base.Add(res, update); - } + double _cci = (_avgDv == 0) ? 0 : (this._tp[this._tp.Count - 1] - _avgTp) / (0.015 * _avgDv); + var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _cci); + return base.Add(res, update); + } - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _tp.Clear(); - } + //reset calculation + public override void Reset() + { + _tp.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/CMO_Series.cs b/Calculations/_Updated/CMO_Series.cs index ea800ed2..fe793bb0 100644 --- a/Calculations/_Updated/CMO_Series.cs +++ b/Calculations/_Updated/CMO_Series.cs @@ -18,73 +18,83 @@ Sources: */ -public class CMO_Series : TSeries { - private readonly System.Collections.Generic.List _buff_up = new(); - private readonly System.Collections.Generic.List _buff_dn = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private double _plast_value, _last_value; +public class CMO_Series : TSeries +{ + private readonly System.Collections.Generic.List _buff_up = new(); + private readonly System.Collections.Generic.List _buff_dn = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private double _plast_value, _last_value; - //core constructors - public CMO_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"CMO({period})"; - } - public CMO_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public CMO_Series() : this(period: 0, useNaN: false) { } - public CMO_Series(int period) : this(period: period, useNaN: false) { } - public CMO_Series(TBars source) : this(source.Close, 0, false) { } - public CMO_Series(TBars source, int period) : this(source.Close, period, false) { } - public CMO_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public CMO_Series(TSeries source) : this(source, 0, false) { } - public CMO_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public CMO_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"CMO({period})"; + } + public CMO_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public CMO_Series() : this(period: 0, useNaN: false) { } + public CMO_Series(int period) : this(period: period, useNaN: false) { } + public CMO_Series(TBars source) : this(source.Close, 0, false) { } + public CMO_Series(TBars source, int period) : this(source.Close, period, false) { } + public CMO_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public CMO_Series(TSeries source) : this(source, 0, false) { } + public CMO_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { _last_value = _plast_value; } else { _plast_value = _last_value; } - BufferTrim(buffer:_buff_up, (TValue.v > _last_value) ? TValue.v - _last_value : 0, period:_period, update: update); - BufferTrim(buffer: _buff_dn, (TValue.v < _last_value) ? _last_value - TValue.v : 0, period: _period, update: 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; } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) { _last_value = _plast_value; } else { _plast_value = _last_value; } + BufferTrim(buffer: _buff_up, (TValue.v > _last_value) ? TValue.v - _last_value : 0, period: _period, update: update); + BufferTrim(buffer: _buff_dn, (TValue.v < _last_value) ? _last_value - TValue.v : 0, period: _period, update: 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; } - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _cmo); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _cmo); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buff_up.Clear(); - _buff_dn.Clear(); - } + //reset calculation + public override void Reset() + { + _buff_up.Clear(); + _buff_dn.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/CUSUM_Series.cs b/Calculations/_Updated/CUSUM_Series.cs index 08897f07..38036f94 100644 --- a/Calculations/_Updated/CUSUM_Series.cs +++ b/Calculations/_Updated/CUSUM_Series.cs @@ -11,61 +11,70 @@ Sources: https://en.wikipedia.org/wiki/CUSUM */ -public class CUSUM_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); +public class CUSUM_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public CUSUM_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"CUSUM({period})"; - } - public CUSUM_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public CUSUM_Series() : this(period: 0, useNaN: false) { } - public CUSUM_Series(int period) : this(period: period, useNaN: false) { } - public CUSUM_Series(TBars source) : this(source.Close, 0, false) { } - public CUSUM_Series(TBars source, int period) : this(source.Close, period, false) { } - public CUSUM_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public CUSUM_Series(TSeries source) : this(source, period: 0, useNaN: false) { } - public CUSUM_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public CUSUM_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"CUSUM({period})"; + } + public CUSUM_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public CUSUM_Series() : this(period: 0, useNaN: false) { } + public CUSUM_Series(int period) : this(period: period, useNaN: false) { } + public CUSUM_Series(TBars source) : this(source.Close, 0, false) { } + public CUSUM_Series(TBars source, int period) : this(source.Close, period, false) { } + public CUSUM_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public CUSUM_Series(TSeries source) : this(source, period: 0, useNaN: false) { } + public CUSUM_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sum = 0; - for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; } - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sum); - return base.Add(res, update); - } + double _sum = 0; + for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sum); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/DECAY_Series.cs b/Calculations/_Updated/DECAY_Series.cs index 263875c3..8236956e 100644 --- a/Calculations/_Updated/DECAY_Series.cs +++ b/Calculations/_Updated/DECAY_Series.cs @@ -13,71 +13,81 @@ DECAY: */ -public class DECAY_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly bool _exp; - private double _pdecay, _ppdecay; - private readonly double _dfactor; +public class DECAY_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly bool _exp; + private double _pdecay, _ppdecay; + private readonly double _dfactor; - //core constructors - public DECAY_Series(int period, bool exponential, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"DECAY({period})"; - _exp = exponential; - _dfactor = (_exp) ? 1.0 - 1.0 / (double)_period : 1 / (double)_period; - _pdecay = _ppdecay = 0; - } - public DECAY_Series(TSeries source, int period, bool exponential, bool useNaN) : this(period, exponential, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public DECAY_Series() : this(period: 0, exponential: false, useNaN: false) { } - public DECAY_Series(int period) : this(period: period, exponential: false, useNaN: false) { } - public DECAY_Series(TBars source) : this(source.Close, period: 0, exponential: false, useNaN: false) { } - public DECAY_Series(TBars source, int period) : this(source.Close, period: period, exponential:false, useNaN:false) { } - public DECAY_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, exponential: false, useNaN) { } - public DECAY_Series(TSeries source) : this(source, period: 0, exponential: false, useNaN:false) { } - public DECAY_Series(TSeries source, int period) : this(source: source, period: period, exponential: false, useNaN: false) { } - public DECAY_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, exponential: false, useNaN: useNaN) { } + //core constructors + public DECAY_Series(int period, bool exponential, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"DECAY({period})"; + _exp = exponential; + _dfactor = (_exp) ? 1.0 - 1.0 / (double)_period : 1 / (double)_period; + _pdecay = _ppdecay = 0; + } + public DECAY_Series(TSeries source, int period, bool exponential, bool useNaN) : this(period, exponential, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public DECAY_Series() : this(period: 0, exponential: false, useNaN: false) { } + public DECAY_Series(int period) : this(period: period, exponential: false, useNaN: false) { } + public DECAY_Series(TBars source) : this(source.Close, period: 0, exponential: false, useNaN: false) { } + public DECAY_Series(TBars source, int period) : this(source.Close, period: period, exponential: false, useNaN: false) { } + public DECAY_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, exponential: false, useNaN) { } + public DECAY_Series(TSeries source) : this(source, period: 0, exponential: false, useNaN: false) { } + public DECAY_Series(TSeries source, int period) : this(source: source, period: period, exponential: false, useNaN: false) { } + public DECAY_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, exponential: false, useNaN: useNaN) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } - if (update) { _pdecay = _ppdecay; } - else { _ppdecay = _pdecay; } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } + if (update) { _pdecay = _ppdecay; } + else { _ppdecay = _pdecay; } - if (this.Count == 0) { _pdecay = TValue.v; } - double _decay = Math.Max(TValue.v, Math.Max((_exp) ? _pdecay * _dfactor : _pdecay - _dfactor, 0)); - _pdecay = _decay; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _decay); - return base.Add(res, update); - } + if (this.Count == 0) { _pdecay = TValue.v; } + double _decay = Math.Max(TValue.v, Math.Max((_exp) ? _pdecay * _dfactor : _pdecay - _dfactor, 0)); + _pdecay = _decay; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _decay); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _pdecay = _ppdecay = 0; - } + //reset calculation + public override void Reset() + { + _pdecay = _ppdecay = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/DEMA_Series.cs b/Calculations/_Updated/DEMA_Series.cs index dffd9f71..8bcf0ed7 100644 --- a/Calculations/_Updated/DEMA_Series.cs +++ b/Calculations/_Updated/DEMA_Series.cs @@ -17,111 +17,128 @@ Remark: */ -public class DEMA_Series : TSeries { - private double _k; - private double _sum, _oldsum; - private double _lastema1, _oldema1, _lastema2, _oldema2; - private int _len; - private readonly bool _useSMA; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class DEMA_Series : TSeries +{ + private double _k; + private double _sum, _oldsum; + private double _lastema1, _oldema1, _lastema2, _oldema2; + private int _len; + private readonly bool _useSMA; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; -//core constructor - public DEMA_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - _useSMA = useSMA; - Name = $"DEMA({period})"; - _k = 2.0 / (_period + 1); - _len = 0; - _sum = _oldsum = _lastema1 = _lastema2 = 0; - } - //generic constructors (source) + //core constructor + public DEMA_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + _useSMA = useSMA; + Name = $"DEMA({period})"; + _k = 2.0 / (_period + 1); + _len = 0; + _sum = _oldsum = _lastema1 = _lastema2 = 0; + } + //generic constructors (source) - public DEMA_Series() : this(0, false, true) {} - public DEMA_Series(int period) : this(period, false, true) {} - public DEMA_Series(TBars source) : this(source.Close, 0, false) {} - public DEMA_Series(TBars source, int period) : this(source.Close, period, false) {} - public DEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public DEMA_Series(TSeries source, int period) : this(source, period, false, true) {} - public DEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) {} - public DEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public DEMA_Series() : this(0, false, true) { } + public DEMA_Series(int period) : this(period, false, true) { } + public DEMA_Series(TBars source) : this(source.Close, 0, false) { } + public DEMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public DEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public DEMA_Series(TSeries source, int period) : this(source, period, false, true) { } + public DEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } + public DEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } -// core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - _lastema1 = _oldema1; - _lastema2 = _oldema2; - _sum = _oldsum; - } - else { - _oldema1 = _lastema1; - _oldema2 = _lastema2; - _oldsum = _sum; - _len++; - } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + _lastema1 = _oldema1; + _lastema2 = _oldema2; + _sum = _oldsum; + } + else + { + _oldema1 = _lastema1; + _oldema2 = _lastema2; + _oldsum = _sum; + _len++; + } - if (_period == 0) { - _k = 2.0 / (_len + 1); - } + if (_period == 0) + { + _k = 2.0 / (_len + 1); + } - double _ema1, _ema2, _dema; - if (Count == 0) { - _ema1 = _ema2 = _sum = TValue.v; - } - else if (_len <= _period && _useSMA && _period != 0) { - _sum += TValue.v; - _ema1 = _sum / Math.Min(_len, _period); - _ema2 = _ema1; - } - else { - _ema1 = (TValue.v - _lastema1) * _k + _lastema1; - _ema2 = (_ema1 - _lastema2) * _k + _lastema2; - } + double _ema1, _ema2, _dema; + if (Count == 0) + { + _ema1 = _ema2 = _sum = TValue.v; + } + else if (_len <= _period && _useSMA && _period != 0) + { + _sum += TValue.v; + _ema1 = _sum / Math.Min(_len, _period); + _ema2 = _ema1; + } + else + { + _ema1 = (TValue.v - _lastema1) * _k + _lastema1; + _ema2 = (_ema1 - _lastema2) * _k + _lastema2; + } - _dema = 2 * _ema1 - _ema2; + _dema = 2 * _ema1 - _ema2; - _lastema1 = double.IsNaN(_ema1) ? _lastema1 : _ema1; - _lastema2 = double.IsNaN(_ema2) ? _lastema2 : _ema2; + _lastema1 = double.IsNaN(_ema1) ? _lastema1 : _ema1; + _lastema2 = double.IsNaN(_ema2) ? _lastema2 : _ema2; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _dema); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _dema); + return base.Add(res, update); + } -//variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { - return (DateTime.Today, double.NaN); - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) + { + return (DateTime.Today, double.NaN); + } - foreach (var item in data) { - Add(item, false); - } + foreach (var item in data) + { + Add(item, false); + } - return _data.Last; - } + return _data.Last; + } - public (DateTime t, double v) Add(bool update) { - return Add(_data.Last, update); - } + public (DateTime t, double v) Add(bool update) + { + return Add(_data.Last, update); + } - public (DateTime t, double v) Add() { - return Add(_data.Last, false); - } + public (DateTime t, double v) Add() + { + return Add(_data.Last, false); + } - private new void Sub(object source, TSeriesEventArgs e) { - Add(_data.Last, e.update); - } - - //reset calculation - public override void Reset() { - _sum = _oldsum = _lastema1 = _lastema2 = 0; - _len = 0; - } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(_data.Last, e.update); + } + + //reset calculation + public override void Reset() + { + _sum = _oldsum = _lastema1 = _lastema2 = 0; + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/DWMA_Series.cs b/Calculations/_Updated/DWMA_Series.cs index 20283c34..d9d9b847 100644 --- a/Calculations/_Updated/DWMA_Series.cs +++ b/Calculations/_Updated/DWMA_Series.cs @@ -11,112 +11,133 @@ DWMA: Double Weighted Moving Average */ -public class DWMA_Series : TSeries { - private readonly List _buffer = new(); - private List _weights; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - protected int _len; +public class DWMA_Series : TSeries +{ + private readonly List _buffer = new(); + private List _weights; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + protected int _len; -//core constructors - public DWMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"DWMA({period})"; - _len = 0; - _weights = CalculateWeights(_period); - } + //core constructors + public DWMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"DWMA({period})"; + _len = 0; + _weights = CalculateWeights(_period); + } - public DWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public DWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - public DWMA_Series() : this(0, false) { - } + public DWMA_Series() : this(0, false) + { + } - public DWMA_Series(int period) : this(period, false) { - } + public DWMA_Series(int period) : this(period, false) + { + } - public DWMA_Series(TBars source) : this(source.Close, 0, false) { - } + public DWMA_Series(TBars source) : this(source.Close, 0, false) + { + } - public DWMA_Series(TBars source, int period) : this(source.Close, period, false) { - } + public DWMA_Series(TBars source, int period) : this(source.Close, period, false) + { + } - public DWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { - } + public DWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) + { + } - public DWMA_Series(TSeries source, int period) : this(source, period, false) { - } + public DWMA_Series(TSeries source, int period) : this(source, period, false) + { + } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(_buffer, TValue.v, _period, update); - if (_period == 0) { - _len++; - _weights = CalculateWeights(_len); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(_buffer, TValue.v, _period, update); + if (_period == 0) + { + _len++; + _weights = CalculateWeights(_len); + } - double _dwma = 0, _wsum = 0; - var bufferCount = _buffer.Count; + double _dwma = 0, _wsum = 0; + var bufferCount = _buffer.Count; - var lockObj = new object(); - Parallel.For(0, bufferCount, i => - { - var temp = _buffer[i] * _weights[i]; - lock (lockObj) { - _dwma += temp; - _wsum += _weights[i]; - } - }); - _dwma /= _wsum; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _dwma); - return base.Add(res, update); - } + var lockObj = new object(); + Parallel.For(0, bufferCount, i => + { + var temp = _buffer[i] * _weights[i]; + lock (lockObj) + { + _dwma += temp; + _wsum += _weights[i]; + } + }); + _dwma /= _wsum; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _dwma); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { - return (DateTime.Today, double.NaN); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) + { + return (DateTime.Today, double.NaN); + } - foreach (var item in data) { - Add(item, false); - } + foreach (var item in data) + { + Add(item, false); + } - return _data.Last; - } + return _data.Last; + } - public (DateTime t, double v) Add(bool update) { - return Add(_data.Last, update); - } + public (DateTime t, double v) Add(bool update) + { + return Add(_data.Last, update); + } - public (DateTime t, double v) Add() { - return Add(_data.Last, false); - } + public (DateTime t, double v) Add() + { + return Add(_data.Last, false); + } - private new void Sub(object source, TSeriesEventArgs e) { - Add(_data.Last, e.update); - } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(_data.Last, e.update); + } - //calculating weights - private static List CalculateWeights(int period) { - var weights = new List(period); - for (var i = 0; i < period; i++) { - weights.Add((i + 1) * (i + 1)); - } + //calculating weights + private static List CalculateWeights(int period) + { + var weights = new List(period); + for (var i = 0; i < period; i++) + { + weights.Add((i + 1) * (i + 1)); + } - return weights; - } + return weights; + } - //reset calculation - public override void Reset() { - _len = 0; - _buffer.Clear(); - _weights = CalculateWeights(_period); - } + //reset calculation + public override void Reset() + { + _len = 0; + _buffer.Clear(); + _weights = CalculateWeights(_period); + } } \ No newline at end of file diff --git a/Calculations/_Updated/EMA_Series.cs b/Calculations/_Updated/EMA_Series.cs index 174d978a..26edf8ef 100644 --- a/Calculations/_Updated/EMA_Series.cs +++ b/Calculations/_Updated/EMA_Series.cs @@ -21,100 +21,116 @@ Issues: */ -public class EMA_Series : TSeries { - private double _k; - private double _lastema, _oldema; - private double _sum, _oldsum; - private int _len; - private readonly bool _useSMA; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class EMA_Series : TSeries +{ + private double _k; + private double _lastema, _oldema; + private double _sum, _oldsum; + private int _len; + private readonly bool _useSMA; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; -//core constructors + //core constructors - public EMA_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - _useSMA = useSMA; - Name = $"EMA({period})"; - _k = 2.0 / (_period + 1); - _len = 0; - _sum = _oldsum = _lastema = _oldema = 0; - } - public EMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public EMA_Series() : this(0, false, true) {} - public EMA_Series(int period) : this(period, false, true) {} - public EMA_Series(TBars source) : this(source.Close, 0, false) {} - public EMA_Series(TBars source, int period) : this(source.Close, period, false) {} - public EMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public EMA_Series(TSeries source, int period) : this(source, period, false, true) {} - public EMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) {} + public EMA_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + _useSMA = useSMA; + Name = $"EMA({period})"; + _k = 2.0 / (_period + 1); + _len = 0; + _sum = _oldsum = _lastema = _oldema = 0; + } + public EMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public EMA_Series() : this(0, false, true) { } + public EMA_Series(int period) : this(period, false, true) { } + public EMA_Series(TBars source) : this(source.Close, 0, false) { } + public EMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public EMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public EMA_Series(TSeries source, int period) : this(source, period, false, true) { } + public EMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - _lastema = _oldema; - _sum = _oldsum; - } - else { - _oldema = _lastema; - _oldsum = _sum; - _len++; - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + _lastema = _oldema; + _sum = _oldsum; + } + else + { + _oldema = _lastema; + _oldsum = _sum; + _len++; + } - double _ema = 0; - if (_period == 0) { - _k = 2.0 / (_len + 1); - } + double _ema = 0; + if (_period == 0) + { + _k = 2.0 / (_len + 1); + } - if (Count == 0) { - _ema = _sum = TValue.v; - } - else if (_len <= _period && _useSMA && _period != 0) { - _sum += TValue.v; - if (_period != 0 && _len > _period) { - _sum -= _data[Count - _period - (update ? 1 : 0)].v; - } + if (Count == 0) + { + _ema = _sum = TValue.v; + } + else if (_len <= _period && _useSMA && _period != 0) + { + _sum += TValue.v; + if (_period != 0 && _len > _period) + { + _sum -= _data[Count - _period - (update ? 1 : 0)].v; + } - _ema = _sum / Math.Min(_len, _period); - } - else { - _ema = _k * (TValue.v - _lastema) + _lastema; - } + _ema = _sum / Math.Min(_len, _period); + } + else + { + _ema = _k * (TValue.v - _lastema) + _lastema; + } - _lastema = double.IsNaN(_ema) ? _lastema : _ema; + _lastema = double.IsNaN(_ema) ? _lastema : _ema; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _ema); - return base.Add(res, update); - } - -//variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } - - //reset calculation - public override void Reset() { - _sum = _oldsum = _lastema = _oldema = 0; - _len = 0; - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _ema); + return base.Add(res, update); + } + + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _sum = _oldsum = _lastema = _oldema = 0; + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/ENTROPY_Series.cs b/Calculations/_Updated/ENTROPY_Series.cs index 27592dfd..6c3bd399 100644 --- a/Calculations/_Updated/ENTROPY_Series.cs +++ b/Calculations/_Updated/ENTROPY_Series.cs @@ -18,70 +18,80 @@ Sources: */ -public class ENTROPY_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly double _logbase; - private readonly System.Collections.Generic.List _buffer = new(); - private readonly System.Collections.Generic.List _buff2 = new(); +public class ENTROPY_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly double _logbase; + private readonly System.Collections.Generic.List _buffer = new(); + private readonly System.Collections.Generic.List _buff2 = new(); - //core constructors - public ENTROPY_Series(int period, double logbase, bool useNaN) { - _period = period; - _NaN = useNaN; - _logbase = logbase; - Name = $"ENTROPY({period})"; - } - public ENTROPY_Series(TSeries source, int period, double logbase, bool useNaN) : this(period, logbase, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public ENTROPY_Series() : this(period: 0, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(int period) : this(period: period, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(TBars source) : this(source.Close, period: 0, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(TBars source, int period) : this(source.Close, period, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, logbase: 2.0, useNaN: useNaN) { } - public ENTROPY_Series(TSeries source) : this(source, period: 0, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(TSeries source, int period) : this(source: source, period: period, logbase: 2.0, useNaN: false) { } - public ENTROPY_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, logbase: 2.0, useNaN: useNaN) { } + //core constructors + public ENTROPY_Series(int period, double logbase, bool useNaN) + { + _period = period; + _NaN = useNaN; + _logbase = logbase; + Name = $"ENTROPY({period})"; + } + public ENTROPY_Series(TSeries source, int period, double logbase, bool useNaN) : this(period, logbase, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public ENTROPY_Series() : this(period: 0, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(int period) : this(period: period, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(TBars source) : this(source.Close, period: 0, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(TBars source, int period) : this(source.Close, period, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, logbase: 2.0, useNaN: useNaN) { } + public ENTROPY_Series(TSeries source) : this(source, period: 0, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(TSeries source, int period) : this(source: source, period: period, logbase: 2.0, useNaN: false) { } + public ENTROPY_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, logbase: 2.0, useNaN: useNaN) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sum = _buffer.Sum(); - double _pp = this._buffer[^1] / _sum; - double _ppp = -_pp * Math.Log(_pp) / Math.Log(this._logbase); - BufferTrim(_buff2, _ppp, _period, update); - double _entp = _buff2.Sum(); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _entp); - return base.Add(res, update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + double _sum = _buffer.Sum(); + double _pp = this._buffer[^1] / _sum; + double _ppp = -_pp * Math.Log(_pp) / Math.Log(this._logbase); + BufferTrim(_buff2, _ppp, _period, update); + double _entp = _buff2.Sum(); + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _entp); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - _buff2.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + _buff2.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/FWMA_Series.cs b/Calculations/_Updated/FWMA_Series.cs index 81134148..f9976814 100644 --- a/Calculations/_Updated/FWMA_Series.cs +++ b/Calculations/_Updated/FWMA_Series.cs @@ -10,85 +10,96 @@ FWMA: Fibonacci's Weighted Moving Average is similar to a Weighted Moving Averag (WMA) where the weights are based on the Fibonacci Sequence. */ -public class FWMA_Series : TSeries { - private readonly List _buffer = new(); - private List _weights; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - protected int _len; +public class FWMA_Series : TSeries +{ + private readonly List _buffer = new(); + private List _weights; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + protected int _len; - public FWMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"FWMA({period})"; - _len = 0; - _weights = CalculateWeights(_period); - } + public FWMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"FWMA({period})"; + _len = 0; + _weights = CalculateWeights(_period); + } - public FWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public FWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - public FWMA_Series() : this(period: 0, useNaN: false) { } - public FWMA_Series(int period) : this(period: period, useNaN: false) { } - public FWMA_Series(TBars source) : this(source.Close, 0, false) { } - public FWMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public FWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public FWMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + public FWMA_Series() : this(period: 0, useNaN: false) { } + public FWMA_Series(int period) : this(period: period, useNaN: false) { } + public FWMA_Series(TBars source) : this(source.Close, 0, false) { } + public FWMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public FWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public FWMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - if (_period == 0) { - _len++; - _weights = CalculateWeights(_len); - } - double _fwma = 0; - double totalWeights = _weights.Sum(); - object lockObj = new object(); - Parallel.For(0, _buffer.Count, i => - { - double temp = _buffer[i] * _weights[i]; - lock (lockObj) { _fwma += temp; } - }); - _fwma /= totalWeights; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _fwma); - return base.Add(res, update); - } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + if (_period == 0) + { + _len++; + _weights = CalculateWeights(_len); + } + double _fwma = 0; + double totalWeights = _weights.Sum(); + object lockObj = new object(); + Parallel.For(0, _buffer.Count, i => + { + double temp = _buffer[i] * _weights[i]; + lock (lockObj) { _fwma += temp; } + }); + _fwma /= totalWeights; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _fwma); + return base.Add(res, update); + } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - private static List CalculateWeights(int period) { - //to prevent overflow, max period can be no more than 1476 - period = (period > 1476) ? 1476 : period; - List weights = new List(period); - BigInteger a = 0; - BigInteger b = 1; - for (int i = 0; i < period; i++) { - BigInteger temp = a; - a = b; - b = temp + b; - weights.Add((double)Decimal.Parse(a.ToString())); - } - return weights; - } + private static List CalculateWeights(int period) + { + //to prevent overflow, max period can be no more than 1476 + period = (period > 1476) ? 1476 : period; + List weights = new List(period); + BigInteger a = 0; + BigInteger b = 1; + for (int i = 0; i < period; i++) + { + BigInteger temp = a; + a = b; + b = temp + b; + weights.Add((double)Decimal.Parse(a.ToString())); + } + return weights; + } - public override void Reset() { - _weights = CalculateWeights(_period); - _buffer.Clear(); - } + public override void Reset() + { + _weights = CalculateWeights(_period); + _buffer.Clear(); + } } diff --git a/Calculations/_Updated/HEMA_Series.cs b/Calculations/_Updated/HEMA_Series.cs index 60aacda4..c52f6c06 100644 --- a/Calculations/_Updated/HEMA_Series.cs +++ b/Calculations/_Updated/HEMA_Series.cs @@ -13,104 +13,121 @@ Raw HMA = (2 * EMA1) - EMA2 EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1) */ -public class HEMA_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private double _k1, _k2, _k3; - private int _len; - private double _lastema1, _oldema1; - private double _lastema2, _oldema2; - private double _lasthema, _oldhema; +public class HEMA_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private double _k1, _k2, _k3; + private int _len; + private double _lastema1, _oldema1; + private double _lastema2, _oldema2; + private double _lasthema, _oldhema; - //core constructors - public HEMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"HEMA({period})"; - (_k1, _k2, _k3) = CalculateK(_period); - _len = 0; - _lastema1 = _oldema1 = _lastema2 = _oldema2 = _lasthema = _oldhema = 0; - } - public HEMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public HEMA_Series() : this(period: 0, useNaN: false) { } - public HEMA_Series(int period) : this(period: period, useNaN: false) { } - public HEMA_Series(TBars source) : this(source.Close, 0, false) { } - public HEMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public HEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public HEMA_Series(TSeries source) : this(source, 0, false) { } - public HEMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public HEMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"HEMA({period})"; + (_k1, _k2, _k3) = CalculateK(_period); + _len = 0; + _lastema1 = _oldema1 = _lastema2 = _oldema2 = _lasthema = _oldhema = 0; + } + public HEMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public HEMA_Series() : this(period: 0, useNaN: false) { } + public HEMA_Series(int period) : this(period: period, useNaN: false) { } + public HEMA_Series(TBars source) : this(source.Close, 0, false) { } + public HEMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public HEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public HEMA_Series(TSeries source) : this(source, 0, false) { } + public HEMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - _lastema1 = _oldema1; - _lastema2 = _oldema2; - _lasthema = _oldhema; - } - else { - _oldema1 = _lastema1; - _oldema2 = _lastema2; - _oldhema = _lasthema; - } - double _ema1, _ema2, _hema; - if (_period == 0) { - _len++; - (_k1, _k2, _k3) = CalculateK(_len); - } - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, double.NaN), update); - } else if (this.Count == 0) { - _ema1 = _ema2 = _hema = TValue.v; - } - else { - _ema1 = _k1 * (TValue.v - _lastema1) + _lastema1; - _ema2 = _k2 * (TValue.v - _lastema2) + _lastema2; - _hema = _k3 * (((2 * _ema1) - _ema2) - _lasthema) + _lasthema; - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + _lastema1 = _oldema1; + _lastema2 = _oldema2; + _lasthema = _oldhema; + } + else + { + _oldema1 = _lastema1; + _oldema2 = _lastema2; + _oldhema = _lasthema; + } + double _ema1, _ema2, _hema; + if (_period == 0) + { + _len++; + (_k1, _k2, _k3) = CalculateK(_len); + } + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, double.NaN), update); + } + else if (this.Count == 0) + { + _ema1 = _ema2 = _hema = TValue.v; + } + else + { + _ema1 = _k1 * (TValue.v - _lastema1) + _lastema1; + _ema2 = _k2 * (TValue.v - _lastema2) + _lastema2; + _hema = _k3 * (((2 * _ema1) - _ema2) - _lasthema) + _lasthema; + } - _lastema1 = _ema1; - _lastema2 = _ema2; - _lasthema = _hema; + _lastema1 = _ema1; + _lastema2 = _ema2; + _lasthema = _hema; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hema); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hema); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _lastema1 = _lastema2 = _lasthema = 0; - _oldema1 = _oldema2 = _oldhema = 0; - _len = 0; - } + //reset calculation + public override void Reset() + { + _lastema1 = _lastema2 = _lasthema = 0; + _oldema1 = _oldema2 = _oldhema = 0; + _len = 0; + } - public static (double k1, double k2, double k3) CalculateK(int len) { - double k1 = 8 / (double)(len + 7); - double k2 = 3 / (double)(len + 2); - double k3 = 2 / Math.Sqrt(len + 3); + public static (double k1, double k2, double k3) CalculateK(int len) + { + double k1 = 8 / (double)(len + 7); + double k2 = 3 / (double)(len + 2); + double k3 = 2 / Math.Sqrt(len + 3); - return (k1, k2, k3); - } + return (k1, k2, k3); + } } \ No newline at end of file diff --git a/Calculations/_Updated/HMA_Series.cs b/Calculations/_Updated/HMA_Series.cs index 01736639..4401886e 100644 --- a/Calculations/_Updated/HMA_Series.cs +++ b/Calculations/_Updated/HMA_Series.cs @@ -18,71 +18,81 @@ HMA = WMA(sqrt(n)) of Raw HMA */ -public class HMA_Series : TSeries { - protected int _period, _period2, _psqrt; - protected readonly bool _NaN; - protected readonly TSeries _data; - protected WMA_Series _wma1, _wma2, _wma3; +public class HMA_Series : TSeries +{ + protected int _period, _period2, _psqrt; + protected readonly bool _NaN; + protected readonly TSeries _data; + protected WMA_Series _wma1, _wma2, _wma3; - //core constructors - public HMA_Series(int period, bool useNaN) { - _period = period; - _period2 = period /2; - _psqrt = (int)Math.Sqrt(period); - _NaN = useNaN; - _wma1 = new(Math.Max(_period2,1), false); - _wma2 = new(Math.Max(_period,1), false); - _wma3 = new(Math.Max(_psqrt,1), useNaN); - Name = $"HMA({period})"; - } - public HMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public HMA_Series() : this(period: 0, useNaN: false) { } - public HMA_Series(int period) : this(period: period, useNaN: false) { } - public HMA_Series(TBars source) : this(source.Close, 0, false) { } - public HMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public HMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public HMA_Series(TSeries source) : this(source, 0, false) { } - public HMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public HMA_Series(int period, bool useNaN) + { + _period = period; + _period2 = period / 2; + _psqrt = (int)Math.Sqrt(period); + _NaN = useNaN; + _wma1 = new(Math.Max(_period2, 1), false); + _wma2 = new(Math.Max(_period, 1), false); + _wma3 = new(Math.Max(_psqrt, 1), useNaN); + Name = $"HMA({period})"; + } + public HMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public HMA_Series() : this(period: 0, useNaN: false) { } + public HMA_Series(int period) : this(period: period, useNaN: false) { } + public HMA_Series(TBars source) : this(source.Close, 0, false) { } + public HMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public HMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public HMA_Series(TSeries source) : this(source, 0, false) { } + public HMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (_period == 0) { - _wma1.Len = this.Count / 2; - _wma2.Len = this.Count; - _wma1.Len = (int)Math.Sqrt(this.Count); - } - double _w1 = _wma1.Add(TValue, update).v; - double _w2 = _wma2.Add(TValue, update).v; - double _hma = _wma3.Add((2 * _w1) - _w2, update).v; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hma); - return base.Add(res, update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (_period == 0) + { + _wma1.Len = this.Count / 2; + _wma2.Len = this.Count; + _wma1.Len = (int)Math.Sqrt(this.Count); + } + double _w1 = _wma1.Add(TValue, update).v; + double _w2 = _wma2.Add(TValue, update).v; + double _hma = _wma3.Add((2 * _w1) - _w2, update).v; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hma); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _wma1.Reset(); - _wma2.Reset(); - _wma3.Reset(); - } + //reset calculation + public override void Reset() + { + _wma1.Reset(); + _wma2.Reset(); + _wma3.Reset(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/HWMA_Series.cs b/Calculations/_Updated/HWMA_Series.cs index 8f360b52..6e3f7896 100644 --- a/Calculations/_Updated/HWMA_Series.cs +++ b/Calculations/_Updated/HWMA_Series.cs @@ -31,102 +31,116 @@ HWMA[i] = F[i] + V[i] + 0.5 * A[i] */ -public class HWMA_Series : TSeries { - private int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - double _nA, _nB, _nC; - double _pF, _pV, _pA; - double _ppF, _ppV, _ppA; +public class HWMA_Series : TSeries +{ + private int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + double _nA, _nB, _nC; + double _pF, _pV, _pA; + double _ppF, _ppV, _ppA; - //core constructors + //core constructors - public HWMA_Series(double nA, double nB, double nC, bool useNaN) { - _period = (int)((2 - nA) / nA); - _nA = nA; - _nB = nB; - _nC = nC; - _NaN = useNaN; - Name = $"HWMA({_period})"; - _len = 0; - } - public HWMA_Series(TSeries source, double nA, double nB, double nC, bool useNaN = false) : this(nA, nB, nC, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public HWMA_Series() : this(period: 0, useNaN: false) { } - public HWMA_Series(int period) : this(period, useNaN: false) { } - public HWMA_Series(int period, bool useNaN) : this(nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN) { - _period = period; - } - public HWMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { } - public HWMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public HWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public HWMA_Series(TSeries source, int period) : this(source, period, false) { } - public HWMA_Series(TSeries source, int period, bool useNaN) : this(source, nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN: useNaN) { } + public HWMA_Series(double nA, double nB, double nC, bool useNaN) + { + _period = (int)((2 - nA) / nA); + _nA = nA; + _nB = nB; + _nC = nC; + _NaN = useNaN; + Name = $"HWMA({_period})"; + _len = 0; + } + public HWMA_Series(TSeries source, double nA, double nB, double nC, bool useNaN = false) : this(nA, nB, nC, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public HWMA_Series() : this(period: 0, useNaN: false) { } + public HWMA_Series(int period) : this(period, useNaN: false) { } + public HWMA_Series(int period, bool useNaN) : this(nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN) + { + _period = period; + } + public HWMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { } + public HWMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public HWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public HWMA_Series(TSeries source, int period) : this(source, period, false) { } + public HWMA_Series(TSeries source, int period, bool useNaN) : this(source, nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN: useNaN) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } - double _F, _V, _A; - if (_len == 0) { _pF = TValue.v; _pA = _pV = 0; } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } + double _F, _V, _A; + if (_len == 0) { _pF = TValue.v; _pA = _pV = 0; } - if (update) { _pF = _ppF; _pV = _ppV; _pA = _ppA; } - else { - _ppF = _pF; - _ppV = _pV; - _ppA = _pA; - _len++; - } + if (update) { _pF = _ppF; _pV = _ppV; _pA = _ppA; } + else + { + _ppF = _pF; + _ppV = _pV; + _ppA = _pA; + _len++; + } - if (_period == 0) { - _nA = 2 / (1 + (double)_len); - _nB = 1 / (double)_len; - _nC = 1 / (double)_len; - } - if (_period == 1) { - _nA = 1; - _nB = 0; - _nC = 0; - } + if (_period == 0) + { + _nA = 2 / (1 + (double)_len); + _nB = 1 / (double)_len; + _nC = 1 / (double)_len; + } + if (_period == 1) + { + _nA = 1; + _nB = 0; + _nC = 0; + } - _F = (1 - _nA) * (_pF + _pV + 0.5 * _pA) + _nA * TValue.v; - _V = (1 - _nB) * (_pV + _pA) + _nB * (_F - _pF); - _A = (1 - _nC) * _pA + _nC * (_V - _pV); + _F = (1 - _nA) * (_pF + _pV + 0.5 * _pA) + _nA * TValue.v; + _V = (1 - _nB) * (_pV + _pA) + _nB * (_F - _pF); + _A = (1 - _nC) * _pA + _nC * (_V - _pV); - double _hwma = _F + _V + 0.5 * _A; - _pF = _F; - _pV = _V; - _pA = _A; + double _hwma = _F + _V + 0.5 * _A; + _pF = _F; + _pV = _V; + _pA = _A; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hwma); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _hwma); + return base.Add(res, update); + } - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _len = 0; - } + //reset calculation + public override void Reset() + { + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/KAMA_Series.cs b/Calculations/_Updated/KAMA_Series.cs index 74065605..ae3a96cd 100644 --- a/Calculations/_Updated/KAMA_Series.cs +++ b/Calculations/_Updated/KAMA_Series.cs @@ -24,84 +24,95 @@ Remark: */ -public class KAMA_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - private double _lastkama, _lastlastkama; - private readonly double _scFast, _scSlow; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class KAMA_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + private double _lastkama, _lastlastkama; + private readonly double _scFast, _scSlow; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public KAMA_Series(int period, int fast, int slow, bool useNaN) { - _period = period; - _NaN = useNaN; - _scFast = 2.0 / (((period < fast) ? period : fast) + 1); - _scSlow = 2.0 / (slow + 1); - _lastkama = _lastlastkama = 0; - Name = $"KAMA({period})"; - } - public KAMA_Series(TSeries source, int period, int fast, int slow, bool useNaN) : this(period, fast, slow, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public KAMA_Series() : this(period: 0, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(int period) : this(period: period, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(TBars source) : this(source.Close, period: 0, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(TBars source, int period) : this(source.Close, period: period, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, fast: 2, slow: 30, useNaN: useNaN) { } - public KAMA_Series(TSeries source) : this(source, period: 0, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(TSeries source, int period) : this(source: source, period: period, fast: 2, slow: 30, useNaN: false) { } - public KAMA_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, fast: 2, slow: 30, useNaN: useNaN) { } - public KAMA_Series(TSeries source, int period, int fast, int slow) : this(source: source, period: period, fast: fast, slow: slow, useNaN: false) { } + //core constructors + public KAMA_Series(int period, int fast, int slow, bool useNaN) + { + _period = period; + _NaN = useNaN; + _scFast = 2.0 / (((period < fast) ? period : fast) + 1); + _scSlow = 2.0 / (slow + 1); + _lastkama = _lastlastkama = 0; + Name = $"KAMA({period})"; + } + public KAMA_Series(TSeries source, int period, int fast, int slow, bool useNaN) : this(period, fast, slow, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public KAMA_Series() : this(period: 0, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(int period) : this(period: period, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(TBars source) : this(source.Close, period: 0, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(TBars source, int period) : this(source.Close, period: period, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period: period, fast: 2, slow: 30, useNaN: useNaN) { } + public KAMA_Series(TSeries source) : this(source, period: 0, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(TSeries source, int period) : this(source: source, period: period, fast: 2, slow: 30, useNaN: false) { } + public KAMA_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, fast: 2, slow: 30, useNaN: useNaN) { } + public KAMA_Series(TSeries source, int period, int fast, int slow) : this(source: source, period: period, fast: fast, slow: slow, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } - if (update) { _lastkama = _lastlastkama; } - else { _lastlastkama = _lastkama; } - BufferTrim(buffer: _buffer, value: TValue.v, period: _period + 1, update: update); + if (update) { _lastkama = _lastlastkama; } + else { _lastlastkama = _lastkama; } + BufferTrim(buffer: _buffer, value: TValue.v, period: _period + 1, update: update); - double _kama = 0; - if (this.Count < _period) { _kama = TValue.v; } - else { - double _change = Math.Abs(_buffer[^1] - _buffer[(_buffer.Count > _period + 1) ? 1 : 0]); - double _sumpv = 0; - for (int i = 1; i < _buffer.Count; i++) { _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); } - double _er = (_sumpv == 0) ? 0 : _change / _sumpv; - double _sc = (_er * (_scFast - _scSlow)) + _scSlow; - _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama))); - } - _lastkama = _kama; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _kama); - return base.Add(res, update); - } + double _kama = 0; + if (this.Count < _period) { _kama = TValue.v; } + else + { + double _change = Math.Abs(_buffer[^1] - _buffer[(_buffer.Count > _period + 1) ? 1 : 0]); + double _sumpv = 0; + for (int i = 1; i < _buffer.Count; i++) { _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); } + double _er = (_sumpv == 0) ? 0 : _change / _sumpv; + double _sc = (_er * (_scFast - _scSlow)) + _scSlow; + _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama))); + } + _lastkama = _kama; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _kama); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - _lastkama = _lastlastkama = 0; - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + _lastkama = _lastlastkama = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/KURTOSIS_Series.cs b/Calculations/_Updated/KURTOSIS_Series.cs index 2c4e10c8..bfc972af 100644 --- a/Calculations/_Updated/KURTOSIS_Series.cs +++ b/Calculations/_Updated/KURTOSIS_Series.cs @@ -25,72 +25,83 @@ Sources: */ -public class KURTOSIS_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly System.Collections.Generic.List _buffer = new(); +public class KURTOSIS_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly System.Collections.Generic.List _buffer = new(); - //core constructors - public KURTOSIS_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"KURTOSIS({period})"; - } - public KURTOSIS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public KURTOSIS_Series() : this(period: 0, useNaN: false) { } - public KURTOSIS_Series(int period) : this(period: period, useNaN: false) { } - public KURTOSIS_Series(TSeries source) : this(source, period: 0, useNaN: false) { } - public KURTOSIS_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public KURTOSIS_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"KURTOSIS({period})"; + } + public KURTOSIS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public KURTOSIS_Series() : this(period: 0, useNaN: false) { } + public KURTOSIS_Series(int period) : this(period: period, useNaN: false) { } + public KURTOSIS_Series(TSeries source) : this(source, period: 0, useNaN: false) { } + public KURTOSIS_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _n = _buffer.Count; - double _avg = _buffer.Average(); + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + double _n = _buffer.Count; + double _avg = _buffer.Average(); - double _s2 = 0; - double _s4 = 0; - for (int i = 0; i < this._buffer.Count; i++) { - _s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg); - _s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg); - } + double _s2 = 0; + double _s4 = 0; + for (int i = 0; i < this._buffer.Count; i++) + { + _s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg); + _s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg); + } - double _Vx = _s2 / (_n - 1); - double _kurt = (_n > 3) ? - (_n * (_n + 1) * _s4) / (_Vx * _Vx * (_n - 3) * (_n - 1) * (_n - 2)) - (3 * (_n - 1) * (_n - 1) / ((_n - 2) * (_n - 3))) //using Sheskin Algo - : (_s2 * _s2) / _n - 3; //using Snedecor and Cochran (1967) algo - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _kurt); - return base.Add(res, update); - } + double _Vx = _s2 / (_n - 1); + double _kurt = (_n > 3) ? + (_n * (_n + 1) * _s4) / (_Vx * _Vx * (_n - 3) * (_n - 1) * (_n - 2)) - (3 * (_n - 1) * (_n - 1) / ((_n - 2) * (_n - 3))) //using Sheskin Algo + : (_s2 * _s2) / _n - 3; //using Snedecor and Cochran (1967) algo + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _kurt); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MACD_Series.cs b/Calculations/_Updated/MACD_Series.cs index 20d8c86b..251f6577 100644 --- a/Calculations/_Updated/MACD_Series.cs +++ b/Calculations/_Updated/MACD_Series.cs @@ -11,68 +11,78 @@ MACD: Moving Average Convergence/Divergence */ -public class MACD_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); +public class MACD_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _slow, _fast, _signal; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly EMA_Series _TSlow; - private readonly EMA_Series _TFast; - public EMA_Series Signal { get; } + protected readonly int _slow, _fast, _signal; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly EMA_Series _TSlow; + private readonly EMA_Series _TFast; + public EMA_Series Signal { get; } - //core constructors - public MACD_Series(int slow = 26, int fast = 12, int signal = 9, bool useNaN = false) { - _slow = slow; - _fast = fast; - _signal = signal; - _NaN = useNaN; - Name = $"MACD({slow},{fast},{signal})"; - _TSlow = new(slow, useNaN:false, useSMA:true); - _TFast = new(fast, useNaN: false, useSMA: true); - Signal = new(signal, useNaN: false, useSMA: true); - } - public MACD_Series(TSeries source, int slow, int fast, int signal, bool useNaN) : this(slow, fast, signal, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MACD_Series(TSeries source) : this(source:source, slow:26, fast:12, signal:9 , useNaN:false) { } - public MACD_Series(TSeries source, int slow, int fast, int signal) : this(source: source, slow: slow, fast:fast, signal:signal, useNaN: false) { } + //core constructors + public MACD_Series(int slow = 26, int fast = 12, int signal = 9, bool useNaN = false) + { + _slow = slow; + _fast = fast; + _signal = signal; + _NaN = useNaN; + Name = $"MACD({slow},{fast},{signal})"; + _TSlow = new(slow, useNaN: false, useSMA: true); + _TFast = new(fast, useNaN: false, useSMA: true); + Signal = new(signal, useNaN: false, useSMA: true); + } + public MACD_Series(TSeries source, int slow, int fast, int signal, bool useNaN) : this(slow, fast, signal, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MACD_Series(TSeries source) : this(source: source, slow: 26, fast: 12, signal: 9, useNaN: false) { } + public MACD_Series(TSeries source, int slow, int fast, int signal) : this(source: source, slow: slow, fast: fast, signal: signal, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } - var _sslow = _TSlow.Add(TValue,update); - var _sfast = _TFast.Add(TValue, update); - Signal.Add((TValue.t, _sfast.v-_sslow.v)); + var _sslow = _TSlow.Add(TValue, update); + var _sfast = _TFast.Add(TValue, update); + Signal.Add((TValue.t, _sfast.v - _sslow.v)); - var res = (TValue.t, Count < _fast - 1 && _NaN ? double.NaN : _sfast.v-_sslow.v); - return base.Add(res, update); - } + var res = (TValue.t, Count < _fast - 1 && _NaN ? double.NaN : _sfast.v - _sslow.v); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MAD_Series.cs b/Calculations/_Updated/MAD_Series.cs index 4f18a04b..3ba8ca1b 100644 --- a/Calculations/_Updated/MAD_Series.cs +++ b/Calculations/_Updated/MAD_Series.cs @@ -17,63 +17,72 @@ Sources: */ -public class MAD_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MAD_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MAD_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MAD({period})"; - } - public MAD_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MAD_Series() : this(period: 0, useNaN: false) { } - public MAD_Series(int period) : this(period: period, useNaN: false) { } - public MAD_Series(TBars source) : this(source.Close, 0, false) { } - public MAD_Series(TBars source, int period) : this(source.Close, period, false) { } - public MAD_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MAD_Series(TSeries source) : this(source, 0, false) { } - public MAD_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MAD_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MAD({period})"; + } + public MAD_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MAD_Series() : this(period: 0, useNaN: false) { } + public MAD_Series(int period) : this(period: period, useNaN: false) { } + public MAD_Series(TBars source) : this(source.Close, 0, false) { } + public MAD_Series(TBars source, int period) : this(source.Close, period, false) { } + public MAD_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MAD_Series(TSeries source) : this(source, 0, false) { } + public MAD_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); - double _mad = 0; - for (int i = 0; i < _buffer.Count; i++) { _mad += Math.Abs(_buffer[i] - _sma); } - _mad /= this._buffer.Count; + double _sma = _buffer.Average(); + double _mad = 0; + for (int i = 0; i < _buffer.Count; i++) { _mad += Math.Abs(_buffer[i] - _sma); } + _mad /= this._buffer.Count; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mad); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mad); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MAE_Series.cs b/Calculations/_Updated/MAE_Series.cs index 9bf7a6a9..7a8d05f6 100644 --- a/Calculations/_Updated/MAE_Series.cs +++ b/Calculations/_Updated/MAE_Series.cs @@ -14,64 +14,73 @@ Sources: */ -public class MAE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MAE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MAE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MSE({period})"; - } - public MAE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MAE_Series() : this(period: 0, useNaN: false) { } - public MAE_Series(int period) : this(period: period, useNaN: false) { } - public MAE_Series(TBars source) : this(source.Close, 0, false) { } - public MAE_Series(TBars source, int period) : this(source.Close, period, false) { } - public MAE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MAE_Series(TSeries source) : this(source, 0, false) { } - public MAE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MAE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MSE({period})"; + } + public MAE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MAE_Series() : this(period: 0, useNaN: false) { } + public MAE_Series(int period) : this(period: period, useNaN: false) { } + public MAE_Series(TBars source) : this(source.Close, 0, false) { } + public MAE_Series(TBars source, int period) : this(source.Close, period, false) { } + public MAE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MAE_Series(TSeries source) : this(source, 0, false) { } + public MAE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _mae = 0; - for (int i = 0; i < _buffer.Count; i++) { _mae += Math.Abs(_buffer[i] - _sma); } - _mae /= this._buffer.Count; + double _mae = 0; + for (int i = 0; i < _buffer.Count; i++) { _mae += Math.Abs(_buffer[i] - _sma); } + _mae /= this._buffer.Count; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mae); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mae); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MAMA_Series.cs b/Calculations/_Updated/MAMA_Series.cs index c4dd2a51..e450337a 100644 --- a/Calculations/_Updated/MAMA_Series.cs +++ b/Calculations/_Updated/MAMA_Series.cs @@ -17,173 +17,191 @@ Sources: */ -public class MAMA_Series : TSeries { - private int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MAMA_Series : TSeries +{ + private int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - private double sumPr; - private double fastl, slowl; - private (double i, double i1, double i2, double i3, double i4, double i5, double i6, double io) pr, i1, q1, sm, dt; - private (double i, double i1, double io) i2, q2, re, im, pd, ph, mama, fama; - public TSeries Fama { get; } - private double mamaseed, famaseed; + private double sumPr; + private double fastl, slowl; + private (double i, double i1, double i2, double i3, double i4, double i5, double i6, double io) pr, i1, q1, sm, dt; + private (double i, double i1, double io) i2, q2, re, im, pd, ph, mama, fama; + public TSeries Fama { get; } + private double mamaseed, famaseed; - //core constructors + //core constructors - public MAMA_Series(double fastlimit, double slowlimit, bool useNaN) { - _period = (int)(2 / fastlimit) - 1; - fastl = fastlimit; - slowl = slowlimit; - Fama = new TSeries(); - _NaN = useNaN; - Name = $"MAMA({_period})"; - _len = 0; - } - public MAMA_Series(TSeries source, double fastlimit, double slowlimit, bool useNaN = false) : this(fastlimit, slowlimit, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MAMA_Series() : this(period: 0, useNaN: false) { } - public MAMA_Series(int period) : this(period, useNaN: false) { } - public MAMA_Series(int period, bool useNaN) : this(fastlimit: 2 / (period + 1), slowlimit: 0.2 / (period + 1), useNaN) { - _period = period; - } - public MAMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { } - public MAMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public MAMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MAMA_Series(TSeries source, int period) : this(source, period, false) { } - public MAMA_Series(TSeries source, int period, bool useNaN) : this(source, fastlimit: 2 / ((double)period + 1), slowlimit: 0.2 / ((double)period + 1), useNaN: useNaN) { } + public MAMA_Series(double fastlimit, double slowlimit, bool useNaN) + { + _period = (int)(2 / fastlimit) - 1; + fastl = fastlimit; + slowl = slowlimit; + Fama = new TSeries(); + _NaN = useNaN; + Name = $"MAMA({_period})"; + _len = 0; + } + public MAMA_Series(TSeries source, double fastlimit, double slowlimit, bool useNaN = false) : this(fastlimit, slowlimit, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MAMA_Series() : this(period: 0, useNaN: false) { } + public MAMA_Series(int period) : this(period, useNaN: false) { } + public MAMA_Series(int period, bool useNaN) : this(fastlimit: 2 / (period + 1), slowlimit: 0.2 / (period + 1), useNaN) + { + _period = period; + } + public MAMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { } + public MAMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public MAMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MAMA_Series(TSeries source, int period) : this(source, period, false) { } + public MAMA_Series(TSeries source, int period, bool useNaN) : this(source, fastlimit: 2 / ((double)period + 1), slowlimit: 0.2 / ((double)period + 1), useNaN: useNaN) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } - if (!update) { - // roll forward (oldx = x) - pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i; - i1.io = i1.i6; i1.i6 = i1.i5; i1.i5 = i1.i4; i1.i4 = i1.i3; i1.i3 = i1.i2; i1.i2 = i1.i1; i1.i1 = i1.i; - q1.io = q1.i6; q1.i6 = q1.i5; q1.i5 = q1.i4; q1.i4 = q1.i3; q1.i3 = q1.i2; q1.i2 = q1.i1; q1.i1 = q1.i; - dt.io = dt.i6; dt.i6 = dt.i5; dt.i5 = dt.i4; dt.i4 = dt.i3; dt.i3 = dt.i2; dt.i2 = dt.i1; dt.i1 = dt.i; - sm.io = sm.i6; sm.i6 = sm.i5; sm.i5 = sm.i4; sm.i4 = sm.i3; sm.i3 = sm.i2; sm.i2 = sm.i1; sm.i1 = sm.i; - i2.io = i2.i1; i2.i1 = i2.i; q2.io = q2.i1; q2.i1 = q2.i; - re.io = re.i1; re.i1 = re.i; im.io = im.i1; im.i1 = im.i; - pd.io = pd.i1; pd.i1 = pd.i; ph.io = ph.i1; ph.i1 = ph.i; - mama.io = mama.i1; mama.i1 = mama.i; - fama.io = fama.i1; - fama.i1 = fama.i; - _len++; - } - if (_period == 0) { - fastl = 2 / (double)_len; - slowl = fastl * 0.1; - } - if (_period == 1) { - fastl = 1; - slowl = 1; - } - var i = _len - 1; - pr.i = TValue.v; - if (i > 5) { - var adj = 0.075 * pd.i1 + 0.54; + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } + if (!update) + { + // roll forward (oldx = x) + pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i; + i1.io = i1.i6; i1.i6 = i1.i5; i1.i5 = i1.i4; i1.i4 = i1.i3; i1.i3 = i1.i2; i1.i2 = i1.i1; i1.i1 = i1.i; + q1.io = q1.i6; q1.i6 = q1.i5; q1.i5 = q1.i4; q1.i4 = q1.i3; q1.i3 = q1.i2; q1.i2 = q1.i1; q1.i1 = q1.i; + dt.io = dt.i6; dt.i6 = dt.i5; dt.i5 = dt.i4; dt.i4 = dt.i3; dt.i3 = dt.i2; dt.i2 = dt.i1; dt.i1 = dt.i; + sm.io = sm.i6; sm.i6 = sm.i5; sm.i5 = sm.i4; sm.i4 = sm.i3; sm.i3 = sm.i2; sm.i2 = sm.i1; sm.i1 = sm.i; + i2.io = i2.i1; i2.i1 = i2.i; q2.io = q2.i1; q2.i1 = q2.i; + re.io = re.i1; re.i1 = re.i; im.io = im.i1; im.i1 = im.i; + pd.io = pd.i1; pd.i1 = pd.i; ph.io = ph.i1; ph.i1 = ph.i; + mama.io = mama.i1; mama.i1 = mama.i; + fama.io = fama.i1; + fama.i1 = fama.i; + _len++; + } + if (_period == 0) + { + fastl = 2 / (double)_len; + slowl = fastl * 0.1; + } + if (_period == 1) + { + fastl = 1; + slowl = 1; + } + var i = _len - 1; + pr.i = TValue.v; + if (i > 5) + { + var adj = 0.075 * pd.i1 + 0.54; - // smooth and detrender - sm.i = (4 * pr.i + 3 * pr.i1 + 2 * pr.i2 + pr.i3) / 10; - dt.i = (0.0962 * sm.i + 0.5769 * sm.i2 - 0.5769 * sm.i4 - 0.0962 * sm.i6) * adj; + // smooth and detrender + sm.i = (4 * pr.i + 3 * pr.i1 + 2 * pr.i2 + pr.i3) / 10; + dt.i = (0.0962 * sm.i + 0.5769 * sm.i2 - 0.5769 * sm.i4 - 0.0962 * sm.i6) * adj; - // in-phase and quadrature - q1.i = (0.0962 * dt.i + 0.5769 * dt.i2 - 0.5769 * dt.i4 - 0.0962 * dt.i6) * adj; - i1.i = dt.i3; + // in-phase and quadrature + q1.i = (0.0962 * dt.i + 0.5769 * dt.i2 - 0.5769 * dt.i4 - 0.0962 * dt.i6) * adj; + i1.i = dt.i3; - // advance the phases by 90 degrees - double jI = (0.0962 * i1.i + 0.5769 * i1.i2 - 0.5769 * i1.i4 - 0.0962 * i1.i6) * adj; - double jQ = (0.0962 * q1.i + 0.5769 * q1.i2 - 0.5769 * q1.i4 - 0.0962 * q1.i6) * adj; + // advance the phases by 90 degrees + double jI = (0.0962 * i1.i + 0.5769 * i1.i2 - 0.5769 * i1.i4 - 0.0962 * i1.i6) * adj; + double jQ = (0.0962 * q1.i + 0.5769 * q1.i2 - 0.5769 * q1.i4 - 0.0962 * q1.i6) * adj; - // phasor addition for 3-bar averaging - i2.i = i1.i - jQ; - q2.i = q1.i + jI; + // phasor addition for 3-bar averaging + i2.i = i1.i - jQ; + q2.i = q1.i + jI; - i2.i = 0.2 * i2.i + 0.8 * i2.i1; // smoothing it - q2.i = 0.2 * q2.i + 0.8 * q2.i1; + i2.i = 0.2 * i2.i + 0.8 * i2.i1; // smoothing it + q2.i = 0.2 * q2.i + 0.8 * q2.i1; - // homodyne discriminator - re.i = i2.i * i2.i1 + q2.i * q2.i1; - im.i = i2.i * q2.i1 - q2.i * i2.i1; + // homodyne discriminator + re.i = i2.i * i2.i1 + q2.i * q2.i1; + im.i = i2.i * q2.i1 - q2.i * i2.i1; - re.i = 0.2 * re.i + 0.8 * re.i1; // smoothing it - im.i = 0.2 * im.i + 0.8 * im.i1; + re.i = 0.2 * re.i + 0.8 * re.i1; // smoothing it + im.i = 0.2 * im.i + 0.8 * im.i1; - // calculate period - pd.i = im.i != 0 && re.i != 0 ? 6.283185307179586 / Math.Atan(im.i / re.i) : 0d; + // calculate period + pd.i = im.i != 0 && re.i != 0 ? 6.283185307179586 / Math.Atan(im.i / re.i) : 0d; - // adjust period to thresholds - pd.i = pd.i > 1.5 * pd.i1 ? 1.5 * pd.i1 : pd.i; - pd.i = pd.i < 0.67 * pd.i1 ? 0.67 * pd.i1 : pd.i; - pd.i = pd.i < 6d ? 6d : pd.i; - pd.i = pd.i > 50d ? 50d : pd.i; + // adjust period to thresholds + pd.i = pd.i > 1.5 * pd.i1 ? 1.5 * pd.i1 : pd.i; + pd.i = pd.i < 0.67 * pd.i1 ? 0.67 * pd.i1 : pd.i; + pd.i = pd.i < 6d ? 6d : pd.i; + pd.i = pd.i > 50d ? 50d : pd.i; - // smooth the period - pd.i = 0.2 * pd.i + 0.8 * pd.i1; + // smooth the period + pd.i = 0.2 * pd.i + 0.8 * pd.i1; - // determine phase position - ph.i = i1.i != 0 ? Math.Atan(q1.i / i1.i) * 57.29577951308232 : 0; + // determine phase position + ph.i = i1.i != 0 ? Math.Atan(q1.i / i1.i) * 57.29577951308232 : 0; - // change in phase - var delta = Math.Max(ph.i1 - ph.i, 1d); + // change in phase + var delta = Math.Max(ph.i1 - ph.i, 1d); - // adaptive alpha value - var alpha = Math.Max(fastl / delta, slowl); + // adaptive alpha value + var alpha = Math.Max(fastl / delta, slowl); - // final indicators - mama.i = alpha * (pr.i - mama.i1) + mama.i1; - fama.i = 0.5d * alpha * (mama.i - fama.i1) + fama.i1; - } - else { - sumPr += pr.i; - pd.i = sm.i = dt.i = i1.i = q1.i = i2.i = q2.i = re.i = im.i = ph.i = 0; - mama.i = fama.i = sumPr / (i + 1); + // final indicators + mama.i = alpha * (pr.i - mama.i1) + mama.i1; + fama.i = 0.5d * alpha * (mama.i - fama.i1) + fama.i1; + } + else + { + sumPr += pr.i; + pd.i = sm.i = dt.i = i1.i = q1.i = i2.i = q2.i = re.i = im.i = ph.i = 0; + mama.i = fama.i = sumPr / (i + 1); - if (_len == 1) { - mamaseed = famaseed = TValue.v; - } - else { - mamaseed = fastl * (TValue.v - mamaseed) + mamaseed; - famaseed = slowl * (TValue.v - famaseed) + famaseed; - } - } + if (_len == 1) + { + mamaseed = famaseed = TValue.v; + } + else + { + mamaseed = fastl * (TValue.v - mamaseed) + mamaseed; + famaseed = slowl * (TValue.v - famaseed) + famaseed; + } + } - double _fama = (i > 5) ? fama.i : famaseed; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _fama); - Fama.Add(res, update); - double _mama = (i > 5) ? mama.i : mamaseed; - res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mama); - return base.Add(res, update); - } + double _fama = (i > 5) ? fama.i : famaseed; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _fama); + Fama.Add(res, update); + double _mama = (i > 5) ? mama.i : mamaseed; + res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mama); + return base.Add(res, update); + } - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _len = 0; - } + //reset calculation + public override void Reset() + { + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/MAPE_Series.cs b/Calculations/_Updated/MAPE_Series.cs index 944daf86..b2869c63 100644 --- a/Calculations/_Updated/MAPE_Series.cs +++ b/Calculations/_Updated/MAPE_Series.cs @@ -20,66 +20,76 @@ Remark: */ -public class MAPE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MAPE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MAPE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MAPE({period})"; - } - public MAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MAPE_Series() : this(period: 0, useNaN: false) { } - public MAPE_Series(int period) : this(period: period, useNaN: false) { } - public MAPE_Series(TBars source) : this(source.Close, 0, false) { } - public MAPE_Series(TBars source, int period) : this(source.Close, period, false) { } - public MAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MAPE_Series(TSeries source) : this(source, 0, false) { } - public MAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MAPE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MAPE({period})"; + } + public MAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MAPE_Series() : this(period: 0, useNaN: false) { } + public MAPE_Series(int period) : this(period: period, useNaN: false) { } + public MAPE_Series(TBars source) : this(source.Close, 0, false) { } + public MAPE_Series(TBars source, int period) : this(source.Close, period, false) { } + public MAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MAPE_Series(TSeries source) : this(source, 0, false) { } + public MAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _mape = 0; - for (int i = 0; i < _buffer.Count; i++) { - _mape += (_buffer[i] != 0) ? Math.Abs(_buffer[i] - _sma) / Math.Abs(_buffer[i]) : double.PositiveInfinity; - } - _mape /= (_buffer.Count > 0) ? _buffer.Count : 1; + double _mape = 0; + for (int i = 0; i < _buffer.Count; i++) + { + _mape += (_buffer[i] != 0) ? Math.Abs(_buffer[i] - _sma) / Math.Abs(_buffer[i]) : double.PositiveInfinity; + } + _mape /= (_buffer.Count > 0) ? _buffer.Count : 1; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mape); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mape); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MAX_Series.cs b/Calculations/_Updated/MAX_Series.cs index 8a2facff..4c96e41e 100644 --- a/Calculations/_Updated/MAX_Series.cs +++ b/Calculations/_Updated/MAX_Series.cs @@ -10,59 +10,68 @@ MAX - Maximum value in the given period in the series. */ -public class MAX_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MAX_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MAX_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MAX({period})"; - } - public MAX_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MAX_Series() : this(period: 0, useNaN: false) { } - public MAX_Series(int period) : this(period: period, useNaN: false) { } - public MAX_Series(TBars source) : this(source.Close, 0, false) { } - public MAX_Series(TBars source, int period) : this(source.Close, period, false) { } - public MAX_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MAX_Series(TSeries source) : this(source, 0, false) { } - public MAX_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MAX_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MAX({period})"; + } + public MAX_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MAX_Series() : this(period: 0, useNaN: false) { } + public MAX_Series(int period) : this(period: period, useNaN: false) { } + public MAX_Series(TBars source) : this(source.Close, 0, false) { } + public MAX_Series(TBars source, int period) : this(source.Close, period, false) { } + public MAX_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MAX_Series(TSeries source) : this(source, 0, false) { } + public MAX_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _max= _buffer.Max(); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _max); - return base.Add(res, update); - } + double _max = _buffer.Max(); + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _max); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MEDIAN_Series.cs b/Calculations/_Updated/MEDIAN_Series.cs index fde7c634..e896d1ce 100644 --- a/Calculations/_Updated/MEDIAN_Series.cs +++ b/Calculations/_Updated/MEDIAN_Series.cs @@ -23,64 +23,73 @@ Sources: */ -public class MEDIAN_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MEDIAN_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MEDIAN_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MEDIAN({period})"; - } - public MEDIAN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MEDIAN_Series() : this(period: 0, useNaN: false) { } - public MEDIAN_Series(int period) : this(period: period, useNaN: false) { } - public MEDIAN_Series(TBars source) : this(source.Close, 0, false) { } - public MEDIAN_Series(TBars source, int period) : this(source.Close, period, false) { } - public MEDIAN_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MEDIAN_Series(TSeries source) : this(source, 0, false) { } - public MEDIAN_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MEDIAN_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MEDIAN({period})"; + } + public MEDIAN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MEDIAN_Series() : this(period: 0, useNaN: false) { } + public MEDIAN_Series(int period) : this(period: period, useNaN: false) { } + public MEDIAN_Series(TBars source) : this(source.Close, 0, false) { } + public MEDIAN_Series(TBars source, int period) : this(source.Close, period, false) { } + public MEDIAN_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MEDIAN_Series(TSeries source) : this(source, 0, false) { } + public MEDIAN_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - System.Collections.Generic.List _s = new(this._buffer); - _s.Sort(); - int _p1 = _s.Count / 2; - int _p2 = Math.Max(0, (_s.Count / 2) - 1); - double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2; + System.Collections.Generic.List _s = new(this._buffer); + _s.Sort(); + int _p1 = _s.Count / 2; + int _p2 = Math.Max(0, (_s.Count / 2) - 1); + double _med = (_s.Count % 2 != 0) ? _s[_p1] : (_s[_p1] + _s[_p2]) / 2; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _med); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _med); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MIDPOINT_Series.cs b/Calculations/_Updated/MIDPOINT_Series.cs index c410be23..ca27243a 100644 --- a/Calculations/_Updated/MIDPOINT_Series.cs +++ b/Calculations/_Updated/MIDPOINT_Series.cs @@ -13,60 +13,69 @@ Sources: */ -public class MIDPOINT_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MIDPOINT_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MIDPOINT_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MIDPOINT({period})"; - } - public MIDPOINT_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MIDPOINT_Series() : this(period: 0, useNaN: false) { } - public MIDPOINT_Series(int period) : this(period: period, useNaN: false) { } - public MIDPOINT_Series(TBars source) : this(source.Close, 0, false) { } - public MIDPOINT_Series(TBars source, int period) : this(source.Close, period, false) { } - public MIDPOINT_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MIDPOINT_Series(TSeries source) : this(source, 0, false) { } - public MIDPOINT_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MIDPOINT_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MIDPOINT({period})"; + } + public MIDPOINT_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MIDPOINT_Series() : this(period: 0, useNaN: false) { } + public MIDPOINT_Series(int period) : this(period: period, useNaN: false) { } + public MIDPOINT_Series(TBars source) : this(source.Close, 0, false) { } + public MIDPOINT_Series(TBars source, int period) : this(source.Close, period, false) { } + public MIDPOINT_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MIDPOINT_Series(TSeries source) : this(source, 0, false) { } + public MIDPOINT_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _max= _buffer.Max(); - double _min = _buffer.Min(); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : (_max+_min)*0.5); - return base.Add(res, update); - } + double _max = _buffer.Max(); + double _min = _buffer.Min(); + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : (_max + _min) * 0.5); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MIDPRICE_Series.cs b/Calculations/_Updated/MIDPRICE_Series.cs index 5b2bf73f..099f90c8 100644 --- a/Calculations/_Updated/MIDPRICE_Series.cs +++ b/Calculations/_Updated/MIDPRICE_Series.cs @@ -9,57 +9,66 @@ MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in t */ -public class MIDPRICE_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TBars _data; - private readonly System.Collections.Generic.List _bufferhi = new(); - private readonly System.Collections.Generic.List _bufferlo = new(); +public class MIDPRICE_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TBars _data; + private readonly System.Collections.Generic.List _bufferhi = new(); + private readonly System.Collections.Generic.List _bufferlo = new(); - //core constructors - public MIDPRICE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MIDPRICE({period})"; - } - public MIDPRICE_Series(TBars source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(data: _data); - } - public MIDPRICE_Series() : this(period: 2, useNaN: false) { } - public MIDPRICE_Series(int period) : this(period: period, useNaN: false) { } - public MIDPRICE_Series(TBars source) : this(source, period: 2, useNaN: false) { } - public MIDPRICE_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MIDPRICE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MIDPRICE({period})"; + } + public MIDPRICE_Series(TBars source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(data: _data); + } + public MIDPRICE_Series() : this(period: 2, useNaN: false) { } + public MIDPRICE_Series(int period) : this(period: period, useNaN: false) { } + public MIDPRICE_Series(TBars source) : this(source, period: 2, useNaN: false) { } + public MIDPRICE_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - BufferTrim(_bufferhi, TBar.h, _period, update); - BufferTrim(_bufferlo, TBar.l, _period, update); - double _mid = (_bufferhi.Max() + _bufferlo.Min()) * 0.5; + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + BufferTrim(_bufferhi, TBar.h, _period, update); + BufferTrim(_bufferlo, TBar.l, _period, update); + double _mid = (_bufferhi.Max() + _bufferlo.Min()) * 0.5; - var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _mid); - return base.Add(res, update); - } + var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _mid); + return base.Add(res, update); + } - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _bufferhi.Clear(); - _bufferlo.Clear(); - } + //reset calculation + public override void Reset() + { + _bufferhi.Clear(); + _bufferlo.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MIN_Series.cs b/Calculations/_Updated/MIN_Series.cs index 2b34aa7b..4bb44ca9 100644 --- a/Calculations/_Updated/MIN_Series.cs +++ b/Calculations/_Updated/MIN_Series.cs @@ -10,59 +10,68 @@ MIN - Minimum value in the given period in the series. */ -public class MIN_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MIN_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MIN_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MAX({period})"; - } - public MIN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MIN_Series() : this(period: 0, useNaN: false) { } - public MIN_Series(int period) : this(period: period, useNaN: false) { } - public MIN_Series(TBars source) : this(source.Close, 0, false) { } - public MIN_Series(TBars source, int period) : this(source.Close, period, false) { } - public MIN_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MIN_Series(TSeries source) : this(source, 0, false) { } - public MIN_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MIN_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MAX({period})"; + } + public MIN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MIN_Series() : this(period: 0, useNaN: false) { } + public MIN_Series(int period) : this(period: period, useNaN: false) { } + public MIN_Series(TBars source) : this(source.Close, 0, false) { } + public MIN_Series(TBars source, int period) : this(source.Close, period, false) { } + public MIN_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MIN_Series(TSeries source) : this(source, 0, false) { } + public MIN_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _max= _buffer.Min(); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _max); - return base.Add(res, update); - } + double _max = _buffer.Min(); + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _max); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/MSE_Series.cs b/Calculations/_Updated/MSE_Series.cs index a918962e..7be1a30a 100644 --- a/Calculations/_Updated/MSE_Series.cs +++ b/Calculations/_Updated/MSE_Series.cs @@ -13,64 +13,73 @@ Sources: */ -public class MSE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class MSE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public MSE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"MSE({period})"; - } - public MSE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public MSE_Series() : this(period: 0, useNaN: false) { } - public MSE_Series(int period) : this(period: period, useNaN: false) { } - public MSE_Series(TBars source) : this(source.Close, 0, false) { } - public MSE_Series(TBars source, int period) : this(source.Close, period, false) { } - public MSE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public MSE_Series(TSeries source) : this(source, 0, false) { } - public MSE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public MSE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"MSE({period})"; + } + public MSE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public MSE_Series() : this(period: 0, useNaN: false) { } + public MSE_Series(int period) : this(period: period, useNaN: false) { } + public MSE_Series(TBars source) : this(source.Close, 0, false) { } + public MSE_Series(TBars source, int period) : this(source.Close, period, false) { } + public MSE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public MSE_Series(TSeries source) : this(source, 0, false) { } + public MSE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _mse = 0; - for (int i = 0; i < _buffer.Count; i++) { _mse += (_buffer[i] - _sma) * (_buffer[i] - _sma); } - _mse /= this._buffer.Count; + double _mse = 0; + for (int i = 0; i < _buffer.Count; i++) { _mse += (_buffer[i] - _sma) * (_buffer[i] - _sma); } + _mse /= this._buffer.Count; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mse); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _mse); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/OBV_Series.cs b/Calculations/_Updated/OBV_Series.cs index 40aa2c6e..f589cc3b 100644 --- a/Calculations/_Updated/OBV_Series.cs +++ b/Calculations/_Updated/OBV_Series.cs @@ -26,71 +26,81 @@ Note: */ -public class OBV_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TBars _data; - private double _lastobv, _lastlastobv; - private double _lastclose, _lastlastclose; +public class OBV_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TBars _data; + private double _lastobv, _lastlastobv; + private double _lastclose, _lastlastclose; - //core constructors - public OBV_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"OBV({period})"; - this._lastobv = this._lastlastobv = 0; - this._lastclose = this._lastlastclose = 0; - } - public OBV_Series(TBars source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(data: _data); - } - public OBV_Series() : this(period: 2, useNaN: false) { } - public OBV_Series(int period) : this(period: period, useNaN: false) { } - public OBV_Series(TBars source) : this(source, period: 2, useNaN: false) { } - public OBV_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public OBV_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"OBV({period})"; + this._lastobv = this._lastlastobv = 0; + this._lastclose = this._lastlastclose = 0; + } + public OBV_Series(TBars source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(data: _data); + } + public OBV_Series() : this(period: 2, useNaN: false) { } + public OBV_Series(int period) : this(period: period, useNaN: false) { } + public OBV_Series(TBars source) : this(source, period: 2, useNaN: false) { } + public OBV_Series(TBars source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { - if (update) { - this._lastobv = this._lastlastobv; - this._lastclose = this._lastlastclose; - } + 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; } + 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._lastlastobv = this._lastobv; + this._lastobv = _obv; - this._lastlastclose = this._lastclose; - this._lastclose = TBar.c; + this._lastlastclose = this._lastclose; + this._lastclose = TBar.c; - var res = (TBar.t, (this.Count < this._period && this._NaN) ? double.NaN : _obv); - return base.Add(res, update); - } + var res = (TBar.t, (this.Count < this._period && this._NaN) ? double.NaN : _obv); + return base.Add(res, update); + } - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - this._lastobv = this._lastlastobv = 0; - this._lastclose = this._lastlastclose = 0; - } + //reset calculation + public override void Reset() + { + this._lastobv = this._lastlastobv = 0; + this._lastclose = this._lastlastclose = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/RMA_Series.cs b/Calculations/_Updated/RMA_Series.cs index 5a624bd9..217c895d 100644 --- a/Calculations/_Updated/RMA_Series.cs +++ b/Calculations/_Updated/RMA_Series.cs @@ -20,97 +20,114 @@ Issues: */ -public class RMA_Series : TSeries { - private double _k; - private double _lastrma, _oldrma; - private double _sum, _oldsum; - private readonly bool _useSMA; - private int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class RMA_Series : TSeries +{ + private double _k; + private double _lastrma, _oldrma; + private double _sum, _oldsum; + private readonly bool _useSMA; + private int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; -//core constructor - public RMA_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - _useSMA = useSMA; - Name = $"RMA({period})"; - _k = 1.0 / (double)(this._period); - _len = 0; - _sum = _oldsum = _lastrma = _oldrma = 0; - } - //generic constructors (source) + //core constructor + public RMA_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + _useSMA = useSMA; + Name = $"RMA({period})"; + _k = 1.0 / (double)(this._period); + _len = 0; + _sum = _oldsum = _lastrma = _oldrma = 0; + } + //generic constructors (source) - public RMA_Series() : this(0, false, true) {} - public RMA_Series(int period) : this(period, false, true) {} - public RMA_Series(TBars source) : this(source.Close, 0, false) {} - public RMA_Series(TBars source, int period) : this(source.Close, period, false) {} - public RMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public RMA_Series(TSeries source, int period) : this(source, period, false, true) {} - public RMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) {} - public RMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public RMA_Series() : this(0, false, true) { } + public RMA_Series(int period) : this(period, false, true) { } + public RMA_Series(TBars source) : this(source.Close, 0, false) { } + public RMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public RMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public RMA_Series(TSeries source, int period) : this(source, period, false, true) { } + public RMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } + public RMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } -// core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - _lastrma = _oldrma; - _sum = _oldsum; - } - else { - _oldrma = _lastrma; - _oldsum = _sum; - _len++; - } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + _lastrma = _oldrma; + _sum = _oldsum; + } + else + { + _oldrma = _lastrma; + _oldsum = _sum; + _len++; + } - double _rma = 0; - if (_period == 0) { - _k = 1.0 / (double)(this._len); - } + double _rma = 0; + if (_period == 0) + { + _k = 1.0 / (double)(this._len); + } - if (Count == 0) { - _rma = _sum = TValue.v; + if (Count == 0) + { + _rma = _sum = TValue.v; - } else if (_len <= _period && _useSMA && _period != 0) { - _sum += TValue.v; - if (_period != 0 && _len > _period) { - _sum -= _data[Count - _period - (update ? 1 : 0)].v; - } - _rma = _sum / Math.Min(_len, _period); - } - else { - _rma = _k * (TValue.v - _lastrma) + _lastrma; - } + } + else if (_len <= _period && _useSMA && _period != 0) + { + _sum += TValue.v; + if (_period != 0 && _len > _period) + { + _sum -= _data[Count - _period - (update ? 1 : 0)].v; + } + _rma = _sum / Math.Min(_len, _period); + } + else + { + _rma = _k * (TValue.v - _lastrma) + _lastrma; + } - _lastrma = double.IsNaN(_rma) ? _lastrma : _rma; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _rma); - return base.Add(res, update); - } + _lastrma = double.IsNaN(_rma) ? _lastrma : _rma; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _rma); + return base.Add(res, update); + } -//variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _sum = _oldsum = _lastrma = _oldrma = 0; - _len = 0; - } + //reset calculation + public override void Reset() + { + _sum = _oldsum = _lastrma = _oldrma = 0; + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/RSI_Series.cs b/Calculations/_Updated/RSI_Series.cs index 8d3979a1..ee9c883b 100644 --- a/Calculations/_Updated/RSI_Series.cs +++ b/Calculations/_Updated/RSI_Series.cs @@ -15,106 +15,120 @@ Sources: */ -public class RSI_Series : TSeries { - private readonly System.Collections.Generic.List _gain = new(); - private readonly System.Collections.Generic.List _loss = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private double _avgGain, _avgLoss, _lastValue; - private double _avgGain_o, _avgLoss_o, _lastValue_o; - private int i; +public class RSI_Series : TSeries +{ + private readonly System.Collections.Generic.List _gain = new(); + private readonly System.Collections.Generic.List _loss = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private double _avgGain, _avgLoss, _lastValue; + private double _avgGain_o, _avgLoss_o, _lastValue_o; + private int i; - //core constructors - public RSI_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"RSI({period})"; - i = 0; - } - public RSI_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public RSI_Series() : this(period: 0, useNaN: false) { } - public RSI_Series(int period) : this(period: period, useNaN: false) { } - public RSI_Series(TBars source) : this(source.Close, 0, false) { } - public RSI_Series(TBars source, int period) : this(source.Close, period, false) { } - public RSI_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public RSI_Series(TSeries source) : this(source, 0, false) { } - public RSI_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public RSI_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"RSI({period})"; + i = 0; + } + public RSI_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public RSI_Series() : this(period: 0, useNaN: false) { } + public RSI_Series(int period) : this(period: period, useNaN: false) { } + public RSI_Series(TBars source) : this(source.Close, 0, false) { } + public RSI_Series(TBars source, int period) : this(source.Close, period, false) { } + public RSI_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public RSI_Series(TSeries source) : this(source, 0, false) { } + public RSI_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { - double _rsi = 0; - if (update) { - _lastValue = _lastValue_o; - _avgGain = _avgGain_o; - _avgLoss = _avgLoss_o; - } - else { - _lastValue_o = _lastValue; - _avgGain_o = _avgGain; - _avgLoss_o = _avgLoss; - } + 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; } + if (i == 0) { _lastValue = TValue.v; } - double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0; - BufferTrim(_gain, _gainval, _period, update); - double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0; - BufferTrim(_loss, _lossval, _period, update); - _lastValue = TValue.v; + double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0; + BufferTrim(_gain, _gainval, _period, update); + double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0; + BufferTrim(_loss, _lossval, _period, update); + _lastValue = TValue.v; - // calculate RSI - if (i > _period && _period != 0) { - _avgGain = ((_avgGain * (_period - 1)) + _gain[^1]) / _period; - _avgLoss = ((_avgLoss * (_period - 1)) + _loss[^1]) / _period; - 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]; } + // calculate RSI + if (i > _period && _period != 0) + { + _avgGain = ((_avgGain * (_period - 1)) + _gain[^1]) / _period; + _avgLoss = ((_avgLoss * (_period - 1)) + _loss[^1]) / _period; + 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; + _avgGain = _sumGain / _gain.Count; + _avgLoss = _sumLoss / _loss.Count; - _rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100; - } - if (!update) { i++; } + _rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100; + } + if (!update) { i++; } - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _rsi); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _rsi); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - i = 0; - } + //reset calculation + public override void Reset() + { + i = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/SDEV_Series.cs b/Calculations/_Updated/SDEV_Series.cs index ab5ca503..b7b5cc1a 100644 --- a/Calculations/_Updated/SDEV_Series.cs +++ b/Calculations/_Updated/SDEV_Series.cs @@ -18,65 +18,74 @@ Remark: */ -public class SDEV_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class SDEV_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public SDEV_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SDEV({period})"; - } - public SDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SDEV_Series() : this(period: 0, useNaN: false) { } - public SDEV_Series(int period) : this(period: period, useNaN: false) { } - public SDEV_Series(TBars source) : this(source.Close, 0, false) { } - public SDEV_Series(TBars source, int period) : this(source.Close, period, false) { } - public SDEV_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SDEV_Series(TSeries source) : this(source, 0, false) { } - public SDEV_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public SDEV_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SDEV({period})"; + } + public SDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SDEV_Series() : this(period: 0, useNaN: false) { } + public SDEV_Series(int period) : this(period: period, useNaN: false) { } + public SDEV_Series(TBars source) : this(source.Close, 0, false) { } + public SDEV_Series(TBars source, int period) : this(source.Close, period, false) { } + public SDEV_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SDEV_Series(TSeries source) : this(source, 0, false) { } + public SDEV_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _var = 0; - for (int i = 0; i < _buffer.Count; i++) { _var += (_buffer[i] - _sma) * (_buffer[i] - _sma); } - _var /= this._buffer.Count; - double _sdev = Math.Sqrt(_var); + double _var = 0; + for (int i = 0; i < _buffer.Count; i++) { _var += (_buffer[i] - _sma) * (_buffer[i] - _sma); } + _var /= this._buffer.Count; + double _sdev = Math.Sqrt(_var); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sdev); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sdev); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/SLOPE_Series.cs b/Calculations/_Updated/SLOPE_Series.cs index 4aef642e..8d7580c2 100644 --- a/Calculations/_Updated/SLOPE_Series.cs +++ b/Calculations/_Updated/SLOPE_Series.cs @@ -22,101 +22,109 @@ Sources: */ -public class SLOPE_Series : TSeries { - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly TSeries p_Intercept = new(); - private readonly TSeries p_RSquared = new(); - private readonly TSeries p_StdDev = new(); - private readonly System.Collections.Generic.List _buffer = new(); - public TSeries Intercept => p_Intercept; - public TSeries RSquared => p_RSquared; - public TSeries StdDev => p_StdDev; - //core constructors - public SLOPE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SLOPE({period})"; - } - public SLOPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SLOPE_Series() : this(period: 0, useNaN: false) { } - public SLOPE_Series(int period) : this(period: period, useNaN: false) { } - public SLOPE_Series(TBars source) : this(source.Close, 0, false) { } - public SLOPE_Series(TBars source, int period) : this(source.Close, period, false) { } - public SLOPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SLOPE_Series(TSeries source) : this(source, 0, false) { } - public SLOPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } +public class SLOPE_Series : TSeries +{ + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly TSeries p_Intercept = new(); + private readonly TSeries p_RSquared = new(); + private readonly TSeries p_StdDev = new(); + private readonly System.Collections.Generic.List _buffer = new(); + public TSeries Intercept => p_Intercept; + public TSeries RSquared => p_RSquared; + public TSeries StdDev => p_StdDev; + //core constructors + public SLOPE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SLOPE({period})"; + } + public SLOPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SLOPE_Series() : this(period: 0, useNaN: false) { } + public SLOPE_Series(int period) : this(period: period, useNaN: false) { } + public SLOPE_Series(TBars source) : this(source.Close, 0, false) { } + public SLOPE_Series(TBars source, int period) : this(source.Close, period, false) { } + public SLOPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SLOPE_Series(TSeries source) : this(source, 0, false) { } + public SLOPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - int _len = this._buffer.Count; + int _len = this._buffer.Count; - // get averages for period - double sumX = 0; - double sumY = 0; + // get averages for period + double sumX = 0; + double sumY = 0; - for (int p = 0; p < _len; p++) { - sumX += this.Count - _len + 2 + p; - sumY += _buffer[p]; - } - double avgX = sumX / _len; - double avgY = sumY / _len; + for (int p = 0; p < _len; p++) + { + sumX += this.Count - _len + 2 + p; + sumY += _buffer[p]; + } + double avgX = sumX / _len; + double avgY = sumY / _len; - // least squares method - double sumSqX = 0; - double sumSqY = 0; - double sumSqXY = 0; + // least squares method + double sumSqX = 0; + double sumSqY = 0; + double sumSqXY = 0; - for (int p = 0; p < _len; p++) { - double devX = this.Count - _len + 2 + p - avgX; - double devY = _buffer[p] - avgY; + for (int p = 0; p < _len; p++) + { + double devX = this.Count - _len + 2 + p - avgX; + double devY = _buffer[p] - avgY; - sumSqX += devX * devX; - sumSqY += devY * devY; - sumSqXY += devX * devY; - } + sumSqX += devX * devX; + sumSqY += devY * devY; + sumSqXY += devX * devY; + } - double _slope = sumSqXY / sumSqX; - double _intercept = avgY - (_slope * avgX); + double _slope = sumSqXY / sumSqX; + double _intercept = avgY - (_slope * avgX); - // calculate Standard Deviation and R-Squared - double stdDevX = Math.Sqrt(sumSqX / _len); - double stdDevY = Math.Sqrt(sumSqY / _len); - double _StdDev = stdDevY; + // calculate Standard Deviation and R-Squared + double stdDevX = Math.Sqrt(sumSqX / _len); + double stdDevY = Math.Sqrt(sumSqY / _len); + double _StdDev = stdDevY; - double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0; - double _RSquared = arrr * arrr; + double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0; + double _RSquared = arrr * arrr; - var ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _intercept); - p_Intercept.Add(ret, update); + var ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _intercept); + p_Intercept.Add(ret, update); - ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _StdDev); - p_StdDev.Add(ret, update); + ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _StdDev); + p_StdDev.Add(ret, update); - ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _RSquared); - p_RSquared.Add(ret, update); + ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _RSquared); + p_RSquared.Add(ret, update); - ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _slope); - return base.Add(ret, update); - } + ret = (TValue.t, this.Count < this._period - 1 && this._NaN ? double.NaN : _slope); + return base.Add(ret, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/SMAPE_Series.cs b/Calculations/_Updated/SMAPE_Series.cs index b79a3442..082fcd26 100644 --- a/Calculations/_Updated/SMAPE_Series.cs +++ b/Calculations/_Updated/SMAPE_Series.cs @@ -13,63 +13,72 @@ Sources: */ -public class SMAPE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class SMAPE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public SMAPE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SMAPE({period})"; - } - public SMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SMAPE_Series() : this(period: 0, useNaN: false) { } - public SMAPE_Series(int period) : this(period: period, useNaN: false) { } - public SMAPE_Series(TBars source) : this(source.Close, 0, false) { } - public SMAPE_Series(TBars source, int period) : this(source.Close, period, false) { } - public SMAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SMAPE_Series(TSeries source) : this(source, 0, false) { } - public SMAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public SMAPE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SMAPE({period})"; + } + public SMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SMAPE_Series() : this(period: 0, useNaN: false) { } + public SMAPE_Series(int period) : this(period: period, useNaN: false) { } + public SMAPE_Series(TBars source) : this(source.Close, 0, false) { } + public SMAPE_Series(TBars source, int period) : this(source.Close, period, false) { } + public SMAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SMAPE_Series(TSeries source) : this(source, 0, false) { } + public SMAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); - double _smape = 0; - for (int i = 0; i < _buffer.Count; i++) { _smape += Math.Abs(_buffer[i] - _sma) / (Math.Abs(_buffer[i]) + Math.Abs(_sma)); } - _smape /= this._buffer.Count; + double _sma = _buffer.Average(); + double _smape = 0; + for (int i = 0; i < _buffer.Count; i++) { _smape += Math.Abs(_buffer[i] - _sma) / (Math.Abs(_buffer[i]) + Math.Abs(_sma)); } + _smape /= this._buffer.Count; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _smape); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _smape); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/SMA_Series.cs b/Calculations/_Updated/SMA_Series.cs index c9a817f0..0c5a19fa 100644 --- a/Calculations/_Updated/SMA_Series.cs +++ b/Calculations/_Updated/SMA_Series.cs @@ -16,81 +16,97 @@ Remark: implementation, but it does allow incremental additions of inputs and real-time calculations of SMA() */ -public class SMA_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); +public class SMA_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); - private double _sum, _oldsum; - private readonly int _period; - private readonly TSeries _data; - protected readonly bool _NaN; + private double _sum, _oldsum; + private readonly int _period; + private readonly TSeries _data; + protected readonly bool _NaN; - //core constructor - public SMA_Series(int period, bool useNaN) { - _period = Math.Max(0, period); - _NaN = useNaN; - Name = $"SMA({period})"; - _sum = _oldsum = 0; - } - public SMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SMA_Series() : this(0, false) {} - public SMA_Series(int period) : this(period, false) {} - public SMA_Series(TBars source) : this(source.Close, 0, false) {} - public SMA_Series(TBars source, int period) : this(source.Close, period, false) {} - public SMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public SMA_Series(TSeries source) : this(source, 0, false) {} - public SMA_Series(TSeries source, int period) : this(source, period, false) {} + //core constructor + public SMA_Series(int period, bool useNaN) + { + _period = Math.Max(0, period); + _NaN = useNaN; + Name = $"SMA({period})"; + _sum = _oldsum = 0; + } + public SMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SMA_Series() : this(0, false) { } + public SMA_Series(int period) : this(period, false) { } + public SMA_Series(TBars source) : this(source.Close, 0, false) { } + public SMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public SMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SMA_Series(TSeries source) : this(source, 0, false) { } + public SMA_Series(TSeries source, int period) : this(source, period, false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { return (TValue.t, double.NaN); - } else { - if (update && _buffer.Count > 0) { - _sum -= _buffer[^1]; - _buffer[^1] = TValue.v; - _oldsum = _sum; - } - else { - _buffer.Add(TValue.v); - _oldsum = _sum; - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return (TValue.t, double.NaN); + } + else + { + if (update && _buffer.Count > 0) + { + _sum -= _buffer[^1]; + _buffer[^1] = TValue.v; + _oldsum = _sum; + } + else + { + _buffer.Add(TValue.v); + _oldsum = _sum; + } - _sum += TValue.v; - if (_period != 0 && _buffer.Count > _period) { - _sum -= _buffer[0]; - _buffer.RemoveAt(0); - } - } + _sum += TValue.v; + if (_period != 0 && _buffer.Count > _period) + { + _sum -= _buffer[0]; + _buffer.RemoveAt(0); + } + } - double _div = _period == 0 ? _buffer.Count : Math.Min(_buffer.Count, _period); - var _sma = _sum / _div; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sma); - return base.Add(res, update); - } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + double _div = _period == 0 ? _buffer.Count : Math.Min(_buffer.Count, _period); + var _sma = _sum / _div; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sma); + return base.Add(res, update); + } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _sum = _oldsum = 0; - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _sum = _oldsum = 0; + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/SMMA_Series.cs b/Calculations/_Updated/SMMA_Series.cs index 8f464cc1..46b975c5 100644 --- a/Calculations/_Updated/SMMA_Series.cs +++ b/Calculations/_Updated/SMMA_Series.cs @@ -18,76 +18,88 @@ Sources: */ -public class SMMA_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); +public class SMMA_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private double _lastsmma, _lastlastsmma; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private double _lastsmma, _lastlastsmma; - //core constructors - public SMMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SMMA({period})"; - } - public SMMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SMMA_Series() : this(period: 0, useNaN: false) { } - public SMMA_Series(int period) : this(period: period, useNaN: false) { } - public SMMA_Series(TBars source) : this(source.Close, 0, false) { } - public SMMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public SMMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SMMA_Series(TSeries source) : this(source, 0, false) { } - public SMMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public SMMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SMMA({period})"; + } + public SMMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SMMA_Series() : this(period: 0, useNaN: false) { } + public SMMA_Series(int period) : this(period: period, useNaN: false) { } + public SMMA_Series(TBars source) : this(source.Close, 0, false) { } + public SMMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public SMMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SMMA_Series(TSeries source) : this(source, 0, false) { } + public SMMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, double.NaN),update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, double.NaN), update); + } - double _smma = 0; - if (update) { this._lastsmma = this._lastlastsmma; } + double _smma = 0; + if (update) { this._lastsmma = this._lastlastsmma; } - if (this.Count < this._period) { - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - _smma = _buffer.Average(); - } - else { - _smma = ((_lastsmma * (_period - 1)) + TValue.v) / _period; - } + if (this.Count < this._period) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + _smma = _buffer.Average(); + } + else + { + _smma = ((_lastsmma * (_period - 1)) + TValue.v) / _period; + } - this._lastlastsmma = this._lastsmma; - this._lastsmma = _smma; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _smma); - return base.Add(res, update); - } + this._lastlastsmma = this._lastsmma; + this._lastsmma = _smma; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _smma); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - this._lastsmma = this._lastlastsmma = 0; - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + this._lastsmma = this._lastlastsmma = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/SSDEV_Series.cs b/Calculations/_Updated/SSDEV_Series.cs index 2b5f62d3..490c579c 100644 --- a/Calculations/_Updated/SSDEV_Series.cs +++ b/Calculations/_Updated/SSDEV_Series.cs @@ -18,65 +18,74 @@ Remark: */ -public class SSDEV_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class SSDEV_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public SSDEV_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SSDEV({period})"; - } - public SSDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SSDEV_Series() : this(period: 0, useNaN: false) { } - public SSDEV_Series(int period) : this(period: period, useNaN: false) { } - public SSDEV_Series(TBars source) : this(source.Close, 0, false) { } - public SSDEV_Series(TBars source, int period) : this(source.Close, period, false) { } - public SSDEV_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SSDEV_Series(TSeries source) : this(source, 0, false) { } - public SSDEV_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public SSDEV_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SSDEV({period})"; + } + public SSDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SSDEV_Series() : this(period: 0, useNaN: false) { } + public SSDEV_Series(int period) : this(period: period, useNaN: false) { } + public SSDEV_Series(TBars source) : this(source.Close, 0, false) { } + public SSDEV_Series(TBars source, int period) : this(source.Close, period, false) { } + public SSDEV_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SSDEV_Series(TSeries source) : this(source, 0, false) { } + public SSDEV_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _svar = 0; - for (int i = 0; i < this._buffer.Count; i++) { _svar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } - _svar /= (_buffer.Count > 1) ? _buffer.Count - 1 : 1; // Bessel's correction - double _ssdev = Math.Sqrt(_svar); + double _svar = 0; + for (int i = 0; i < this._buffer.Count; i++) { _svar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } + _svar /= (_buffer.Count > 1) ? _buffer.Count - 1 : 1; // Bessel's correction + double _ssdev = Math.Sqrt(_svar); - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _ssdev); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _ssdev); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/SVAR_Series.cs b/Calculations/_Updated/SVAR_Series.cs index bb693c54..01020519 100644 --- a/Calculations/_Updated/SVAR_Series.cs +++ b/Calculations/_Updated/SVAR_Series.cs @@ -18,64 +18,73 @@ Remark: */ -public class SVAR_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class SVAR_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public SVAR_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"SVAR({period})"; - } - public SVAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public SVAR_Series() : this(period: 0, useNaN: false) { } - public SVAR_Series(int period) : this(period: period, useNaN: false) { } - public SVAR_Series(TBars source) : this(source.Close, 0, false) { } - public SVAR_Series(TBars source, int period) : this(source.Close, period, false) { } - public SVAR_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public SVAR_Series(TSeries source) : this(source, 0, false) { } - public SVAR_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public SVAR_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"SVAR({period})"; + } + public SVAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public SVAR_Series() : this(period: 0, useNaN: false) { } + public SVAR_Series(int period) : this(period: period, useNaN: false) { } + public SVAR_Series(TBars source) : this(source.Close, 0, false) { } + public SVAR_Series(TBars source, int period) : this(source.Close, period, false) { } + public SVAR_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public SVAR_Series(TSeries source) : this(source, 0, false) { } + public SVAR_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _svar = 0; - for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); } - _svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction + double _svar = 0; + for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); } + _svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _svar); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _svar); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/T3_Series.cs b/Calculations/_Updated/T3_Series.cs index 7cba0dcd..6f87ea07 100644 --- a/Calculations/_Updated/T3_Series.cs +++ b/Calculations/_Updated/T3_Series.cs @@ -14,148 +14,160 @@ Sources: http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/ */ -public class T3_Series : TSeries { - private readonly double _k, _k1m, _c1, _c2, _c3, _c4; - private readonly System.Collections.Generic.List _buffer1 = new(); - private readonly System.Collections.Generic.List _buffer2 = new(); - private readonly System.Collections.Generic.List _buffer3 = new(); - private readonly System.Collections.Generic.List _buffer4 = new(); - private readonly System.Collections.Generic.List _buffer5 = new(); - private readonly System.Collections.Generic.List _buffer6 = new(); - private readonly bool _useSMA; - private double _lastema1, _lastema2, _lastema3, _lastema4, _lastema5, _lastema6; - private double _llastema1, _llastema2, _llastema3, _llastema4, _llastema5, _llastema6; - protected int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class T3_Series : TSeries +{ + private readonly double _k, _k1m, _c1, _c2, _c3, _c4; + private readonly System.Collections.Generic.List _buffer1 = new(); + private readonly System.Collections.Generic.List _buffer2 = new(); + private readonly System.Collections.Generic.List _buffer3 = new(); + private readonly System.Collections.Generic.List _buffer4 = new(); + private readonly System.Collections.Generic.List _buffer5 = new(); + private readonly System.Collections.Generic.List _buffer6 = new(); + private readonly bool _useSMA; + private double _lastema1, _lastema2, _lastema3, _lastema4, _lastema5, _lastema6; + private double _llastema1, _llastema2, _llastema3, _llastema4, _llastema5, _llastema6; + protected int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public T3_Series(int period, double vfactor, bool useSMA, bool useNaN) { - _period = period; - _len = 0; - _NaN = useNaN; - Name = $"T3({period})"; - _useSMA = useSMA; - double _a = vfactor; //0.7; //0.618 - _c1 = -_a * _a * _a; - _c2 = 3 * _a * _a + 3 * _a * _a * _a; - _c3 = -6 * _a * _a - 3 * _a - 3 * _a * _a * _a; - _c4 = 1 + 3 * _a + _a * _a * _a + 3 * _a * _a; + //core constructors + public T3_Series(int period, double vfactor, bool useSMA, bool useNaN) + { + _period = period; + _len = 0; + _NaN = useNaN; + Name = $"T3({period})"; + _useSMA = useSMA; + double _a = vfactor; //0.7; //0.618 + _c1 = -_a * _a * _a; + _c2 = 3 * _a * _a + 3 * _a * _a * _a; + _c3 = -6 * _a * _a - 3 * _a - 3 * _a * _a * _a; + _c4 = 1 + 3 * _a + _a * _a * _a + 3 * _a * _a; - _k = 2.0 / (_period + 1); - _k1m = 1.0 - _k; - _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0; - } - public T3_Series(TSeries source, int period, double vfactor, bool useSMA, bool useNaN) : this(period, vfactor, useSMA, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public T3_Series() : this(period: 0, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(int period) : this(period: period, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(TBars source) : this(source.Close, 0, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(TBars source, int period) : this(source.Close, period, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(TBars source, int period, bool useNaN) : this(source.Close, period, vfactor: 0.7, useSMA: true, useNaN: useNaN) { } - public T3_Series(TBars source, int period, double vfactor, bool useNaN) : this(source.Close, period, vfactor: vfactor, useSMA: true, useNaN: useNaN) { } - public T3_Series(TBars source, int period, bool useSMA, bool useNaN) : this(source.Close, period, vfactor: 0.7, useSMA: useSMA, useNaN: useNaN) { } - public T3_Series(TSeries source) : this(source, 0, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(TSeries source, int period) : this(source: source, period: period, vfactor: 0.7, useSMA: true, useNaN: false) { } - public T3_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, vfactor: 0.7, useSMA: true, useNaN: useNaN) { } - public T3_Series(TSeries source, int period, double vfactor) : this(source: source, period: period, vfactor: vfactor, useSMA: true, useNaN: false) { } - public T3_Series(TSeries source, int period, double vfactor, bool useNaN) : this(source: source, period: period, vfactor: vfactor, useSMA: true, useNaN: useNaN) { } + _k = 2.0 / (_period + 1); + _k1m = 1.0 - _k; + _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0; + } + public T3_Series(TSeries source, int period, double vfactor, bool useSMA, bool useNaN) : this(period, vfactor, useSMA, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public T3_Series() : this(period: 0, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(int period) : this(period: period, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(TBars source) : this(source.Close, 0, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(TBars source, int period) : this(source.Close, period, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(TBars source, int period, bool useNaN) : this(source.Close, period, vfactor: 0.7, useSMA: true, useNaN: useNaN) { } + public T3_Series(TBars source, int period, double vfactor, bool useNaN) : this(source.Close, period, vfactor: vfactor, useSMA: true, useNaN: useNaN) { } + public T3_Series(TBars source, int period, bool useSMA, bool useNaN) : this(source.Close, period, vfactor: 0.7, useSMA: useSMA, useNaN: useNaN) { } + public T3_Series(TSeries source) : this(source, 0, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(TSeries source, int period) : this(source: source, period: period, vfactor: 0.7, useSMA: true, useNaN: false) { } + public T3_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, vfactor: 0.7, useSMA: true, useNaN: useNaN) { } + public T3_Series(TSeries source, int period, double vfactor) : this(source: source, period: period, vfactor: vfactor, useSMA: true, useNaN: false) { } + public T3_Series(TSeries source, int period, double vfactor, bool useNaN) : this(source: source, period: period, vfactor: vfactor, useSMA: true, useNaN: useNaN) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - double _ema1, _ema2, _ema3, _ema4, _ema5, _ema6; - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN),update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + double _ema1, _ema2, _ema3, _ema4, _ema5, _ema6; + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } - if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; _lastema4 = _llastema4; _lastema5 = _llastema5; _lastema6 = _llastema6; } - else { _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _llastema4 = _lastema4; _llastema5 = _lastema5; _llastema6 = _lastema6; } + if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; _lastema4 = _llastema4; _lastema5 = _llastema5; _lastema6 = _llastema6; } + else { _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _llastema4 = _lastema4; _llastema5 = _lastema5; _llastema6 = _lastema6; } - if (_len == 0) { _lastema1 = _lastema2 = _lastema3 = _lastema4 = _lastema5 = _lastema6 = TValue.v; } - + if (_len == 0) { _lastema1 = _lastema2 = _lastema3 = _lastema4 = _lastema5 = _lastema6 = TValue.v; } - if ((_len < _period) && _useSMA) { - BufferTrim(_buffer1, TValue.v, _period, update); - _ema1 = 0; - for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; } - _ema1 /= _buffer1.Count; - BufferTrim(_buffer2, _ema1, _period, update); - _ema2 = 0; - for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } - _ema2 /= _buffer2.Count; + if ((_len < _period) && _useSMA) + { + BufferTrim(_buffer1, TValue.v, _period, update); + _ema1 = 0; + for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; } + _ema1 /= _buffer1.Count; - BufferTrim(_buffer3, _ema2, _period, update); - _ema3 = 0; - for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; } - _ema3 /= _buffer3.Count; + BufferTrim(_buffer2, _ema1, _period, update); + _ema2 = 0; + for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } + _ema2 /= _buffer2.Count; - BufferTrim(_buffer4, _ema3, _period, update); - _ema4 = 0; - for (int i = 0; i < _buffer4.Count; i++) { _ema4 += _buffer4[i]; } - _ema4 /= _buffer4.Count; + BufferTrim(_buffer3, _ema2, _period, update); + _ema3 = 0; + for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; } + _ema3 /= _buffer3.Count; - BufferTrim(_buffer5, _ema4, _period, update); - _ema5 = 0; - for (int i = 0; i < _buffer5.Count; i++) { _ema5 += _buffer5[i]; } - _ema5 /= _buffer5.Count; + BufferTrim(_buffer4, _ema3, _period, update); + _ema4 = 0; + for (int i = 0; i < _buffer4.Count; i++) { _ema4 += _buffer4[i]; } + _ema4 /= _buffer4.Count; - BufferTrim(_buffer6, _ema5, _period, update); - _ema6 = 0; - for (int i = 0; i < _buffer6.Count; i++) { _ema6 += _buffer6[i]; } - _ema6 /= _buffer6.Count; - } - else { - _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m); - _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m); - _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m); - _ema4 = (_ema3 * this._k) + (this._lastema4 * this._k1m); - _ema5 = (_ema4 * this._k) + (this._lastema5 * this._k1m); - _ema6 = (_ema5 * this._k) + (this._lastema6 * this._k1m); - } - _len++; - _lastema1 = _ema1; - _lastema2 = _ema2; - _lastema3 = _ema3; - _lastema4 = _ema4; - _lastema5 = _ema5; - _lastema6 = _ema6; + BufferTrim(_buffer5, _ema4, _period, update); + _ema5 = 0; + for (int i = 0; i < _buffer5.Count; i++) { _ema5 += _buffer5[i]; } + _ema5 /= _buffer5.Count; - double _T3 = _c1 * _ema6 + _c2 * _ema5 + _c3 * _ema4 + _c4 * _ema3; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _T3); - return base.Add(res, update); - } + BufferTrim(_buffer6, _ema5, _period, update); + _ema6 = 0; + for (int i = 0; i < _buffer6.Count; i++) { _ema6 += _buffer6[i]; } + _ema6 /= _buffer6.Count; + } + else + { + _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m); + _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m); + _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m); + _ema4 = (_ema3 * this._k) + (this._lastema4 * this._k1m); + _ema5 = (_ema4 * this._k) + (this._lastema5 * this._k1m); + _ema6 = (_ema5 * this._k) + (this._lastema6 * this._k1m); + } + _len++; + _lastema1 = _ema1; + _lastema2 = _ema2; + _lastema3 = _ema3; + _lastema4 = _ema4; + _lastema5 = _ema5; + _lastema6 = _ema6; - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + double _T3 = _c1 * _ema6 + _c2 * _ema5 + _c3 * _ema4 + _c4 * _ema3; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _T3); + return base.Add(res, update); + } - //reset calculation - public override void Reset() { - _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0; - _buffer1.Clear(); - _buffer2.Clear(); - _buffer3.Clear(); - _buffer4.Clear(); - _buffer5.Clear(); - _buffer6.Clear(); - _len = 0; - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0; + _buffer1.Clear(); + _buffer2.Clear(); + _buffer3.Clear(); + _buffer4.Clear(); + _buffer5.Clear(); + _buffer6.Clear(); + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/TBars.cs b/Calculations/_Updated/TBars.cs index 0c0274d4..7b9af4ce 100644 --- a/Calculations/_Updated/TBars.cs +++ b/Calculations/_Updated/TBars.cs @@ -12,127 +12,142 @@ TBars class - includes all series for common data used in indicators and other c public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)> { - public string Name { get; set; } - private readonly TSeries _open = new("open"); - private readonly TSeries _high = new("high"); - private readonly TSeries _low = new("low"); - private readonly TSeries _close = new("close"); - private readonly TSeries _volume = new("volume"); - private readonly TSeries _hl2 = new("HL2"); - private readonly TSeries _oc2 = new("OC2"); - private readonly TSeries _ohl3 = new("OHL3"); - private readonly TSeries _hlc3 = new("HLC3"); - private readonly TSeries _ohlc4 = new("OHLC4"); - private readonly TSeries _hlcc4 = new("HLCC4"); + public string Name { get; set; } + private readonly TSeries _open = new("open"); + private readonly TSeries _high = new("high"); + private readonly TSeries _low = new("low"); + private readonly TSeries _close = new("close"); + private readonly TSeries _volume = new("volume"); + private readonly TSeries _hl2 = new("HL2"); + private readonly TSeries _oc2 = new("OC2"); + private readonly TSeries _ohl3 = new("OHL3"); + private readonly TSeries _hlc3 = new("HLC3"); + private readonly TSeries _ohlc4 = new("OHLC4"); + private readonly TSeries _hlcc4 = new("HLCC4"); - public TSeries Open => this._open; - public TSeries High => this._high; - public TSeries Low => this._low; - public TSeries Close => this._close; - public TSeries Volume => this._volume; - public TSeries HL2 => this._hl2; - public TSeries OC2 => this._oc2; - public TSeries OHL3 => this._ohl3; - public TSeries HLC3 => this._hlc3; - public TSeries OHLC4 => this._ohlc4; - public TSeries HLCC4 => this._hlcc4; + public TSeries Open => this._open; + public TSeries High => this._high; + public TSeries Low => this._low; + public TSeries Close => this._close; + public TSeries Volume => this._volume; + public TSeries HL2 => this._hl2; + public TSeries OC2 => this._oc2; + public TSeries OHL3 => this._ohl3; + public TSeries HLC3 => this._hlc3; + public TSeries OHLC4 => this._ohlc4; + public TSeries HLCC4 => this._hlcc4; - public TBars() { } + public TBars() { } - public TBars(string Name) { - this.Name = Name; - } - - public (DateTime t, double o, double h, double l, double c, double v) Last => this[^1]; - public TBars Tail(int count = 10) - { - TBars outBars = new(); - if (count > this.Count) { count = this.Count; } - for (int i = this.Count - count; i < this.Count; i++) { outBars.Add(this[i]); } - return outBars; - } - public TSeries Select(int source) - { - return source switch + public TBars(string Name) { - 0 => _open, - 1 => _high, - 2 => _low, - 3 => _close, - 4 => _hl2, - 5 => _oc2, - 6 => _ohl3, - 7 => _hlc3, - 8 => _ohlc4, - _ => _hlcc4, - }; - } - public static string SelectStr(int source) - { - return source switch - { - 0 => "Open", - 1 => "High", - 2 => "Low", - 3 => "Close", - 4 => "HL2", - 5 => "OC2", - 6 => "OHL3", - 7 => "HLC3", - 8 => "OHLC4", - _ => "HLCC4", - }; - } - - public virtual (DateTime t, double v) Add((double o, double h, double l, double c, double v) p, bool update = false) => - Add((t: (this.Count == 0) ? DateTime.Today : this[^1].t.AddDays(1),p.o,p.h,p.l,p.c,p.v),update); - - public virtual (DateTime t, double v) Add(double o, double h, double l, double c, double v, bool update = false) => - Add((o,h,l,c,v),update); - - public virtual (DateTime t, double v) Add(DateTime t, double o, double h, double l, double c, double v, bool update = false) => - this.Add((t, o, h, l, c, v), update); - - public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - if (update) { this[^1] = TBar; } else { base.Add(TBar); } - - _open.Add((TBar.t, TBar.o), update); - _high.Add((TBar.t, TBar.h), update); - _low.Add((TBar.t, TBar.l), update); - _close.Add((TBar.t, TBar.c), update); - _volume.Add((TBar.t, TBar.v), update); - _hl2.Add((TBar.t, (TBar.h + TBar.l) * 0.5), update); - _oc2.Add((TBar.t, (TBar.o + TBar.c) * 0.5), update); - _ohl3.Add((TBar.t, (TBar.o + TBar.h + TBar.l) * 0.333333333333333), update); - _hlc3.Add((TBar.t, (TBar.h + TBar.l + TBar.c) * 0.333333333333333), update); - _ohlc4.Add((TBar.t, (TBar.o + TBar.h + TBar.l + TBar.c) * 0.25), update); - _hlcc4.Add((TBar.t, (TBar.h + TBar.l + TBar.c + TBar.c) * 0.25), update); - - this.OnEvent(update); - return (TBar.t, (TBar.o + TBar.h + TBar.l + TBar.c) * 0.25); - } - - public delegate void NewDataEventHandler(object source, TSeriesEventArgs args); - public event NewDataEventHandler Pub; - protected virtual void OnEvent(bool update = false) { if (Pub != null && Pub.Target != this) { - Pub(this, new TSeriesEventArgs { update = update }); } } - - public void Sub(object source, TSeriesEventArgs e) { TBars ss = (TBars)source; if (ss.Count > 1) { - for (int i = 0; i < ss.Count; i++) { this.Add(ss[i]); } - } else { - this.Add(ss[^1], e.update); + this.Name = Name; } - } - /// common helpers - public static void BufferTrim(System.Collections.Generic.List buffer, double value, int period, bool update) { - if (!update) { - buffer.Add(value); - if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); } - return; - } - buffer[^1] = value; - } - public virtual void Reset() { - } + public (DateTime t, double o, double h, double l, double c, double v) Last => this[^1]; + public TBars Tail(int count = 10) + { + TBars outBars = new(); + if (count > this.Count) { count = this.Count; } + for (int i = this.Count - count; i < this.Count; i++) { outBars.Add(this[i]); } + return outBars; + } + public TSeries Select(int source) + { + return source switch + { + 0 => _open, + 1 => _high, + 2 => _low, + 3 => _close, + 4 => _hl2, + 5 => _oc2, + 6 => _ohl3, + 7 => _hlc3, + 8 => _ohlc4, + _ => _hlcc4, + }; + } + public static string SelectStr(int source) + { + return source switch + { + 0 => "Open", + 1 => "High", + 2 => "Low", + 3 => "Close", + 4 => "HL2", + 5 => "OC2", + 6 => "OHL3", + 7 => "HLC3", + 8 => "OHLC4", + _ => "HLCC4", + }; + } + + public virtual (DateTime t, double v) Add((double o, double h, double l, double c, double v) p, bool update = false) => + Add((t: (this.Count == 0) ? DateTime.Today : this[^1].t.AddDays(1), p.o, p.h, p.l, p.c, p.v), update); + + public virtual (DateTime t, double v) Add(double o, double h, double l, double c, double v, bool update = false) => + Add((o, h, l, c, v), update); + + public virtual (DateTime t, double v) Add(DateTime t, double o, double h, double l, double c, double v, bool update = false) => + this.Add((t, o, h, l, c, v), update); + + public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + if (update) { this[^1] = TBar; } else { base.Add(TBar); } + + _open.Add((TBar.t, TBar.o), update); + _high.Add((TBar.t, TBar.h), update); + _low.Add((TBar.t, TBar.l), update); + _close.Add((TBar.t, TBar.c), update); + _volume.Add((TBar.t, TBar.v), update); + _hl2.Add((TBar.t, (TBar.h + TBar.l) * 0.5), update); + _oc2.Add((TBar.t, (TBar.o + TBar.c) * 0.5), update); + _ohl3.Add((TBar.t, (TBar.o + TBar.h + TBar.l) * 0.333333333333333), update); + _hlc3.Add((TBar.t, (TBar.h + TBar.l + TBar.c) * 0.333333333333333), update); + _ohlc4.Add((TBar.t, (TBar.o + TBar.h + TBar.l + TBar.c) * 0.25), update); + _hlcc4.Add((TBar.t, (TBar.h + TBar.l + TBar.c + TBar.c) * 0.25), update); + + this.OnEvent(update); + return (TBar.t, (TBar.o + TBar.h + TBar.l + TBar.c) * 0.25); + } + + public delegate void NewDataEventHandler(object source, TSeriesEventArgs args); + public event NewDataEventHandler Pub; + protected virtual void OnEvent(bool update = false) + { + if (Pub != null && Pub.Target != this) + { + Pub(this, new TSeriesEventArgs { update = update }); + } + } + + public void Sub(object source, TSeriesEventArgs e) + { + TBars ss = (TBars)source; if (ss.Count > 1) + { + for (int i = 0; i < ss.Count; i++) { this.Add(ss[i]); } + } + else + { + this.Add(ss[^1], e.update); + } + } + + /// common helpers + public static void BufferTrim(System.Collections.Generic.List buffer, double value, int period, bool update) + { + if (!update) + { + buffer.Add(value); + if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); } + return; + } + buffer[^1] = value; + } + public virtual void Reset() + { + } } diff --git a/Calculations/_Updated/TEMA_Series.cs b/Calculations/_Updated/TEMA_Series.cs index f48019fa..88218161 100644 --- a/Calculations/_Updated/TEMA_Series.cs +++ b/Calculations/_Updated/TEMA_Series.cs @@ -18,103 +18,117 @@ Remark: */ -public class TEMA_Series : TSeries { - private double _k; - private double _sum, _oldsum; - private double _lastema1, _oldema1, _lastema2, _oldema2, _lastema3, _oldema3; - private int _len; - private readonly bool _useSMA; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class TEMA_Series : TSeries +{ + private double _k; + private double _sum, _oldsum; + private double _lastema1, _oldema1, _lastema2, _oldema2, _lastema3, _oldema3; + private int _len; + private readonly bool _useSMA; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; -//core constructor - public TEMA_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - _useSMA = useSMA; - Name = $"TEMA({period})"; - _k = 2.0 / (_period + 1); - _len = 0; - _sum = _oldsum = _lastema1 = _lastema2 = _lastema3 = 0; - } - public TEMA_Series() : this(0, false, true) {} - public TEMA_Series(int period) : this(period, false, true) {} - public TEMA_Series(TBars source) : this(source.Close, 0, false) {} - public TEMA_Series(TBars source, int period) : this(source.Close, period, false) {} - public TEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public TEMA_Series(TSeries source, int period) : this(source, period, false, true) {} - public TEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) {} - public TEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - -// core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - _lastema1 = _oldema1; - _lastema2 = _oldema2; - _lastema3 = _oldema3; - _sum = _oldsum; - } - else { - _oldema1 = _lastema1; - _oldema2 = _lastema2; - _oldema3 = _lastema3; - _oldsum = _sum; - _len++; - } + //core constructor + public TEMA_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + _useSMA = useSMA; + Name = $"TEMA({period})"; + _k = 2.0 / (_period + 1); + _len = 0; + _sum = _oldsum = _lastema1 = _lastema2 = _lastema3 = 0; + } + public TEMA_Series() : this(0, false, true) { } + public TEMA_Series(int period) : this(period, false, true) { } + public TEMA_Series(TBars source) : this(source.Close, 0, false) { } + public TEMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public TEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public TEMA_Series(TSeries source, int period) : this(source, period, false, true) { } + public TEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } + public TEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - if (_period == 0) { _k = 2.0 / (_len + 1); } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + _lastema1 = _oldema1; + _lastema2 = _oldema2; + _lastema3 = _oldema3; + _sum = _oldsum; + } + else + { + _oldema1 = _lastema1; + _oldema2 = _lastema2; + _oldema3 = _lastema3; + _oldsum = _sum; + _len++; + } - double _ema1, _ema2, _ema3, _tema; - if (this.Count == 0) { - _ema1 = _ema2 = _ema3 =_sum = TValue.v; - } - else if (_len <= _period && _useSMA && _period != 0) { - _sum += TValue.v; - _ema1 = _sum / Math.Min(_len, _period); - _ema2 = _ema1; - _ema3 = _ema2; - } - else { - _ema1 = (TValue.v - _lastema1) * _k + _lastema1; - _ema2 = (_ema1 - _lastema2) * _k + _lastema2; - _ema3 = (_ema2 - _lastema3) * _k + _lastema3; - } + if (_period == 0) { _k = 2.0 / (_len + 1); } - _tema = (3 * (_ema1 - _ema2)) + _ema3; + double _ema1, _ema2, _ema3, _tema; + if (this.Count == 0) + { + _ema1 = _ema2 = _ema3 = _sum = TValue.v; + } + else if (_len <= _period && _useSMA && _period != 0) + { + _sum += TValue.v; + _ema1 = _sum / Math.Min(_len, _period); + _ema2 = _ema1; + _ema3 = _ema2; + } + else + { + _ema1 = (TValue.v - _lastema1) * _k + _lastema1; + _ema2 = (_ema1 - _lastema2) * _k + _lastema2; + _ema3 = (_ema2 - _lastema3) * _k + _lastema3; + } - _lastema1 = Double.IsNaN(_ema1)?_lastema1:_ema1; - _lastema2 = Double.IsNaN(_ema2)?_lastema2:_ema2; - _lastema3 = Double.IsNaN(_ema3) ? _lastema3 : _ema3; + _tema = (3 * (_ema1 - _ema2)) + _ema3; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _tema); - return base.Add(res, update); - } - -//variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } - - //reset calculation - public override void Reset() { - _sum = _oldsum = _lastema1 = _lastema2 = 0; - _len = 0; - } + _lastema1 = Double.IsNaN(_ema1) ? _lastema1 : _ema1; + _lastema2 = Double.IsNaN(_ema2) ? _lastema2 : _ema2; + _lastema3 = Double.IsNaN(_ema3) ? _lastema3 : _ema3; + + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _tema); + return base.Add(res, update); + } + + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _sum = _oldsum = _lastema1 = _lastema2 = 0; + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/TRIMA_Series.cs b/Calculations/_Updated/TRIMA_Series.cs index 050a4b88..703f594d 100644 --- a/Calculations/_Updated/TRIMA_Series.cs +++ b/Calculations/_Updated/TRIMA_Series.cs @@ -15,70 +15,80 @@ Remark: */ -public class TRIMA_Series : TSeries { - private readonly int _p1a, _p1b; - private readonly SMA_Series sma, trima; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class TRIMA_Series : TSeries +{ + private readonly int _p1a, _p1b; + private readonly SMA_Series sma, trima; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public TRIMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"xMA({period})"; - _p1a = (int)Math.Floor((period * 0.5) + 1); - _p1b = (int)Math.Ceiling(0.5 * period); - sma = new(_p1a); - trima = new(_p1b); + //core constructors + public TRIMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"xMA({period})"; + _p1a = (int)Math.Floor((period * 0.5) + 1); + _p1b = (int)Math.Ceiling(0.5 * period); + sma = new(_p1a); + trima = new(_p1b); - } - public TRIMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public TRIMA_Series() : this(period: 0, useNaN: false) { } - public TRIMA_Series(int period) : this(period: period, useNaN: false) { } - public TRIMA_Series(TBars source) : this(source.Close, 0, false) { } - public TRIMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public TRIMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public TRIMA_Series(TSeries source) : this(source, 0, false) { } - public TRIMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + } + public TRIMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public TRIMA_Series() : this(period: 0, useNaN: false) { } + public TRIMA_Series(int period) : this(period: period, useNaN: false) { } + public TRIMA_Series(TBars source) : this(source.Close, 0, false) { } + public TRIMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public TRIMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public TRIMA_Series(TSeries source) : this(source, 0, false) { } + public TRIMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } - var _sma = sma.Add(TValue, update); - var _trima = trima.Add(_sma, update); + var _sma = sma.Add(TValue, update); + var _trima = trima.Add(_sma, update); - var res = (_trima.t, Count < _period - 1 && _NaN ? double.NaN : _trima.v); - return base.Add(res, update); - } + var res = (_trima.t, Count < _period - 1 && _NaN ? double.NaN : _trima.v); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - sma.Reset(); - trima.Reset(); - } + //reset calculation + public override void Reset() + { + sma.Reset(); + trima.Reset(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/TRIX_Series.cs b/Calculations/_Updated/TRIX_Series.cs index f955bf04..049c23da 100644 --- a/Calculations/_Updated/TRIX_Series.cs +++ b/Calculations/_Updated/TRIX_Series.cs @@ -14,105 +14,119 @@ Sources: */ -public class TRIX_Series : TSeries { - private readonly double _k; - private readonly System.Collections.Generic.List _buffer1 = new(); - private readonly System.Collections.Generic.List _buffer2 = new(); - private readonly System.Collections.Generic.List _buffer3 = new(); - private double _lastema1, _lastema2, _lastema3; - private double _llastema1, _llastema2, _llastema3; - private int _len; - private readonly bool _useSMA; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class TRIX_Series : TSeries +{ + private readonly double _k; + private readonly System.Collections.Generic.List _buffer1 = new(); + private readonly System.Collections.Generic.List _buffer2 = new(); + private readonly System.Collections.Generic.List _buffer3 = new(); + private double _lastema1, _lastema2, _lastema3; + private double _llastema1, _llastema2, _llastema3; + private int _len; + private readonly bool _useSMA; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; -//core constructors + //core constructors - public TRIX_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - _useSMA = useSMA; - Name = $"TRIX({period})"; - _k = 2.0 / (_period + 1); - _len = 0; - _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = 0; - } - public TRIX_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public TRIX_Series() : this(0, false, true) {} - public TRIX_Series(int period) : this(period, false, true) {} - public TRIX_Series(TBars source) : this(source.Close, 0, false) {} - public TRIX_Series(TBars source, int period) : this(source.Close, period, false) {} - public TRIX_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {} - public TRIX_Series(TSeries source, int period) : this(source, period, false, true) {} - public TRIX_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) {} + public TRIX_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + _useSMA = useSMA; + Name = $"TRIX({period})"; + _k = 2.0 / (_period + 1); + _len = 0; + _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = 0; + } + public TRIX_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public TRIX_Series() : this(0, false, true) { } + public TRIX_Series(int period) : this(period, false, true) { } + public TRIX_Series(TBars source) : this(source.Close, 0, false) { } + public TRIX_Series(TBars source, int period) : this(source.Close, period, false) { } + public TRIX_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public TRIX_Series(TSeries source, int period) : this(source, period, false, true) { } + public TRIX_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (double.IsNaN(TValue.v)) { - return base.Add((TValue.t, Double.NaN), update); - } - if (_len == 0) { _lastema1 = _lastema2 = _lastema3 = TValue.v; } - if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; } - else { _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _len++; - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (double.IsNaN(TValue.v)) + { + return base.Add((TValue.t, Double.NaN), update); + } + if (_len == 0) { _lastema1 = _lastema2 = _lastema3 = TValue.v; } + if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; } + else + { + _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _len++; + } - double _ema1, _ema2, _ema3; - if ((this.Count < _period) && _useSMA) { - BufferTrim(_buffer1, TValue.v, _period, update); - _ema1 = 0; - for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; } - _ema1 /= _buffer1.Count; + double _ema1, _ema2, _ema3; + if ((this.Count < _period) && _useSMA) + { + BufferTrim(_buffer1, TValue.v, _period, update); + _ema1 = 0; + for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; } + _ema1 /= _buffer1.Count; - BufferTrim(_buffer2, _ema1, _period, update); - _ema2 = 0; - for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } - _ema2 /= _buffer2.Count; + BufferTrim(_buffer2, _ema1, _period, update); + _ema2 = 0; + for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; } + _ema2 /= _buffer2.Count; - BufferTrim(_buffer3, _ema2, _period, update); - _ema3 = 0; - for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; } - _ema3 /= _buffer3.Count; - } - else { - _ema1 = (TValue.v - _lastema1) * _k + _lastema1; - _ema2 = (_ema1 - _lastema2) * _k + _lastema2; - _ema3 = (_ema2 - _lastema3) * _k + _lastema3; - } - double _trix = 100 * (_ema3 - _lastema3) / _lastema3; - _lastema1 = _ema1; - _lastema2 = _ema2; - _lastema3 = _ema3; + BufferTrim(_buffer3, _ema2, _period, update); + _ema3 = 0; + for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; } + _ema3 /= _buffer3.Count; + } + else + { + _ema1 = (TValue.v - _lastema1) * _k + _lastema1; + _ema2 = (_ema1 - _lastema2) * _k + _lastema2; + _ema3 = (_ema2 - _lastema3) * _k + _lastema3; + } + double _trix = 100 * (_ema3 - _lastema3) / _lastema3; + _lastema1 = _ema1; + _lastema2 = _ema2; + _lastema3 = _ema3; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _trix); - return base.Add(res, update); - } - -//variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } - - //reset calculation - public override void Reset() { - _len = 0; - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _trix); + return base.Add(res, update); + } + + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } + + //reset calculation + public override void Reset() + { + _len = 0; + } } \ No newline at end of file diff --git a/Calculations/_Updated/TR_Series.cs b/Calculations/_Updated/TR_Series.cs index 9365d5f6..308e08e8 100644 --- a/Calculations/_Updated/TR_Series.cs +++ b/Calculations/_Updated/TR_Series.cs @@ -18,62 +18,74 @@ Sources: */ -public class TR_Series : TSeries { - protected readonly TBars _data; - private double _cm1, _cm1_o; +public class TR_Series : TSeries +{ + protected readonly TBars _data; + private double _cm1, _cm1_o; - //core constructors - public TR_Series() { - Name = $"TR()"; - _cm1 = _cm1_o = double.NaN; - } - public TR_Series(TBars source) { - _data = source; - Name = $"TR({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _cm1 = _cm1_o = double.NaN; - _data.Pub += Sub; - Add(data: _data); - } + //core constructors + public TR_Series() + { + Name = $"TR()"; + _cm1 = _cm1_o = double.NaN; + } + public TR_Series(TBars source) + { + _data = source; + Name = $"TR({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _cm1 = _cm1_o = double.NaN; + _data.Pub += Sub; + Add(data: _data); + } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { - if (update) { - _cm1 = _cm1_o; - } - else { - _cm1_o = _cm1; - } + if (update) + { + _cm1 = _cm1_o; + } + else + { + _cm1_o = _cm1; + } - if (_cm1 is double.NaN) { - _cm1 = TBar.c; - } + 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); - _cm1 = TBar.c; - var ret = (TBar.t, Math.Max(d1, Math.Max(d2, d3))); - return base.Add(ret, update); + double d1 = Math.Abs(TBar.h - TBar.l); + double d2 = Math.Abs(_cm1 - TBar.h); + double d3 = Math.Abs(_cm1 - TBar.l); + _cm1 = TBar.c; + var ret = (TBar.t, Math.Max(d1, Math.Max(d2, d3))); + return base.Add(ret, update); - } + } - public new void Add(TBars data) { - foreach (var item in data) { Add(item, false); } - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TBar: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TBar: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TBar: _data.Last, update: e.update); - } + public new void Add(TBars data) + { + foreach (var item in data) { Add(item, false); } + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TBar: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TBar: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TBar: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _cm1 = _cm1_o = double.NaN; - } + //reset calculation + public override void Reset() + { + _cm1 = _cm1_o = double.NaN; + } } \ No newline at end of file diff --git a/Calculations/_Updated/TSeries.cs b/Calculations/_Updated/TSeries.cs index 4a8a6312..00ba50a2 100644 --- a/Calculations/_Updated/TSeries.cs +++ b/Calculations/_Updated/TSeries.cs @@ -15,103 +15,123 @@ TSeries is the cornerstone of all QuanTAlib classes. - includes publishing and subscribing methods that attach to events */ -public class TSeriesEventArgs : EventArgs { - public bool update { get; set; } +public class TSeriesEventArgs : EventArgs +{ + public bool update { get; set; } } -public class TSeries : List<(DateTime t, double v)> { - private readonly (DateTime t, double v) Default = (DateTime.MinValue, double.NaN); - public IEnumerable t => this.Select(item => item.t); - public IEnumerable v => this.Select(item => item.v); - public (DateTime t, double v) Last => Count > 0 ? this[^1] : Default; +public class TSeries : List<(DateTime t, double v)> +{ + private readonly (DateTime t, double v) Default = (DateTime.MinValue, double.NaN); + public IEnumerable t => this.Select(item => item.t); + public IEnumerable v => this.Select(item => item.v); + public (DateTime t, double v) Last => Count > 0 ? this[^1] : Default; - public int Length => Count; - public string Name { get; set; } - public int Keep = 0; + public int Length => Count; + public string Name { get; set; } + public int Keep = 0; - public TSeries() { - this.Name = "data"; - } + public TSeries() + { + this.Name = "data"; + } - public TSeries(string Name) { - this.Name = Name; - } + public TSeries(string Name) + { + this.Name = Name; + } - public virtual (DateTime t, double v) Add(double v, bool update = false) { - return Add((t: Count == 0 ? DateTime.Today : this[^1].t.AddDays(1), v), update); - } + public virtual (DateTime t, double v) Add(double v, bool update = false) + { + return Add((t: Count == 0 ? DateTime.Today : this[^1].t.AddDays(1), v), update); + } - public virtual (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - if (update) { - this[^1] = TValue; - } - else { - base.Add(TValue); - } + public virtual (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + if (update) + { + this[^1] = TValue; + } + else + { + base.Add(TValue); + } - OnEvent(update); - return TValue; - } + OnEvent(update); + return TValue; + } - public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) { - if (update) { - this[this.Count - 1] = (TBar.t, TBar.c); - } - else { - base.Add((TBar.t, TBar.c)); - } + public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) + { + if (update) + { + this[this.Count - 1] = (TBar.t, TBar.c); + } + else + { + base.Add((TBar.t, TBar.c)); + } - OnEvent(update); - return (TBar.t, TBar.c); - } + OnEvent(update); + return (TBar.t, TBar.c); + } - public virtual (DateTime t, double v) Add(TSeries data) { - foreach (var item in data) { Add(item); } - return data.Last; - } + public virtual (DateTime t, double v) Add(TSeries data) + { + foreach (var item in data) { Add(item); } + return data.Last; + } - public virtual (DateTime t, double v) Add(TBars data) { - foreach (var item in data) { Add(item.c, false); } - return (data.Last.t, data.Last.c); - } + public virtual (DateTime t, double v) Add(TBars data) + { + foreach (var item in data) { Add(item.c, false); } + return (data.Last.t, data.Last.c); + } - public void Sub(object source, TSeriesEventArgs e) { - var data = (TSeries) source; - if (data == null) { return; } - foreach (var item in data) { Add(item); } - } + public void Sub(object source, TSeriesEventArgs e) + { + var data = (TSeries)source; + if (data == null) { return; } + foreach (var item in data) { Add(item); } + } - public delegate void NewEventHandler(object source, TSeriesEventArgs args); + public delegate void NewEventHandler(object source, TSeriesEventArgs args); - public event NewEventHandler Pub; + public event NewEventHandler Pub; - protected virtual void OnEvent(bool update = false) - { - if (Keep > 0) { - TrimToSize(keep:Keep); - } - Pub?.Invoke(this, new TSeriesEventArgs {update = update}); - } + protected virtual void OnEvent(bool update = false) + { + if (Keep > 0) + { + TrimToSize(keep: Keep); + } + Pub?.Invoke(this, new TSeriesEventArgs { update = update }); + } - /// common helpers - public static void BufferTrim(List buffer, double value, int period, bool update) { - if (!update) { - buffer.Add(value); - if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); } - return; - } - buffer[^1] = value; - } - public virtual void Reset() { - } + /// common helpers + public static void BufferTrim(List buffer, double value, int period, bool update) + { + if (!update) + { + buffer.Add(value); + if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); } + return; + } + buffer[^1] = value; + } + public virtual void Reset() + { + } - public void TrimToSize(int keep) { - if (keep >= this.Count) { - return; // No need to trim if the series is already smaller than or equal to n - } + public void TrimToSize(int keep) + { + if (keep >= this.Count) + { + return; // No need to trim if the series is already smaller than or equal to n + } - // Remove elements from the beginning of the list - int elementsToRemove = this.Count - keep; - RemoveRange(0, elementsToRemove); - } + // Remove elements from the beginning of the list + int elementsToRemove = this.Count - keep; + RemoveRange(0, elementsToRemove); + } } diff --git a/Calculations/_Updated/VAR_Series.cs b/Calculations/_Updated/VAR_Series.cs index fcd0caba..20b7a556 100644 --- a/Calculations/_Updated/VAR_Series.cs +++ b/Calculations/_Updated/VAR_Series.cs @@ -18,64 +18,73 @@ Remark: */ -public class VAR_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class VAR_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public VAR_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"VAR({period})"; - } - public VAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public VAR_Series() : this(period: 0, useNaN: false) { } - public VAR_Series(int period) : this(period: period, useNaN: false) { } - public VAR_Series(TBars source) : this(source.Close, 0, false) { } - public VAR_Series(TBars source, int period) : this(source.Close, period, false) { } - public VAR_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public VAR_Series(TSeries source) : this(source, 0, false) { } - public VAR_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public VAR_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"VAR({period})"; + } + public VAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public VAR_Series() : this(period: 0, useNaN: false) { } + public VAR_Series(int period) : this(period: period, useNaN: false) { } + public VAR_Series(TBars source) : this(source.Close, 0, false) { } + public VAR_Series(TBars source, int period) : this(source.Close, period, false) { } + public VAR_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public VAR_Series(TSeries source) : this(source, 0, false) { } + public VAR_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _pvar = 0; - for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } - _pvar /= this._buffer.Count; + double _pvar = 0; + for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } + _pvar /= this._buffer.Count; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _pvar); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _pvar); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/WMAPE_Series.cs b/Calculations/_Updated/WMAPE_Series.cs index bbbdeee4..7dfc95cb 100644 --- a/Calculations/_Updated/WMAPE_Series.cs +++ b/Calculations/_Updated/WMAPE_Series.cs @@ -15,68 +15,78 @@ Sources: */ -public class WMAPE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class WMAPE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public WMAPE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"WMAPE({period})"; - } - public WMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public WMAPE_Series() : this(period: 0, useNaN: false) { } - public WMAPE_Series(int period) : this(period: period, useNaN: false) { } - public WMAPE_Series(TBars source) : this(source.Close, 0, false) { } - public WMAPE_Series(TBars source, int period) : this(source.Close, period, false) { } - public WMAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public WMAPE_Series(TSeries source) : this(source, 0, false) { } - public WMAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public WMAPE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"WMAPE({period})"; + } + public WMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public WMAPE_Series() : this(period: 0, useNaN: false) { } + public WMAPE_Series(int period) : this(period: period, useNaN: false) { } + public WMAPE_Series(TBars source) : this(source.Close, 0, false) { } + public WMAPE_Series(TBars source, int period) : this(source.Close, period, false) { } + public WMAPE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public WMAPE_Series(TSeries source) : this(source, 0, false) { } + public WMAPE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - double _sma = _buffer.Average(); + double _sma = _buffer.Average(); - double _div = 0; - double _wmape = 0; - for (int i = 0; i < _buffer.Count; i++) { - _wmape += Math.Abs(_buffer[i] - _sma); - _div += Math.Abs(_buffer[i]); - } - _wmape = (_div != 0) ? _wmape / _div : double.PositiveInfinity; + double _div = 0; + double _wmape = 0; + for (int i = 0; i < _buffer.Count; i++) + { + _wmape += Math.Abs(_buffer[i] - _sma); + _div += Math.Abs(_buffer[i]); + } + _wmape = (_div != 0) ? _wmape / _div : double.PositiveInfinity; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _wmape); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _wmape); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/WMA_Series.cs b/Calculations/_Updated/WMA_Series.cs index f423e3ca..957660fd 100644 --- a/Calculations/_Updated/WMA_Series.cs +++ b/Calculations/_Updated/WMA_Series.cs @@ -17,88 +17,101 @@ Sources: */ -public class WMA_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - private System.Collections.Generic.List _weights; - protected int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - protected int _len; - public int Len { - get { return _len; } - set { _len = value; } - } +public class WMA_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + private System.Collections.Generic.List _weights; + protected int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + protected int _len; + public int Len + { + get { return _len; } + set { _len = value; } + } - //core constructors - public WMA_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"WMA({period})"; - _len = 1; - _weights = CalculateWeights(_period); - } - public WMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public WMA_Series() : this(period: 0, useNaN: false) { } - public WMA_Series(int period) : this(period: period, useNaN: false) { } - public WMA_Series(TBars source) : this(source.Close, 0, false) { } - public WMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public WMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public WMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public WMA_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"WMA({period})"; + _len = 1; + _weights = CalculateWeights(_period); + } + public WMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public WMA_Series() : this(period: 0, useNaN: false) { } + public WMA_Series(int period) : this(period: period, useNaN: false) { } + public WMA_Series(TBars source) : this(source.Close, 0, false) { } + public WMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public WMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public WMA_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update=false) { - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - if (_period == 0) { - _weights = CalculateWeights(_len); - _len++; - } - double _wma = 0; - double totalWeights = (_buffer.Count * (_buffer.Count + 1)) * 0.5; - object lockObj = new object(); - Parallel.For(0, _buffer.Count, i => - { - double temp = _buffer[i] * this._weights[i]; - lock (lockObj) { _wma += temp; } - }); - _wma /= totalWeights; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _wma); - return base.Add(res, update); - } + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + if (_period == 0) + { + _weights = CalculateWeights(_len); + _len++; + } + double _wma = 0; + double totalWeights = (_buffer.Count * (_buffer.Count + 1)) * 0.5; + object lockObj = new object(); + Parallel.For(0, _buffer.Count, i => + { + double temp = _buffer[i] * this._weights[i]; + lock (lockObj) { _wma += temp; } + }); + _wma /= totalWeights; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _wma); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //calculating weights - private static List CalculateWeights(int period) { - List weights = new List(period); - for (int i = 0; i < period; i++) { - weights.Add(i + 1); - } - return weights; - } + //calculating weights + private static List CalculateWeights(int period) + { + List weights = new List(period); + for (int i = 0; i < period; i++) + { + weights.Add(i + 1); + } + return weights; + } - //reset calculation - public override void Reset() { - _len = 0; - _weights = CalculateWeights(_period); - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _len = 0; + _weights = CalculateWeights(_period); + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/ZLEMA_Series.cs b/Calculations/_Updated/ZLEMA_Series.cs index 0f7cd56c..d0c2158d 100644 --- a/Calculations/_Updated/ZLEMA_Series.cs +++ b/Calculations/_Updated/ZLEMA_Series.cs @@ -21,75 +21,85 @@ Remark: */ -public class ZLEMA_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - private int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly EMA_Series _ema; +public class ZLEMA_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + private int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly EMA_Series _ema; - //core constructor - public ZLEMA_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - Name = $"ZLEMA({period})"; - _len = 1; - _ema = new(period); - } - //generic constructors (source) + //core constructor + public ZLEMA_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + Name = $"ZLEMA({period})"; + _len = 1; + _ema = new(period); + } + //generic constructors (source) - public ZLEMA_Series() : this(0, false, true) { } - public ZLEMA_Series(int period) : this(period, false, true) { } - public ZLEMA_Series(TBars source) : this(source.Close, 0, false) { } - public ZLEMA_Series(TBars source, int period) : this(source.Close, period, false) { } - public ZLEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public ZLEMA_Series(TSeries source, int period) : this(source, period, false, true) { } - public ZLEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } - public ZLEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public ZLEMA_Series() : this(0, false, true) { } + public ZLEMA_Series(int period) : this(period, false, true) { } + public ZLEMA_Series(TBars source) : this(source.Close, 0, false) { } + public ZLEMA_Series(TBars source, int period) : this(source.Close, period, false) { } + public ZLEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public ZLEMA_Series(TSeries source, int period) : this(source, period, false, true) { } + public ZLEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } + public ZLEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - int _lag; - if (_period == 0) { - _lag = (int)((_len - 1) * 0.5); - _len++; - } - else { _lag = (int)((_period - 1) * 0.5); } - _lag = Math.Min(_lag, _buffer.Count - 1); - _lag = Math.Max(_lag, 0) + 1; - double _zlValue = 2 * TValue.v - _buffer[^_lag]; - double _zlema = _ema.Add((TValue.t, _zlValue), update).v; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zlema); - return base.Add(res, update); - } + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + int _lag; + if (_period == 0) + { + _lag = (int)((_len - 1) * 0.5); + _len++; + } + else { _lag = (int)((_period - 1) * 0.5); } + _lag = Math.Min(_lag, _buffer.Count - 1); + _lag = Math.Max(_lag, 0) + 1; + double _zlValue = 2 * TValue.v - _buffer[^_lag]; + double _zlema = _ema.Add((TValue.t, _zlValue), update).v; + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zlema); + return base.Add(res, update); + } - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - _ema.Reset(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + _ema.Reset(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/ZL_Series.cs b/Calculations/_Updated/ZL_Series.cs index 033088e4..f7f6088b 100644 --- a/Calculations/_Updated/ZL_Series.cs +++ b/Calculations/_Updated/ZL_Series.cs @@ -17,74 +17,84 @@ Sources: */ -public class ZL_Series: TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - private int _len; - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; - private readonly EMA_Series _ema; +public class ZL_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + private int _len; + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; + private readonly EMA_Series _ema; - //core constructor - public ZL_Series(int period, bool useNaN, bool useSMA) { - _period = period; - _NaN = useNaN; - Name = $"ZL({period})"; - _len = 1; - _ema = new(period); - } - //generic constructors (source) + //core constructor + public ZL_Series(int period, bool useNaN, bool useSMA) + { + _period = period; + _NaN = useNaN; + Name = $"ZL({period})"; + _len = 1; + _ema = new(period); + } + //generic constructors (source) - public ZL_Series() : this(0, false, true) { } - public ZL_Series(int period) : this(period, false, true) { } - public ZL_Series(TBars source) : this(source.Close, 0, false) { } - public ZL_Series(TBars source, int period) : this(source.Close, period, false) { } - public ZL_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public ZL_Series(TSeries source, int period) : this(source, period, false, true) { } - public ZL_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } - public ZL_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } + public ZL_Series() : this(0, false, true) { } + public ZL_Series(int period) : this(period, false, true) { } + public ZL_Series(TBars source) : this(source.Close, 0, false) { } + public ZL_Series(TBars source, int period) : this(source.Close, period, false) { } + public ZL_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public ZL_Series(TSeries source, int period) : this(source, period, false, true) { } + public ZL_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { } + public ZL_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); - int _lag; - if (_period == 0) { - _lag = (int)((_len - 1) * 0.5); - _len++; - } - else { _lag = (int)((_period - 1) * 0.5); } - _lag = Math.Min(_lag, _buffer.Count - 1); - _lag = Math.Max(_lag, 0) + 1; - double _zlValue = 2 * TValue.v - _buffer[^_lag]; + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + int _lag; + if (_period == 0) + { + _lag = (int)((_len - 1) * 0.5); + _len++; + } + else { _lag = (int)((_period - 1) * 0.5); } + _lag = Math.Min(_lag, _buffer.Count - 1); + _lag = Math.Max(_lag, 0) + 1; + double _zlValue = 2 * TValue.v - _buffer[^_lag]; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zlValue); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zlValue); + return base.Add(res, update); + } - //variation of Add() - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + //variation of Add() + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - _ema.Reset(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + _ema.Reset(); + } } \ No newline at end of file diff --git a/Calculations/_Updated/ZSCORE_Series.cs b/Calculations/_Updated/ZSCORE_Series.cs index 06c37130..d8e5699d 100644 --- a/Calculations/_Updated/ZSCORE_Series.cs +++ b/Calculations/_Updated/ZSCORE_Series.cs @@ -24,65 +24,74 @@ Calculation: */ -public class ZSCORE_Series : TSeries { - private readonly System.Collections.Generic.List _buffer = new(); - protected readonly int _period; - protected readonly bool _NaN; - protected readonly TSeries _data; +public class ZSCORE_Series : TSeries +{ + private readonly System.Collections.Generic.List _buffer = new(); + protected readonly int _period; + protected readonly bool _NaN; + protected readonly TSeries _data; - //core constructors - public ZSCORE_Series(int period, bool useNaN) { - _period = period; - _NaN = useNaN; - Name = $"ZSCORE({period})"; - } - public ZSCORE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) { - _data = source; - Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; - _data.Pub += Sub; - Add(_data); - } - public ZSCORE_Series() : this(period: 0, useNaN: false) { } - public ZSCORE_Series(int period) : this(period: period, useNaN: false) { } - public ZSCORE_Series(TBars source) : this(source.Close, 0, false) { } - public ZSCORE_Series(TBars source, int period) : this(source.Close, period, false) { } - public ZSCORE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } - public ZSCORE_Series(TSeries source) : this(source, 0, false) { } - public ZSCORE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } + //core constructors + public ZSCORE_Series(int period, bool useNaN) + { + _period = period; + _NaN = useNaN; + Name = $"ZSCORE({period})"; + } + public ZSCORE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) + { + _data = source; + Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})"; + _data.Pub += Sub; + Add(_data); + } + public ZSCORE_Series() : this(period: 0, useNaN: false) { } + public ZSCORE_Series(int period) : this(period: period, useNaN: false) { } + public ZSCORE_Series(TBars source) : this(source.Close, 0, false) { } + public ZSCORE_Series(TBars source, int period) : this(source.Close, period, false) { } + public ZSCORE_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { } + public ZSCORE_Series(TSeries source) : this(source, 0, false) { } + public ZSCORE_Series(TSeries source, int period) : this(source: source, period: period, useNaN: false) { } - ////////////////// - // core Add() algo - public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) { - BufferTrim(buffer:_buffer, value:TValue.v, period:_period, update: update); - double _sma = _buffer.Average(); + ////////////////// + // core Add() algo + public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) + { + BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update); + double _sma = _buffer.Average(); - double _pvar = 0; - for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } - _pvar /= this._buffer.Count; - double _psdev = Math.Sqrt(_pvar); - double _zscore = (_psdev == 0) ? 1 : (TValue.v - _sma) / _psdev; + double _pvar = 0; + for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); } + _pvar /= this._buffer.Count; + double _psdev = Math.Sqrt(_pvar); + double _zscore = (_psdev == 0) ? 1 : (TValue.v - _sma) / _psdev; - var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zscore); - return base.Add(res, update); - } + var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _zscore); + return base.Add(res, update); + } - public override (DateTime t, double v) Add(TSeries data) { - if (data == null) { return (DateTime.Today, Double.NaN); } - foreach (var item in data) { Add(item, false); } - return _data.Last; - } - public (DateTime t, double v) Add(bool update) { - return this.Add(TValue: _data.Last, update: update); - } - public (DateTime t, double v) Add() { - return Add(TValue: _data.Last, update: false); - } - private new void Sub(object source, TSeriesEventArgs e) { - Add(TValue: _data.Last, update: e.update); - } + public override (DateTime t, double v) Add(TSeries data) + { + if (data == null) { return (DateTime.Today, Double.NaN); } + foreach (var item in data) { Add(item, false); } + return _data.Last; + } + public (DateTime t, double v) Add(bool update) + { + return this.Add(TValue: _data.Last, update: update); + } + public (DateTime t, double v) Add() + { + return Add(TValue: _data.Last, update: false); + } + private new void Sub(object source, TSeriesEventArgs e) + { + Add(TValue: _data.Last, update: e.update); + } - //reset calculation - public override void Reset() { - _buffer.Clear(); - } + //reset calculation + public override void Reset() + { + _buffer.Clear(); + } } \ No newline at end of file diff --git a/Indicators/Charts/2MACross_chart.cs b/Indicators/Charts/2MACross_chart.cs index 58a8063d..19ead156 100644 --- a/Indicators/Charts/2MACross_chart.cs +++ b/Indicators/Charts/2MACross_chart.cs @@ -4,270 +4,284 @@ using System.Linq; using TradingPlatform.BusinessLayer; namespace QuanTAlib; -public class MovingAverage_chart : Indicator { - #region Parameters - [InputParameter("MA1: Type:", 0, variants: new object[] - { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, - "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] - private int MA1type = 15; +public class MovingAverage_chart : Indicator +{ + #region Parameters + [InputParameter("MA1: Type:", 0, variants: new object[] + { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, + "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] + private int MA1type = 15; - [InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)] - private int MA1Period = 10; + [InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)] + private int MA1Period = 10; - [InputParameter("MA1: Data source:", 2, variants: new object[] - { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, - "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] - private int MA1DataSource = 3; + [InputParameter("MA1: Data source:", 2, variants: new object[] + { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, + "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] + private int MA1DataSource = 3; - [InputParameter("MA2: Type:", 3, variants: new object[] - { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, - "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] - private int MA2type = 16; + [InputParameter("MA2: Type:", 3, variants: new object[] + { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, + "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] + private int MA2type = 16; - [InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)] - private int MA2Period = 50; + [InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)] + private int MA2Period = 50; - [InputParameter("MA2: Data source:", 5, variants: new object[] - { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, - "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] - private int MA2DataSource = 8; + [InputParameter("MA2: Data source:", 5, variants: new object[] + { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, + "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] + private int MA2DataSource = 8; - [InputParameter("Long trades", 6)] - private bool LongTrades = true; + [InputParameter("Long trades", 6)] + private bool LongTrades = true; - [InputParameter("Short trades", 6)] - private bool ShortTrades = true; + [InputParameter("Short trades", 6)] + private bool ShortTrades = true; - #endregion Parameters + #endregion Parameters - protected HistoricalData History; - private TBars bars; + protected HistoricalData History; + private TBars bars; - /////// - private TSeries MA1, MA2; - private CROSS_Series trades; - private COMPARE_Series overunder; + /////// + private TSeries MA1, MA2; + private CROSS_Series trades; + private COMPARE_Series overunder; - /////// + /////// - public MovingAverage_chart() { - this.SeparateWindow = false; - this.Name = "MAs Crossover"; - this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid); - this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid); - } + public MovingAverage_chart() + { + this.SeparateWindow = false; + this.Name = "MAs Crossover"; + this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid); + this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid); + } - protected override void OnInit() { - this.bars = new(); - this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); - for (int i = this.History.Count - 1; i >= 0; i--) { - var rec = this.History[i, SeekOriginHistory.Begin]; - bars.Add(rec.TimeLeft, rec[PriceType.Open], - rec[PriceType.High], rec[PriceType.Low], - rec[PriceType.Close], rec[PriceType.Volume]); - } - this.Name = "MAs Cross: [ "; - switch (MA1type) { - case 0: - MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"SMA"; - break; - case 1: - MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"EMA"; - break; - case 2: - MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"WMA"; - break; - case 3: - MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"T3"; - break; - case 4: - MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"SMMA"; - break; - case 5: - MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"TRIMA"; - break; - case 6: - MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"DWMA"; - break; - case 7: - MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period); - this.Name += $"FWMA"; - break; - case 8: - MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"DEMA"; - break; - case 9: - MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"TEMA"; - break; - case 10: - MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"ALMA"; - break; - case 11: - MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"HMA"; - break; - case 12: - MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"HEMA"; - break; - case 13: - double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period); - MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); - this.Name += $"MAMA"; - break; - case 14: - MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"KAMA"; - break; - case 15: - MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"ZLEMA"; - break; - default: - MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"JMA"; - break; - } + protected override void OnInit() + { + this.bars = new(); + this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); + for (int i = this.History.Count - 1; i >= 0; i--) + { + var rec = this.History[i, SeekOriginHistory.Begin]; + bars.Add(rec.TimeLeft, rec[PriceType.Open], + rec[PriceType.High], rec[PriceType.Low], + rec[PriceType.Close], rec[PriceType.Volume]); + } + this.Name = "MAs Cross: [ "; + switch (MA1type) + { + case 0: + MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"SMA"; + break; + case 1: + MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"EMA"; + break; + case 2: + MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"WMA"; + break; + case 3: + MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"T3"; + break; + case 4: + MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"SMMA"; + break; + case 5: + MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"TRIMA"; + break; + case 6: + MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"DWMA"; + break; + case 7: + MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period); + this.Name += $"FWMA"; + break; + case 8: + MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"DEMA"; + break; + case 9: + MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"TEMA"; + break; + case 10: + MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"ALMA"; + break; + case 11: + MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"HMA"; + break; + case 12: + MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"HEMA"; + break; + case 13: + double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period); + MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); + this.Name += $"MAMA"; + break; + case 14: + MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"KAMA"; + break; + case 15: + MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"ZLEMA"; + break; + default: + MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"JMA"; + break; + } - this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : "; + this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : "; - switch (MA2type) { - case 0: - MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"SMA"; - break; - case 1: - MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"EMA"; - break; - case 2: - MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"WMA"; - break; - case 3: - MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"T3"; - break; - case 4: - MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"SMMA"; - break; - case 5: - MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"TRIMA"; - break; - case 6: - MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"DWMA"; - break; - case 7: - MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period); - this.Name += $"FWMA"; - break; - case 8: - MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"DEMA"; - break; - case 9: - MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"TEMA"; - break; - case 10: - MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"ALMA"; - break; - case 11: - MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"HMA"; - break; - case 12: - MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"HEMA"; - break; - case 13: - double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period); - MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); - this.Name += $"MAMA"; - break; - case 14: - MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"KAMA"; - break; - case 15: - MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"ZLEMA"; - break; - default: - MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"JMA"; - break; - } - this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]"; + switch (MA2type) + { + case 0: + MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"SMA"; + break; + case 1: + MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"EMA"; + break; + case 2: + MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"WMA"; + break; + case 3: + MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"T3"; + break; + case 4: + MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"SMMA"; + break; + case 5: + MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"TRIMA"; + break; + case 6: + MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"DWMA"; + break; + case 7: + MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period); + this.Name += $"FWMA"; + break; + case 8: + MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"DEMA"; + break; + case 9: + MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"TEMA"; + break; + case 10: + MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"ALMA"; + break; + case 11: + MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"HMA"; + break; + case 12: + MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"HEMA"; + break; + case 13: + double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period); + MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); + this.Name += $"MAMA"; + break; + case 14: + MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"KAMA"; + break; + case 15: + MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"ZLEMA"; + break; + default: + MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"JMA"; + break; + } + this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]"; - int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100); - MA1.Keep = maxKeep; - MA2.Keep = maxKeep; - trades.Keep = maxKeep; - overunder.Keep = maxKeep; + int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100); + MA1.Keep = maxKeep; + MA2.Keep = maxKeep; + trades.Keep = maxKeep; + overunder.Keep = maxKeep; - overunder = new(MA1, MA2); - trades = new(MA1, MA2); - } + overunder = new(MA1, MA2); + trades = new(MA1, MA2); + } - protected override void OnUpdate(UpdateArgs args) { - bool update = !(args.Reason == UpdateReason.NewBar || - args.Reason == UpdateReason.HistoricalBar); - this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), - this.GetPrice(PriceType.High), - this.GetPrice(PriceType.Low), - this.GetPrice(PriceType.Close), - this.GetPrice(PriceType.Volume), update); - this.SetValue(this.MA1[^1].v, lineIndex: 0); - this.SetValue(this.MA2[^1].v, lineIndex: 1); + protected override void OnUpdate(UpdateArgs args) + { + bool update = !(args.Reason == UpdateReason.NewBar || + args.Reason == UpdateReason.HistoricalBar); + this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), + this.GetPrice(PriceType.High), + this.GetPrice(PriceType.Low), + this.GetPrice(PriceType.Close), + this.GetPrice(PriceType.Volume), update); + this.SetValue(this.MA1[^1].v, lineIndex: 0); + this.SetValue(this.MA2[^1].v, lineIndex: 1); - if (trades[^1].v == 1) { - this.EndCloud(0, 1, Color.Empty); - if (LongTrades) { - this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); - this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green)); - } - if (ShortTrades) { - this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow)); - } - } - if (trades[^1].v == -1) { - this.EndCloud(0, 1, Color.Empty); - if (ShortTrades) { - this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow)); - this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red)); - } - if (LongTrades) { - this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); - } - } - } - public override void OnPaintChart(PaintChartEventArgs args) { - base.OnPaintChart(args); - if (this.CurrentChart == null) {return;} - Graphics graphics = args.Graphics; - var mainWindow = this.CurrentChart.MainWindow; - int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left)); - int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right))); - int historycount = HistoricalData.Count; - int ymax = mainWindow.ClientRectangle.Height; - int xmax = mainWindow.ClientRectangle.Width; + if (trades[^1].v == 1) + { + this.EndCloud(0, 1, Color.Empty); + if (LongTrades) + { + this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); + this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green)); + } + if (ShortTrades) + { + this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow)); + } + } + if (trades[^1].v == -1) + { + this.EndCloud(0, 1, Color.Empty); + if (ShortTrades) + { + this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow)); + this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red)); + } + if (LongTrades) + { + this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); + } + } + } + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + if (this.CurrentChart == null) { return; } + Graphics graphics = args.Graphics; + var mainWindow = this.CurrentChart.MainWindow; + int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left)); + int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right))); + int historycount = HistoricalData.Count; + int ymax = mainWindow.ClientRectangle.Height; + int xmax = mainWindow.ClientRectangle.Width; - /* + /* for (int i = leftIndex; i <= rightIndex; i++) { int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i))); int width = this.CurrentChart.BarsWidth; @@ -280,5 +294,5 @@ public class MovingAverage_chart : Indicator { graphics.FillRectangle(bb, xi, ymax - height, width, height); } */ - } + } } diff --git a/Indicators/Charts/2MASlope_chart.cs b/Indicators/Charts/2MASlope_chart.cs index 65acfa9c..c031e513 100644 --- a/Indicators/Charts/2MASlope_chart.cs +++ b/Indicators/Charts/2MASlope_chart.cs @@ -4,304 +4,317 @@ using System.Linq; using TradingPlatform.BusinessLayer; namespace QuanTAlib; -public class MovingAverageSlope_chart : Indicator { - #region Parameters - [InputParameter("MA1: Type:", 0, variants: new object[] - { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, - "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] - private int MA1type = 16; +public class MovingAverageSlope_chart : Indicator +{ + #region Parameters + [InputParameter("MA1: Type:", 0, variants: new object[] + { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, + "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] + private int MA1type = 16; - [InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)] - private int MA1Period = 10; + [InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)] + private int MA1Period = 10; - [InputParameter("MA1: Data source:", 2, variants: new object[] - { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, - "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] - private int MA1DataSource = 3; + [InputParameter("MA1: Data source:", 2, variants: new object[] + { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, + "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] + private int MA1DataSource = 3; - [InputParameter("MA2: Type:", 3, variants: new object[] - { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, - "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] - private int MA2type = 6; + [InputParameter("MA2: Type:", 3, variants: new object[] + { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9, + "ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})] + private int MA2type = 6; - [InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)] - private int MA2Period = 50; + [InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)] + private int MA2Period = 50; - [InputParameter("MA2: Data source:", 5, variants: new object[] - { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, - "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] - private int MA2DataSource = 8; + [InputParameter("MA2: Data source:", 5, variants: new object[] + { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, + "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] + private int MA2DataSource = 8; - [InputParameter("Data required for slope calc:", 6, 2, 10, 1, 1)] - private int SlopePeriod = 3; + [InputParameter("Data required for slope calc:", 6, 2, 10, 1, 1)] + private int SlopePeriod = 3; - [InputParameter("Long trades", 7)] - private bool LongTrades = true; + [InputParameter("Long trades", 7)] + private bool LongTrades = true; - [InputParameter("Short trades", 8)] - private bool ShortTrades; + [InputParameter("Short trades", 8)] + private bool ShortTrades; - #endregion Parameters + #endregion Parameters - protected HistoricalData History; - private TBars bars; + protected HistoricalData History; + private TBars bars; - /////// - private TSeries MA1, MA2; - private SLOPE_Series sMA1, sMA2; - private CROSS_Series sig1, sig2; + /////// + private TSeries MA1, MA2; + private SLOPE_Series sMA1, sMA2; + private CROSS_Series sig1, sig2; - private bool inLong, inShort; - /////// + private bool inLong, inShort; + /////// - public MovingAverageSlope_chart() { - this.SeparateWindow = false; - this.Name = "Slopes convergence"; - this.AddLineSeries("MA1", Color.DarkSlateGray, 2, LineStyle.Solid); - this.AddLineSeries("MA2", Color.DarkSlateGray, 2, LineStyle.Solid); - } + public MovingAverageSlope_chart() + { + this.SeparateWindow = false; + this.Name = "Slopes convergence"; + this.AddLineSeries("MA1", Color.DarkSlateGray, 2, LineStyle.Solid); + this.AddLineSeries("MA2", Color.DarkSlateGray, 2, LineStyle.Solid); + } - protected override void OnInit() { - this.bars = new(); - this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); - for (int i = this.History.Count - 1; i >= 0; i--) { - var rec = this.History[i, SeekOriginHistory.Begin]; - bars.Add(rec.TimeLeft, rec[PriceType.Open], - rec[PriceType.High], rec[PriceType.Low], - rec[PriceType.Close], rec[PriceType.Volume]); - } - this.Name = "Slopes convergence: [ "; - switch (MA1type) { - case 0: - MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"SMA"; - break; - case 1: - MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"EMA"; - break; - case 2: - MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"WMA"; - break; - case 3: - MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"T3"; - break; - case 4: - MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"SMMA"; - break; - case 5: - MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"TRIMA"; - break; - case 6: - MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"DWMA"; - break; - case 7: - MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period); - this.Name += $"FWMA"; - break; - case 8: - MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"DEMA"; - break; - case 9: - MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"TEMA"; - break; - case 10: - MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"ALMA"; - break; - case 11: - MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"HMA"; - break; - case 12: - MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"HEMA"; - break; - case 13: - double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period); - MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); - this.Name += $"MAMA"; - break; - case 14: - MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"KAMA"; - break; - case 15: - MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"ZLEMA"; - break; - default: - MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); - this.Name += $"JMA"; - break; - } + protected override void OnInit() + { + this.bars = new(); + this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); + for (int i = this.History.Count - 1; i >= 0; i--) + { + var rec = this.History[i, SeekOriginHistory.Begin]; + bars.Add(rec.TimeLeft, rec[PriceType.Open], + rec[PriceType.High], rec[PriceType.Low], + rec[PriceType.Close], rec[PriceType.Volume]); + } + this.Name = "Slopes convergence: [ "; + switch (MA1type) + { + case 0: + MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"SMA"; + break; + case 1: + MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"EMA"; + break; + case 2: + MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"WMA"; + break; + case 3: + MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"T3"; + break; + case 4: + MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"SMMA"; + break; + case 5: + MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"TRIMA"; + break; + case 6: + MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"DWMA"; + break; + case 7: + MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period); + this.Name += $"FWMA"; + break; + case 8: + MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"DEMA"; + break; + case 9: + MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"TEMA"; + break; + case 10: + MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"ALMA"; + break; + case 11: + MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"HMA"; + break; + case 12: + MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"HEMA"; + break; + case 13: + double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period); + MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); + this.Name += $"MAMA"; + break; + case 14: + MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"KAMA"; + break; + case 15: + MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"ZLEMA"; + break; + default: + MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); + this.Name += $"JMA"; + break; + } - this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : "; + this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : "; - switch (MA2type) { - case 0: - MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"SMA"; - break; - case 1: - MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"EMA"; - break; - case 2: - MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"WMA"; - break; - case 3: - MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"T3"; - break; - case 4: - MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"SMMA"; - break; - case 5: - MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"TRIMA"; - break; - case 6: - MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"DWMA"; - break; - case 7: - MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period); - this.Name += $"FWMA"; - break; - case 8: - MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"DEMA"; - break; - case 9: - MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"TEMA"; - break; - case 10: - MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"ALMA"; - break; - case 11: - MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"HMA"; - break; - case 12: - MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"HEMA"; - break; - case 13: - double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period); - MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); - this.Name += $"MAMA"; - break; - case 14: - MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"KAMA"; - break; - case 15: - MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"ZLEMA"; - break; - default: - MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); - this.Name += $"JMA"; - break; - } - this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]"; + switch (MA2type) + { + case 0: + MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"SMA"; + break; + case 1: + MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"EMA"; + break; + case 2: + MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"WMA"; + break; + case 3: + MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"T3"; + break; + case 4: + MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"SMMA"; + break; + case 5: + MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"TRIMA"; + break; + case 6: + MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"DWMA"; + break; + case 7: + MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period); + this.Name += $"FWMA"; + break; + case 8: + MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"DEMA"; + break; + case 9: + MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"TEMA"; + break; + case 10: + MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"ALMA"; + break; + case 11: + MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"HMA"; + break; + case 12: + MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"HEMA"; + break; + case 13: + double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period); + MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false); + this.Name += $"MAMA"; + break; + case 14: + MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"KAMA"; + break; + case 15: + MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"ZLEMA"; + break; + default: + MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false); + this.Name += $"JMA"; + break; + } + this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]"; - sMA1 = new(MA1, SlopePeriod); - sMA2 = new(MA2, SlopePeriod); - sig1 = new(sMA1, 0); - sig2 = new(sMA2, 0); + sMA1 = new(MA1, SlopePeriod); + sMA2 = new(MA2, SlopePeriod); + sig1 = new(sMA1, 0); + sig2 = new(sMA2, 0); - int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100); + int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100); - MA1.Keep = maxKeep; - MA2.Keep = maxKeep; - sMA1.Keep = maxKeep; - sMA2.Keep = maxKeep; - sig1.Keep = maxKeep; - sig2.Keep = maxKeep; - } + MA1.Keep = maxKeep; + MA2.Keep = maxKeep; + sMA1.Keep = maxKeep; + sMA2.Keep = maxKeep; + sig1.Keep = maxKeep; + sig2.Keep = maxKeep; + } - protected override void OnUpdate(UpdateArgs args) { - bool update = !(args.Reason == UpdateReason.NewBar || - args.Reason == UpdateReason.HistoricalBar); - this.bars.Add(this.Time(),this.Open(), this.High(), this.Low(), this.Close(), this.Volume(), update); - this.SetValue(this.MA1[^1].v, lineIndex: 0); - this.SetValue(this.MA2[^1].v, lineIndex: 1); + protected override void OnUpdate(UpdateArgs args) + { + bool update = !(args.Reason == UpdateReason.NewBar || + args.Reason == UpdateReason.HistoricalBar); + this.bars.Add(this.Time(), this.Open(), this.High(), this.Low(), this.Close(), this.Volume(), update); + this.SetValue(this.MA1[^1].v, lineIndex: 0); + this.SetValue(this.MA2[^1].v, lineIndex: 1); - Color s1Color= (this.sMA1[^1].v > 0)?Color.LimeGreen:Color.OrangeRed; - Color s2Color = (this.sMA2[^1].v > 0) ? Color.LimeGreen : Color.OrangeRed; + Color s1Color = (this.sMA1[^1].v > 0) ? Color.LimeGreen : Color.OrangeRed; + Color s2Color = (this.sMA2[^1].v > 0) ? Color.LimeGreen : Color.OrangeRed; - this.LinesSeries[0].SetMarker(0,s1Color); - this.LinesSeries[1].SetMarker(0,s2Color); + this.LinesSeries[0].SetMarker(0, s1Color); + this.LinesSeries[1].SetMarker(0, s2Color); - if (sig1[^1].v > 0 || sig2[^1].v > 0) { - if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades) - { - inLong = true; - this.BeginCloud(0, 1, Color.FromArgb(127, Color.DarkGreen)); - this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v)? 0 : 1 ].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); - } - else { - this.EndCloud(0, 1, Color.Empty); - if (inShort && this.Count > 1) - { - this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow)); - inShort = false; - } - } - } + if (sig1[^1].v > 0 || sig2[^1].v > 0) + { + if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades) + { + inLong = true; + this.BeginCloud(0, 1, Color.FromArgb(127, Color.DarkGreen)); + this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); + } + else + { + this.EndCloud(0, 1, Color.Empty); + if (inShort && this.Count > 1) + { + this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow)); + inShort = false; + } + } + } - if (sig1[^1].v < 0 || sig2[^1].v < 0) { - if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades) - { - inShort = true; - this.BeginCloud(0, 1, Color.FromArgb(100, Color.Red)); - this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow)); - } - else { - this.EndCloud(0, 1, Color.Empty); - if (inLong && this.Count > 1) { - LinesSeries[(this.MA1[^1].v > this.MA2[^1].v)?1:0].SetMarker(1, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); - inLong = false; - } - } - } - } - public override void OnPaintChart(PaintChartEventArgs args) { - base.OnPaintChart(args); - if (this.CurrentChart == null) {return;} - Graphics graphics = args.Graphics; - var mainWindow = this.CurrentChart.MainWindow; - int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left)); - int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right))); -/* - int historycount = HistoricalData.Count; - int ymax = mainWindow.ClientRectangle.Height; + if (sig1[^1].v < 0 || sig2[^1].v < 0) + { + if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades) + { + inShort = true; + this.BeginCloud(0, 1, Color.FromArgb(100, Color.Red)); + this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow)); + } + else + { + this.EndCloud(0, 1, Color.Empty); + if (inLong && this.Count > 1) + { + LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); + inLong = false; + } + } + } + } + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + if (this.CurrentChart == null) { return; } + Graphics graphics = args.Graphics; + var mainWindow = this.CurrentChart.MainWindow; + int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left)); + int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right))); + /* + int historycount = HistoricalData.Count; + int ymax = mainWindow.ClientRectangle.Height; - for (int i = leftIndex; i <= rightIndex; i++) { - int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i))); - int width = this.CurrentChart.BarsWidth; - int height = (int)((equity[i+historycount].v) *proportion); + for (int i = leftIndex; i <= rightIndex; i++) { + int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i))); + int width = this.CurrentChart.BarsWidth; + int height = (int)((equity[i+historycount].v) *proportion); - Brush bb = Brushes.DarkSlateGray; - bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb; - bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb; + Brush bb = Brushes.DarkSlateGray; + bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb; + bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb; - graphics.FillRectangle(bb, xi, ymax - height, width, height); - } -*/ - } + graphics.FillRectangle(bb, xi, ymax - height, width, height); + } + */ + } } diff --git a/Indicators/Charts/JMA_chart.cs b/Indicators/Charts/JMA_chart.cs index 449f6965..d35174cf 100644 --- a/Indicators/Charts/JMA_chart.cs +++ b/Indicators/Charts/JMA_chart.cs @@ -6,92 +6,99 @@ using TradingPlatform.BusinessLayer; using TradingPlatform.BusinessLayer.Chart; namespace QuanTAlib; -public class JMA_chart : Indicator { - #region Parameters +public class JMA_chart : Indicator +{ + #region Parameters - [InputParameter("Data source", 0, variants: new object[] - { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, - "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] - private int DataSource = 3; + [InputParameter("Data source", 0, variants: new object[] + { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5, + "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })] + private int DataSource = 3; - [InputParameter("Smoothing period", 1, 1, 999, 1, 1)] - private int Period = 9; + [InputParameter("Smoothing period", 1, 1, 999, 1, 1)] + private int Period = 9; - [InputParameter("Volatility short", 2, 3, 50, 1, 1)] - private int Vshort = 10; + [InputParameter("Volatility short", 2, 3, 50, 1, 1)] + private int Vshort = 10; - [InputParameter("Volatility long", 3, 20, 500, 1, 1)] - private int Vlong = 65; + [InputParameter("Volatility long", 3, 20, 500, 1, 1)] + private int Vlong = 65; - [InputParameter("Phase", 4, -100, 100, 1, 2)] - private double Jphase; + [InputParameter("Phase", 4, -100, 100, 1, 2)] + private double Jphase; - #endregion Parameters + #endregion Parameters - /////// - private JMA_Series indicator; - /////// + /////// + private JMA_Series indicator; + /////// - protected TBars bars; - protected IChartWindow mainWindow; - protected Graphics graphics; - protected int firstOnScreenBarIndex, lastOnScreenBarIndex; - protected HistoricalData History; - protected int HistPeriod; - public JMA_chart() { - Name = "JMA - Jurik Moving Avg"; - Description = "Jurik Moving Average description"; - AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3,lineStyle: LineStyle.Solid); - SeparateWindow = false; - HistPeriod = Period; - } + protected TBars bars; + protected IChartWindow mainWindow; + protected Graphics graphics; + protected int firstOnScreenBarIndex, lastOnScreenBarIndex; + protected HistoricalData History; + protected int HistPeriod; + public JMA_chart() + { + Name = "JMA - Jurik Moving Avg"; + Description = "Jurik Moving Average description"; + AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); + SeparateWindow = false; + HistPeriod = Period; + } - protected override void OnInit() { - base.OnInit(); - bars = new(); - var dur1 = this.HistoricalData.FromTime; - var dur = this.HistoricalData.Period.Duration.TotalSeconds * (HistPeriod * 4); //seconds of two periods + protected override void OnInit() + { + base.OnInit(); + bars = new(); + var dur1 = this.HistoricalData.FromTime; + var dur = this.HistoricalData.Period.Duration.TotalSeconds * (HistPeriod * 4); //seconds of two periods - this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); + this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); - for (int i = this.History.Count - 1; i >= 0; i--) { + for (int i = this.History.Count - 1; i >= 0; i--) + { - var rec = this.History[i, SeekOriginHistory.Begin]; + var rec = this.History[i, SeekOriginHistory.Begin]; - bars.Add(rec.TimeLeft, rec[PriceType.Open], - rec[PriceType.High], rec[PriceType.Low], - rec[PriceType.Close], rec[PriceType.Volume]); - } + bars.Add(rec.TimeLeft, rec[PriceType.Open], + rec[PriceType.High], rec[PriceType.Low], + rec[PriceType.Close], rec[PriceType.Volume]); + } - indicator = new(source: bars.Select(DataSource), period: Period, phase: Jphase, vshort: Vshort, vlong: Vlong, useNaN: true); - indicator.Keep = Math.Max(Period, 100); - } + indicator = new(source: bars.Select(DataSource), period: Period, phase: Jphase, vshort: Vshort, vlong: Vlong, useNaN: true); + indicator.Keep = Math.Max(Period, 100); + } - protected override void OnUpdate(UpdateArgs args) { - base.OnUpdate(args); - bars.Add(Time(), GetPrice(PriceType.Open), - GetPrice(PriceType.High), - GetPrice(PriceType.Low), - GetPrice(PriceType.Close), - GetPrice(PriceType.Volume), - update: !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar)); - - this.SetValue(indicator[^1].v, lineIndex: 0); - } - public override void OnPaintChart(PaintChartEventArgs args) { - base.OnPaintChart(args); - if (this.CurrentChart == null) { - return; - } + protected override void OnUpdate(UpdateArgs args) + { + base.OnUpdate(args); + bars.Add(Time(), GetPrice(PriceType.Open), + GetPrice(PriceType.High), + GetPrice(PriceType.Low), + GetPrice(PriceType.Close), + GetPrice(PriceType.Volume), + update: !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar)); - graphics = args.Graphics; - mainWindow = this.CurrentChart.MainWindow; + this.SetValue(indicator[^1].v, lineIndex: 0); + } + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + if (this.CurrentChart == null) + { + return; + } - DateTime leftTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left); - DateTime rightTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right); - firstOnScreenBarIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(leftTime); - lastOnScreenBarIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(rightTime)); - } + graphics = args.Graphics; + mainWindow = this.CurrentChart.MainWindow; + + DateTime leftTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left); + DateTime rightTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right); + firstOnScreenBarIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(leftTime); + lastOnScreenBarIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(rightTime)); + } } diff --git a/Indicators/Charts/TrailingStop.cs b/Indicators/Charts/TrailingStop.cs index 50a1d4f7..8ee9f476 100644 --- a/Indicators/Charts/TrailingStop.cs +++ b/Indicators/Charts/TrailingStop.cs @@ -5,91 +5,98 @@ using System.Linq; using TradingPlatform.BusinessLayer; namespace QuanTAlib; -public class TrailingStop_chart : Indicator { - #region Parameters +public class TrailingStop_chart : Indicator +{ + #region Parameters - [InputParameter("Period", 0, 1, 100, 1, 1)] - protected int _period = 30; - - [InputParameter("Factor", 1, 1, 100, 0.1, 1)] - protected double _factor = 10; + [InputParameter("Period", 0, 1, 100, 1, 1)] + protected int _period = 30; - [InputParameter("Long TS", 2)] - private bool _LongTS = true; + [InputParameter("Factor", 1, 1, 100, 0.1, 1)] + protected double _factor = 10; - [InputParameter("Short TS", 3)] - private bool _ShortTS = true; + [InputParameter("Long TS", 2)] + private bool _LongTS = true; - #endregion Parameters + [InputParameter("Short TS", 3)] + private bool _ShortTS = true; - /////// - private HistoricalData History; - private TBars bars; - private ATR_Series _atr; - private double _tslineL, _ratchetL, _tslineS, _ratchetS; + #endregion Parameters - /////// + /////// + private HistoricalData History; + private TBars bars; + private ATR_Series _atr; + private double _tslineL, _ratchetL, _tslineS, _ratchetS; - public TrailingStop_chart() { - Name = $"ATR Trailing Stop"; - AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1,lineStyle: LineStyle.Dot); - AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); + /////// - AddLineSeries(lineName: "TrailingATR Short", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot); - AddLineSeries(lineName: "Ratchet Short", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); - - SeparateWindow = false; - } + public TrailingStop_chart() + { + Name = $"ATR Trailing Stop"; + AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot); + AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); + + AddLineSeries(lineName: "TrailingATR Short", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot); + AddLineSeries(lineName: "Ratchet Short", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); + + SeparateWindow = false; + } - protected override void OnInit() { - this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})"; - this.bars = new(); + protected override void OnInit() + { + this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})"; + this.bars = new(); - this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); - for (int i = this.History.Count - 1; i >= 0; i--) { - var rec = this.History[i, SeekOriginHistory.Begin]; - bars.Add(rec.TimeLeft, rec[PriceType.Open], - rec[PriceType.High], rec[PriceType.Low], - rec[PriceType.Close], rec[PriceType.Volume]); - } - _atr = new(source: bars, _period, useNaN: true); - _ratchetL = Double.NegativeInfinity; - _ratchetS = Double.PositiveInfinity; + this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); + for (int i = this.History.Count - 1; i >= 0; i--) + { + var rec = this.History[i, SeekOriginHistory.Begin]; + bars.Add(rec.TimeLeft, rec[PriceType.Open], + rec[PriceType.High], rec[PriceType.Low], + rec[PriceType.Close], rec[PriceType.Volume]); + } + _atr = new(source: bars, _period, useNaN: true); + _ratchetL = Double.NegativeInfinity; + _ratchetS = Double.PositiveInfinity; - this.LinesSeries[0].Visible = _LongTS; - this.LinesSeries[1].Visible = _LongTS; - this.LinesSeries[2].Visible = _ShortTS; - this.LinesSeries[3].Visible = _ShortTS; - } + this.LinesSeries[0].Visible = _LongTS; + this.LinesSeries[1].Visible = _LongTS; + this.LinesSeries[2].Visible = _ShortTS; + this.LinesSeries[3].Visible = _ShortTS; + } - protected override void OnUpdate(UpdateArgs args) { - bool update = !(args.Reason == UpdateReason.NewBar || - args.Reason == UpdateReason.HistoricalBar); - this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), - this.GetPrice(PriceType.High), - this.GetPrice(PriceType.Low), - this.GetPrice(PriceType.Close), - this.GetPrice(PriceType.Volume), update); - - _tslineL = bars.High[^1].v - (_factor * _atr[^1].v); - _ratchetL = Math.Max(_tslineL,_ratchetL); - if (_ratchetL > bars.Low[^1].v) { - this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); - _ratchetL = _tslineL; - } + protected override void OnUpdate(UpdateArgs args) + { + bool update = !(args.Reason == UpdateReason.NewBar || + args.Reason == UpdateReason.HistoricalBar); + this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), + this.GetPrice(PriceType.High), + this.GetPrice(PriceType.Low), + this.GetPrice(PriceType.Close), + this.GetPrice(PriceType.Volume), update); - _tslineS = bars.High[^1].v + (_factor * _atr[^1].v); - _ratchetS = Math.Min(_tslineS, _ratchetS); - if (_ratchetS < bars.High[^1].v) { - this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow)); - _ratchetS = _tslineS; - } + _tslineL = bars.High[^1].v - (_factor * _atr[^1].v); + _ratchetL = Math.Max(_tslineL, _ratchetL); + if (_ratchetL > bars.Low[^1].v) + { + this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); + _ratchetL = _tslineL; + } - this.SetValue(_tslineL, lineIndex: 0); - this.SetValue(_ratchetL, lineIndex: 1); - this.SetValue(_tslineS, lineIndex: 2); - this.SetValue(_ratchetS, lineIndex: 3); - } + _tslineS = bars.High[^1].v + (_factor * _atr[^1].v); + _ratchetS = Math.Min(_tslineS, _ratchetS); + if (_ratchetS < bars.High[^1].v) + { + this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow)); + _ratchetS = _tslineS; + } + + this.SetValue(_tslineL, lineIndex: 0); + this.SetValue(_ratchetL, lineIndex: 1); + this.SetValue(_tslineS, lineIndex: 2); + this.SetValue(_ratchetS, lineIndex: 3); + } } diff --git a/Tests/Basic tests/Indicators.cs b/Tests/Basic tests/Indicators.cs index a9a9175e..0bac1c17 100644 --- a/Tests/Basic tests/Indicators.cs +++ b/Tests/Basic tests/Indicators.cs @@ -6,8 +6,8 @@ namespace Basics; #nullable disable public class Indicators { - private static Type[] maSeriesTypes = new Type[] - { + private static Type[] maSeriesTypes = new Type[] + { typeof(SMA_Series), typeof(EMA_Series), typeof(DEMA_Series), @@ -28,128 +28,129 @@ public class Indicators typeof(TRIMA_Series), typeof(MAMA_Series), typeof(HWMA_Series), -}; + }; - [Theory] - [MemberData(nameof(MASeriesData))] - public void Name_exists(Type classType) - { - TSeries data = new("Data") {1,2,3}; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - Assert.NotEmpty(MA_Series.Name); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Series_Length(Type classType) - { - GBM_Feed feed = new(1000); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - Assert.Equal(1000, MA_Series.Count); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Return_data(Type classType) - { - TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - var result = MA_Series.Add(20); - Assert.Equal(result.v, MA_Series.Last.v); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Update(Type classType) - { - TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - var pre_update = MA_Series.Last.v; - - double pre_data = data.Last.v; - data.Add(20, true); - data.Add(pre_data, true); - - Assert.Equal(pre_update, MA_Series.Last.v); - Assert.Equal(data.Count, MA_Series.Count); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Period_zero(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 0, false) as TSeries; - Assert.Equal(data.Count, MA_Series.Count); - Assert.False(double.IsNaN(MA_Series.Last.v)); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Reset(Type classType) - { - GBM_Feed feed = new(10); - TSeries data = feed.OHLC4; - var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries; - MA_Series.Reset(); - data.Add(0); - Assert.Equal(data.Last.v, MA_Series.Last.v); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Period_one(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 1, false) as TSeries; - Assert.InRange(MA_Series.Last.v - data.Last.v, -10e-6, 10e-6); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void NaN_test(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.True(double.IsNaN(MA_Series[0].v)); - Assert.True(double.IsNaN(MA_Series[8].v)); - Assert.False(double.IsNaN(MA_Series[9].v)); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Edge_numbers(Type classType) - { - TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity }; - var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.Equal(4, MA_Series.Count); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void handling_NaN(Type classType) { - TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; -var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.False(double.IsNaN(MA_Series.Last.v)); - } - -public static IEnumerable MASeriesData() - { - foreach (var type in maSeriesTypes) + [Theory] + [MemberData(nameof(MASeriesData))] + public void Name_exists(Type classType) { - yield return new object[] { type }; + TSeries data = new("Data") { 1, 2, 3 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + Assert.NotEmpty(MA_Series.Name); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Series_Length(Type classType) + { + GBM_Feed feed = new(1000); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + Assert.Equal(1000, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Return_data(Type classType) + { + TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + var result = MA_Series.Add(20); + Assert.Equal(result.v, MA_Series.Last.v); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Update(Type classType) + { + TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + var pre_update = MA_Series.Last.v; + + double pre_data = data.Last.v; + data.Add(20, true); + data.Add(pre_data, true); + + Assert.Equal(pre_update, MA_Series.Last.v); + Assert.Equal(data.Count, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Period_zero(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 0, false) as TSeries; + Assert.Equal(data.Count, MA_Series.Count); + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Reset(Type classType) + { + GBM_Feed feed = new(10); + TSeries data = feed.OHLC4; + var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries; + MA_Series.Reset(); + data.Add(0); + Assert.Equal(data.Last.v, MA_Series.Last.v); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Period_one(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 1, false) as TSeries; + Assert.InRange(MA_Series.Last.v - data.Last.v, -10e-6, 10e-6); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void NaN_test(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.True(double.IsNaN(MA_Series[0].v)); + Assert.True(double.IsNaN(MA_Series[8].v)); + Assert.False(double.IsNaN(MA_Series[9].v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Edge_numbers(Type classType) + { + TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity }; + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.Equal(4, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void handling_NaN(Type classType) + { + TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + public static IEnumerable MASeriesData() + { + foreach (var type in maSeriesTypes) + { + yield return new object[] { type }; + } } - } } #nullable restore \ No newline at end of file diff --git a/Tests/Basic tests/Oscillators.cs b/Tests/Basic tests/Oscillators.cs index 8ca89557..61911d66 100644 --- a/Tests/Basic tests/Oscillators.cs +++ b/Tests/Basic tests/Oscillators.cs @@ -7,8 +7,8 @@ namespace Basics; #nullable disable public class Oscillators { - private static Type[] maSeriesTypes = new[] - { + private static Type[] maSeriesTypes = new[] + { typeof(BIAS_Series), typeof(MAX_Series), typeof(MIN_Series), @@ -20,7 +20,7 @@ public class Oscillators typeof(MAD_Series), typeof(MAPE_Series), typeof(MAE_Series), - typeof(MSE_Series), + typeof(MSE_Series), typeof(SDEV_Series), typeof(SMAPE_Series), typeof(WMAPE_Series), @@ -35,126 +35,127 @@ public class Oscillators typeof(BBANDS_Series), }; - [Theory] - [MemberData(nameof(MASeriesData))] - public void Name_exists(Type classType) - { - TSeries data = new("Data") {1,2,3}; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - Assert.NotEmpty(MA_Series.Name); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Series_Length(Type classType) - { - GBM_Feed feed = new(1000); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - Assert.Equal(1000, MA_Series.Count); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Return_data(Type classType) - { - TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - var result = MA_Series.Add(20); - Assert.Equal(result.v, MA_Series.Last.v); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Update(Type classType) - { - TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - - var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; - var pre_update = MA_Series.Last.v; - - double pre_data = data.Last.v; - data.Add(20, true); - data.Add(pre_data, true); - - Assert.Equal(pre_update, MA_Series.Last.v); - Assert.Equal(data.Count, MA_Series.Count); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Period_zero(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 0, false) as TSeries; - Assert.Equal(data.Count, MA_Series.Count); - Assert.False(double.IsNaN(MA_Series.Last.v)); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Reset(Type classType) - { - GBM_Feed feed = new(10); - TSeries data = feed.OHLC4; - var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries; - MA_Series.Reset(); - data.Add(1); - Assert.False(double.IsNaN(MA_Series.Last.v)); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Period_one(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 1, false) as TSeries; - Assert.False(double.IsNaN(MA_Series[^1].v)); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void NaN_test(Type classType) - { - GBM_Feed feed = new(100); - TSeries data = feed.OHLC4; - - var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.True(double.IsNaN(MA_Series[0].v)); - Assert.True(double.IsNaN(MA_Series[8].v)); - Assert.False(double.IsNaN(MA_Series[9].v)); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Edge_numbers(Type classType) - { - TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity }; - var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.Equal(4, MA_Series.Count); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void handling_NaN(Type classType) { - TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; -var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; - Assert.False(double.IsNaN(MA_Series.Last.v)); - } - -public static IEnumerable MASeriesData() - { - foreach (var type in maSeriesTypes) + [Theory] + [MemberData(nameof(MASeriesData))] + public void Name_exists(Type classType) { - yield return new object[] { type }; + TSeries data = new("Data") { 1, 2, 3 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + Assert.NotEmpty(MA_Series.Name); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Series_Length(Type classType) + { + GBM_Feed feed = new(1000); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + Assert.Equal(1000, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Return_data(Type classType) + { + TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + var result = MA_Series.Add(20); + Assert.Equal(result.v, MA_Series.Last.v); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Update(Type classType) + { + TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries; + var pre_update = MA_Series.Last.v; + + double pre_data = data.Last.v; + data.Add(20, true); + data.Add(pre_data, true); + + Assert.Equal(pre_update, MA_Series.Last.v); + Assert.Equal(data.Count, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Period_zero(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 0, false) as TSeries; + Assert.Equal(data.Count, MA_Series.Count); + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Reset(Type classType) + { + GBM_Feed feed = new(10); + TSeries data = feed.OHLC4; + var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries; + MA_Series.Reset(); + data.Add(1); + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Period_one(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 1, false) as TSeries; + Assert.False(double.IsNaN(MA_Series[^1].v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void NaN_test(Type classType) + { + GBM_Feed feed = new(100); + TSeries data = feed.OHLC4; + + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.True(double.IsNaN(MA_Series[0].v)); + Assert.True(double.IsNaN(MA_Series[8].v)); + Assert.False(double.IsNaN(MA_Series[9].v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Edge_numbers(Type classType) + { + TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity }; + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.Equal(4, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void handling_NaN(Type classType) + { + TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; + var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries; + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + public static IEnumerable MASeriesData() + { + foreach (var type in maSeriesTypes) + { + yield return new object[] { type }; + } } - } } #nullable restore \ No newline at end of file diff --git a/Tests/Basic tests/TBars_input.cs b/Tests/Basic tests/TBars_input.cs index 0b984821..39850ef6 100644 --- a/Tests/Basic tests/TBars_input.cs +++ b/Tests/Basic tests/TBars_input.cs @@ -7,8 +7,8 @@ namespace Basics; #nullable disable public class TBars { - private static Type[] maSeriesTypes = new Type[] - { + private static Type[] maSeriesTypes = new Type[] + { typeof(ATR_Series), typeof(ATRP_Series), typeof(TR_Series), @@ -17,80 +17,81 @@ public class TBars typeof(OBV_Series), typeof(ADOSC_Series), typeof(MIDPRICE_Series), -}; + }; - [Theory] - [MemberData(nameof(MASeriesData))] - public void Name_exists(Type classType) - { - GBM_Feed data = new(10); - - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - Assert.NotEmpty(MA_Series.Name); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Series_Length(Type classType) - { - GBM_Feed data = new(1000); - - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - Assert.Equal(1000, MA_Series.Count); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Return_data(Type classType) - { - GBM_Feed data = new(10); - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - var result = MA_Series.Add((DateTime.Today, 1,2,3,4,5)); - Assert.Equal(result.v, MA_Series.Last.v); - } - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Update(Type classType) - { - GBM_Feed data = new(10); - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - var pre_update = MA_Series.Last; - - var pre_data = data.Last; - data.Add((DateTime.Today, 1, 2, 3, 4, 5), true); - data.Add(pre_data, true); - - Assert.Equal(pre_update.v, MA_Series.Last.v); - Assert.Equal(data.Count, MA_Series.Count); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Reset(Type classType) - { - GBM_Feed data = new(10); - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - MA_Series.Reset(); - data.Add(); - Assert.False(double.IsNaN(MA_Series.Last.v)); -} - - [Theory] - [MemberData(nameof(MASeriesData))] - public void Period_default(Type classType) { - GBM_Feed data = new(100); - - var MA_Series = Activator.CreateInstance(classType, data) as TSeries; - Assert.False(double.IsNaN(MA_Series.Last.v)); - } - - public static IEnumerable MASeriesData() - { - foreach (var type in maSeriesTypes) + [Theory] + [MemberData(nameof(MASeriesData))] + public void Name_exists(Type classType) { - yield return new object[] { type }; + GBM_Feed data = new(10); + + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + Assert.NotEmpty(MA_Series.Name); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Series_Length(Type classType) + { + GBM_Feed data = new(1000); + + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + Assert.Equal(1000, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Return_data(Type classType) + { + GBM_Feed data = new(10); + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + var result = MA_Series.Add((DateTime.Today, 1, 2, 3, 4, 5)); + Assert.Equal(result.v, MA_Series.Last.v); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Update(Type classType) + { + GBM_Feed data = new(10); + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + var pre_update = MA_Series.Last; + + var pre_data = data.Last; + data.Add((DateTime.Today, 1, 2, 3, 4, 5), true); + data.Add(pre_data, true); + + Assert.Equal(pre_update.v, MA_Series.Last.v); + Assert.Equal(data.Count, MA_Series.Count); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Reset(Type classType) + { + GBM_Feed data = new(10); + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + MA_Series.Reset(); + data.Add(); + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + [Theory] + [MemberData(nameof(MASeriesData))] + public void Period_default(Type classType) + { + GBM_Feed data = new(100); + + var MA_Series = Activator.CreateInstance(classType, data) as TSeries; + Assert.False(double.IsNaN(MA_Series.Last.v)); + } + + public static IEnumerable MASeriesData() + { + foreach (var type in maSeriesTypes) + { + yield return new object[] { type }; + } } - } } #nullable restore \ No newline at end of file diff --git a/Tests/Pairs/DIV_Test.cs b/Tests/Pairs/DIV_Test.cs index d3e57573..824bd553 100644 --- a/Tests/Pairs/DIV_Test.cs +++ b/Tests/Pairs/DIV_Test.cs @@ -5,60 +5,60 @@ using QuanTAlib; namespace Pairs; public class DIV_Test { - [Fact] - public void DIVSeriesSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15 }; - TSeries b = new() { 5, 4, 3, 2, 1, 3 }; - DIV_Series c = new(a, b); - Assert.Equal(5, c.Last().v); - } + [Fact] + public void DIVSeriesSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15 }; + TSeries b = new() { 5, 4, 3, 2, 1, 3 }; + DIV_Series c = new(a, b); + Assert.Equal(5, c.Last().v); + } - [Fact] - public void DIVSeriesDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; - DIV_Series c = new(a, 0); - Assert.Equal(double.PositiveInfinity, c.Last().v); - } + [Fact] + public void DIVSeriesDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; + DIV_Series c = new(a, 0); + Assert.Equal(double.PositiveInfinity, c.Last().v); + } - [Fact] - public void DIVDoubleSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 3.0 }; - DIV_Series c = new(12.0, a); - Assert.Equal(4.0, c.Last().v); - } + [Fact] + public void DIVDoubleSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 3.0 }; + DIV_Series c = new(12.0, a); + Assert.Equal(4.0, c.Last().v); + } - [Fact] - public void DIVEventing_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 0 }; - DIV_Series c = new(a, b); - a.Add(12.0); - b.Add(2); - Assert.Equal(6.0, c.Last().v); - } + [Fact] + public void DIVEventing_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 0 }; + DIV_Series c = new(a, b); + a.Add(12.0); + b.Add(2); + Assert.Equal(6.0, c.Last().v); + } - [Fact] - public void DIVUpdatewDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15 }; - double b = 2; - DIV_Series c = new(a, b); - a.Add(10, true); - Assert.Equal(5, c.Last().v); - } + [Fact] + public void DIVUpdatewDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15 }; + double b = 2; + DIV_Series c = new(a, b); + a.Add(10, true); + Assert.Equal(5, c.Last().v); + } - [Fact] - public void DIVUpdating_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 1 }; - DIV_Series c = new(a, b); - a.Add(10, true); - b.Add(2, true); - Assert.Equal(5, c.Last().v); - } + [Fact] + public void DIVUpdating_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 1 }; + DIV_Series c = new(a, b); + a.Add(10, true); + b.Add(2, true); + Assert.Equal(5, c.Last().v); + } } diff --git a/Tests/Pairs/MUL_Test.cs b/Tests/Pairs/MUL_Test.cs index 22a343e5..583422b8 100644 --- a/Tests/Pairs/MUL_Test.cs +++ b/Tests/Pairs/MUL_Test.cs @@ -5,60 +5,60 @@ using QuanTAlib; namespace Pairs; public class MUL_Test { - [Fact] - public void MULSeriesSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 1 }; - MUL_Series c = new(a, b); - Assert.Equal(5, c.Last().v); - } + [Fact] + public void MULSeriesSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 1 }; + MUL_Series c = new(a, b); + Assert.Equal(5, c.Last().v); + } - [Fact] - public void MULSeriesDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - MUL_Series c = new(a, 10.0); - Assert.Equal(50, c.Last().v); - } + [Fact] + public void MULSeriesDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + MUL_Series c = new(a, 10.0); + Assert.Equal(50, c.Last().v); + } - [Fact] - public void MULDoubleSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - MUL_Series c = new(5.0, a); - Assert.Equal(25, c.Last().v); - } + [Fact] + public void MULDoubleSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + MUL_Series c = new(5.0, a); + Assert.Equal(25, c.Last().v); + } - [Fact] - public void MULEventing_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 0 }; - MUL_Series c = new(a, b); - a.Add(2); - b.Add(5); - Assert.Equal(10, c.Last().v); - } + [Fact] + public void MULEventing_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 0 }; + MUL_Series c = new(a, b); + a.Add(2); + b.Add(5); + Assert.Equal(10, c.Last().v); + } - [Fact] - public void MULUpdateDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - double b = 10; - MUL_Series c = new(a, b); - a.Add(2, true); - Assert.Equal(20, c.Last().v); - } + [Fact] + public void MULUpdateDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + double b = 10; + MUL_Series c = new(a, b); + a.Add(2, true); + Assert.Equal(20, c.Last().v); + } - [Fact] - public void MULUpdating_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 0 }; - MUL_Series c = new(a, b); - a.Add(10, true); - b.Add(10, true); - Assert.Equal(100, c.Last().v); - } + [Fact] + public void MULUpdating_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 0 }; + MUL_Series c = new(a, b); + a.Add(10, true); + b.Add(10, true); + Assert.Equal(100, c.Last().v); + } } diff --git a/Tests/Pairs/SUB_Test.cs b/Tests/Pairs/SUB_Test.cs index abed75f1..e2f3d6af 100644 --- a/Tests/Pairs/SUB_Test.cs +++ b/Tests/Pairs/SUB_Test.cs @@ -5,60 +5,60 @@ using QuanTAlib; namespace Pairs; public class SUB_Test { - [Fact] - public void SUBSeriesSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 1 }; - SUB_Series c = new(a, b); - Assert.Equal(4, c.Last().v); - } + [Fact] + public void SUBSeriesSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 1 }; + SUB_Series c = new(a, b); + Assert.Equal(4, c.Last().v); + } - [Fact] - public void SUBSeriesDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; - SUB_Series c = new(a, 10.0); - Assert.Equal(5.0, c.Last().v); - } + [Fact] + public void SUBSeriesDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; + SUB_Series c = new(a, 10.0); + Assert.Equal(5.0, c.Last().v); + } - [Fact] - public void SUBDoubleSeries_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; - SUB_Series c = new(10.0, a); - Assert.Equal(-5.0, c.Last().v); - } + [Fact] + public void SUBDoubleSeries_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15.0 }; + SUB_Series c = new(10.0, a); + Assert.Equal(-5.0, c.Last().v); + } - [Fact] - public void SUBEventing_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 0 }; - SUB_Series c = new(a, b); - a.Add(7.0); - b.Add(2); - Assert.Equal(5.0, c.Last().v); - } + [Fact] + public void SUBEventing_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 0 }; + SUB_Series c = new(a, b); + a.Add(7.0); + b.Add(2); + Assert.Equal(5.0, c.Last().v); + } - [Fact] - public void SUBUpdatewDouble_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 15 }; - double b = 10; - SUB_Series c = new(a, b); - a.Add(1, true); - Assert.Equal(-9, c.Last().v); - } + [Fact] + public void SUBUpdatewDouble_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 15 }; + double b = 10; + SUB_Series c = new(a, b); + a.Add(1, true); + Assert.Equal(-9, c.Last().v); + } - [Fact] - public void SUBUpdating_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - TSeries b = new() { 5, 4, 3, 2, 1, 1 }; - SUB_Series c = new(a, b); - a.Add(10, true); - b.Add(0, true); - Assert.Equal(10, c.Last().v); - } + [Fact] + public void SUBUpdating_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + TSeries b = new() { 5, 4, 3, 2, 1, 1 }; + SUB_Series c = new(a, b); + a.Add(10, true); + b.Add(0, true); + Assert.Equal(10, c.Last().v); + } } diff --git a/Tests/Pairs/TBars_Test.cs b/Tests/Pairs/TBars_Test.cs index e23e10f7..47b97c89 100644 --- a/Tests/Pairs/TBars_Test.cs +++ b/Tests/Pairs/TBars_Test.cs @@ -10,52 +10,52 @@ public class TBars_Test { TBars s = new() { (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue, c: Double.NegativeInfinity, v: Double.PositiveInfinity) }; var tup = (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue, - c: Double.NegativeInfinity, v: Double.PositiveInfinity); + c: Double.NegativeInfinity, v: Double.PositiveInfinity); Assert.Equal(tup, s[^1]); } [Fact] public void Casting_Parameters() { - TBars s = new() - { - { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false } - }; - Assert.Equal(0.1, s[^1].o); - Assert.Equal(1.1, s[^1].h); - Assert.Equal(2.1, s[^1].l); - Assert.Equal(3.1, s[^1].c); - Assert.Equal(4.1, s[^1].v); - Assert.Equal(DateTime.Today, s[^1].t); - Assert.Single(s); - } + TBars s = new() + { + { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false } + }; + Assert.Equal(0.1, s[^1].o); + Assert.Equal(1.1, s[^1].h); + Assert.Equal(2.1, s[^1].l); + Assert.Equal(3.1, s[^1].c); + Assert.Equal(4.1, s[^1].v); + Assert.Equal(DateTime.Today, s[^1].t); + Assert.Single(s); + } [Fact] public void Updating_Value() { - TBars s = new() - { - { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 } - }; - s.Add(DateTime.Today, 1.0, 1.0, 1.0, 1.0, 1.0, update: false); - s.Add(DateTime.Today, 0.0, 0.0, 0.0, 0.0, 0.0, update: true); - Assert.Equal(0.0, s[^1].o); - Assert.Equal(0.0, s[^1].h); - Assert.Equal(0.0, s[^1].l); - Assert.Equal(0.0, s[^1].c); - Assert.Equal(0.0, s[^1].v); - Assert.Equal(2, s.Count); + TBars s = new() + { + { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 } + }; + s.Add(DateTime.Today, 1.0, 1.0, 1.0, 1.0, 1.0, update: false); + s.Add(DateTime.Today, 0.0, 0.0, 0.0, 0.0, 0.0, update: true); + Assert.Equal(0.0, s[^1].o); + Assert.Equal(0.0, s[^1].h); + Assert.Equal(0.0, s[^1].l); + Assert.Equal(0.0, s[^1].c); + Assert.Equal(0.0, s[^1].v); + Assert.Equal(2, s.Count); } [Fact] public void Extracting_TSeries() { - TBars s = new() - { - { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 }, - { DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1 } - }; + TBars s = new() + { + { DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 }, + { DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1 } + }; - TSeries t = s.Open; + TSeries t = s.Open; Assert.Equal(t.t, s.Open.t); Assert.Equal(t.v, s.Open.v); @@ -91,22 +91,22 @@ public class TBars_Test Assert.Equal(t.t, s.HLC3.t); Assert.Equal(t.v, s.HLC3.v); - t = s.OHLC4; - Assert.Equal(t.t, s.OHLC4.t); - Assert.Equal(t.v, s.OHLC4.v); + t = s.OHLC4; + Assert.Equal(t.t, s.OHLC4.t); + Assert.Equal(t.v, s.OHLC4.v); - t = s.HLCC4; - Assert.Equal(t.t, s.HLCC4.t); - Assert.Equal(t.v, s.HLCC4.v); - } + t = s.HLCC4; + Assert.Equal(t.t, s.HLCC4.t); + Assert.Equal(t.v, s.HLCC4.v); + } [Fact] public void Broadcasting_Events() { - TBars s = new() { (DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1) }; - TSeries t = new(); - s.Close.Pub += t.Sub; - s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false); - Assert.Equal(s.Close.v, t.v); - Assert.Equal(s.Close.Count, t.Count); - } + TBars s = new() { (DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1) }; + TSeries t = new(); + s.Close.Pub += t.Sub; + s.Add(DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false); + Assert.Equal(s.Close.v, t.v); + Assert.Equal(s.Close.Count, t.Count); + } } diff --git a/Tests/Validations/Trends/Pandas_TA.cs b/Tests/Validations/Trends/Pandas_TA.cs index f6953454..471d7753 100644 --- a/Tests/Validations/Trends/Pandas_TA.cs +++ b/Tests/Validations/Trends/Pandas_TA.cs @@ -7,395 +7,463 @@ using Python.Runtime; namespace Validations; -public class PandasTA : IDisposable { - private bool disposed = false; - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, skip; - private readonly int digits; - private readonly dynamic np; - private readonly dynamic ta; - private readonly dynamic pd; - private readonly dynamic df; +public class PandasTA : IDisposable +{ + private bool disposed = false; + private readonly GBM_Feed bars; + private readonly Random rnd = new(); + private readonly int period, skip; + private readonly int digits; + private readonly dynamic np; + private readonly dynamic ta; + private readonly dynamic pd; + private readonly dynamic df; - public PandasTA() { - bars = new GBM_Feed(5000, 0.8, 0.0); - period = rnd.Next(28) + 3; - skip = period + 50; - digits = 8; + public PandasTA() + { + bars = new GBM_Feed(5000, 0.8, 0.0); + period = rnd.Next(28) + 3; + skip = period + 50; + digits = 8; - var pythonDLL = PythonLibrary.Locate(); - Runtime.PythonDLL = pythonDLL; - PythonEngine.Initialize(); + var pythonDLL = PythonLibrary.Locate(); + Runtime.PythonDLL = pythonDLL; + PythonEngine.Initialize(); - np = Py.Import("numpy"); - pd = Py.Import("pandas"); - ta = Py.Import("pandas_ta"); + np = Py.Import("numpy"); + pd = Py.Import("pandas"); + ta = Py.Import("pandas_ta"); - string[] cols = {"open", "high", "low", "close", "volume"}; - var ary = new double[bars.Count, 5]; - for (var i = 0; i < bars.Count; i++) { - ary[i, 0] = bars.Open[i].v; - ary[i, 1] = bars.High[i].v; - ary[i, 2] = bars.Low[i].v; - ary[i, 3] = bars.Close[i].v; - ary[i, 4] = bars.Volume[i].v; - } + string[] cols = { "open", "high", "low", "close", "volume" }; + var ary = new double[bars.Count, 5]; + for (var i = 0; i < bars.Count; i++) + { + ary[i, 0] = bars.Open[i].v; + ary[i, 1] = bars.High[i].v; + ary[i, 2] = bars.Low[i].v; + ary[i, 3] = bars.Close[i].v; + ary[i, 4] = bars.Volume[i].v; + } - df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols)); - } + df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols)); + } - public void Dispose() { - Dispose(true); - PythonEngine.Shutdown(); - GC.SuppressFinalize(this); - } + public void Dispose() + { + Dispose(true); + PythonEngine.Shutdown(); + GC.SuppressFinalize(this); + } - ~PandasTA() { - Dispose(false); - } + ~PandasTA() + { + Dispose(false); + } - protected virtual void Dispose(bool disposing) { - if (!disposed) { - disposed = true; - } - } + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + } + } - [Fact] - private void ADL() { - ADL_Series QL = new(bars); - var pta = df.ta.ad(high: df.high, low: df.low, close: df.close, volume: df.volume); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void ADL() + { + ADL_Series QL = new(bars); + var pta = df.ta.ad(high: df.high, low: df.low, close: df.close, volume: df.volume); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void BBANDS() { - BBANDS_Series QL = new(bars.Close, period); - var pta = df.ta.bbands(close: df.close, length: period).to_numpy(); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL.Lower[i].v; - var PanTA_item = (double) pta[i][0]; //lower - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Mid[i].v; - PanTA_item = (double) pta[i][1]; //mid - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Upper[i].v; - PanTA_item = (double) pta[i][2]; //upper - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void BBANDS() + { + BBANDS_Series QL = new(bars.Close, period); + var pta = df.ta.bbands(close: df.close, length: period).to_numpy(); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL.Lower[i].v; + var PanTA_item = (double)pta[i][0]; //lower + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Mid[i].v; + PanTA_item = (double)pta[i][1]; //mid + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Upper[i].v; + PanTA_item = (double)pta[i][2]; //upper + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void BIAS() { - BIAS_Series QL = new(bars.Close, period, false); - var pta = df.ta.bias(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void BIAS() + { + BIAS_Series QL = new(bars.Close, period, false); + var pta = df.ta.bias(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void CCI() { - CCI_Series QL = new(bars, period, false); - var pta = df.ta.cci(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void CCI() + { + CCI_Series QL = new(bars, period, false); + var pta = df.ta.cci(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void DEMA() { - DEMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.dema(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void DEMA() + { + DEMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.dema(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void EMA() { - EMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.ema(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void EMA() + { + EMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.ema(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void ENTROPY() { - ENTROPY_Series QL = new(bars.Close, period, false); - var pta = df.ta.entropy(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void ENTROPY() + { + ENTROPY_Series QL = new(bars.Close, period, false); + var pta = df.ta.entropy(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void HL2() { - var pta = df.ta.hl2(high: df.high, low: df.low); - for (var i = bars.HL2.Length - 1; i > skip; i--) { - var QL_item = bars.HL2[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void HL2() + { + var pta = df.ta.hl2(high: df.high, low: df.low); + for (var i = bars.HL2.Length - 1; i > skip; i--) + { + var QL_item = bars.HL2[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void HLC3() { - var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close); - for (var i = bars.HLC3.Length; i > skip; i--) { - var QL_item = bars.HLC3[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void HLC3() + { + var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close); + for (var i = bars.HLC3.Length; i > skip; i--) + { + var QL_item = bars.HLC3[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void HMA() { - HMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.hma(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void HMA() + { + HMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.hma(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void KURTOSIS() { - KURTOSIS_Series QL = new(bars.Close, period, false); - var pta = df.ta.kurtosis(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void KURTOSIS() + { + KURTOSIS_Series QL = new(bars.Close, period, false); + var pta = df.ta.kurtosis(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void MACD() { - MACD_Series QL = new(bars.Close, 26, 12, 9, false); - var pta = df.ta.macd(close: df.close).to_numpy(); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1][0]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Signal[i - 1].v; - PanTA_item = (double) pta[i - 1][2]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void MACD() + { + MACD_Series QL = new(bars.Close, 26, 12, 9, false); + var pta = df.ta.macd(close: df.close).to_numpy(); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1][0]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Signal[i - 1].v; + PanTA_item = (double)pta[i - 1][2]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void MAD() { - MAD_Series QL = new(bars.Close, period, false); - var pta = df.ta.mad(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void MAD() + { + MAD_Series QL = new(bars.Close, period, false); + var pta = df.ta.mad(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void MEDIAN() { - MEDIAN_Series QL = new(bars.Close, period); - var pta = df.ta.median(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void MEDIAN() + { + MEDIAN_Series QL = new(bars.Close, period); + var pta = df.ta.median(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void OBV() { - OBV_Series QL = new(bars); - var pta = df.ta.obv(close: df.close, volume: df.volume); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void OBV() + { + OBV_Series QL = new(bars); + var pta = df.ta.obv(close: df.close, volume: df.volume); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void OHLC4() { - var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); - for (var i = bars.OHLC4.Length; i > skip; i--) { - var QL_item = bars.OHLC4[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void OHLC4() + { + var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); + for (var i = bars.OHLC4.Length; i > skip; i--) + { + var QL_item = bars.OHLC4[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void SDEV() { - SDEV_Series QL = new(bars.Close, period, false); - var pta = df.ta.stdev(close: df.close, length: period, ddof: 0); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void SDEV() + { + SDEV_Series QL = new(bars.Close, period, false); + var pta = df.ta.stdev(close: df.close, length: period, ddof: 0); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void SMA() { - SMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.sma(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void SMA() + { + SMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.sma(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void SSDEV() { - SSDEV_Series QL = new(bars.Close, period, false); - var pta = df.ta.stdev(close: df.close, length: period, ddof: 1); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void SSDEV() + { + SSDEV_Series QL = new(bars.Close, period, false); + var pta = df.ta.stdev(close: df.close, length: period, ddof: 1); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void SVARIANCE() { - SVAR_Series QL = new(bars.Close, period); - var pta = df.ta.variance(close: df.close, length: period, ddof: 1); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void SVARIANCE() + { + SVAR_Series QL = new(bars.Close, period); + var pta = df.ta.variance(close: df.close, length: period, ddof: 1); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void TEMA() { - TEMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.tema(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void TEMA() + { + TEMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.tema(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void TR() { - TR_Series QL = new(bars); - var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void TR() + { + TR_Series QL = new(bars); + var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void TRIMA() { - // TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right - TRIMA_Series QL = new(bars.Close, 11); - var pta = df.ta.trima(close: df.close, length: 11); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void TRIMA() + { + // TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right + TRIMA_Series QL = new(bars.Close, 11); + var pta = df.ta.trima(close: df.close, length: 11); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void VARIANCE() { - VAR_Series QL = new(bars.Close, period); - var pta = df.ta.variance(close: df.close, length: period, ddof: 0); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void VARIANCE() + { + VAR_Series QL = new(bars.Close, period); + var pta = df.ta.variance(close: df.close, length: period, ddof: 0); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void WMA() { - WMA_Series QL = new(bars.Close, period, false); - var pta = df.ta.wma(close: df.close, length: period); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void WMA() + { + WMA_Series QL = new(bars.Close, period, false); + var pta = df.ta.wma(close: df.close, length: period); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - [Fact] - private void ZSCORE() { - ZSCORE_Series QL = new(bars.Close, period, false); - var pta = df.ta.zscore(close: df.close, length: period, ddof: 0); - for (var i = QL.Length - 1; i > skip; i--) { - var QL_item = QL[i - 1].v; - var PanTA_item = (double) pta[i - 1]; - Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } + [Fact] + private void ZSCORE() + { + ZSCORE_Series QL = new(bars.Close, period, false); + var pta = df.ta.zscore(close: df.close, length: period, ddof: 0); + for (var i = QL.Length - 1; i > skip; i--) + { + var QL_item = QL[i - 1].v; + var PanTA_item = (double)pta[i - 1]; + Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } } -public static class PythonLibrary { - public static string Locate() { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(';') ?? Array.Empty(); - foreach (string path in paths) { - string[] pythonDLLs = Directory.GetFiles(path, "python3*.dll"); - if (pythonDLLs.Length > 0) { - foreach (string item in pythonDLLs) { - if (!item.EndsWith("python3.dll", StringComparison.OrdinalIgnoreCase)) { - return item; - } - } +public static class PythonLibrary +{ + public static string Locate() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(';') ?? Array.Empty(); + foreach (string path in paths) + { + string[] pythonDLLs = Directory.GetFiles(path, "python3*.dll"); + if (pythonDLLs.Length > 0) + { + foreach (string item in pythonDLLs) + { + if (!item.EndsWith("python3.dll", StringComparison.OrdinalIgnoreCase)) + { + return item; + } + } - } - } - throw new FileNotFoundException("Python library not found in PATH"); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { + } + } + throw new FileNotFoundException("Python library not found in PATH"); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { return "/usr/lib/x86_64-linux-gnu/libpython3.10.so"; -/* - List pythonLibraries = new List(); - List directoriesToSearch = new List { "/home/runner/.local/lib" }; // Add more directories as needed - string filePattern = "libpython3.*.so"; - SearchFiles(directoriesToSearch, filePattern, pythonLibraries); + /* + List pythonLibraries = new List(); + List directoriesToSearch = new List { "/home/runner/.local/lib" }; // Add more directories as needed + string filePattern = "libpython3.*.so"; + SearchFiles(directoriesToSearch, filePattern, pythonLibraries); - if (pythonLibraries.Count > 0) { - return pythonLibraries[0]; - } - else { - throw new FileNotFoundException("Python library not found"); - } -*/ - } + if (pythonLibraries.Count > 0) { + return pythonLibraries[0]; + } + else { + throw new FileNotFoundException("Python library not found"); + } + */ + } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - throw new NotSupportedException("Not supported yet"); - } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + throw new NotSupportedException("Not supported yet"); + } - else { throw new NotSupportedException("Unsupported operating system"); } - } - static void SearchFiles(List directoriesToSearch, string filePattern, List foundFiles) + else { throw new NotSupportedException("Unsupported operating system"); } + } + static void SearchFiles(List directoriesToSearch, string filePattern, List foundFiles) { foreach (string directory in directoriesToSearch) { diff --git a/Tests/Validations/Trends/Skender.cs b/Tests/Validations/Trends/Skender.cs index a3950e96..d26f48e4 100644 --- a/Tests/Validations/Trends/Skender.cs +++ b/Tests/Validations/Trends/Skender.cs @@ -6,481 +6,484 @@ using Xunit; namespace Validations; public class Skender { - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, digits, skip; - private readonly IEnumerable quotes; + private readonly GBM_Feed bars; + private readonly Random rnd = new(); + private readonly int period, digits, skip; + private readonly IEnumerable quotes; - public Skender() - { - bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2); - period = rnd.Next(30) + 5; - digits = 6; //minimizing rounding errors in type conversions - skip = period+2; + public Skender() + { + bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2); + period = rnd.Next(30) + 5; + digits = 6; //minimizing rounding errors in type conversions + skip = period + 2; - quotes = bars.Select(q => new Quote - { - Date = q.t, - Open = (decimal)q.o, - High = (decimal)q.h, - Low = (decimal)q.l, - Close = (decimal)q.c, - Volume = (decimal)q.v - }); - } + quotes = bars.Select(q => new Quote + { + Date = q.t, + Open = (decimal)q.o, + High = (decimal)q.h, + Low = (decimal)q.l, + Close = (decimal)q.c, + Volume = (decimal)q.v + }); + } -/* - [Fact] - public void ADL() - { - ADL_Series QL = new(bars); - var SK = quotes.GetAdl().Select(i => i.Adl); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1)!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - */ - [Fact] - public void ALMA() - { - ALMA_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetAlma(period).Select(i => i.Alma.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void ATR() - { - ATR_Series QL = new(bars, period:period,useNaN: false); - var SK = quotes.GetAtr(period).Select(i => i.Atr.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void ATRP() - { - ATRP_Series QL = new(bars, period, false); - var SK = quotes.GetAtr(period).Select(i => i.Atrp.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void BBANDS() - { - BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false); - var SK = quotes.GetBollingerBands(period, 2.0); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL.Mid[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Sma!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - QL_item = QL.Upper[i - 1].v; - SK_item = SK.ElementAt(i - 1).UpperBand!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - QL_item = QL.Lower[i - 1].v; - SK_item = SK.ElementAt(i - 1).LowerBand!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - QL_item = QL.Bandwidth[i - 1].v; - SK_item = SK.ElementAt(i - 1).Width!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - QL_item = QL.PercentB[i - 1].v; - SK_item = SK.ElementAt(i - 1).PercentB!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - QL_item = QL.Zscore[i - 1].v; - SK_item = SK.ElementAt(i - 1).ZScore!.Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void CCI() - { - CCI_Series QL = new(bars, period, false); - var SK = quotes.GetCci(period).Select(i => i.Cci.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } + /* + [Fact] + public void ADL() + { + ADL_Series QL = new(bars); + var SK = quotes.GetAdl().Select(i => i.Adl); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1)!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); + } + } + */ [Fact] - public void CMO() - { - CMO_Series QL = new(bars.Close, period, false); - var SK = quotes.GetCmo(period).Select(i => i.Cmo.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) + public void ALMA() { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void CORR() - { - CORR_Series QL = new(bars.High, bars.Low, period, false); - var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Correlation.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void COVAR() - { - COVAR_Series QL = new(bars.High, bars.Low, period, false); - var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Covariance.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); + ALMA_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetAlma(period).Select(i => i.Alma.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } } - } - [Fact] - public void DEMA() - { - DEMA_Series QL = new(bars.Close, period, false, useSMA: true); - var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void EMA() - { - EMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void HL2() - { - TSeries QL = bars.HL2; - var SK = quotes.GetBaseQuote(CandlePart.HL2).ToList(); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void HLC3() - { - TSeries QL = bars.HLC3; - var SK = quotes.GetBaseQuote(CandlePart.HLC3).ToList(); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void HMA() - { - HMA_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetHma(period).Select(i => i.Hma.Null2NaN()!); - for (int i = QL.Length; i > skip*2; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - - [Fact] - public void KAMA() - { - // TODO: check precision of KAMA() - KAMA_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!); - for (int i = QL.Length; i > skip+2; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void SLOPE() - { - SLOPE_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetSlope(period); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = (double)SK.ElementAt(i - 1).Slope!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - QL_item = QL.Intercept[i - 1].v; - SK_item = (double)SK.ElementAt(i - 1).Intercept!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - QL_item = QL.RSquared[i - 1].v; - SK_item = (double)SK.ElementAt(i - 1).RSquared!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - QL_item = QL.StdDev[i - 1].v; - SK_item = (double)SK.ElementAt(i - 1).StdDev!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void MACD() - { - MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false); - var SK = quotes.GetMacd(12, 26, 9); - for (int i = QL.Length; i > 27; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Macd.Null2NaN()!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - //QL_item = QL.Signal[i - 1].v; - //SK_item = SK.ElementAt(i - 1).Signal.Null2NaN()!; - //Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void MAD() - { - MAD_Series QL = new(bars.Close, period, false); - var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mad.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void MAMA() - { - MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05); - var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Mama.Null2NaN()!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - QL_item = QL.Fama[i - 1].v; - SK_item = SK.ElementAt(i - 1).Fama.Null2NaN()!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void MAPE() - { - MAPE_Series QL = new(bars.Close, period, false); - var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mape.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void MSE() - { - MSE_Series QL = new(bars.Close, period, false); - var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mse.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void OBV() - { - OBV_Series QL = new(bars, period, false); - var SK = quotes.GetObv(period).Select(i => i.Obv!); - for (int i = QL.Length; i > skip; i--) { - double QL_item = QL.Last().v; - // adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB - double SK_item = SK.Last()! + (double)quotes.First().Volume!; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void OC2() - { - TSeries QL = bars.OC2; - var SK = quotes.GetBaseQuote(CandlePart.OC2).ToList(); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void OHL3() - { - TSeries QL = bars.OHL3; - var SK = quotes.GetBaseQuote(CandlePart.OHL3).ToList(); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void OHLC4() - { - TSeries QL = bars.OHLC4; - var SK = quotes.GetBaseQuote(CandlePart.OHLC4).ToList(); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1).Value; - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void RSI() - { - RSI_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetRsi(period).Select(i => i.Rsi.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void SDEV() - { - SDEV_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetStdDev(period).Select(i => i.StdDev.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void SMA() - { - SMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void SMMA() - { - SMMA_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetSmma(period).Select(i => i.Smma.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void T3() - { - T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, false); - var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!); - for (int i = QL.Length; i > period*15; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void TRIX() { - TRIX_Series QL = new(bars.Close, period, false); - var SK = quotes.GetTrix(period).Select(i => i.Trix.Null2NaN()!); - for (int i = QL.Length; i > period*12; i--) { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); - } - } - [Fact] - public void TEMA() - { - TEMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetTema(period).Select(i => i.Tema.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void TR() - { - TR_Series QL = new(bars); - var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } - [Fact] - public void WMA() - { - WMA_Series QL = new(bars.Close, period, false); - var SK = quotes.GetWma(period).Select(i => i.Wma.Null2NaN()!); - for (int i = QL.Length; i > skip*2; i--) - { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); - } - } [Fact] - public void ZSCORE() - { - ZSCORE_Series QL = new(bars.Close, period, useNaN: false); - var SK = quotes.GetStdDev(period).Select(i => i.ZScore.Null2NaN()!); - for (int i = QL.Length; i > skip; i--) + public void ATR() { - double QL_item = QL[i - 1].v; - double SK_item = SK.ElementAt(i - 1); - Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); + ATR_Series QL = new(bars, period: period, useNaN: false); + var SK = quotes.GetAtr(period).Select(i => i.Atr.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void ATRP() + { + ATRP_Series QL = new(bars, period, false); + var SK = quotes.GetAtr(period).Select(i => i.Atrp.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void BBANDS() + { + BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false); + var SK = quotes.GetBollingerBands(period, 2.0); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL.Mid[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Sma!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Upper[i - 1].v; + SK_item = SK.ElementAt(i - 1).UpperBand!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Lower[i - 1].v; + SK_item = SK.ElementAt(i - 1).LowerBand!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Bandwidth[i - 1].v; + SK_item = SK.ElementAt(i - 1).Width!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.PercentB[i - 1].v; + SK_item = SK.ElementAt(i - 1).PercentB!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Zscore[i - 1].v; + SK_item = SK.ElementAt(i - 1).ZScore!.Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void CCI() + { + CCI_Series QL = new(bars, period, false); + var SK = quotes.GetCci(period).Select(i => i.Cci.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void CMO() + { + CMO_Series QL = new(bars.Close, period, false); + var SK = quotes.GetCmo(period).Select(i => i.Cmo.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void CORR() + { + CORR_Series QL = new(bars.High, bars.Low, period, false); + var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Correlation.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void COVAR() + { + COVAR_Series QL = new(bars.High, bars.Low, period, false); + var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Covariance.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void DEMA() + { + DEMA_Series QL = new(bars.Close, period, false, useSMA: true); + var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void EMA() + { + EMA_Series QL = new(bars.Close, period, false); + var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void HL2() + { + TSeries QL = bars.HL2; + var SK = quotes.GetBaseQuote(CandlePart.HL2).ToList(); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void HLC3() + { + TSeries QL = bars.HLC3; + var SK = quotes.GetBaseQuote(CandlePart.HLC3).ToList(); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void HMA() + { + HMA_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetHma(period).Select(i => i.Hma.Null2NaN()!); + for (int i = QL.Length; i > skip * 2; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + + [Fact] + public void KAMA() + { + // TODO: check precision of KAMA() + KAMA_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!); + for (int i = QL.Length; i > skip + 2; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void SLOPE() + { + SLOPE_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetSlope(period); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = (double)SK.ElementAt(i - 1).Slope!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Intercept[i - 1].v; + SK_item = (double)SK.ElementAt(i - 1).Intercept!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.RSquared[i - 1].v; + SK_item = (double)SK.ElementAt(i - 1).RSquared!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.StdDev[i - 1].v; + SK_item = (double)SK.ElementAt(i - 1).StdDev!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void MACD() + { + MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false); + var SK = quotes.GetMacd(12, 26, 9); + for (int i = QL.Length; i > 27; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Macd.Null2NaN()!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + //QL_item = QL.Signal[i - 1].v; + //SK_item = SK.ElementAt(i - 1).Signal.Null2NaN()!; + //Assert.InRange(SK_item! - QL_item, -Math.Pow(10,-digits), Math.Pow(10,-digits)); + } + } + [Fact] + public void MAD() + { + MAD_Series QL = new(bars.Close, period, false); + var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mad.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void MAMA() + { + MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05); + var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Mama.Null2NaN()!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + QL_item = QL.Fama[i - 1].v; + SK_item = SK.ElementAt(i - 1).Fama.Null2NaN()!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void MAPE() + { + MAPE_Series QL = new(bars.Close, period, false); + var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mape.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void MSE() + { + MSE_Series QL = new(bars.Close, period, false); + var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mse.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void OBV() + { + OBV_Series QL = new(bars, period, false); + var SK = quotes.GetObv(period).Select(i => i.Obv!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL.Last().v; + // adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB + double SK_item = SK.Last()! + (double)quotes.First().Volume!; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void OC2() + { + TSeries QL = bars.OC2; + var SK = quotes.GetBaseQuote(CandlePart.OC2).ToList(); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void OHL3() + { + TSeries QL = bars.OHL3; + var SK = quotes.GetBaseQuote(CandlePart.OHL3).ToList(); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void OHLC4() + { + TSeries QL = bars.OHLC4; + var SK = quotes.GetBaseQuote(CandlePart.OHLC4).ToList(); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1).Value; + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void RSI() + { + RSI_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetRsi(period).Select(i => i.Rsi.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void SDEV() + { + SDEV_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetStdDev(period).Select(i => i.StdDev.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void SMA() + { + SMA_Series QL = new(bars.Close, period, false); + var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void SMMA() + { + SMMA_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetSmma(period).Select(i => i.Smma.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void T3() + { + T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, false); + var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!); + for (int i = QL.Length; i > period * 15; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void TRIX() + { + TRIX_Series QL = new(bars.Close, period, false); + var SK = quotes.GetTrix(period).Select(i => i.Trix.Null2NaN()!); + for (int i = QL.Length; i > period * 12; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void TEMA() + { + TEMA_Series QL = new(bars.Close, period, false); + var SK = quotes.GetTema(period).Select(i => i.Tema.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void TR() + { + TR_Series QL = new(bars); + var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void WMA() + { + WMA_Series QL = new(bars.Close, period, false); + var SK = quotes.GetWma(period).Select(i => i.Wma.Null2NaN()!); + for (int i = QL.Length; i > skip * 2; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } + } + [Fact] + public void ZSCORE() + { + ZSCORE_Series QL = new(bars.Close, period, useNaN: false); + var SK = quotes.GetStdDev(period).Select(i => i.ZScore.Null2NaN()!); + for (int i = QL.Length; i > skip; i--) + { + double QL_item = QL[i - 1].v; + double SK_item = SK.ElementAt(i - 1); + Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits)); + } } - } } diff --git a/Tests/Validations/Trends/TA_LIB.cs b/Tests/Validations/Trends/TA_LIB.cs index 01e40c2a..9c8e27f9 100644 --- a/Tests/Validations/Trends/TA_LIB.cs +++ b/Tests/Validations/Trends/TA_LIB.cs @@ -6,478 +6,482 @@ using QuanTAlib; namespace Validations; public class Ta_Lib { - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, digits, skip; - private readonly double[] TALIB; - private readonly double[] TALIB2; - private readonly double[] inopen; - private readonly double[] inhigh; - private readonly double[] inlow; - private readonly double[] inclose; - private readonly double[] involume; + private readonly GBM_Feed bars; + private readonly Random rnd = new(); + private readonly int period, digits, skip; + private readonly double[] TALIB; + private readonly double[] TALIB2; + private readonly double[] inopen; + private readonly double[] inhigh; + private readonly double[] inlow; + private readonly double[] inclose; + private readonly double[] involume; - public Ta_Lib() - { - bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); - period = rnd.Next(28) + 3; - skip = period+2; - digits = 9; + public Ta_Lib() + { + bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); + period = rnd.Next(28) + 3; + skip = period + 2; + digits = 9; - TALIB = new double[bars.Count]; - TALIB2 = new double[bars.Count]; - inopen = bars.Open.v.ToArray(); - inhigh = bars.High.v.ToArray(); - inlow = bars.Low.v.ToArray(); - inclose = bars.Close.v.ToArray(); - involume = bars.Volume.v.ToArray(); - } + TALIB = new double[bars.Count]; + TALIB2 = new double[bars.Count]; + inopen = bars.Open.v.ToArray(); + inhigh = bars.High.v.ToArray(); + inlow = bars.Low.v.ToArray(); + inclose = bars.Close.v.ToArray(); + involume = bars.Volume.v.ToArray(); + } - [Fact] - public void ADD() - { - ADD_Series QL = new(bars.Open, bars.Close); - Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void ADD() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + ADD_Series QL = new(bars.Open, bars.Close); + Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void ADL() - { - ADL_Series QL = new(bars); - Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > 0; i--) + [Fact] + public void ADL() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void ADOSC() - { - ADOSC_Series QL = new(bars, 3, 10, false); - Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip*2; i--) - { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + ADL_Series QL = new(bars); + Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > 0; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void ATR() - { - ATR_Series QL = new(bars, period:period, useNaN: false); - Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void ADOSC() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + ADOSC_Series QL = new(bars, 3, 10, false); + Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip * 2; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void ATR() + { + ATR_Series QL = new(bars, period: period, useNaN: false); + Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void BBANDS() - { - double[] outMiddle = new double[bars.Count]; - double[] outUpper = new double[bars.Count]; - double[] outLower = new double[bars.Count]; - BBANDS_Series QL = new(bars.Close, period: period, multiplier: 2.0, false); - Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: period, optInNbDevUp: 2.0, optInNbDevDn: 2.0); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void BBANDS() { - double QL_item = QL.Upper[i].v; - double TA_item = outUpper[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); - QL_item = QL.Mid[i].v; - TA_item = outMiddle[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); - QL_item = QL.Lower[i].v; - TA_item = outLower[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); + double[] outMiddle = new double[bars.Count]; + double[] outUpper = new double[bars.Count]; + double[] outLower = new double[bars.Count]; + BBANDS_Series QL = new(bars.Close, period: period, multiplier: 2.0, false); + Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: period, optInNbDevUp: 2.0, optInNbDevDn: 2.0); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL.Upper[i].v; + double TA_item = outUpper[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); + QL_item = QL.Mid[i].v; + TA_item = outMiddle[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); + QL_item = QL.Lower[i].v; + TA_item = outLower[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits)); + } } - } - [Fact] - public void CCI() - { - CCI_Series QL = new(bars, period, false); - Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void CCI() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + CCI_Series QL = new(bars, period, false); + Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - /* CMO in TA-LIB is not valid - [Fact] - public void CMO() { - CMO_Series QL = new(bars.Close, period, false); - Core.Cmo(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - */ - [Fact] - public void CORR() - { - CORR_Series QL = new(bars.Open, bars.Close, period); - Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period); - for (int i = QL.Length - 1; i > skip; i--) + /* CMO in TA-LIB is not valid + [Fact] + public void CMO() { + CMO_Series QL = new(bars.Close, period, false); + Core.Cmo(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + */ + [Fact] + public void CORR() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + CORR_Series QL = new(bars.Open, bars.Close, period); + Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void DEMA() - { - DEMA_Series QL = new(bars.Close, period, false, useSMA: false); - Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > period*10; i--) + [Fact] + public void DEMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + DEMA_Series QL = new(bars.Close, period, false, useSMA: false); + Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > period * 10; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void DIV() - { - DIV_Series QL = new(bars.Open, bars.Close); - Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void DIV() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + DIV_Series QL = new(bars.Open, bars.Close); + Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void EMA() - { - EMA_Series QL = new(bars.Close, period, false); - Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void EMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + EMA_Series QL = new(bars.Close, period, false); + Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void HL2() - { - TSeries QL = bars.HL2; - Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void HL2() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TSeries QL = bars.HL2; + Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void HLC3() - { - TSeries QL = bars.HLC3; - Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void HLC3() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TSeries QL = bars.HLC3; + Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void HLCC4() - { - TSeries QL = bars.HLCC4; - Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void HLCC4() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TSeries QL = bars.HLCC4; + Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void KAMA() { - KAMA_Series QL = new(bars.Close, period, fast: 2, slow: 30); - Core.Kama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period); - for (int i = QL.Length - 1; i > skip * 15; i--) { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void MACD() - { - double[] macdSignal = new double[bars.Count]; - double[] macdHist = new double[bars.Count]; - MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false); - // TA-LIB runs EMA without SMA, leaving first 100 values for convergence - Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _, optInFastPeriod: 12, optInSlowPeriod: 26, optInSignalPeriod: 9); - for (int i = QL.Length - 1; i > 100; i--) + [Fact] + public void KAMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Signal[i].v; - TA_item = macdSignal[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + KAMA_Series QL = new(bars.Close, period, fast: 2, slow: 30); + Core.Kama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period); + for (int i = QL.Length - 1; i > skip * 15; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - /* - [Fact] - public void MAMA() - { - MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05); - Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05); - for (int i = QL.Length - 1; i > skip * 10; i--) + [Fact] + public void MACD() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits-1), Math.Exp(-digits-1)); + double[] macdSignal = new double[bars.Count]; + double[] macdHist = new double[bars.Count]; + MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false); + // TA-LIB runs EMA without SMA, leaving first 100 values for convergence + Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _, optInFastPeriod: 12, optInSlowPeriod: 26, optInSignalPeriod: 9); + for (int i = QL.Length - 1; i > 100; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Signal[i].v; + TA_item = macdSignal[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - */ - [Fact] - public void MAX() - { - MAX_Series QL = new(bars.Close, period, false); - Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + /* + [Fact] + public void MAMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MAMA_Series QL = new(bars.Close, fastlimit: 0.5, slowlimit: 0.05); + Core.Mama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outMama: TALIB, outFama: TALIB2, outBegIdx: out int outBegIdx, outNbElement: out _, optInFastLimit: 0.5, optInSlowLimit: 0.05); + for (int i = QL.Length - 1; i > skip * 10; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits-1), Math.Exp(-digits-1)); + } } - } - [Fact] - public void MIDPOINT() - { - MIDPOINT_Series QL = new(bars.Close, period, false); - Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + */ + [Fact] + public void MAX() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MAX_Series QL = new(bars.Close, period, false); + Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void MIDPRICE() - { - MIDPRICE_Series QL = new(bars, period, false); - Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void MIDPOINT() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MIDPOINT_Series QL = new(bars.Close, period, false); + Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void MIN() - { - MIN_Series QL = new(bars.Close, period, false); - Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void MIDPRICE() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MIDPRICE_Series QL = new(bars, period, false); + Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void MUL() - { - MUL_Series QL = new(bars.Open, bars.Close); - Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void MIN() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MIN_Series QL = new(bars.Close, period, false); + Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void OBV() - { - OBV_Series QL = new(bars, period, false); - Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void MUL() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + MUL_Series QL = new(bars.Open, bars.Close); + Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void OHLC4() - { - TSeries QL = bars.OHLC4; - Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void OBV() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + OBV_Series QL = new(bars, period, false); + Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void RSI() - { - RSI_Series QL = new(bars.Close, period, false); - Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void OHLC4() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TSeries QL = bars.OHLC4; + Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void SDEV() - { - SDEV_Series QL = new(bars.Close, period, false); - Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void RSI() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + RSI_Series QL = new(bars.Close, period, false); + Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void SMA() - { - SMA_Series QL = new(bars.Close, period, false); - Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void SDEV() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + SDEV_Series QL = new(bars.Close, period, false); + Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void SUB() - { - SUB_Series QL = new(bars.Open, bars.Close); - Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void SMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + SMA_Series QL = new(bars.Close, period, false); + Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void SUM() - { - CUSUM_Series QL = new(bars.Close, period, false); - Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void SUB() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + SUB_Series QL = new(bars.Open, bars.Close); + Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void T3() - { - T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false); - Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7); - for (int i = QL.Length - 1; i > period*10; i--) + [Fact] + public void SUM() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + CUSUM_Series QL = new(bars.Close, period, false); + Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void TEMA() - { - TEMA_Series QL = new(bars.Close, period, false); - Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip * 15; i--) + [Fact] + public void T3() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false); + Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7); + for (int i = QL.Length - 1; i > period * 10; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void TR() - { - TR_Series QL = new(bars); - Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void TEMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TEMA_Series QL = new(bars.Close, period, false); + Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip * 15; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void TRIMA() - { - TRIMA_Series QL = new(bars.Close, period, false); - Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void TR() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TR_Series QL = new(bars); + Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void TRIX() { - TRIX_Series QL = new(bars.Close, period, useNaN: false, useSMA: true); - Core.Trix(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > period*10; i--) { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void VAR() - { - VAR_Series QL = new(bars.Close, period, false); - Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip * 15; i--) + [Fact] + public void TRIMA() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TRIMA_Series QL = new(bars.Close, period, false); + Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void WMA() - { - WMA_Series QL = new(bars.Close, period, false); - Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void TRIX() { - double QL_item = QL[i].v; - double TA_item = TALIB[i - outBegIdx]; - Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + TRIX_Series QL = new(bars.Close, period, useNaN: false, useSMA: true); + Core.Trix(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > period * 10; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void VAR() + { + VAR_Series QL = new(bars.Close, period, false); + Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip * 15; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void WMA() + { + WMA_Series QL = new(bars.Close, period, false); + Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TA_item = TALIB[i - outBegIdx]; + Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } } diff --git a/Tests/Validations/Trends/Tulip.cs b/Tests/Validations/Trends/Tulip.cs index 150f3688..32774221 100644 --- a/Tests/Validations/Trends/Tulip.cs +++ b/Tests/Validations/Trends/Tulip.cs @@ -6,114 +6,114 @@ using QuanTAlib; namespace Validations; public class Tulip_Test { - private readonly GBM_Feed bars; - private readonly Random rnd = new(); - private readonly int period, digits, skip; - private readonly double[] outdata; - private readonly double[] inopen; - private readonly double[] inhigh; - private readonly double[] inlow; - private readonly double[] inclose; - private readonly double[] involume; + private readonly GBM_Feed bars; + private readonly Random rnd = new(); + private readonly int period, digits, skip; + private readonly double[] outdata; + private readonly double[] inopen; + private readonly double[] inhigh; + private readonly double[] inlow; + private readonly double[] inclose; + private readonly double[] involume; - public Tulip_Test() - { - bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); - period = rnd.Next(28) + 3; - skip = period+5; - digits = 8; + public Tulip_Test() + { + bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3); + period = rnd.Next(28) + 3; + skip = period + 5; + digits = 8; - outdata = new double[bars.Count]; - inopen = bars.Open.v.ToArray(); - inhigh = bars.High.v.ToArray(); - inlow = bars.Low.v.ToArray(); - inclose = bars.Close.v.ToArray()!; - involume = bars.Volume.v.ToArray()!; + outdata = new double[bars.Count]; + inopen = bars.Open.v.ToArray(); + inhigh = bars.High.v.ToArray(); + inlow = bars.Low.v.ToArray(); + inclose = bars.Close.v.ToArray()!; + involume = bars.Volume.v.ToArray()!; - } - [Fact] - public void ADL() - { - double[][] arrin = {inhigh, inlow, inclose, involume }; - double[][] arrout = { outdata }; - ADL_Series QL = new(bars); - Tulip.Indicators.ad.Run(inputs: arrin, options: new double[] { }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void ADD() - { - double[][] arrin = { inhigh, inlow }; - double[][] arrout = { outdata }; - ADD_Series QL = new(bars.High, bars.Low); - Tulip.Indicators.add.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void ADOSC() - { - double[][] arrin = { inhigh, inlow, inclose, involume }; - double[][] arrout = { outdata }; - int s = 3; - ADOSC_Series QL = new(bars, s, period, false); - Tulip.Indicators.adosc.Run(inputs: arrin, options: new double[] { s, period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i-period+1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void ATR() - { - double[][] arrin = { inhigh, inlow, inclose }; - double[][] arrout = { outdata }; + } + [Fact] + public void ADL() + { + double[][] arrin = { inhigh, inlow, inclose, involume }; + double[][] arrout = { outdata }; + ADL_Series QL = new(bars); + Tulip.Indicators.ad.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void ADD() + { + double[][] arrin = { inhigh, inlow }; + double[][] arrout = { outdata }; + ADD_Series QL = new(bars.High, bars.Low); + Tulip.Indicators.add.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void ADOSC() + { + double[][] arrin = { inhigh, inlow, inclose, involume }; + double[][] arrout = { outdata }; + int s = 3; + ADOSC_Series QL = new(bars, s, period, false); + Tulip.Indicators.adosc.Run(inputs: arrin, options: new double[] { s, period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void ATR() + { + double[][] arrin = { inhigh, inlow, inclose }; + double[][] arrout = { outdata }; - ATR_Series QL = new(bars, period:period, useNaN:false); - Tulip.Indicators.atr.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - //Tulip ATR doesn't use warm-up SMA, compensating with 200 warming bars - for (int i = QL.Length - 1; i > 200+skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void BBANDS() - { - double[][] arrin = { inclose }; - double[] outmid = new double[bars.Count]; - double[] outlower = new double[bars.Count]; - double[] outupper = new double[bars.Count]; - double[][] arrout = { outlower, outmid, outupper}; - BBANDS_Series QL = new(bars.Close, period, 2, false); - Tulip.Indicators.bbands.Run(inputs: arrin, options: new double[] { period, 2 }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL.Lower[i].v; - double TU_item = outlower[i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Mid[i].v; - TU_item = outmid[i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - QL_item = QL.Upper[i].v; - TU_item = outupper[i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - /* + ATR_Series QL = new(bars, period: period, useNaN: false); + Tulip.Indicators.atr.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + //Tulip ATR doesn't use warm-up SMA, compensating with 200 warming bars + for (int i = QL.Length - 1; i > 200 + skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void BBANDS() + { + double[][] arrin = { inclose }; + double[] outmid = new double[bars.Count]; + double[] outlower = new double[bars.Count]; + double[] outupper = new double[bars.Count]; + double[][] arrout = { outlower, outmid, outupper }; + BBANDS_Series QL = new(bars.Close, period, 2, false); + Tulip.Indicators.bbands.Run(inputs: arrin, options: new double[] { period, 2 }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL.Lower[i].v; + double TU_item = outlower[i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Mid[i].v; + TU_item = outmid[i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + QL_item = QL.Upper[i].v; + TU_item = outupper[i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + /* [Fact] public void CCI() { double[][] arrin = { inhigh, inlow, inclose }; @@ -128,349 +128,397 @@ public class Tulip_Test } } */ - [Fact] - public void CMO() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - CMO_Series QL = new(bars.Close, period, useNaN: false); - Tulip.Indicators.cmo.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void DECAY() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - DECAY_Series QL = new(bars.Close, period, useNaN: false); - Tulip.Indicators.decay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip + 200; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void DEMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - DEMA_Series QL = new(bars.Close, period, useNaN: false, useSMA: false); - Tulip.Indicators.dema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip+200; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i-(period+period-2)]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void DIV() { - double[][] arrin = { inhigh, inlow }; - double[][] arrout = { outdata }; - DIV_Series QL = new(bars.High, bars.Low); - Tulip.Indicators.div.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void EDECAY() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - DECAY_Series QL = new(bars.Close, period, exponential: true, useNaN: false); - Tulip.Indicators.edecay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip + 200; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void EMA() - { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - // Tulip EMA doesn't use SMA to warm-up - EMA_Series QL = new(bars.Close, period, false, useSMA: false); - Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) + [Fact] + public void CMO() { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + CMO_Series QL = new(bars.Close, period, useNaN: false); + Tulip.Indicators.cmo.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } } - } - [Fact] - public void HL2() { - double[][] arrin = { inhigh, inlow }; - double[][] arrout = { outdata }; + [Fact] + public void DECAY() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + DECAY_Series QL = new(bars.Close, period, useNaN: false); + Tulip.Indicators.decay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 200; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void DEMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + DEMA_Series QL = new(bars.Close, period, useNaN: false, useSMA: false); + Tulip.Indicators.dema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 200; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - (period + period - 2)]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void DIV() + { + double[][] arrin = { inhigh, inlow }; + double[][] arrout = { outdata }; + DIV_Series QL = new(bars.High, bars.Low); + Tulip.Indicators.div.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void EDECAY() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + DECAY_Series QL = new(bars.Close, period, exponential: true, useNaN: false); + Tulip.Indicators.edecay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 200; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void EMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + // Tulip EMA doesn't use SMA to warm-up + EMA_Series QL = new(bars.Close, period, false, useSMA: false); + Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void HL2() + { + double[][] arrin = { inhigh, inlow }; + double[][] arrout = { outdata }; - TSeries QL = bars.HL2; - Tulip.Indicators.medprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void HLC3() { - double[][] arrin = { inhigh, inlow, inclose }; - double[][] arrout = { outdata }; + TSeries QL = bars.HL2; + Tulip.Indicators.medprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void HLC3() + { + double[][] arrin = { inhigh, inlow, inclose }; + double[][] arrout = { outdata }; - TSeries QL = bars.HLC3; - Tulip.Indicators.typprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void HLCC4() { - double[][] arrin = { inhigh, inlow, inclose }; - double[][] arrout = { outdata }; + TSeries QL = bars.HLC3; + Tulip.Indicators.typprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void HLCC4() + { + double[][] arrin = { inhigh, inlow, inclose }; + double[][] arrout = { outdata }; - TSeries QL = bars.HLCC4; - Tulip.Indicators.wcprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - - [Fact] - public void HMA() { - int p = 10; - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - HMA_Series QL = new(bars.Close, p, false); - Tulip.Indicators.hma.Run(inputs: arrin, options: new double[] { p }, outputs: arrout); - for (int i = QL.Length - 1; i > skip+2; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - p - 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits-2), Math.Exp(-digits-2)); - } - } - - [Fact] - public void KAMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - KAMA_Series QL = new(bars.Close, period); - Tulip.Indicators.kama.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > 250; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - - [Fact] - public void LINREG() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - SLOPE_Series QL = new(bars.Close, period); - Tulip.Indicators.linregslope.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period+1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void MACD() { + TSeries QL = bars.HLCC4; + Tulip.Indicators.wcprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } - double[] outsignal = new double[bars.Count]; - double[] outhist = new double[bars.Count]; - double[][] arrin = { inclose }; - double[][] arrout = { outdata, outsignal, outhist }; - MACD_Series QL = new(bars.Close, slow: 26,fast: 10, signal: 9); - Tulip.Indicators.macd.Run(inputs: arrin, options: new double[] { 10,26,9 }, outputs: arrout); - for (int i = QL.Length - 1; i > 150; i--) { - double QL_item = QL[i].v; - double TU_item =outdata[i - 26+1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void MAX() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - MAX_Series QL = new(bars.Close, period, false); - Tulip.Indicators.max.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i-period+1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void MIN() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - MIN_Series QL = new(bars.Close, period, false); - Tulip.Indicators.min.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void MUL() { - double[][] arrin = { inhigh, inlow }; - double[][] arrout = { outdata }; - MUL_Series QL = new(bars.High, bars.Low); - Tulip.Indicators.mul.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void OBV() { - double[][] arrin = { inclose, involume }; - double[][] arrout = { outdata }; - OBV_Series QL = new(bars, period, false); - Tulip.Indicators.obv.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i] + arrin[1][0]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void OHLC4() - { - double[][] arrin = { inopen, inhigh, inlow, inclose }; - double[][] arrout = { outdata }; + [Fact] + public void HMA() + { + int p = 10; + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + HMA_Series QL = new(bars.Close, p, false); + Tulip.Indicators.hma.Run(inputs: arrin, options: new double[] { p }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 2; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - p - 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits - 2), Math.Exp(-digits - 2)); + } + } - TSeries QL = bars.OHLC4; - Tulip.Indicators.avgprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void RMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - RMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.wilders.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void RSI() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - RSI_Series QL = new(bars.Close, period, false); - Tulip.Indicators.rsi.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void SMA() - { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - SMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].v; - double TU_item = arrout[0][i-period+1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void SDEV() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - SDEV_Series QL = new(bars.Close, period, false); - Tulip.Indicators.stddev.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void SUB() { - double[][] arrin = { inhigh, inlow }; - double[][] arrout = { outdata }; - SUB_Series QL = new(bars.High, bars.Low); - Tulip.Indicators.sub.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void SUM() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - CUSUM_Series QL = new(bars.Close, period, false); - Tulip.Indicators.sum.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void TR() { - double[][] arrin = { inhigh,inlow,inclose }; - double[][] arrout = { outdata }; - TR_Series QL = new(bars); - Tulip.Indicators.tr.Run(inputs: arrin, options: new double[] {}, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void TEMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - TEMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.tema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip+200; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - (period-1)*3]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void TRIMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - TRIMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.trima.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - /* + [Fact] + public void KAMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + KAMA_Series QL = new(bars.Close, period); + Tulip.Indicators.kama.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > 250; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + + [Fact] + public void LINREG() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + SLOPE_Series QL = new(bars.Close, period); + Tulip.Indicators.linregslope.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void MACD() + { + + double[] outsignal = new double[bars.Count]; + double[] outhist = new double[bars.Count]; + double[][] arrin = { inclose }; + double[][] arrout = { outdata, outsignal, outhist }; + MACD_Series QL = new(bars.Close, slow: 26, fast: 10, signal: 9); + Tulip.Indicators.macd.Run(inputs: arrin, options: new double[] { 10, 26, 9 }, outputs: arrout); + for (int i = QL.Length - 1; i > 150; i--) + { + double QL_item = QL[i].v; + double TU_item = outdata[i - 26 + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void MAX() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + MAX_Series QL = new(bars.Close, period, false); + Tulip.Indicators.max.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void MIN() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + MIN_Series QL = new(bars.Close, period, false); + Tulip.Indicators.min.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void MUL() + { + double[][] arrin = { inhigh, inlow }; + double[][] arrout = { outdata }; + MUL_Series QL = new(bars.High, bars.Low); + Tulip.Indicators.mul.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void OBV() + { + double[][] arrin = { inclose, involume }; + double[][] arrout = { outdata }; + OBV_Series QL = new(bars, period, false); + Tulip.Indicators.obv.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i] + arrin[1][0]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void OHLC4() + { + double[][] arrin = { inopen, inhigh, inlow, inclose }; + double[][] arrout = { outdata }; + + TSeries QL = bars.OHLC4; + Tulip.Indicators.avgprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void RMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + RMA_Series QL = new(bars.Close, period, false); + Tulip.Indicators.wilders.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void RSI() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + RSI_Series QL = new(bars.Close, period, false); + Tulip.Indicators.rsi.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void SMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + SMA_Series QL = new(bars.Close, period, false); + Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void SDEV() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + SDEV_Series QL = new(bars.Close, period, false); + Tulip.Indicators.stddev.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void SUB() + { + double[][] arrin = { inhigh, inlow }; + double[][] arrout = { outdata }; + SUB_Series QL = new(bars.High, bars.Low); + Tulip.Indicators.sub.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void SUM() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + CUSUM_Series QL = new(bars.Close, period, false); + Tulip.Indicators.sum.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void TR() + { + double[][] arrin = { inhigh, inlow, inclose }; + double[][] arrout = { outdata }; + TR_Series QL = new(bars); + Tulip.Indicators.tr.Run(inputs: arrin, options: new double[] { }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void TEMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + TEMA_Series QL = new(bars.Close, period, false); + Tulip.Indicators.tema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 200; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - (period - 1) * 3]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void TRIMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + TRIMA_Series QL = new(bars.Close, period, false); + Tulip.Indicators.trima.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + /* [Fact] public void TRIX() { double[][] arrin = { inclose }; @@ -484,41 +532,47 @@ public class Tulip_Test } } */ - [Fact] - public void VAR() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - VAR_Series QL = new(bars.Close, period, false); - Tulip.Indicators.var.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void WMA() { - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - WMA_Series QL = new(bars.Close, period, false); - Tulip.Indicators.wma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - for (int i = QL.Length - 1; i > skip; i--) { - double QL_item = QL[i].v; - double TU_item = arrout[0][i - period + 1]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); - } - } - [Fact] - public void ZLEMA() { - int p = 4; - double[][] arrin = { inclose }; - double[][] arrout = { outdata }; - ZLEMA_Series QL = new(bars.Close, p, false); - Tulip.Indicators.zlema.Run(inputs: arrin, options: new double[] { p }, outputs: arrout); - for (int i = QL.Length - 1; i > skip+20; i--) { - double QL_item = QL[i].v; - double TU_item = outdata[i]; - Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits-2), Math.Exp(-digits-2)); - } - } + [Fact] + public void VAR() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + VAR_Series QL = new(bars.Close, period, false); + Tulip.Indicators.var.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void WMA() + { + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + WMA_Series QL = new(bars.Close, period, false); + Tulip.Indicators.wma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); + for (int i = QL.Length - 1; i > skip; i--) + { + double QL_item = QL[i].v; + double TU_item = arrout[0][i - period + 1]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); + } + } + [Fact] + public void ZLEMA() + { + int p = 4; + double[][] arrin = { inclose }; + double[][] arrout = { outdata }; + ZLEMA_Series QL = new(bars.Close, p, false); + Tulip.Indicators.zlema.Run(inputs: arrin, options: new double[] { p }, outputs: arrout); + for (int i = QL.Length - 1; i > skip + 20; i--) + { + double QL_item = QL[i].v; + double TU_item = outdata[i]; + Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits - 2), Math.Exp(-digits - 2)); + } + } } diff --git a/v2/GBM_Feed.cs b/v2/GBM_Feed.cs new file mode 100644 index 00000000..6a203c1f --- /dev/null +++ b/v2/GBM_Feed.cs @@ -0,0 +1,57 @@ +namespace QuanTAlib; +public class GBM_Feed +{ + private readonly double _mu; + private readonly double _sigma; + private readonly Random _random; + private double _lastClose; + private double _lastHigh; + private double _lastLow; + + public GBM_Feed(double initialPrice, double mu, double sigma) + { + _lastClose = initialPrice; + _lastHigh = initialPrice; + _lastLow = initialPrice; + _mu = mu; + _sigma = sigma; + _random = Random.Shared; + } + + public TBar Generate(bool IsNew = true) + { + DateTime time = DateTime.UtcNow; + double dt = 1.0 / 252; // Assuming daily steps in a trading year of 252 days + double drift = (_mu - 0.5 * _sigma * _sigma) * dt; + double diffusion = _sigma * Math.Sqrt(dt) * NormalRandom(); + double newClose = _lastClose * Math.Exp(drift + diffusion); + + double open = _lastClose; + double high = Math.Max(open, newClose) * (1 + _random.NextDouble() * 0.01); + double low = Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01); + double volume = 1000 + _random.NextDouble() * 1000; // Random volume between 1000 and 2000 + + if (!IsNew) + { + high = Math.Max(_lastHigh, high); + low = Math.Min(_lastLow, low); + } + else + { + _lastClose = newClose; + } + + _lastHigh = high; + _lastLow = low; + + return new TBar(time, open, high, low, newClose, volume, IsNew); + } + + private double NormalRandom() + { + // Box-Muller transform to generate standard normal random variable + double u1 = 1.0 - _random.NextDouble(); // Uniform(0,1] random doubles + double u2 = 1.0 - _random.NextDouble(); + return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); + } +} \ No newline at end of file diff --git a/v2/Indicators/EMA.cs b/v2/Indicators/EMA.cs new file mode 100644 index 00000000..3448461a --- /dev/null +++ b/v2/Indicators/EMA.cs @@ -0,0 +1,42 @@ +namespace QuanTAlib; + +public class EMA +{ + private double lastEma, lastEmaCandidate, k; + private int period, i; + public TValue Value { get; private set; } + public bool IsHot { get; private set; } + + public EMA(int period) + { + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.k = 2.0 / (period + 1); + this.lastEma = this.lastEmaCandidate = double.NaN; + this.i = 0; + } + public TValue Update(TValue input, bool IsNew = true) + { + double ema; + + if (double.IsNaN(lastEma)) { lastEma = input.Value; } + + if (IsNew) + { + lastEma = lastEmaCandidate; + i++; + } + + double kk = (i < period) ? (2.0 / (i + 1)) : k; + ema = lastEma + kk * (input.Value - lastEma); + lastEmaCandidate = ema; + + IsHot = i >= period; + Value = new TValue(input.Time, ema, IsNew, IsHot); + return Value; + } +} \ No newline at end of file diff --git a/v2/Indicators/SMA.cs b/v2/Indicators/SMA.cs new file mode 100644 index 00000000..2929cdf0 --- /dev/null +++ b/v2/Indicators/SMA.cs @@ -0,0 +1,53 @@ +namespace QuanTAlib; + +public class SMA +{ + private CircularBuffer buffer = null!; + private int period; + private double sum; + public TValue Value { get; private set; } + public bool IsHot { get; private set; } + + public SMA(int period) + { + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.buffer = new CircularBuffer(period); + this.sum = 0; + this.IsHot = false; + this.Value = default; + } + + public TValue Update(TValue input, bool IsNew = true) + { + if (buffer.Count == 0 || isNew) + { + if (buffer.Count == period) + { + sum -= buffer[0]; + } + buffer.Add(input); + sum += input.Value; + } + else + { + sum -= buffer[buffer.Count - 1]; + sum += input.Value; + buffer[buffer.Count - 1] = input; + } + + double sma = sum / buffer.Count; + Value = new TValue(input.Time, sma, isNew, IsHot); + return Value; + } + + double sma = buffer.Count > 0 ? sum / buffer.Count : double.NaN; + IsHot = buffer.Count >= period; + Value = new TValue(input.Time, sma, IsNew, IsHot); + return Value; + } +} diff --git a/v2/Indicators/WMA.cs b/v2/Indicators/WMA.cs new file mode 100644 index 00000000..f938fab9 --- /dev/null +++ b/v2/Indicators/WMA.cs @@ -0,0 +1,64 @@ +namespace QuanTAlib; + +public class WMA +{ + private CircularBuffer buffer = null!; + private CircularBuffer weights = null!; + private int period; + public TValue Value { get; private set; } + public bool IsHot { get; private set; } + + public WMA(int period) + { + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.buffer = new CircularBuffer(period); + this.weights = new CircularBuffer(period); + CalculateWeights(); + this.IsHot = false; + this.Value = default; + } + + public TValue Update(TValue input, bool IsNew = true) + { + if (IsNew) + { + buffer.Add(input); + } + else if (buffer.Count > 0) + { + buffer[buffer.Count - 1] = input; + } + else + { + buffer.Add(input); + } + + double wma = 0; + double totalWeights = 0; + + for (int i = 0; i < buffer.Count; i++) + { + wma += buffer[i] * weights[i]; + totalWeights += weights[i]; + } + + wma /= totalWeights; + + IsHot = buffer.Count >= period; + Value = new TValue(input.Time, wma, IsNew, IsHot); + return Value; + } + + private void CalculateWeights() + { + for (int i = 1; i <= period; i++) + { + weights.Add(i); + } + } +} \ No newline at end of file diff --git a/v2/basics/CircularBuffer.cs b/v2/basics/CircularBuffer.cs new file mode 100644 index 00000000..3e087dd1 --- /dev/null +++ b/v2/basics/CircularBuffer.cs @@ -0,0 +1,57 @@ +namespace QuanTAlib; + +public class CircularBuffer +{ + private double[] _buffer = null!; + private int _start; + private int _size; + + public CircularBuffer(int capacity) + { + _buffer = new double[capacity]; + _start = 0; + _size = 0; + } + + public int Capacity => _buffer.Length; + public int Count => _size; + + public void Add(double item, bool isNew) + { + if (_size == 0 || isNew) + { + // If buffer is empty or isNew is true, add new item + if (_size < Capacity) + { + _buffer[(_start + _size) % Capacity] = item; + _size++; + } + else + { + _buffer[_start] = item; + _start = (_start + 1) % Capacity; + } + } + else + { + // If isNew is false, just update the last item + _buffer[(_start + _size - 1) % Capacity] = item; + } + } + + public double this[int index] + { + get + { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + return _buffer[(_start + index) % Capacity]; + } + set + { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + _buffer[(_start + index) % Capacity] = value; + } + } +} \ No newline at end of file diff --git a/v2/basics/TBar.cs b/v2/basics/TBar.cs new file mode 100644 index 00000000..bb98d683 --- /dev/null +++ b/v2/basics/TBar.cs @@ -0,0 +1,17 @@ +namespace QuanTAlib; +public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) +{ + public DateTime Time { get; init; } = Time; + public double Open { get; init; } = Open; + public double High { get; init; } = High; + public double Low { get; init; } = Low; + public double Close { get; init; } = Close; + public double Volume { get; init; } = Volume; + public bool IsNew { get; init; } = IsNew; + + public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { } + public TBar(double open, double high, double low, double close, double volume) : this(DateTime.UtcNow, open, high, low, close, volume) { } + public TBar((DateTime time, double open, double high, double low, double close, double volume) tuple) : this(tuple.time, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) { } + + 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}]"; +} \ No newline at end of file diff --git a/v2/basics/TValue.cs b/v2/basics/TValue.cs new file mode 100644 index 00000000..83a8efd7 --- /dev/null +++ b/v2/basics/TValue.cs @@ -0,0 +1,20 @@ +namespace QuanTAlib; + +public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) +{ + public DateTime Time { get; init; } = Time; + public double Value { get; init; } = Value; + public bool IsNew { get; init; } = IsNew; + public bool IsHot { get; init; } = IsHot; + + public TValue() : this(DateTime.UtcNow, 0) { } + public TValue(double value) : this(DateTime.UtcNow, value) { } + public TValue((DateTime time, double value) tuple) : this(tuple.time, tuple.value) { } + + public static implicit operator double(TValue tv) => tv.Value; + public static implicit operator DateTime(TValue tv) => tv.Time; + public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value); + + public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: {Value:F2}]"; +} + diff --git a/v2/calculations.csproj b/v2/calculations.csproj new file mode 100644 index 00000000..a7ad53bd --- /dev/null +++ b/v2/calculations.csproj @@ -0,0 +1,31 @@ + + + + net8.0 + enable + enable + preview + false + Indicator + git + Apache-2.0 + false + true + true + true + D:\Quantower\TradingPlatform + v1.140.8 + + + + $(QuantowerPath)\$(QuantowerVersion)\bin\TradingPlatform.BusinessLayer.dll + + + + + + TradingPlatform.BusinessLayer.xml + + + + \ No newline at end of file diff --git a/v2/test.dib b/v2/test.dib new file mode 100644 index 00000000..6c4454f6 --- /dev/null +++ b/v2/test.dib @@ -0,0 +1,277 @@ +#!meta + +{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} + +#!csharp + +#r ".\bin\Debug\calculations.dll" +using QuanTAlib; + +#!csharp + +public class CircularBuffer +{ + private double[] _buffer; + private int _start; + private int _size; + + public CircularBuffer(int capacity) + { + _buffer = new double[capacity]; + _start = 0; + _size = 0; + } + + public int Capacity => _buffer.Length; + public int Count => _size; + + public void Add(double item, bool isNew) + { + if (!isNew) + { + // Add new item + if (_size < Capacity) + { + _buffer[(_start + _size) % Capacity] = item; + _size++; + } + else + { + _start = (_start + 1) % Capacity; + _buffer[(_start + _size - 1) % Capacity] = item; + } + } + else + { + // Update the last item + if (_size > 0) + { + _buffer[(_start + _size - 1) % Capacity] = item; + } + else + { + // If buffer is empty, add the item even if isNew is true + _buffer[0] = item; + _size = 1; + } + } + } + + public double this[int index] + { + get + { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + return _buffer[(_start + index) % Capacity]; + } + set + { + if (index < 0 || index >= _size) + throw new IndexOutOfRangeException(); + _buffer[(_start + index) % Capacity] = value; + } + } +} + +#!csharp + +public class SMA1 +{ + private CircularBuffer buffer; + private int period; + private double sum; + public TValue Value { get; private set; } + public bool IsHot => buffer.Count >= period; + + public SMA1(int period) + { + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.buffer = new CircularBuffer(period); + this.sum = 0; + this.Value = default; + } + + public TValue Update(TValue input, bool isNew = true) + { + if (!isNew) + { + if (buffer.Count == period) + { + sum -= buffer[0]; + } + sum += input.Value; + buffer.Add(input.Value, isNew); + } + else + { + if (buffer.Count > 0) + { + sum -= buffer[buffer.Count - 1]; + sum += input.Value; + buffer.Add(input.Value, isNew); + } + else + { + // If buffer is empty, add the item even if isNew is true + sum += input.Value; + buffer.Add(input.Value, false); + } + } + + double sma = buffer.Count > 0 ? sum / buffer.Count : double.NaN; + Value = new TValue(input.Time, sma, isNew, IsHot); + return Value; + } +} + +#!csharp + +GBM_Feed feed = new(initialPrice: 100, mu: 0.1, sigma: 0.9); +int i=10; +SMA1 ma = new(i); +Console.WriteLine($"{"Close",10} {"MA(" + i + ")",10}"); +for (int i = 0; i < 20; i++) +{ + TValue c =(double)feed.Generate().Close; + ma.Update(1000,false); + ma.Update(-10000,false); + + ma.Update(c,true); + + Console.WriteLine($"{i+1} {(double)c,10:F2} {(double)ma.Value,10:F2}"); +} + +#!csharp + +public class Emitter { + private Random random = new Random(); + public event EventHandler> Pub; + public void Emit() { + DateTime now = DateTime.Now; + double randomValue = random.NextDouble() * 100; // Generates a random number between 0 and 100 + TValue value = new TValue(now, randomValue); + + EventArg eventArg = new EventArg(value, true, true); + OnValuePub(eventArg); + } + protected virtual void OnValuePub(EventArg eventArg) { + Pub?.Invoke(this, eventArg); + } +} + +public class BarEmitter +{ + private Random random = new Random(); + public event EventHandler> Pub; + private double lastClose = 100.0; // Starting price + + public void Emit() + { + double open = lastClose; + double close = open * (1 + (random.NextDouble() - 0.5) * 0.02); // +/- 1% change + double high = Math.Max(open, close) * (1 + random.NextDouble() * 0.005); // Up to 0.5% higher + double low = Math.Min(open, close) * (1 - random.NextDouble() * 0.005); // Up to 0.5% lower + double volume = random.NextDouble() * 1000000; // Random volume between 0 and 1,000,000 + + TBar bar = new TBar(DateTime.Now, open, high, low, close, volume); + lastClose = close; + + EventArg eventArg = new EventArg(bar, true, true); + OnBarPub(eventArg); + } + + protected virtual void OnBarPub(EventArg eventArg) + { + Pub?.Invoke(this, eventArg); + } +} + + +public class Listener +{ + public void Sub(object sender, EventArgs e) + { + if (e is EventArg tValueArg) { + Console.WriteLine($"TValue: {tValueArg.Data.Value:F2}"); + } else if (e is EventArg tBarArg) { + Console.WriteLine($"TBar: o={tBarArg.Data.Open:F2}, v={tBarArg.Data.Volume:F2}"); + } else { + Console.WriteLine($"Unknown type: {e.GetType().Name}"); + } + } +} + +#!csharp + +Emitter em1 = new(); +BarEmitter em2 = new(); +Listener list = new(); + +em1.Pub += list.Sub; +em2.Pub += list.Sub; + +// Emit 5 random values +for (int i = 0; i < 3; i++) { + em1.Emit(); + em2.Emit(); +} + +#!csharp + +public abstract class Indicator { + protected Indicator() { + Init(); } + public virtual void Init() {} + public virtual TValue Calc(TValue input, bool isNew=true, bool isHot=true) { + return new TValue(); + } +} + +public class EMA : Indicator +{ + private double lastEma, lastEmaCandidate, k; + private int period, i; + + public EMA(int period) { + Init(period); + } + + public void Init(int period) + { + this.period = period; + this.k = 2.0 / (period + 1); + this.lastEma = this.lastEmaCandidate = double.NaN; + this.i = 0; + } + + public override TValue Calc(TValue input, bool isNew = true, bool isHot = true) { + double ema; + + if (double.IsNaN(lastEma)) { lastEma = lastEmaCandidate = input.Value; } + + if (isNew) { + lastEma = lastEmaCandidate; + i++; + } + + double kk = (i>=period)?k:(2.0/(i+1)); + ema = lastEma + kk * (input.Value - lastEma); + lastEmaCandidate = ema; + + return new TValue(input.Timestamp, ema); + } +} + +#!csharp + +EMA ema = new(3); +display(ema.Calc(100)); +display(ema.Calc(0,false)); +display(ema.Calc(100,false)); +display(ema.Calc(0));