How can I know if my indicator has taken out a previous high or low?
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();
}
}
}