Category Trend  Published on 06/01/2023

Equal Highs / Lows

Description

Simple indicator that detects if two candles lows or highs are equal and draws a trend line. 

 

Theory being that large funds are using limit orders to buy / sell at a specific price then the IPDA algo will return to this price to clear the book.

Setting to allow for brokers spread manipulation and lookback setting to increase candles considered for equal lows / highs.

 

Best TF is 2min Lookback candle 3 

Best Trading pair - Nasdaq / S&P

You will see how historic areas of Equal Lows / Highs when they send price away still have residing orders at that price so when price action reacts to those areas it is expected.

 



//===============================================================================================================
//......................................... Developed by Yousef Ardalan .........................................
//.................................. Contact Email: joseph.tradingbot@gmail.com .................................
//===============================================================================================================


using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Collections.Generic;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class RelativeEqualHighLow : Indicator
    {

        #region Parameters
        //----------------------------------------------------------------------------------------------------------------------------------
        [Parameter("LookBack Candles", DefaultValue = 1, MinValue = 1, MaxValue = 999)]
        public int LookbackNumber { get; set; }

        [Parameter("Price Offset (pip)", DefaultValue = 0, MinValue = 0)]
        public double PriceOffset { get; set; }

        [Parameter("Cross Count To Eliminate Lines Extending", DefaultValue = 2, MinValue = 1, MaxValue = 999)]
        public int CrossCountToEliminateLinesExtend { get; set; }

        [Parameter("Cross Count To Change Lines Style", DefaultValue = 1, MinValue = 1, MaxValue = 999)]
        public int CrossCountToChangeLinesStyle { get; set; }
        //----------------------------------------------------------------------------------------------------------------------------------
        [Parameter("Color", Group = "Equal High", DefaultValue = "red")]
        public string EquaHighColor { get; set; }

        [Parameter("Thickness", Group = "Equal High", DefaultValue = 1, MinValue = 0)]
        public int EqualHighThickness { get; set; }

        [Parameter("Style Before Cross", Group = "Equal High", DefaultValue = LineStyle.Solid)]
        public LineStyle EqualHighStyle_BeforeCross { get; set; }

        [Parameter("Style After Cross", Group = "Equal High", DefaultValue = LineStyle.Lines)]
        public LineStyle EqualHighStyle_AfterCross { get; set; }
        //----------------------------------------------------------------------------------------------------------------------------------
        [Parameter("Color", Group = "Equal Low", DefaultValue = "blue")]
        public string EqualLowColor { get; set; }

        [Parameter("Thickness", Group = "Equal Low", DefaultValue = 1, MinValue = 0)]
        public int EqualLowThickness { get; set; }

        [Parameter("Style Before Cross", Group = "Equal Low", DefaultValue = LineStyle.Solid)]
        public LineStyle EqualLowStyle_BeforeCross { get; set; }

        [Parameter("Style After Cross", Group = "Equal Low", DefaultValue = LineStyle.Lines)]
        public LineStyle EqualLowStyle_AfterCross { get; set; }
        //----------------------------------------------------------------------------------------------------------------------------------
        #endregion


        #region Private Variables
        List<RelativeEqual> equalHighs = new List<RelativeEqual>();
        List<RelativeEqual> equalLows = new List<RelativeEqual>();
        double DoubleToIntRatio = 0;
        int previousIndex = 0;
        #endregion


        protected override void Initialize()
        {
            DoubleToIntRatio = 100000;
        }
        // Initialize

        public override void Calculate(int index)
        {
            if (index < 2)
                return;

            // to call onece per each bar(candle)
            if (previousIndex == index)
                return;

            #region List
            List<RelativeEqual> eliminatedHighs = new List<RelativeEqual>();
            for (int i = 0; i < equalHighs.Count; i++)
            {
                if (equalHighs[i].crossCounter % 2 == 1)
                {
                    if (Bars[index - 1].High > equalHighs[i].BeforeCross.Y1)
                    {
                        if (equalHighs[i].crossCounter == CrossCountToChangeLinesStyle)
                        {
                            equalHighs[i].BeforeCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].BeforeCross.ExtendToInfinity = false;

                        }
                        if (equalHighs[i].crossCounter == CrossCountToEliminateLinesExtend)
                        {
                            equalHighs[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].AfterCross.ExtendToInfinity = false;
                            eliminatedHighs.Add(equalHighs[i]);
                        }
                        equalHighs[i].crossCounter++;
                    }
                }
                else
                {
                    if (Bars[index - 1].Low < equalHighs[i].BeforeCross.Y1)
                    {
                        if (equalHighs[i].crossCounter == CrossCountToChangeLinesStyle)
                        {
                            equalHighs[i].BeforeCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].BeforeCross.ExtendToInfinity = false;
                        }
                        if (equalHighs[i].crossCounter == CrossCountToEliminateLinesExtend)
                        {
                            equalHighs[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalHighs[i].AfterCross.ExtendToInfinity = false;
                            eliminatedHighs.Add(equalHighs[i]);
                        }
                        equalHighs[i].crossCounter++;
                    }
                }
            }
            for (int i = 0; i < eliminatedHighs.Count; i++)
                equalHighs.Remove(eliminatedHighs[i]);

            //-------------------------------------------------------------------------------------------------------------------
            List<RelativeEqual> eliminatedLows = new List<RelativeEqual>();
            for (int i = 0; i < equalLows.Count; i++)
            {
                if (equalLows[i].crossCounter % 2 == 1)
                {
                    if (Bars[index - 1].Low < equalLows[i].BeforeCross.Y1)
                    {
                        if (equalLows[i].crossCounter == CrossCountToChangeLinesStyle)
                        {
                            equalLows[i].BeforeCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].BeforeCross.ExtendToInfinity = false;
                        }
                        if (equalLows[i].crossCounter == CrossCountToEliminateLinesExtend)
                        {
                            equalLows[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].AfterCross.ExtendToInfinity = false;
                            eliminatedLows.Add(equalLows[i]);
                        }
                        equalLows[i].crossCounter++;
                    }
                }
                else
                {
                    if (Bars[index - 1].High > equalLows[i].BeforeCross.Y1)
                    {
                        if (equalLows[i].crossCounter == CrossCountToChangeLinesStyle)
                        {
                            equalLows[i].BeforeCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].BeforeCross.ExtendToInfinity = false;
                        }
                        if (equalLows[i].crossCounter == CrossCountToEliminateLinesExtend)
                        {
                            equalLows[i].AfterCross.Time2 = Bars[index - 1].OpenTime;
                            equalLows[i].AfterCross.ExtendToInfinity = false;
                            eliminatedLows.Add(equalLows[i]);
                        }
                        equalLows[i].crossCounter++;
                    }
                }
            }
            for (int i = 0; i < eliminatedLows.Count; i++)
                equalLows.Remove(eliminatedLows[i]);
            #endregion

            //==============================================================================================================================

            long HUp = ConvertToInt(Bars[index - 1].High + Symbol.PipSize * PriceOffset);
            long HDown = ConvertToInt(Bars[index - 1].High - Symbol.PipSize * PriceOffset);
            long LUp = ConvertToInt(Bars[index - 1].Low + Symbol.PipSize * PriceOffset);
            long LDown = ConvertToInt(Bars[index - 1].Low - Symbol.PipSize * PriceOffset);

            for (int i = 1; i <= LookbackNumber; i++)
            {
                // HIGH
                var h = ConvertToInt(Bars[index - i - 1].High);
                if (h <= HUp && h >= HDown)
                {
                    string nameBefore = Bars[index - i - 1].OpenTime + " HighBeforeCross " + Bars[index - 1].OpenTime;
                    double y1 = Bars[index - i - 1].High;
                    double y2 = Bars[index - i - 1].High;
                    var time1 = index - i - 1;
                    var time2 = index - 1;
                    var HBeforeCross = Chart.DrawTrendLine(nameBefore, time1, y1, time2, y2, EquaHighColor, EqualHighThickness, EqualHighStyle_BeforeCross);
                    HBeforeCross.ExtendToInfinity = true;
                    HBeforeCross.ZIndex = 1;
                    //HBeforeCross.IsInteractive = true;

                    string nameAfter = Bars[index - i - 1].OpenTime + " HighAfterCross " + Bars[index - 1].OpenTime;
                    var HAfterCross = Chart.DrawTrendLine(nameAfter, time1, y1, time2, y2, EquaHighColor, EqualHighThickness, EqualHighStyle_AfterCross);
                    HAfterCross.ExtendToInfinity = true;
                    HAfterCross.ZIndex = 2;
                    //HAfterCross.IsInteractive = true;

                    RelativeEqual highEqual = new RelativeEqual();
                    highEqual.BeforeCross = HBeforeCross;
                    highEqual.AfterCross = HAfterCross;
                    highEqual.crossCounter = 1;
                    equalHighs.Add(highEqual);
                }

                // LOW
                var l = ConvertToInt(Bars[index - i - 1].Low);
                if (l <= LUp && l >= LDown)
                {
                    string nameBefore = Bars[index - i - 1].OpenTime + " LowBeforeCross " + Bars[index - 1].OpenTime;
                    double y1 = Bars[index - i - 1].Low;
                    double y2 = Bars[index - i - 1].Low;
                    var time1 = index - i - 1;
                    var time2 = index - 1;
                    var LBeforeCross = Chart.DrawTrendLine(nameBefore, time1, y1, time2, y2, EqualLowColor, EqualLowThickness, EqualLowStyle_BeforeCross);
                    LBeforeCross.ExtendToInfinity = true;
                    LBeforeCross.ZIndex = 1;
                    //LBeforeCross.IsInteractive = true;

                    string nameAfter = Bars[index - i - 1].OpenTime + " LowAfterCross " + Bars[index - 1].OpenTime;
                    var LAfterCross = Chart.DrawTrendLine(nameAfter, time1, y1, time2, y2, EqualLowColor, EqualLowThickness, EqualLowStyle_AfterCross);
                    LAfterCross.ExtendToInfinity = true;
                    LAfterCross.ZIndex = 2;
                    //LAfterCross.IsInteractive = true;

                    RelativeEqual lowEqual = new RelativeEqual();
                    lowEqual.BeforeCross = LBeforeCross;
                    lowEqual.AfterCross = LAfterCross;
                    lowEqual.crossCounter = 1;
                    equalLows.Add(lowEqual);
                }


            }
            //for
            previousIndex = index;

        }
        // Calculate


        public class RelativeEqual
        {
            public ChartTrendLine BeforeCross;
            public ChartTrendLine AfterCross;
            public int crossCounter = 1;
        }

        public long ConvertToInt(double n)
        {
            try
            {
                long longNum = long.Parse((n * DoubleToIntRatio).ToString());
                return longNum;
            } catch (Exception)
            {
                string Err = "*** EXCEPTION ***     N = " + n + "    -----     N * Do2InRa.ToSt = " + (n * DoubleToIntRatio).ToString();
                Print(Err);
                throw;
            }
        }


    }
    // class

}


EY
eyeballpaul

Joined on 07.11.2018

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: RelativeEqualHighLow.algo
  • Rating: 5
  • Installs: 2523
  • Modified: 13/02/2022 17:23
Comments
Log in to add a comment.
RI

What setting is better for SP500?

It look like buy/sell liquidity

If this can auto show the VIMs will much better