Double Top/Bottom

# ─────────────────────────────────────────────
# │ MarketFragments.com | DNA & Market │
# │ info@marketfragments.com │
# │ www.marketfragments.com │
# ─────────────────────────────────────────────
# Time →
# │
# █ █ █│ █
# █ █ █ │ █ █
# █ █ █ │ █ █ █ ╭─╮
# █ █ █ │ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ █ █╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ ╰─────╯
# ──────┴──────────────────────────────────────────────────────────────
# T1 T2 T3 T4 T5 T6
#
# Double Top/Bottom Detection with Variance Handling
declare upper;
Input ShowtradeLevels = no;
input lookBackLength =75; # Look-back period for the first peak
input proximityThreshold = 0.5; # Proximity threshold for comparing highs
input varianceThreshold = 0.005; # Allowable variance for double top matching
input tpadvalue = 0;#hint ticksize padding in addition to breakout
Input stdev_Multi = 3;
Input breakout_stdev_Multi =1.5;# hint in addition to y stdev for breakout
def O = open;
def H = high;
def c =close;
def L = low;
def V = volume;
def bn= barnumber();
def nan = double.nan;
def tickSize = if(!IsNaN(TickSize()),TickSize(),.01);
def padtick =(tpadvalue+tickSize);
def y_stdDev = StDev(c,5);
# Define the current high
def currentHigh = high;
# Define the current low
def currentLow = low;
# Calculate the highest high within the look-back range
def highestInRange = fold i = 1 to lookBackLength with maxHigh = h do
if GetValue(h, i) > maxHigh then GetValue(h, i) else maxHigh;
# Calculate the lowest low within the look-back range
def lowestInRange = fold i2 = 1 to lookBackLength with minLow = l do
if GetValue(l, i2) < minLow then GetValue(l, i2) else minLow;
def l1 = if lowestInRange!=lowestInRange[1] then lowestInRange else l1[1];
def l2 = if l1!=l1[1] then l1[1] else l2[1];
def h1 = if highestInRange!=highestInRange[1] then highestInRange else h1[1];
def h2 = if h1!=h1[1] then h1[1] else h2[1];
# Condition for a double top:
# 1. Current high is within variance of the highest point in the range.
# 2. All highs in between are lower than the current high and the highest point.
def dt1 =if AbsValue(currentHigh - highestInRange) <= varianceThreshold then 1 else nan ;
def dt2 =if ( fold j = 1 to lookBackLength - 1 with allLower = 1 do
if GetValue(h, j) < currentHigh and GetValue(h, j) < highestInRange
then allLower
else 0) then 1 else nan ;
def doubleTop=if !isnan(dt1) && !isnan(dt2) then 1 else nan ;
# Condition for a double bottom:
# 1. Current low is within variance of the lowest point in the range.
# 2. All lows in between are higher than the current low and the lowest point.
def db1 = if AbsValue(currentLow - lowestInRange) <= varianceThreshold then 1 else nan ;
def db2 = if (fold j2 = 1 to lookBackLength - 1 with allHigher = 1 do
if GetValue(l, j2) > currentLow and GetValue(l, j2) > lowestInRange
then allHigher
else 0) then 1 else nan ;
def doubleBottom = if !isnan(db1) && !isnan(db2) then 1 else nan ;
def isfinalcond = if !isnan(doubleTop) then -100
else
if !isnan(doubleBottom) then 100
else 0;
#def testzone = if isfinalcond then 1 else if testzone[1]>=4 then 0 else testzone[1]+1;
#def teststdevmultiplec = if !testzone && testzone[1] then StDev(c[1],5) else teststdevmultiplec[1];
#def teststdevmultipleh = if !testzone && testzone[1] then StDev(h[1],5) else teststdevmultipleh[1];
#def teststdevmultiplel = if !testzone && testzone[1] then StDev(l[1],5) else teststdevmultiplel[1];
# plot values
def xh;
def xhbreak;
def xl;
def xlbreak;
if bn==1{
xh=nan;
xhbreak =nan;
xl=nan;
xlbreak = nan;
} else if isfinalcond==-100{
xh=h+padtick;
xhbreak =xh- (breakout_stdev_Multi * y_stdDev)-padtick;
xl=xl[1];
xlbreak =xlbreak[1];
} else if isfinalcond==100{
xh=xh[1];
xhbreak =xhbreak[1];
xl=l-padtick;
xlbreak =xl+ (breakout_stdev_Multi *y_stdDev)+padtick;
} else{
xh=xh[1];
xhbreak =xhbreak[1];
xl=xl[1];
xlbreak =xlbreak[1];
}
# Plot the double top indicator if conditions are met
plot isDoubleTop = if !isnan(doubleTop) then high else nan ;
isDoubleTop.SetPaintingStrategy(PaintingStrategy.POINTS);
isDoubleTop.SetDefaultColor(Color.RED);
isDoubleTop.SetLineWeight(3);
# Plot the double bottom indicator if conditions are met
plot isDoubleBottom = if !isnan(doubleBottom) then low else double.nan;
isDoubleBottom.SetPaintingStrategy(PaintingStrategy.POINTS);
isDoubleBottom.SetDefaultColor(Color.GREEN);
isDoubleBottom.SetLineWeight(3);
# trade plots
plot phline = xh;
phline.SetPaintingStrategy(paintingStrategy.LINE);
phline.AssignValueColor( if c>xh then Color.green else color.red);
phline.setlineWeight(1);
phline.setHiding(ShowtradeLevels);#ShowOnlyPi
plot phbreak= xhbreak;
phbreak.SetPaintingStrategy(paintingStrategy.LINE);
phbreak.AssignValueColor( if c>xhbreak then Color.green else color.red);
phbreak.setlineWeight(2);
phbreak.setHiding(ShowtradeLevels);#ShowOnlyPi
plot plline = xl;
plline.SetPaintingStrategy(paintingStrategy.LINE);
plline.AssignValueColor( if c<xl then Color.red else color.green);
plline.setlineWeight(1);
plline.setHiding(ShowtradeLevels);#ShowOnlyPivots
plot plbreak= xlbreak;
plbreak.SetPaintingStrategy(paintingStrategy.LINE);
plbreak.AssignValueColor( if c<xlbreak then Color.green else color.red);
plbreak.setlineWeight(2);
plbreak.setHiding(ShowtradeLevels);#ShowOnlyPivots

