From 32615af18bf5ad9412c8c2448dc573f04beba68c Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Sun, 6 Nov 2022 16:43:24 -0800 Subject: [PATCH] for dev branch --- Quantower/Indicators/JMA_chart.cs | 52 ----- Quantower/Indicators/PSDEV_chart.cs | 53 ----- Quantower/Indicators/SDEV_chart.cs | 106 ++++----- Quantower/Indicators/ZLMA_chart.cs | 11 +- Source/Feeds/Alphavantage_Feed.cs | 4 +- Source/Indicators/JMA_Series.cs | 323 ++++++++++++++-------------- Source/QuanTAlib.csproj | 4 +- Source/Statistics/PSDEV_Series.cs | 44 ---- Source/Statistics/SDEV_Series.cs | 86 ++++---- Tests/MovingAvg/JMA_Test.cs | 33 --- Tests/Statistics/PSDEV_Test.cs | 66 +++--- Tests/Statistics/SDEV_Test .cs | 66 +++--- Tests/Validations/TA_LIB.cs | 10 + docs/ma-comparison.dib | 244 --------------------- 14 files changed, 346 insertions(+), 756 deletions(-) delete mode 100644 Quantower/Indicators/JMA_chart.cs delete mode 100644 Quantower/Indicators/PSDEV_chart.cs delete mode 100644 Source/Statistics/PSDEV_Series.cs delete mode 100644 Tests/MovingAvg/JMA_Test.cs delete mode 100644 docs/ma-comparison.dib diff --git a/Quantower/Indicators/JMA_chart.cs b/Quantower/Indicators/JMA_chart.cs deleted file mode 100644 index e2f13cb4..00000000 --- a/Quantower/Indicators/JMA_chart.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class JMA_chart : Indicator -{ - #region Parameters - - [InputParameter("Smoothing period", 0, 1, 999, 1, 1)] - private int Period = 10; - - [InputParameter("Data source", 1, 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; - - #endregion Parameters - - private TBars bars ; - - /////// - private JMA_Series indicator; - /////// - - public JMA_chart() - { - this.SeparateWindow = false; - this.Name = "JMA - Jurik Moving Average"; - this.Description = "Jurik Moving Average description"; - this.AddLineSeries("JMA", Color.RoyalBlue, 3, LineStyle.Solid); - } - - protected override void OnInit() - { - this.ShortName = - "JMA (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")"; - this.bars = new(); - this.indicator = new(source: bars.Select(this.DataSource), - period: this.Period, useNaN: false); - } - 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); - double result = this.indicator[this.indicator.Count - 1].v; - this.SetValue(result); - } -} diff --git a/Quantower/Indicators/PSDEV_chart.cs b/Quantower/Indicators/PSDEV_chart.cs deleted file mode 100644 index 372d7ba6..00000000 --- a/Quantower/Indicators/PSDEV_chart.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class PSDEV_chart : Indicator -{ - #region Parameters - - [InputParameter("Smoothing period", 0, 1, 999, 1, 1)] - private int Period = 10; - - [InputParameter("Data source", 1, 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 = 8; - - #endregion Parameters - - private TBars bars; - - ///////dotnet - private PSDEV_Series indicator; - /////// - - public PSDEV_chart() - { - this.SeparateWindow = true; - this.Name = "PSDEV - Population Standard Deviation (Biased)"; - this.Description = "PSDEV description"; - this.AddLineSeries("PSDEV", Color.RoyalBlue, 3, LineStyle.Solid); - } - - protected override void OnInit() - { - this.bars = new(); - this.ShortName = - "PSDEV (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")"; - this.indicator = new(source: bars.Select(this.DataSource), - period: this.Period, useNaN: true); - } - 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); - double result = this.indicator[this.indicator.Count - 1].v; - - this.SetValue(result, 0); - } -} diff --git a/Quantower/Indicators/SDEV_chart.cs b/Quantower/Indicators/SDEV_chart.cs index 80a9ad1f..17c87873 100644 --- a/Quantower/Indicators/SDEV_chart.cs +++ b/Quantower/Indicators/SDEV_chart.cs @@ -1,53 +1,53 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class SDEV_chart : Indicator -{ - #region Parameters - - [InputParameter("Smoothing period", 0, 1, 999, 1, 1)] - private int Period = 10; - - [InputParameter("Data source", 1, 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 = 8; - - #endregion Parameters - - private TBars bars; - - ///////dotnet - private SDEV_Series indicator; - /////// - - public SDEV_chart() - { - this.SeparateWindow = true; - this.Name = "SDEV - Sample Standard Deviation (Unbiased)"; - this.Description = "SDEV description"; - this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid); - } - - protected override void OnInit() - { - this.bars = new(); - this.ShortName = - "SDEV (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")"; - this.indicator = new(source: bars.Select(this.DataSource), - period: this.Period, useNaN: true); - } - 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); - double result = this.indicator[this.indicator.Count - 1].v; - - this.SetValue(result, 0); - } -} +using System.Drawing; +using TradingPlatform.BusinessLayer; +namespace QuanTAlib; + +public class SDEV_chart : Indicator +{ + #region Parameters + + [InputParameter("Smoothing period", 0, 1, 999, 1, 1)] + private int Period = 10; + + [InputParameter("Data source", 1, 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 = 8; + + #endregion Parameters + + private TBars bars; + + ///////dotnet + private SDEV_Series indicator; + /////// + + public SDEV_chart() + { + this.SeparateWindow = true; + this.Name = "SDEV - Population Standard Deviation (Biased)"; + this.Description = "SDEV description"; + this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid); + } + + protected override void OnInit() + { + this.bars = new(); + this.ShortName = + "SDEV (" + TBars.SelectStr(this.DataSource) + ", " + this.Period + ")"; + this.indicator = new(source: bars.Select(this.DataSource), + period: this.Period, useNaN: true); + } + 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); + double result = this.indicator[this.indicator.Count - 1].v; + + this.SetValue(result, 0); + } +} diff --git a/Quantower/Indicators/ZLMA_chart.cs b/Quantower/Indicators/ZLMA_chart.cs index 35cddbdf..eb054d72 100644 --- a/Quantower/Indicators/ZLMA_chart.cs +++ b/Quantower/Indicators/ZLMA_chart.cs @@ -30,12 +30,12 @@ public class ZLMA_chart : Indicator private readonly int matype = 2; #endregion Parameters - + private TBars bars; - /////// + /////// private TSeries indicator; - /////// - + /////// + public ZLMA_chart() { this.SeparateWindow = false; @@ -72,8 +72,7 @@ public class ZLMA_chart : Indicator 4 => new TEMA_Series(source: zerolag, period: this.Period, useNaN: false), 5 => new HMA_Series(source: zerolag, period: this.Period, useNaN: false), 6 => new KAMA_Series(source: zerolag, period: this.Period, useNaN: false), - 7 => new JMA_Series(source: zerolag, period: this.Period, useNaN: false), - 8 => new SMMA_Series(source: zerolag, period: this.Period, useNaN: false), + 7 => new SMMA_Series(source: zerolag, period: this.Period, useNaN: false), _ => new EMA_Series(source: zerolag, period: this.Period, useNaN: false) }; } diff --git a/Source/Feeds/Alphavantage_Feed.cs b/Source/Feeds/Alphavantage_Feed.cs index 046b9fa3..62d9be8d 100644 --- a/Source/Feeds/Alphavantage_Feed.cs +++ b/Source/Feeds/Alphavantage_Feed.cs @@ -13,6 +13,8 @@ Alphavantage - Free API to collect quotes for stock, Forex and crypto. It requir */ +/* TODO: refactor into three feeds: FX, Crypto, Stock */ + public class Alphavantage_Feed : TBars { public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1} @@ -113,7 +115,7 @@ public class Alphavantage_Feed : TBars { Interval.Month => "_MONTHLY", Interval.Week => "_WEEKLY", - Interval.Day => "_DAILY", + Interval.Day => "_DAILY_ADJUSTED", Interval.Hour => "_INTRADAY&interval=60min", Interval.Min30 => "_INTRADAY&interval=30min", Interval.Min15 => "_INTRADAY&interval=15min", diff --git a/Source/Indicators/JMA_Series.cs b/Source/Indicators/JMA_Series.cs index e1dec0e1..0b09d939 100644 --- a/Source/Indicators/JMA_Series.cs +++ b/Source/Indicators/JMA_Series.cs @@ -1,159 +1,164 @@ -namespace QuanTAlib; -using System; - -/* -JMA: Jurik Moving Average - Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the - underlying activity. It has extremely low lag, is very smooth and is responsive - to market gaps. - -Sources: - https://c.mql5.com/forextsd/forum/164/jurik_1.pdf - https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/ - -Issues: - Real JMA algorithm is not published and this formula is derived through - deduction and reverse analysis of JMA behavior. It is really close, but not - exact - published JMA tests against JMA.CSV fail with small deviation. The - original algo is slightly different, yet this approximation is close enough. - - */ - -public class JMA_Series : Single_TSeries_Indicator -{ - private readonly System.Collections.Generic.List vbuffer10; - private readonly System.Collections.Generic.List vsum65; - - private double prev_ma1, prev_det0, prev_det1, prev_jma, bsmax, bsmin; - private double o_prev_ma1, o_prev_det0, o_prev_det1, o_prev_jma, o_bsmax, o_bsmin; - - private readonly double pr, pow1, len2, beta, rvolty; - - public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN) - { - this.vbuffer10 = new(); - this.vsum65 = new(); - - // constants - this.pr = (phase < -100) ? 0.5 : (phase > 100) ? 2.5 : (phase * 0.01) + 1.5; - double len1 = Math.Max((Math.Log(Math.Sqrt(0.5 * (_p - 1))) / Math.Log(2.0)) + 2.0, 0); - this.pow1 = Math.Max(len1 - 2, 0.5); - this.rvolty = Math.Exp((1 / this.pow1) * Math.Log(len1)); - this.len2 = Math.Sqrt(0.5 * (_p - 1)) * len1; - this.beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2); - if (base._data.Count > 0) { base.Add(base._data); } - } - - public override void Add((System.DateTime t, double v) TValue, bool update) - { - if (this.Count == 0) - { - this.prev_ma1 = this.prev_jma = TValue.v; - this.bsmax = this.bsmin = this.prev_det0 = this.prev_det1 = 0; - } - - if (update) - { - this.prev_jma = this.o_prev_jma; - this.prev_ma1 = this.o_prev_ma1; - this.prev_det0 = this.o_prev_det0; - this.prev_det1 = this.o_prev_det1; - this.bsmax = this.o_bsmax; - this.bsmin = this.o_bsmin; - } - else - { - this.o_prev_jma = this.prev_jma; - this.o_prev_ma1 = this.prev_ma1; - this.o_prev_det0 = this.prev_det0; - this.o_prev_det1 = this.prev_det1; - this.o_bsmax = this.bsmax; - this.o_bsmin = this.bsmin; - } - - double hprice = TValue.v; - double lprice = TValue.v; - for (int i = 0; i <= Math.Min(9, this._data.Count - 1); i++) - { - var _item = this._data[this._data.Count - 1 - i].v; - hprice = (_item > hprice) ? _item : hprice; - lprice = (_item < lprice) ? _item : lprice; - } - double del1 = hprice - this.bsmax; - double del2 = lprice - this.bsmin; - - double volty = (Math.Abs(del1) != Math.Abs(del2)) - ? Math.Max(Math.Abs(del1), Math.Abs(del2)) - : 0; - if (update) - { - this.vbuffer10[this.vbuffer10.Count - 1] = volty; - } - else - { - this.vbuffer10.Add(volty); - } - if (this.vbuffer10.Count > 10) - { - this.vbuffer10.RemoveAt(0); - } - - double prevvsum = - (this.vsum65.Count > 0) ? this.vsum65[this.vsum65.Count - 1] : 0; - double vsumitem = prevvsum + 0.1 * (volty - this.vbuffer10[0]); - if (update) - { - this.vsum65[this.vsum65.Count - 1] = vsumitem; - } - else - { - this.vsum65.Add(vsumitem); - } - if (this.vsum65.Count > 65) - { - this.vsum65.RemoveAt(0); - } - - double avolty = 0; - for (int i = 0; i < this.vsum65.Count; i++) - { - avolty += this.vsum65[i]; - } - - avolty /= this.vsum65.Count; - double dvolty = (avolty > 0) ? volty / avolty : 0; - dvolty = Math.Max((dvolty > this.rvolty) ? this.rvolty : dvolty, 1.0); - - double pow2 = Math.Exp(this.pow1 * Math.Log(dvolty)); - double kv = - Math.Exp(Math.Sqrt(pow2) * Math.Log(this.len2 / (this.len2 + 1))); - - this.bsmax = (del1 > 0) ? hprice : hprice - (kv * del1); - this.bsmin = (del2 < 0) ? lprice : lprice - (kv * del2); - - // adaptive EMA dynamic factor - double pow = Math.Pow(dvolty, this.pow1); - double alpha = Math.Pow(this.beta, pow); - - // 1st stage - preliminary smoothing by adaptive EMA - double ma1 = TValue.v * (1 - alpha) + this.prev_ma1 * alpha; - this.prev_ma1 = ma1; - - // 2nd stage - one more preliminary smoothing by Kalman filter - double det0 = (TValue.v - ma1) * (1 - this.beta) + this.prev_det0 * this.beta; - this.prev_det0 = det0; - double ma2 = ma1 + (this.pr * det0); - - // 3rd stage - final smoothing by Jurik adaptive filter - double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) + - (this.prev_det1 * alpha * alpha); - this.prev_det1 = det1; - var jma = this.prev_jma + det1; - this.prev_jma = jma; - - (System.DateTime t, double v) result = - (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma); - base.Add(result, update); - - } -} \ No newline at end of file +namespace QuanTAlib; +using System; + +/* +JMA: Jurik Moving Average + Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the + underlying activity. It has extremely low lag, is very smooth and is responsive + to market gaps. + +Sources: + https://c.mql5.com/forextsd/forum/164/jurik_1.pdf + https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/ + +Issues: + Real JMA algorithm is not published and this formula is derived through + deduction and reverse analysis of JMA behavior. It is really close, but not + exact - published JMA tests against JMA.CSV fail with small deviation. The + original algo is slightly different, yet this approximation is close enough. + + */ + +/* TODO: This indicator is not calculating results correctly - needs to be debugged */ + +/* +public class JMA_Series : Single_TSeries_Indicator +{ + private readonly System.Collections.Generic.List vbuffer10; + private readonly System.Collections.Generic.List vsum65; + + private double prev_ma1, prev_det0, prev_det1, prev_jma, bsmax, bsmin; + private double o_prev_ma1, o_prev_det0, o_prev_det1, o_prev_jma, o_bsmax, o_bsmin; + + private readonly double pr, pow1, len2, beta, rvolty; + + public JMA_Series(TSeries source, int period, double phase = 0.0, bool useNaN = false) : base(source, period, useNaN) + { + this.vbuffer10 = new(); + this.vsum65 = new(); + + // constants + this.pr = (phase < -100) ? 0.5 : (phase > 100) ? 2.5 : (phase * 0.01) + 1.5; + double len1 = Math.Max((Math.Log(Math.Sqrt(0.5 * (_p - 1))) / Math.Log(2.0)) + 2.0, 0); + this.pow1 = Math.Max(len1 - 2, 0.5); + this.rvolty = Math.Exp((1 / this.pow1) * Math.Log(len1)); + this.len2 = Math.Sqrt(0.5 * (_p - 1)) * len1; + this.beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2); + if (base._data.Count > 0) { base.Add(base._data); } + } + + public override void Add((System.DateTime t, double v) TValue, bool update) + { + if (this.Count == 0) + { + this.prev_ma1 = this.prev_jma = TValue.v; + this.bsmax = this.bsmin = this.prev_det0 = this.prev_det1 = 0; + } + + if (update) + { + this.prev_jma = this.o_prev_jma; + this.prev_ma1 = this.o_prev_ma1; + this.prev_det0 = this.o_prev_det0; + this.prev_det1 = this.o_prev_det1; + this.bsmax = this.o_bsmax; + this.bsmin = this.o_bsmin; + } + else + { + this.o_prev_jma = this.prev_jma; + this.o_prev_ma1 = this.prev_ma1; + this.o_prev_det0 = this.prev_det0; + this.o_prev_det1 = this.prev_det1; + this.o_bsmax = this.bsmax; + this.o_bsmin = this.bsmin; + } + + double hprice = TValue.v; + double lprice = TValue.v; + for (int i = 0; i <= Math.Min(9, this._data.Count - 1); i++) + { + var _item = this._data[this._data.Count - 1 - i].v; + hprice = (_item > hprice) ? _item : hprice; + lprice = (_item < lprice) ? _item : lprice; + } + double del1 = hprice - this.bsmax; + double del2 = lprice - this.bsmin; + + double volty = (Math.Abs(del1) != Math.Abs(del2)) + ? Math.Max(Math.Abs(del1), Math.Abs(del2)) + : 0; + if (update) + { + this.vbuffer10[this.vbuffer10.Count - 1] = volty; + } + else + { + this.vbuffer10.Add(volty); + } + if (this.vbuffer10.Count > 10) + { + this.vbuffer10.RemoveAt(0); + } + + double prevvsum = + (this.vsum65.Count > 0) ? this.vsum65[this.vsum65.Count - 1] : 0; + double vsumitem = prevvsum + 0.1 * (volty - this.vbuffer10[0]); + if (update) + { + this.vsum65[this.vsum65.Count - 1] = vsumitem; + } + else + { + this.vsum65.Add(vsumitem); + } + if (this.vsum65.Count > 65) + { + this.vsum65.RemoveAt(0); + } + + double avolty = 0; + for (int i = 0; i < this.vsum65.Count; i++) + { + avolty += this.vsum65[i]; + } + + avolty /= this.vsum65.Count; + double dvolty = (avolty > 0) ? volty / avolty : 0; + dvolty = Math.Max((dvolty > this.rvolty) ? this.rvolty : dvolty, 1.0); + + double pow2 = Math.Exp(this.pow1 * Math.Log(dvolty)); + double kv = + Math.Exp(Math.Sqrt(pow2) * Math.Log(this.len2 / (this.len2 + 1))); + + this.bsmax = (del1 > 0) ? hprice : hprice - (kv * del1); + this.bsmin = (del2 < 0) ? lprice : lprice - (kv * del2); + + // adaptive EMA dynamic factor + double pow = Math.Pow(dvolty, this.pow1); + double alpha = Math.Pow(this.beta, pow); + + // 1st stage - preliminary smoothing by adaptive EMA + double ma1 = TValue.v * (1 - alpha) + this.prev_ma1 * alpha; + this.prev_ma1 = ma1; + + // 2nd stage - one more preliminary smoothing by Kalman filter + double det0 = (TValue.v - ma1) * (1 - this.beta) + this.prev_det0 * this.beta; + this.prev_det0 = det0; + double ma2 = ma1 + (this.pr * det0); + + // 3rd stage - final smoothing by Jurik adaptive filter + double det1 = ((ma2 - this.prev_jma) * (1 - alpha) * (1 - alpha)) + + (this.prev_det1 * alpha * alpha); + this.prev_det1 = det1; + var jma = this.prev_jma + det1; + this.prev_jma = jma; + + (System.DateTime t, double v) result = + (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : jma); + base.Add(result, update); + + } +} + +*/ \ No newline at end of file diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj index 7ab08bc8..3ce4f983 100644 --- a/Source/QuanTAlib.csproj +++ b/Source/QuanTAlib.csproj @@ -13,7 +13,7 @@ Miha Kralj Miha Kralj readme.md - net7.0;net6.0;netstandard2.0 + net6.0;netstandard2.0 disable preview disable @@ -67,6 +67,6 @@ - + \ No newline at end of file diff --git a/Source/Statistics/PSDEV_Series.cs b/Source/Statistics/PSDEV_Series.cs deleted file mode 100644 index d31f70c4..00000000 --- a/Source/Statistics/PSDEV_Series.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace QuanTAlib; -using System; - -/* -PSDEV: Population Standard Deviation - Population Standard Deviation is the square root of the biased variance, also knons as - Uncorrected Sample Standard Deviation - -Sources: - https://en.wikipedia.org/wiki/Standard_deviation#Uncorrected_sample_standard_deviation - -Remark: - PSDEV (Population Standard Deviation) is also known as a biased/uncorrected Standard Deviation. - For unbiased version that uses Bessel's correction, use SDEV instead. - - */ - -public class PSDEV_Series : Single_TSeries_Indicator -{ - public PSDEV_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) - { - if (base._data.Count > 0) { base.Add(base._data); } - } - private readonly System.Collections.Generic.List _buffer = new(); - - public override void Add((System.DateTime t, double v) TValue, bool update) - { - if (update) { _buffer[_buffer.Count - 1] = TValue.v; } - else { _buffer.Add(TValue.v); } - if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); } - - double _sma = 0; - for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; } - _sma /= 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; - double _psdev = Math.Sqrt(_pvar); - - var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _psdev); - base.Add(result, update); - } -} \ No newline at end of file diff --git a/Source/Statistics/SDEV_Series.cs b/Source/Statistics/SDEV_Series.cs index 0f96c04c..0784d319 100644 --- a/Source/Statistics/SDEV_Series.cs +++ b/Source/Statistics/SDEV_Series.cs @@ -1,44 +1,44 @@ -namespace QuanTAlib; -using System; - -/* -SDEV: (Corrected) Sample Standard Deviation - Sample Standard Deviaton uses Bessel's correction to correct the bias in the variance. - -Sources: - https://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation - Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction - -Remark: - SSDEV (Sample Standard Deviation) is also known as a unbiased/corrected Standard Deviation. - For a population/biased/uncorrected Standard Deviation, use PSDEV instead - - */ - -public class SDEV_Series : Single_TSeries_Indicator -{ - public SDEV_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) - { - if (base._data.Count > 0) { base.Add(base._data); } - } - private readonly System.Collections.Generic.List _buffer = new(); - - public override void Add((System.DateTime t, double v) TValue, bool update) - { - if (update) { this._buffer[this._buffer.Count - 1] = TValue.v; } - else { this._buffer.Add(TValue.v); } - if (this._buffer.Count > this._p && this._p != 0) { this._buffer.RemoveAt(0); } - - double _sma = 0; - for (int i = 0; i < this._buffer.Count; i++) { _sma += this._buffer[i]; } - _sma /= this._buffer.Count; - - 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 _ssdev = Math.Sqrt(_svar); - - var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _ssdev); - base.Add(result, update); - } +namespace QuanTAlib; +using System; + +/* +SDEV: Population Standard Deviation + Population Standard Deviation is the square root of the biased variance, also known as + Uncorrected Sample Standard Deviation + +Sources: + https://en.wikipedia.org/wiki/Standard_deviation#Uncorrected_sample_standard_deviation + +Remark: + SDEV (Population Standard Deviation) is also known as a biased/uncorrected Standard Deviation. + For unbiased version that uses Bessel's correction, use SDEV instead. + + */ + +public class SDEV_Series : Single_TSeries_Indicator +{ + public SDEV_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) + { + if (base._data.Count > 0) { base.Add(base._data); } + } + private readonly System.Collections.Generic.List _buffer = new(); + + public override void Add((System.DateTime t, double v) TValue, bool update) + { + if (update) { _buffer[_buffer.Count - 1] = TValue.v; } + else { _buffer.Add(TValue.v); } + if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); } + + double _sma = 0; + for (int i = 0; i < _buffer.Count; i++) { _sma += _buffer[i]; } + _sma /= 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; + double _psdev = Math.Sqrt(_pvar); + + var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _psdev); + base.Add(result, update); + } } \ No newline at end of file diff --git a/Tests/MovingAvg/JMA_Test.cs b/Tests/MovingAvg/JMA_Test.cs deleted file mode 100644 index 93f7f417..00000000 --- a/Tests/MovingAvg/JMA_Test.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Xunit; -using System; -using QuanTAlib; - -namespace MovingAvg; -public class JMA_Test -{ - [Fact] - public void Add_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - JMA_Series c = new(a, 3); - Assert.Equal(6, c.Count); - a.Add(5); - Assert.Equal(a.Count, c.Count); - a.Add(0, update: true); - Assert.Equal(a.Count, c.Count); - } - - [Fact] - public void Edge_Test() - { - TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; - JMA_Series c = new(a, 3); - Assert.Equal(a.Count, c.Count); - a.Add(double.NaN); - Assert.Equal(a.Count, c.Count); - a.Add(double.PositiveInfinity); - Assert.Equal(a.Count, c.Count); - - } - -} diff --git a/Tests/Statistics/PSDEV_Test.cs b/Tests/Statistics/PSDEV_Test.cs index 04c530dd..503f9a6d 100644 --- a/Tests/Statistics/PSDEV_Test.cs +++ b/Tests/Statistics/PSDEV_Test.cs @@ -1,33 +1,33 @@ -using Xunit; -using System; -using QuanTAlib; - -namespace Statistics; -public class PSDEV_Test -{ - [Fact] - public void Add_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - PSDEV_Series c = new(a, 3); - Assert.Equal(6, c.Count); - a.Add(5); - Assert.Equal(a.Count, c.Count); - a.Add(0, update: true); - Assert.Equal(a.Count, c.Count); - } - - [Fact] - public void Edge_Test() - { - TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; - PSDEV_Series c = new(a, 3); - Assert.Equal(a.Count, c.Count); - a.Add(double.NaN); - Assert.Equal(a.Count, c.Count); - a.Add(double.PositiveInfinity); - Assert.Equal(a.Count, c.Count); - - } - -} +using Xunit; +using System; +using QuanTAlib; + +namespace Statistics; +public class PSDEV_Test +{ + [Fact] + public void Add_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + SDEV_Series c = new(a, 3); + Assert.Equal(6, c.Count); + a.Add(5); + Assert.Equal(a.Count, c.Count); + a.Add(0, update: true); + Assert.Equal(a.Count, c.Count); + } + + [Fact] + public void Edge_Test() + { + TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; + SDEV_Series c = new(a, 3); + Assert.Equal(a.Count, c.Count); + a.Add(double.NaN); + Assert.Equal(a.Count, c.Count); + a.Add(double.PositiveInfinity); + Assert.Equal(a.Count, c.Count); + + } + +} diff --git a/Tests/Statistics/SDEV_Test .cs b/Tests/Statistics/SDEV_Test .cs index 5d316b93..9b50f719 100644 --- a/Tests/Statistics/SDEV_Test .cs +++ b/Tests/Statistics/SDEV_Test .cs @@ -1,33 +1,33 @@ -using Xunit; -using System; -using QuanTAlib; - -namespace Statistics; -public class SDEV_Test -{ - [Fact] - public void Add_Test() - { - TSeries a = new() { 0, 1, 2, 3, 4, 5 }; - SDEV_Series c = new(a, 3); - Assert.Equal(6, c.Count); - a.Add(5); - Assert.Equal(a.Count, c.Count); - a.Add(0, update: true); - Assert.Equal(a.Count, c.Count); - } - - [Fact] - public void Edge_Test() - { - TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; - SDEV_Series c = new(a, 3); - Assert.Equal(a.Count, c.Count); - a.Add(double.NaN); - Assert.Equal(a.Count, c.Count); - a.Add(double.PositiveInfinity); - Assert.Equal(a.Count, c.Count); - - } - -} +using Xunit; +using System; +using QuanTAlib; + +namespace Statistics; +public class SDEV_Test +{ + [Fact] + public void Add_Test() + { + TSeries a = new() { 0, 1, 2, 3, 4, 5 }; + SSDEV_Series c = new(a, 3); + Assert.Equal(6, c.Count); + a.Add(5); + Assert.Equal(a.Count, c.Count); + a.Add(0, update: true); + Assert.Equal(a.Count, c.Count); + } + + [Fact] + public void Edge_Test() + { + TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue }; + SSDEV_Series c = new(a, 3); + Assert.Equal(a.Count, c.Count); + a.Add(double.NaN); + Assert.Equal(a.Count, c.Count); + a.Add(double.PositiveInfinity); + Assert.Equal(a.Count, c.Count); + + } + +} diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs index ebfc1a68..40ef39cb 100644 --- a/Tests/Validations/TA_LIB.cs +++ b/Tests/Validations/TA_LIB.cs @@ -129,4 +129,14 @@ MACD_Series QL = new(this.bars.Close, slow: 26, fast: 12, signal: 9, false); Core.Macd(this.inclose, 0, this.bars.Count - 1, outMacd: this.TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _); Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); } + + [Fact] + public void SDEV() + { + SDEV_Series QL = new(this.bars.Close, this.period, false); + Core.StdDev(this.inclose, 0, this.bars.Count - 1, this.TALIB, out int outBegIdx, out _, this.period); + + Assert.Equal(Math.Round(this.TALIB[this.TALIB.Length - outBegIdx - 1], 8), Math.Round(QL.Last().v, 8)); + } + } diff --git a/docs/ma-comparison.dib b/docs/ma-comparison.dib deleted file mode 100644 index 3f8bf1eb..00000000 --- a/docs/ma-comparison.dib +++ /dev/null @@ -1,244 +0,0 @@ -#!csharp - -#r "nuget: Plotly.NET, 2.0.0-preview.18 " -#r "nuget: Plotly.NET.Interactive, 2.0.0-preview.18 " -#r "nuget: QuanTAlib" - -using Plotly.NET; -using Plotly.NET.LayoutObjects; -using QuanTAlib; - -List x = new() {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96}; -List Spike = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -List Impulse = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -List Triangle = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2}; -List Sawtooth = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -List Sine = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74}; -List Chirp = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97}; -List White = new() {-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09}; -List Gauss = new() {-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61}; -List B = new() {-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06}; -List HF = new() {-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86}; -List ImpulseHF = new() {-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71}; -List SawtoothHF = new() {-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3}; -List SineG = new() {-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35}; -List ChirpG = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58}; -List Complex = new() {175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83}; -List Market = new() {68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25}; - -#!csharp - -TSeries data = new(); - -// change these two values - the period and the type of observed indicator -// currently available indicators are: DEMA_Series, EMA_Series, HEMA_Series, HMA_Series, JMA_Series, RMA_Series, SMA_Series, TEMA_Series, WMA_Series and ZLEMA_Series -int Period = 20; -HMA_Series indicator=new(source: data, period: Period); - -//On charts below, blue line is the data input, the green line is a JMA reference - -#!csharp - -var series = Spike; -ZLEMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Spike"); -chart - -#!csharp - -var series = Impulse; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Impulse"); -chart - -#!csharp - -var series = Triangle; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x, series, false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Triangle"); -chart - -#!csharp - -var series = Sawtooth; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Sawtooth"); -chart - -#!csharp - -var series = Sine; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Sine"); -chart - -#!csharp - -var series = Chirp; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Chirp"); -chart - -#!csharp - -var series = White; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("White"); -chart - -#!csharp - -var series = Gauss; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Gauss"); -chart - -#!csharp - -var series = B; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("B"); -chart - -#!csharp - -var series = HF; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("HF"); -chart - -#!csharp - -var series = ImpulseHF; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("ImpulseHF"); -chart - -#!csharp - -var series = SawtoothHF; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("SawtoothHF"); -chart - -#!csharp - -var series = SineG; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("SineG"); -chart - -#!csharp - -var series = ChirpG; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("ChirpG"); -chart - -#!csharp - -var series = Complex; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Complex"); -chart - -#!csharp - -var series = Market; -data = new(); -indicator=new(source: data, period: Period); -JMA_Series reference = new(source: data, period: Period); -for (int i=0; i(x,series,false,"data").WithLineStyle(Width: 1.0, Color: Color.fromString("blue")); -GenericChart.GenericChart ch2 = Chart2D.Chart.Line(x,indicator.v,false,"sig").WithLineStyle(Width: 2, Color: Color.fromString("red")); -GenericChart.GenericChart ch3 = Chart2D.Chart.Line(x,reference.v,false,"ref").WithLineStyle(Width: 1.5, Color: Color.fromString("green")); -var chart = Chart.Combine(new []{ch1,ch2,ch3}).WithSize(1200,400).WithMargin(Margin.init(1,1,60,1,1,false)).WithTitle("Maket"); -chart