using System; using System.Diagnostics; using System.Drawing; using System.Linq; using TradingPlatform.BusinessLayer; namespace QuanTAlib; public class TrailingStop_chart : Indicator { #region Parameters [InputParameter("Period", 0, 1, 100, 1, 1)] protected int _period = 30; [InputParameter("Factor", 1, 1, 100, 0.1, 1)] protected double _factor = 10; [InputParameter("Long TS", 2)] private bool _LongTS = true; [InputParameter("Short TS", 3)] private bool _ShortTS = true; #endregion Parameters /////// private HistoricalData History; private TBars bars; private ATR_Series _atr; private double _tslineL, _ratchetL, _tslineS, _ratchetS; /////// public TrailingStop_chart() { Name = $"ATR Trailing Stop"; AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot); AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); AddLineSeries(lineName: "TrailingATR Short", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot); AddLineSeries(lineName: "Ratchet Short", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid); SeparateWindow = false; } protected override void OnInit() { this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})"; this.bars = new(); this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime); for (int i = this.History.Count - 1; i >= 0; i--) { var rec = this.History[i, SeekOriginHistory.Begin]; bars.Add(rec.TimeLeft, rec[PriceType.Open], rec[PriceType.High], rec[PriceType.Low], rec[PriceType.Close], rec[PriceType.Volume]); } _atr = new(source: bars, _period, useNaN: true); _ratchetL = Double.NegativeInfinity; _ratchetS = Double.PositiveInfinity; this.LinesSeries[0].Visible = _LongTS; this.LinesSeries[1].Visible = _LongTS; this.LinesSeries[2].Visible = _ShortTS; this.LinesSeries[3].Visible = _ShortTS; } protected override void OnUpdate(UpdateArgs args) { bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar); this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update); _tslineL = bars.High[^1].v - (_factor * _atr[^1].v); _ratchetL = Math.Max(_tslineL, _ratchetL); if (_ratchetL > bars.Low[^1].v) { this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow)); _ratchetL = _tslineL; } _tslineS = bars.High[^1].v + (_factor * _atr[^1].v); _ratchetS = Math.Min(_tslineS, _ratchetS); if (_ratchetS < bars.High[^1].v) { this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow)); _ratchetS = _tslineS; } this.SetValue(_tslineL, lineIndex: 0); this.SetValue(_ratchetL, lineIndex: 1); this.SetValue(_tslineS, lineIndex: 2); this.SetValue(_ratchetS, lineIndex: 3); } }