How can I know if my indicator has taken out a previous high or low?

Created at 10 May 2024, 19:06
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
CT

ctid5083541

Joined 25.05.2022

How can I know if my indicator has taken out a previous high or low?
10 May 2024, 19:06


I want my indicator to indicate to me when price makes a new swing high if it took out a the previous swing high, that is a high, a low, followed by a higher high (like can be seen on the image above marked 1 - it actually took two of them out) or when it makes a new swing low if it took out the previous swing low, that is, a low, a high, followed by a lower low (like can be seen on the image above marked 2). I do not want a trend line or anything like that, I will add more code that will only run when either of the two conditions above are true - one set of code if it is a high, low, higher high, and another set of code if it is a low, high, lower low.

Many thanks in advance.

See the code below:

 

using cAlgo.API;
using System;
using System.Collections.Generic;
using System.Text;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SwingHighsLows : Indicator
    {
        private class Swings
        {
            public int Index { get; set; }
            public double Price { get; set; }

            public Swings()
            {
                Index = 0;
                Price = double.MaxValue;
            }

            public Swings(int index, double price)
            {
                Index = index;
                Price = price;
            }
        }

        // Bar Index
        private int _index;

        // Direction of the SWINGS
        private Direction _direction = Direction.Down;

        // Price of recent High
        private double _highs;

        // Price of recent Low
        private double _lows;

        private bool _bullishSwings;

        private Swings _swingHighLow;
        private List<Swings> _swingHighLowList;

        private enum Direction
        {
            Up,
            Down
        }

        [Parameter("Percentage Move", DefaultValue = 0.0, Step = 0.1, MinValue = 0, Group = "SWINGS")]
        public double PercentageMove { get; set; }

        [Parameter("Display Percentage?", DefaultValue = false, Group = "SWINGS")]
        public bool DisplayPercentChange { get; set; }

        [Parameter("Display Price?", DefaultValue = true, Group = "SWINGS")]
        public bool DisplayPrice { get; set; }

        [Output("SWINGS", LineColor = "White", Thickness = 2, PlotType = PlotType.Line)]
        public IndicatorDataSeries Result { get; set; }

        public override void Calculate(int index)
        {
            _index = index;

            _lows = Bars.LowPrices.LastValue;
            _highs = Bars.HighPrices.LastValue;

            if (Bars.ClosePrices.Count < 2)
                return;

            switch (_direction)
            {
                case Direction.Up:
                    BullishSwing();
                    break;

                case Direction.Down:
                default:
                    BearishSwing();
                    break;
            }
        }

        protected override void Initialize()
        {
            _swingHighLow = new Swings();
            _swingHighLowList = new List<Swings>();
        }
		
        // Get Swing _highs _lows Text
        public string SwingHigh_LowsText(double _currentValue, double _previousValue)
        {
            StringBuilder _textString = new StringBuilder();

            if (DisplayPrice)
                AppendPrice(_textString);

            if (DisplayPercentChange)
                AppendPercentageChange(_currentValue, _previousValue, _textString);

            return _textString.ToString();
        }

        private void AppendPercentageChange(double _currentValue, double _previousValue, StringBuilder _textString)
        {
            if (DisplayPrice)
                _textString.AppendLine();

            string _sign = _bullishSwings ? "+" : "-";
            string _percentage = ( _bullishSwings ? CalculatePercentageChange(_currentValue, _previousValue) : CalculatePercentageChange(_previousValue, _currentValue) ).ToString("F2");

            _textString.Append( string.Format("({0}{1}%)", _sign, _percentage) );
        }

        private void AppendPrice(StringBuilder _textString)
        {
            _textString.Append(_swingHighLow.Price);
        }

        private double CalculatePercentageChange(double _previous, double _current)
        {
            double _change = Math.Abs(_current - _previous);
            return 100 * (double) _change / _previous;
        }

        public void DisplaySWINGSLabel()
        {
            // Get last value
            double _currentValue = _swingHighLowList[_swingHighLowList.Count - 1].Price;
            // Get second last value
            double _previousValue = _swingHighLowList[_swingHighLowList.Count - 2].Price;

            _bullishSwings = _currentValue > _previousValue;
            string _objName = "Swing High Low Label" + _swingHighLow.Index;
            Color _textColour = _bullishSwings ? "Green" : "Red";
            string _labelText = SwingHigh_LowsText(_currentValue, _previousValue);

            ChartText _text = Chart.DrawText(name: _objName, text: _labelText, barIndex: _swingHighLow.Index, y: _swingHighLow.Price, color: _textColour);

            _text.VerticalAlignment = _bullishSwings ? VerticalAlignment.Top : VerticalAlignment.Bottom;
            _text.HorizontalAlignment = HorizontalAlignment.Center;
        }

        private void BearishSwing()
        {
            double _percentChange = (1.0 + PercentageMove * 0.01);

            bool _moveExtreme = _lows <= _swingHighLow.Price;
            bool _changeDirection = _highs >= _swingHighLow.Price * _percentChange;

            if (_moveExtreme)
                MoveExtreme(_lows);
            else if (_changeDirection)
            {
                SetExtreme(_highs);
                _direction = Direction.Up;
            }
        }

        private void BullishSwing()
        {
            double _percentChange = (1.0 - PercentageMove * 0.01);

            bool _moveExtreme = _highs >= _swingHighLow.Price;
            bool _changeDirection = _lows <= _swingHighLow.Price * _percentChange;

            if (_moveExtreme)
                MoveExtreme(_highs);
            else if (_changeDirection)
            {
                SetExtreme(_lows);
                _direction = Direction.Down;
            }
        }

        private void MoveExtreme(double price)
        {
            Result[_swingHighLow.Index] = double.NaN;

            if (_swingHighLowList.Count > 0)
                _swingHighLowList.Remove(_swingHighLowList[_swingHighLowList.Count - 1]);

            Chart.RemoveObject("Remove Swing Highs Lows Label" + _swingHighLow.Index);

            SetExtreme(price);
        }

        private void SetExtreme(double price)
        {
            _swingHighLow = new Swings(_index, price);
            _swingHighLowList.Add(_swingHighLow);
            Result[_swingHighLow.Index] = _swingHighLow.Price;

            if (_swingHighLowList.Count < 2)
                return;

            DisplaySWINGSLabel();
        }
    }
}

@ctid5083541