From 4c689f76e8251eeb9d5197359e9ba55db6ea989f Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 17 Apr 2023 14:54:29 -0700 Subject: [PATCH] New: Slopes convergence indicator --- .../{xMA_chart.cs => 2MACross_chart.cs} | 58 ++-- Indicators/Charts/2MASlope_chart.cs | 293 ++++++++++++++++++ Indicators/Charts/KAMA_chart.cs | 55 ---- Indicators/Charts/MAMA_chart.cs | 62 ---- Indicators/Charts/TrailingStop.cs | 44 ++- 5 files changed, 359 insertions(+), 153 deletions(-) rename Indicators/Charts/{xMA_chart.cs => 2MACross_chart.cs} (85%) create mode 100644 Indicators/Charts/2MASlope_chart.cs delete mode 100644 Indicators/Charts/KAMA_chart.cs delete mode 100644 Indicators/Charts/MAMA_chart.cs diff --git a/Indicators/Charts/xMA_chart.cs b/Indicators/Charts/2MACross_chart.cs similarity index 85% rename from Indicators/Charts/xMA_chart.cs rename to Indicators/Charts/2MACross_chart.cs index a6b412b6..279dab74 100644 --- a/Indicators/Charts/xMA_chart.cs +++ b/Indicators/Charts/2MACross_chart.cs @@ -6,28 +6,28 @@ namespace QuanTAlib; public class MovingAverage_chart : Indicator { #region Parameters - [InputParameter("MA1: Type", 0, variants: new object[] + [InputParameter("MA1: Type:", 0, variants: new object[] { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FMA", 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)] + [InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)] private int MA1Period = 10; - [InputParameter("MA1: Data source", 2, variants: new object[] + [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[] + [InputParameter("MA2: Type:", 3, variants: new object[] { "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FMA", 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)] + [InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)] private int MA2Period = 50; - [InputParameter("MA2: Data source", 5, variants: new object[] + [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; @@ -36,7 +36,7 @@ public class MovingAverage_chart : Indicator { private bool LongTrades = true; [InputParameter("Short trades", 6)] - private bool ShortTrades = false; + private bool ShortTrades = true; #endregion Parameters @@ -47,14 +47,14 @@ public class MovingAverage_chart : Indicator { private TSeries MA1, MA2; private CROSS_Series trades; private COMPARE_Series overunder; - private EQUITY_Series equity; + /////// public MovingAverage_chart() { this.SeparateWindow = false; - this.Name = "2MA Crossover"; - this.AddLineSeries("MA1", Color.SeaGreen, 3, LineStyle.Solid); - this.AddLineSeries("MA2", Color.OrangeRed, 3, LineStyle.Solid); + this.Name = "MAs Crossover"; + this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid); + this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid); } protected override void OnInit() { @@ -66,7 +66,7 @@ public class MovingAverage_chart : Indicator { rec[PriceType.High], rec[PriceType.Low], rec[PriceType.Close], rec[PriceType.Volume]); } - this.Name = "Crossover[ "; + this.Name = "MAs Cross: [ "; switch (MA1type) { case 0: MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false); @@ -216,7 +216,6 @@ public class MovingAverage_chart : Indicator { overunder = new(MA1, MA2); trades = new(MA1, MA2); - equity = new(trades,price: bars.Open,warmup:MA1Period+MA2Period); } protected override void OnUpdate(UpdateArgs args) { @@ -233,21 +232,21 @@ public class MovingAverage_chart : Indicator { if (trades[^1].v == 1) { this.EndCloud(0, 1, Color.Empty); if (LongTrades) { - this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.SeaGreen, upperIcon: IndicatorLineMarkerIconType.UpArrow)); + 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, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); + 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, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); + 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.SeaGreen, upperIcon: IndicatorLineMarkerIconType.DownArrow)); + this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); } } } @@ -260,21 +259,20 @@ public class MovingAverage_chart : Indicator { int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right))); int historycount = HistoricalData.Count; int ymax = mainWindow.ClientRectangle.Height; - int ymin = ymax - (int)(ymax / 4); - double eqmin = equity.v.Min(); - double eqmax = equity.v.Max(); - double proportion = (ymax-ymin) / (eqmax-eqmin); + 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; - 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/2MASlope_chart.cs b/Indicators/Charts/2MASlope_chart.cs new file mode 100644 index 00000000..2c52110e --- /dev/null +++ b/Indicators/Charts/2MASlope_chart.cs @@ -0,0 +1,293 @@ +using System; +using System.Drawing; +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, "FMA", 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: 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, "FMA", 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: 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("Long trades", 7)] + private bool LongTrades = true; + + [InputParameter("Short trades", 8)] + private bool ShortTrades = false; + + #endregion Parameters + + protected HistoricalData History; + private TBars bars; + + /////// + private TSeries MA1, MA2; + private LINREG_Series sMA1, sMA2; + private CROSS_Series sig1, sig2; + /////// + + 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 FMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period); + this.Name += $"FMA"; + 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)}) : "; + + 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 FMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period); + this.Name += $"FMA"; + 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); + } + + 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); + + 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); + + if (sig1[^1].v > 0 || sig2[^1].v > 0) { + if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0) + { + 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); + this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow)); + } + + } + + if (sig1[^1].v < 0 || sig2[^1].v < 0) { + if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0) + { + 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); + this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v)?1:0].SetMarker(1, 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; + +/* + 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; + + graphics.FillRectangle(bb, xi, ymax - height, width, height); + } +*/ + } +} diff --git a/Indicators/Charts/KAMA_chart.cs b/Indicators/Charts/KAMA_chart.cs deleted file mode 100644 index 8de883f7..00000000 --- a/Indicators/Charts/KAMA_chart.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Diagnostics; -using System.Drawing; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class KAMA_chart : Indicator -{ - #region Parameters - - [InputParameter("Smoothing period", 0, 1, 999, 1, 1)] - private int Period = 10; - [InputParameter("Fastest EMA", 1, 1, 999, 1, 1)] - private int Fast = 2; - [InputParameter("Slowest EMA", 2, 1, 999, 1, 1)] - private int Slow = 30; - - [InputParameter("Data source", 3, 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 KAMA_Series indicator; - /////// - - public KAMA_chart() - { - this.SeparateWindow = false; - this.Name = "KAMA - Kaufman's Adaptive Moving Average"; - this.Description = "Kaufman's Adaptive Moving Average description"; - this.AddLineSeries("KAMA", Color.RoyalBlue, 3, LineStyle.Solid); - } - - protected override void OnInit() - { - this.bars = new(); - this.indicator = new(source: bars.Select(this.DataSource), period: this.Period, fast: this.Fast, slow: this.Slow, 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.SetValue(result); - Debug.WriteLine($"{this.indicator[0].v}"); - } -} diff --git a/Indicators/Charts/MAMA_chart.cs b/Indicators/Charts/MAMA_chart.cs deleted file mode 100644 index 65edbcb0..00000000 --- a/Indicators/Charts/MAMA_chart.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class MAMA_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("Fastlimit", 1, 0, 1, 0.001, 5)] - private double fastlimit = 0.5; - - [InputParameter("Slowlimit", 2, 0, 1, 0.001, 5)] - private double slowlimit = 0.05; - #endregion Parameters - - protected HistoricalData History; - private TBars bars; - /////// - private MAMA_Series indicator; - /////// - - public MAMA_chart() :base() { - Name = "MAMA - MESA Adaptive Moving Average"; - AddLineSeries(lineName: "MAMA", lineColor: Color.Yellow, lineWidth: 3,lineStyle: LineStyle.Solid); - SeparateWindow = false; - } - - - 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]); - } - indicator = new(source: bars.Select(DataSource), - fastlimit: fastlimit, slowlimit: fastlimit, - 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); - this.SetValue(indicator[^1].v, lineIndex: 0); - } -} diff --git a/Indicators/Charts/TrailingStop.cs b/Indicators/Charts/TrailingStop.cs index 3df040ca..3413ccb5 100644 --- a/Indicators/Charts/TrailingStop.cs +++ b/Indicators/Charts/TrailingStop.cs @@ -18,7 +18,7 @@ public class TrailingStop_chart : Indicator { private bool _LongTS = true; [InputParameter("Short TS", 3)] - private bool _ShortTS = false; + private bool _ShortTS = true; #endregion Parameters @@ -26,8 +26,8 @@ public class TrailingStop_chart : Indicator { private HistoricalData History; private TBars bars; private ATR_Series _atr; - private double _tslineL, _ratchetL, _tslineS, _ratchetS; + /////// public TrailingStop_chart() :base() { @@ -37,6 +37,7 @@ public class TrailingStop_chart : Indicator { 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; } @@ -73,17 +74,48 @@ public class TrailingStop_chart : Indicator { _tslineL = bars.High[^1].v - (_factor * _atr[^1].v); _ratchetL = Math.Max(_tslineL,_ratchetL); - _ratchetL = (_ratchetL > bars.Low[^1].v) ? _tslineL : _ratchetL; + if (_ratchetL > bars.Low[^1].v) { + this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); + _ratchetL = _tslineL; + } - _tslineS = bars.Low[^1].v + (_factor * _atr[^1].v); + _tslineS = bars.High[^1].v + (_factor * _atr[^1].v); _ratchetS = Math.Min(_tslineS, _ratchetS); - _ratchetS = (_ratchetS < bars.High[^1].v) ? _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); + + } + + 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); + + 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); + } + */ } }