From 3455baaf6cff30c4dbc89e30a5ff099b0081e529 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Sun, 28 Jul 2024 21:26:44 -0700 Subject: [PATCH] refactor structs to records, add new classes for financial calculations, implement EMA and SMA with circular buffer. Generate random financial data using GBM model. Also, test the SMA calculation with sample data. --- .editorconfig | 10 +- .refactoring/base.cs | 268 +++-- .refactoring/test.dib | 23 +- Calculations/Basics/ADD_Series.cs | 21 +- Calculations/Basics/CORR_Series.cs | 50 +- Calculations/Basics/COVAR_Series.cs | 46 +- Calculations/Basics/DIV_Series.cs | 23 +- Calculations/Basics/MUL_Series.cs | 23 +- Calculations/Basics/SUB_Series.cs | 23 +- .../ClassStructures/Pair_TSeries_Abstract.cs | 223 ++-- Calculations/Feeds/Alphavantage_Feed.cs | 6 +- Calculations/Feeds/GBM_Feed.cs | 40 +- Calculations/Feeds/Yahoo_Feed.cs | 44 +- Calculations/Logic/COMPARE_Series.cs | 39 +- Calculations/Logic/CROSS_Series.cs | 51 +- Calculations/Logic/TOrders.cs | 40 +- Calculations/_Updated/ADL_Series.cs | 100 +- Calculations/_Updated/ADOSC_Series.cs | 134 ++- Calculations/_Updated/ALMA_Series.cs | 179 +-- Calculations/_Updated/ATRP_Series.cs | 142 +-- Calculations/_Updated/ATR_Series.cs | 142 +-- Calculations/_Updated/BBANDS_Series.cs | 163 +-- Calculations/_Updated/BIAS_Series.cs | 111 +- Calculations/_Updated/CCI_Series.cs | 127 ++- Calculations/_Updated/CMO_Series.cs | 136 +-- Calculations/_Updated/CUSUM_Series.cs | 111 +- Calculations/_Updated/DECAY_Series.cs | 134 ++- Calculations/_Updated/DEMA_Series.cs | 203 ++-- Calculations/_Updated/DWMA_Series.cs | 197 ++-- Calculations/_Updated/EMA_Series.cs | 190 ++-- Calculations/_Updated/ENTROPY_Series.cs | 134 ++- Calculations/_Updated/FWMA_Series.cs | 161 +-- Calculations/_Updated/HEMA_Series.cs | 199 ++-- Calculations/_Updated/HMA_Series.cs | 136 +-- Calculations/_Updated/HWMA_Series.cs | 190 ++-- Calculations/_Updated/KAMA_Series.cs | 157 +-- Calculations/_Updated/KURTOSIS_Series.cs | 133 ++- Calculations/_Updated/MACD_Series.cs | 124 +- Calculations/_Updated/MAD_Series.cs | 115 +- Calculations/_Updated/MAE_Series.cs | 115 +- Calculations/_Updated/MAMA_Series.cs | 310 ++--- Calculations/_Updated/MAPE_Series.cs | 120 +- Calculations/_Updated/MAX_Series.cs | 109 +- Calculations/_Updated/MEDIAN_Series.cs | 117 +- Calculations/_Updated/MIDPOINT_Series.cs | 111 +- Calculations/_Updated/MIDPRICE_Series.cs | 105 +- Calculations/_Updated/MIN_Series.cs | 109 +- Calculations/_Updated/MSE_Series.cs | 115 +- Calculations/_Updated/OBV_Series.cs | 126 ++- Calculations/_Updated/RMA_Series.cs | 185 +-- Calculations/_Updated/RSI_Series.cs | 196 ++-- Calculations/_Updated/SDEV_Series.cs | 117 +- Calculations/_Updated/SLOPE_Series.cs | 170 +-- Calculations/_Updated/SMAPE_Series.cs | 115 +- Calculations/_Updated/SMA_Series.cs | 156 +-- Calculations/_Updated/SMMA_Series.cs | 140 +-- Calculations/_Updated/SSDEV_Series.cs | 117 +- Calculations/_Updated/SVAR_Series.cs | 115 +- Calculations/_Updated/T3_Series.cs | 272 ++--- Calculations/_Updated/TBars.cs | 249 ++-- Calculations/_Updated/TEMA_Series.cs | 200 ++-- Calculations/_Updated/TRIMA_Series.cs | 128 ++- Calculations/_Updated/TRIX_Series.cs | 200 ++-- Calculations/_Updated/TR_Series.cs | 112 +- Calculations/_Updated/TSeries.cs | 180 +-- Calculations/_Updated/VAR_Series.cs | 115 +- Calculations/_Updated/WMAPE_Series.cs | 124 +- Calculations/_Updated/WMA_Series.cs | 171 +-- Calculations/_Updated/ZLEMA_Series.cs | 140 +-- Calculations/_Updated/ZL_Series.cs | 138 +-- Calculations/_Updated/ZSCORE_Series.cs | 119 +- Indicators/Charts/2MACross_chart.cs | 504 +++++---- Indicators/Charts/2MASlope_chart.cs | 557 ++++----- Indicators/Charts/JMA_chart.cs | 145 +-- Indicators/Charts/TrailingStop.cs | 149 +-- Tests/Basic tests/Indicators.cs | 245 ++-- Tests/Basic tests/Oscillators.cs | 245 ++-- Tests/Basic tests/TBars_input.cs | 149 +-- Tests/Pairs/DIV_Test.cs | 102 +- Tests/Pairs/MUL_Test.cs | 102 +- Tests/Pairs/SUB_Test.cs | 102 +- Tests/Pairs/TBars_Test.cs | 90 +- Tests/Validations/Trends/Pandas_TA.cs | 764 +++++++------ Tests/Validations/Trends/Skender.cs | 935 +++++++-------- Tests/Validations/Trends/TA_LIB.cs | 814 ++++++------- Tests/Validations/Trends/Tulip.cs | 1008 +++++++++-------- v2/GBM_Feed.cs | 57 + v2/Indicators/EMA.cs | 42 + v2/Indicators/SMA.cs | 53 + v2/Indicators/WMA.cs | 64 ++ v2/basics/CircularBuffer.cs | 57 + v2/basics/TBar.cs | 17 + v2/basics/TValue.cs | 20 + v2/calculations.csproj | 31 + v2/test.dib | 277 +++++ 95 files changed, 8661 insertions(+), 7012 deletions(-) create mode 100644 v2/GBM_Feed.cs create mode 100644 v2/Indicators/EMA.cs create mode 100644 v2/Indicators/SMA.cs create mode 100644 v2/Indicators/WMA.cs create mode 100644 v2/basics/CircularBuffer.cs create mode 100644 v2/basics/TBar.cs create mode 100644 v2/basics/TValue.cs create mode 100644 v2/calculations.csproj create mode 100644 v2/test.dib 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));