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
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
What setting is better for SP500?
It look like buy/sell liquidity
If this can auto show the VIMs will much better