diff --git a/Directory.Build.props b/Directory.Build.props index 9a7d675b..b5f399ec 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ net8.0 preview - $(NoWarn);NU1903;NU5104 + $(NoWarn);NU1903;NU5104;NETSDK1057 enable enable true @@ -41,7 +41,7 @@ true false true - + diff --git a/Tests/test_eventing.cs b/Tests/test_eventing.cs index 34c65028..b54a3b67 100644 --- a/Tests/test_eventing.cs +++ b/Tests/test_eventing.cs @@ -21,6 +21,7 @@ public class EventingTests ("Ema", new object[] { DefaultPeriod, true }, new object[] { new TSeries(), DefaultPeriod, true }), ("Epma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), ("Pwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), + ("Fisher", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), ("Frama", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), ("Fwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), ("Gma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), diff --git a/Tests/test_quantower.cs b/Tests/test_quantower.cs index 1429698c..f7221176 100644 --- a/Tests/test_quantower.cs +++ b/Tests/test_quantower.cs @@ -152,5 +152,13 @@ namespace QuanTAlib [Fact] public void Dmx() => TestIndicator("dmx"); [Fact] public void Dpo() => TestIndicator("dpo"); [Fact] public void Macd() => TestIndicator("macd"); + [Fact] public void Mom() => TestIndicator("Series"); + [Fact] public void Pmo() => TestIndicator("Series"); + [Fact] public void Po() => TestIndicator("Series"); + [Fact] public void Ppo() => TestIndicator("Series"); + [Fact] public void Roc() => TestIndicator("Series"); + [Fact] public void Trix() => TestIndicator("Series"); + [Fact] public void Vel() => TestIndicator("Series"); + [Fact] public void Vortex() => TestIndicatorMultipleFields(new[] { "PlusLine", "MinusLine" }); } } diff --git a/lib/averages/_list.md b/lib/averages/_list.md index 4273225c..2492f1bf 100644 --- a/lib/averages/_list.md +++ b/lib/averages/_list.md @@ -2,6 +2,7 @@ ✔️ AFIRMA - Adaptive FIR Moving Average ✔️ ALMA - Arnaud Legoux Moving Average +✔️ CONVOLUTION - 1D Convolution with sliding kernel ✔️ DEMA - Double Exponential Moving Average ✔️ DSMA - Dynamic Simple Moving Average ✔️ DWMA - Dynamic Weighted Moving Average @@ -17,7 +18,7 @@ ✔️ KAMA - Kaufman Adaptive Moving Average ✔️ LTMA - Linear Time Moving Average ✔️ MAAF - Moving Average Adaptive Filter -✔️ *MAMA - MESA Adaptive Moving Average (MAMA, FAMA) +✔️ MAMA - MESA Adaptive Moving Average (MAMA, FAMA) ✔️ MGDI - McGinley Dynamic Indicator ✔️ MMA - Modified Moving Average ✔️ PWMA - Parabolic Weighted Moving Average diff --git a/lib/oscillators/Fisher.cs b/lib/oscillators/Fisher.cs index 9d06af94..aadd5383 100644 --- a/lib/oscillators/Fisher.cs +++ b/lib/oscillators/Fisher.cs @@ -31,7 +31,6 @@ public sealed class Fisher : AbstractBase private readonly int _period; private readonly double[] _prices; private double _prevFisher; - private double _prevValue; /// The data source object that publishes updates. /// The calculation period (default: 10) diff --git a/quantower/Averages/AfirmaIndicator.cs b/quantower/Averages/AfirmaIndicator.cs index 486052da..f852b33d 100644 --- a/quantower/Averages/AfirmaIndicator.cs +++ b/quantower/Averages/AfirmaIndicator.cs @@ -76,7 +76,5 @@ public class AfirmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } - diff --git a/quantower/Averages/AlmaIndicator.cs b/quantower/Averages/AlmaIndicator.cs index 95bee6b7..c5112fce 100644 --- a/quantower/Averages/AlmaIndicator.cs +++ b/quantower/Averages/AlmaIndicator.cs @@ -70,6 +70,5 @@ public class AlmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/DemaIndicator.cs b/quantower/Averages/DemaIndicator.cs index 6db92ee5..1fa15213 100644 --- a/quantower/Averages/DemaIndicator.cs +++ b/quantower/Averages/DemaIndicator.cs @@ -64,6 +64,5 @@ public class DemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/DsmaIndicator.cs b/quantower/Averages/DsmaIndicator.cs index f26fc389..02370c74 100644 --- a/quantower/Averages/DsmaIndicator.cs +++ b/quantower/Averages/DsmaIndicator.cs @@ -68,6 +68,5 @@ public class DsmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/DwmaIndicator.cs b/quantower/Averages/DwmaIndicator.cs index 6f88e496..2cb65bc1 100644 --- a/quantower/Averages/DwmaIndicator.cs +++ b/quantower/Averages/DwmaIndicator.cs @@ -64,6 +64,5 @@ public class DwmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/EmaIndicator.cs b/quantower/Averages/EmaIndicator.cs index a50eaf48..8c790662 100644 --- a/quantower/Averages/EmaIndicator.cs +++ b/quantower/Averages/EmaIndicator.cs @@ -66,6 +66,5 @@ public class EmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/EpmaIndicator.cs b/quantower/Averages/EpmaIndicator.cs index eaa32fd0..45f6af1c 100644 --- a/quantower/Averages/EpmaIndicator.cs +++ b/quantower/Averages/EpmaIndicator.cs @@ -64,6 +64,5 @@ public class EpmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/FramaIndicator.cs b/quantower/Averages/FramaIndicator.cs index 038165ae..8d15d1d9 100644 --- a/quantower/Averages/FramaIndicator.cs +++ b/quantower/Averages/FramaIndicator.cs @@ -64,6 +64,5 @@ public class FramaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/FwmaIndicator.cs b/quantower/Averages/FwmaIndicator.cs index 2a6a90a2..b59da7b8 100644 --- a/quantower/Averages/FwmaIndicator.cs +++ b/quantower/Averages/FwmaIndicator.cs @@ -64,6 +64,5 @@ public class FwmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/GmaIndicator.cs b/quantower/Averages/GmaIndicator.cs index ab93afe3..fa8700a3 100644 --- a/quantower/Averages/GmaIndicator.cs +++ b/quantower/Averages/GmaIndicator.cs @@ -64,6 +64,5 @@ public class GmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/HmaIndicator.cs b/quantower/Averages/HmaIndicator.cs index d1d159da..ec903a34 100644 --- a/quantower/Averages/HmaIndicator.cs +++ b/quantower/Averages/HmaIndicator.cs @@ -64,6 +64,5 @@ public class HmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/HtitIndicator.cs b/quantower/Averages/HtitIndicator.cs index 04daa1b4..f8831085 100644 --- a/quantower/Averages/HtitIndicator.cs +++ b/quantower/Averages/HtitIndicator.cs @@ -61,6 +61,5 @@ public class HtitIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/HwmaIndicator.cs b/quantower/Averages/HwmaIndicator.cs index b201a20a..b92072aa 100644 --- a/quantower/Averages/HwmaIndicator.cs +++ b/quantower/Averages/HwmaIndicator.cs @@ -55,7 +55,7 @@ public class HwmaIndicator : Indicator, IWatchlistIndicator protected override void OnInit() { - if (NA == 0 && NB == 0 && NC == 0) + if ((NA, NB, NC) == (0, 0, 0)) { ma = new Hwma(Periods); } @@ -80,6 +80,5 @@ public class HwmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/JmaIndicator.cs b/quantower/Averages/JmaIndicator.cs index 382e93c0..7eaca362 100644 --- a/quantower/Averages/JmaIndicator.cs +++ b/quantower/Averages/JmaIndicator.cs @@ -70,6 +70,5 @@ public class JmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/KamaIndicator.cs b/quantower/Averages/KamaIndicator.cs index f84c87df..c7456879 100644 --- a/quantower/Averages/KamaIndicator.cs +++ b/quantower/Averages/KamaIndicator.cs @@ -70,6 +70,5 @@ public class KamaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/LtmaIndicator.cs b/quantower/Averages/LtmaIndicator.cs index ce1c4ad4..496d5701 100644 --- a/quantower/Averages/LtmaIndicator.cs +++ b/quantower/Averages/LtmaIndicator.cs @@ -64,6 +64,5 @@ public class LtmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/MaafIndicator.cs b/quantower/Averages/MaafIndicator.cs index 3a5a9647..15550e4d 100644 --- a/quantower/Averages/MaafIndicator.cs +++ b/quantower/Averages/MaafIndicator.cs @@ -67,6 +67,5 @@ public class MaafIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/MamaIndicator.cs b/quantower/Averages/MamaIndicator.cs index 09b9e086..870fc2c1 100644 --- a/quantower/Averages/MamaIndicator.cs +++ b/quantower/Averages/MamaIndicator.cs @@ -73,6 +73,5 @@ public class MamaIndicator : Indicator, IWatchlistIndicator base.OnPaintChart(args); this.PaintSmoothCurve(args, MamaSeries!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); this.PaintSmoothCurve(args, FamaSeries!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/MgdiIndicator.cs b/quantower/Averages/MgdiIndicator.cs index 7e63ffa2..77b0b381 100644 --- a/quantower/Averages/MgdiIndicator.cs +++ b/quantower/Averages/MgdiIndicator.cs @@ -67,6 +67,5 @@ public class MgdiIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/MmaIndicator.cs b/quantower/Averages/MmaIndicator.cs index e4c4fb50..57cc296c 100644 --- a/quantower/Averages/MmaIndicator.cs +++ b/quantower/Averages/MmaIndicator.cs @@ -64,6 +64,5 @@ public class MmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/PwmaIndicator.cs b/quantower/Averages/PwmaIndicator.cs index 52d9ea72..17d7b667 100644 --- a/quantower/Averages/PwmaIndicator.cs +++ b/quantower/Averages/PwmaIndicator.cs @@ -64,6 +64,5 @@ public class PwmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/RemaIndicator.cs b/quantower/Averages/RemaIndicator.cs index b48147d3..80a0916b 100644 --- a/quantower/Averages/RemaIndicator.cs +++ b/quantower/Averages/RemaIndicator.cs @@ -67,6 +67,5 @@ public class RemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/RmaIndicator.cs b/quantower/Averages/RmaIndicator.cs index 5265517e..25270465 100644 --- a/quantower/Averages/RmaIndicator.cs +++ b/quantower/Averages/RmaIndicator.cs @@ -64,6 +64,5 @@ public class RmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/SinemaIndicator.cs b/quantower/Averages/SinemaIndicator.cs index 8c788f8d..8b961acd 100644 --- a/quantower/Averages/SinemaIndicator.cs +++ b/quantower/Averages/SinemaIndicator.cs @@ -64,6 +64,5 @@ public class SinemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/SmaIndicator.cs b/quantower/Averages/SmaIndicator.cs index 66b3d853..31bd9107 100644 --- a/quantower/Averages/SmaIndicator.cs +++ b/quantower/Averages/SmaIndicator.cs @@ -5,7 +5,7 @@ namespace QuanTAlib; public class SmaIndicator : Indicator, IWatchlistIndicator { - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] + [InputParameter("Period", sortIndex: 1, 1, 1000, 1, 0)] public int Period { get; set; } = 14; [InputParameter("Data source", sortIndex: 2, variants: [ @@ -67,6 +67,5 @@ public class SmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, error!.Value.ToString()); } } diff --git a/quantower/Averages/SmmaIndicator.cs b/quantower/Averages/SmmaIndicator.cs index eae89e0a..b43070a2 100644 --- a/quantower/Averages/SmmaIndicator.cs +++ b/quantower/Averages/SmmaIndicator.cs @@ -64,6 +64,5 @@ public class SmmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/T3Indicator.cs b/quantower/Averages/T3Indicator.cs index 953cc773..ccf62cdd 100644 --- a/quantower/Averages/T3Indicator.cs +++ b/quantower/Averages/T3Indicator.cs @@ -70,6 +70,5 @@ public class T3Indicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/TemaIndicator.cs b/quantower/Averages/TemaIndicator.cs index 5fe12a90..f37a03c9 100644 --- a/quantower/Averages/TemaIndicator.cs +++ b/quantower/Averages/TemaIndicator.cs @@ -64,6 +64,5 @@ public class TemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/TrimaIndicator.cs b/quantower/Averages/TrimaIndicator.cs index 73e138db..2350d4e5 100644 --- a/quantower/Averages/TrimaIndicator.cs +++ b/quantower/Averages/TrimaIndicator.cs @@ -64,6 +64,5 @@ public class TrimaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/VidyaIndicator.cs b/quantower/Averages/VidyaIndicator.cs index 54a6b18f..3b4c395c 100644 --- a/quantower/Averages/VidyaIndicator.cs +++ b/quantower/Averages/VidyaIndicator.cs @@ -70,6 +70,5 @@ public class VidyaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/WmaIndicator.cs b/quantower/Averages/WmaIndicator.cs index ef1653dd..bee41d44 100644 --- a/quantower/Averages/WmaIndicator.cs +++ b/quantower/Averages/WmaIndicator.cs @@ -64,6 +64,5 @@ public class WmaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Averages/ZlemaIndicator.cs b/quantower/Averages/ZlemaIndicator.cs index 268d142b..30bf7200 100644 --- a/quantower/Averages/ZlemaIndicator.cs +++ b/quantower/Averages/ZlemaIndicator.cs @@ -67,6 +67,5 @@ public class ZlemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, err!.Value.ToString()); } } diff --git a/quantower/Experiments/ConvolutionIndicator.cs b/quantower/Experiments/ConvolutionIndicator.cs new file mode 100644 index 00000000..f46ad6a4 --- /dev/null +++ b/quantower/Experiments/ConvolutionIndicator.cs @@ -0,0 +1,97 @@ +using System.Drawing; +using System.Linq; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class ConvolutionIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Kernel (comma/space/semicolon separated numbers)", sortIndex: 1)] + public string KernelString { get; set; } = "0.25, 0.5, 0.25, -0.5"; + + [InputParameter("Data source", sortIndex: 2, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Convolution? conv; + private Mape? error; + protected LineSeries? Series; + protected string? SourceName; + private double[]? kernel; + public int MinHistoryDepths => kernel?.Length ?? 3; + int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; + + public ConvolutionIndicator() + { + OnBackGround = true; + SeparateWindow = false; + SourceName = Source.ToString(); + Name = "CONV - Convolution Filter"; + Description = "Convolution Filter with custom kernel"; + kernel = ParseKernel(KernelString); + Series = new(name: $"CONV {string.Join(",", kernel.Select(x => x.ToString("F2")))}", + color: IndicatorExtensions.Averages, + width: 2, + style: LineStyle.Solid); + AddLineSeries(Series); + } + + private static double[] ParseKernel(string kernelStr) + { + // Split on common delimiters: comma, semicolon, space, tab, pipe + var numbers = kernelStr.Split(new[] { ',', ';', ' ', '\t', '|' }, + StringSplitOptions.RemoveEmptyEntries | + StringSplitOptions.TrimEntries); + + var kernel = new double[numbers.Length]; + for (int i = 0; i < numbers.Length; i++) + { + if (!double.TryParse(numbers[i], out kernel[i])) + { + // Default to simple 3-point moving average if parsing fails + return new double[] { 0.25, 0.5, 0.25, -0.5 }; + } + } + return kernel; + } + + protected override void OnInit() + { + kernel = ParseKernel(KernelString); + conv = new Convolution(kernel); + error = new(kernel.Length); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = conv!.Calc(input); + error!.Calc(input, result); + + Series!.SetMarker(0, Color.Transparent); + Series!.SetValue(result.Value); + } + + public override string ShortName => $"CONV {KernelString}:{SourceName}"; + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, kernel!.Length, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Averages/QemaIndicator.cs b/quantower/Experiments/QemaIndicator.cs similarity index 98% rename from quantower/Averages/QemaIndicator.cs rename to quantower/Experiments/QemaIndicator.cs index 1c0e908f..1bb65542 100644 --- a/quantower/Averages/QemaIndicator.cs +++ b/quantower/Experiments/QemaIndicator.cs @@ -73,6 +73,5 @@ public class QemaIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } diff --git a/quantower/Experiments/TestIndicator.cs b/quantower/Experiments/TestIndicator.cs index 665f2b09..37f416d2 100644 --- a/quantower/Experiments/TestIndicator.cs +++ b/quantower/Experiments/TestIndicator.cs @@ -59,7 +59,5 @@ public class TestIndicator : Indicator, IWatchlistIndicator { base.OnPaintChart(args); this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, ShowColdValues, tension: 0.2); - this.DrawText(args, Description); } } - diff --git a/quantower/IndicatorExtensions.cs b/quantower/IndicatorExtensions.cs index 7bcbc61d..e3a7e369 100644 --- a/quantower/IndicatorExtensions.cs +++ b/quantower/IndicatorExtensions.cs @@ -22,6 +22,8 @@ public static class IndicatorExtensions public static readonly Color Statistics = Color.FromArgb(128, 128, 255); // #8080FF - Blue public static readonly Color Oscillators = Color.FromArgb(255, 128, 255); // #FF80FF - Magenta public static readonly Color Momentum = Color.FromArgb(128, 255, 255); // #80FFFF - Cyan + public static readonly Color Experiments = Color.FromArgb(255, 165, 0); // #FFA500 - Orange + public static TValue GetInputValue(this Indicator indicator, UpdateArgs args, SourceType source) { var historicalData = indicator.HistoricalData; diff --git a/quantower/Momentum/MomIndicator.cs b/quantower/Momentum/MomIndicator.cs new file mode 100644 index 00000000..adcf838a --- /dev/null +++ b/quantower/Momentum/MomIndicator.cs @@ -0,0 +1,67 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class MomIndicator : Indicator +{ + [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int Period { get; set; } = 10; + + [InputParameter("Data source", sortIndex: 2, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Mom? mom; + protected LineSeries? Series; + protected string? SourceName; + + public override string ShortName => $"MOM({Period})"; + + public MomIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "MOM - Momentum"; + Description = "A basic momentum indicator that measures the change in price over a specified period"; + + Series = new(name: $"MOM({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + AddLineSeries(Series); + } + + protected override void OnInit() + { + mom = new Mom(period: Period); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = mom!.Calc(input); + + Series!.SetValue(result.Value); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, mom!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/PmoIndicator.cs b/quantower/Momentum/PmoIndicator.cs new file mode 100644 index 00000000..1de142e6 --- /dev/null +++ b/quantower/Momentum/PmoIndicator.cs @@ -0,0 +1,70 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class PmoIndicator : Indicator +{ + [InputParameter("First Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int Period1 { get; set; } = 35; + + [InputParameter("Second Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] + public int Period2 { get; set; } = 20; + + [InputParameter("Data source", sortIndex: 3, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Pmo? pmo; + protected LineSeries? Series; + protected string? SourceName; + + public override string ShortName => $"PMO({Period1},{Period2})"; + + public PmoIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "PMO - Price Momentum Oscillator"; + Description = "A momentum indicator that uses exponential moving averages of ROC to identify overbought and oversold conditions"; + + Series = new(name: $"PMO({Period1},{Period2})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + AddLineSeries(Series); + } + + protected override void OnInit() + { + pmo = new Pmo(period1: Period1, period2: Period2); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = pmo!.Calc(input); + + Series!.SetValue(result.Value); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, pmo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/PoIndicator.cs b/quantower/Momentum/PoIndicator.cs new file mode 100644 index 00000000..f6ab642c --- /dev/null +++ b/quantower/Momentum/PoIndicator.cs @@ -0,0 +1,75 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class PoIndicator : Indicator +{ + [InputParameter("Fast Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int FastPeriod { get; set; } = 10; + + [InputParameter("Slow Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] + public int SlowPeriod { get; set; } = 21; + + [InputParameter("Data source", sortIndex: 3, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Po? po; + protected LineSeries? Series; + protected string? SourceName; + + public override string ShortName => $"PO({FastPeriod},{SlowPeriod})"; + + public PoIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "PO - Price Oscillator"; + Description = "A momentum indicator that measures the difference between two moving averages to identify price momentum"; + + Series = new(name: $"PO({FastPeriod},{SlowPeriod})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + AddLineSeries(Series); + } + + protected override void OnInit() + { + if (FastPeriod >= SlowPeriod) + { + FastPeriod = 10; + SlowPeriod = 21; + } + po = new Po(fastPeriod: FastPeriod, slowPeriod: SlowPeriod); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = po!.Calc(input); + + Series!.SetValue(result.Value); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, po!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/PpoIndicator.cs b/quantower/Momentum/PpoIndicator.cs new file mode 100644 index 00000000..5ffe39e1 --- /dev/null +++ b/quantower/Momentum/PpoIndicator.cs @@ -0,0 +1,75 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class PpoIndicator : Indicator +{ + [InputParameter("Fast Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int FastPeriod { get; set; } = 12; + + [InputParameter("Slow Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] + public int SlowPeriod { get; set; } = 26; + + [InputParameter("Data source", sortIndex: 3, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Ppo? ppo; + protected LineSeries? Series; + protected string? SourceName; + + public override string ShortName => $"PPO({FastPeriod},{SlowPeriod})"; + + public PpoIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "PPO - Percentage Price Oscillator"; + Description = "A momentum indicator that shows the percentage difference between two moving averages"; + + Series = new(name: $"PPO({FastPeriod},{SlowPeriod})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + AddLineSeries(Series); + } + + protected override void OnInit() + { + if (FastPeriod >= SlowPeriod) + { + FastPeriod = 12; + SlowPeriod = 26; + } + ppo = new Ppo(fastPeriod: FastPeriod, slowPeriod: SlowPeriod); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = ppo!.Calc(input); + + Series!.SetValue(result.Value); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, ppo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/RocIndicator.cs b/quantower/Momentum/RocIndicator.cs new file mode 100644 index 00000000..77ef27b8 --- /dev/null +++ b/quantower/Momentum/RocIndicator.cs @@ -0,0 +1,76 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class RocIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int Period { get; set; } = 12; + + [InputParameter("Data source", sortIndex: 2, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Roc? roc; + protected LineSeries? Series; + protected LineSeries? ZeroLine; + protected string? SourceName; + public int MinHistoryDepths => Math.Max(5, Period * 2); + int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; + + public override string ShortName => $"ROC({Period})"; + + public RocIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "ROC - Rate of Change"; + Description = "A momentum indicator that measures the percentage change in price over a specified period"; + + Series = new(name: $"ROC({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); + AddLineSeries(Series); + AddLineSeries(ZeroLine); + } + + protected override void OnInit() + { + roc = new Roc(period: Period); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + if (args.Reason != UpdateReason.NewTick) + return; + + TValue input = this.GetInputValue(args, Source); + TValue result = roc!.Calc(input); + + Series!.SetValue(result.Value); + ZeroLine!.SetValue(0); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, roc!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/TrixIndicator.cs b/quantower/Momentum/TrixIndicator.cs new file mode 100644 index 00000000..eae53f32 --- /dev/null +++ b/quantower/Momentum/TrixIndicator.cs @@ -0,0 +1,67 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class TrixIndicator : Indicator +{ + [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int Period { get; set; } = 18; + + [InputParameter("Data source", sortIndex: 2, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Trix? trix; + protected LineSeries? Series; + protected string? SourceName; + + public override string ShortName => $"TRIX({Period})"; + + public TrixIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "TRIX - Triple Exponential Average Rate of Change"; + Description = "A momentum oscillator that shows the percentage rate of change of a triple exponentially smoothed moving average"; + + Series = new(name: $"TRIX({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + AddLineSeries(Series); + } + + protected override void OnInit() + { + trix = new Trix(period: Period); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = trix!.Calc(input); + + Series!.SetValue(result.Value); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, trix!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/VelIndicator.cs b/quantower/Momentum/VelIndicator.cs new file mode 100644 index 00000000..67b2df2e --- /dev/null +++ b/quantower/Momentum/VelIndicator.cs @@ -0,0 +1,82 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class VelIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] + public int Period { get; set; } = 10; + + [InputParameter("Phase", sortIndex: 2, minimum: -100, maximum: 100, increment: 1)] + public int Phase { get; set; } = 100; + + [InputParameter("Factor", sortIndex: 3, minimum: 0.1, maximum: 0.9, increment: 0.1, decimalPlaces: 2)] + public double Factor { get; set; } = 0.25; + + [InputParameter("Data source", sortIndex: 4, variants: [ + "Open", SourceType.Open, + "High", SourceType.High, + "Low", SourceType.Low, + "Close", SourceType.Close, + "HL/2 (Median)", SourceType.HL2, + "OC/2 (Midpoint)", SourceType.OC2, + "OHL/3 (Mean)", SourceType.OHL3, + "HLC/3 (Typical)", SourceType.HLC3, + "OHLC/4 (Average)", SourceType.OHLC4, + "HLCC/4 (Weighted)", SourceType.HLCC4 + ])] + public SourceType Source { get; set; } = SourceType.Close; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Vel? vel; + protected LineSeries? Series; + protected LineSeries? ZeroLine; + protected string? SourceName; + public int MinHistoryDepths => Math.Max(5, Period * 2); + int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; + + public override string ShortName => $"VEL({Period})"; + + public VelIndicator() + { + OnBackGround = true; + SeparateWindow = true; + SourceName = Source.ToString(); + Name = "VEL - Velocity"; + Description = "An enhanced momentum indicator that applies JMA smoothing to momentum calculation"; + + Series = new(name: $"VEL({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); + ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); + AddLineSeries(Series); + AddLineSeries(ZeroLine); + } + + protected override void OnInit() + { + vel = new Vel(period: Period, phase: Phase, factor: Factor); + SourceName = Source.ToString(); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + if (args.Reason != UpdateReason.NewTick) + return; + + TValue input = this.GetInputValue(args, Source); + TValue result = vel!.Calc(input); + + Series!.SetValue(result.Value); + ZeroLine!.SetValue(0); + Series!.SetMarker(0, Color.Transparent); + } + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, Series!, vel!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +} diff --git a/quantower/Momentum/VortexIndicator.cs b/quantower/Momentum/VortexIndicator.cs new file mode 100644 index 00000000..78853f69 --- /dev/null +++ b/quantower/Momentum/VortexIndicator.cs @@ -0,0 +1,71 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class VortexIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] + public int Periods { get; set; } = 14; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Vortex? vortex; + protected LineSeries? ValueSeries; + protected LineSeries? PlusLine; + protected LineSeries? MinusLine; + protected LineSeries? ZeroLine; + public int MinHistoryDepths => Math.Max(5, Periods * 2); + int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; + + public VortexIndicator() + { + Name = "VORTEX - Vortex Indicator"; + Description = "A technical indicator consisting of two oscillating lines that identify trend reversals"; + SeparateWindow = true; + + ValueSeries = new($"VORTEX({Periods})", color: IndicatorExtensions.Momentum, 2, LineStyle.Solid); + PlusLine = new($"VI+({Periods})", color: Color.Green, 2, LineStyle.Solid); + MinusLine = new($"VI-({Periods})", color: Color.Red, 2, LineStyle.Solid); + ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); + + AddLineSeries(ValueSeries); + AddLineSeries(PlusLine); + AddLineSeries(MinusLine); + AddLineSeries(ZeroLine); + } + + protected override void OnInit() + { + vortex = new Vortex(Periods); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TBar input = IndicatorExtensions.GetInputBar(this, args); + var result = vortex!.Calc(input); + + ValueSeries!.SetValue(result); + PlusLine!.SetValue(vortex.ViPlus); + MinusLine!.SetValue(vortex.ViMinus); + ZeroLine!.SetValue(0); + + ValueSeries!.SetMarker(0, Color.Transparent); + PlusLine!.SetMarker(0, Color.Transparent); + MinusLine!.SetMarker(0, Color.Transparent); + } + +#pragma warning disable CA1416 // Validate platform compatibility + + public override string ShortName => $"VORTEX({Periods})"; + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintSmoothCurve(args, ValueSeries!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + this.PaintSmoothCurve(args, PlusLine!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + this.PaintSmoothCurve(args, MinusLine!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +}