N Bar Reversal Detector [LuxAlgo] for ThinkOrSwim

samer800

Moderator - Expert
VIP
Lifetime
6e46k3T.png

Author Message:

The N Bar Reversal Detector is designed to detect and highlight N-bar reversal patterns in user charts, where N represents the length of the candle sequence used to detect the patterns. The script incorporates various trend indicators to filter out detected signals and offers a range of customizable settings to fit different trading strategies.

CODE:

CSS:
#/ Indicator For TOS
#// © LuxAlgo
# indicator("N Bar Reversal Detector [LuxAlgo]", 'LuxAlgo - N Bar Reversal Detector',
# Converted by Sam4Cok@Samer800    - 10/2024

input showSignals = yes;
input PatternType = {"Normal", "Enhanced", default "All"}; # "Pattern Type"
input ReversalPatternSequenceLength = 7;     # 'Reversal Pattern Sequence Length'
input MinPercentageOfRequiredCandles = 50;   # 'Min Percentage of Required Candles'
input DerivedSupportAndResistance  = {default "Level", "None"}; # "Derived Support and Resistance"
input trendType = {"Moving Average Cloud", "Supertrend", "Donchian Channels", default "None"}; # "Filtering"
input FilteringType = {default "Aligned", "Opposite"};
input movAvgType    = AverageType.HULL;
input fastLength  = 50;               # 'Fast Length'
input slowLength  = 200;              # 'Slow Length'
input atrLength = 10;                 # 'ATR Length'
input supertrendFactor = 3.0;         # 'Factor'
input DonchianChannelLength = 13;     # 'Length'

def na = Double.NaN;
def last = isNaN(close);
def minBars = Max(Min(MinPercentageOfRequiredCandles / 100, 1), 0);
def numBars = Max(ReversalPatternSequenceLength, 2);
def none = DerivedSupportAndResistance==DerivedSupportAndResistance."None";
def filterUp; def filterDn;
Switch (PatternType) {
Case "Normal" :
    filterUp = close < high[numBars];
    filterDn = close > low[numBars];
Case "Enhanced" :
    filterUp = close > high[numBars];
    filterDn = close < low[numBars];
Default :
    filterUp = yes;
    filterDn = yes;
}
Script supertrend {
input factor = 3;
input atrPeriod = 10;
    def src = hl2;
    def tr = if isNaN(high[1]) then high - low else TrueRange(high, close, low);
    def atr = WildersAverage(tr, atrPeriod);
    def upBand = src + factor * atr;
    def loBand = src - factor * atr;
    def lowerBand; def upperBand;
    def prevLowerBand = if isNaN(lowerBand[1]) then prevLowerBand[1] else lowerBand[1];
    def prevUpperBand = if isNaN(upperBand[1]) then prevUpperBand[1] else upperBand[1];
    lowerBand = if loBand > prevLowerBand or close[1] < prevLowerBand then loBand else prevLowerBand;
    upperBand = if upBand < prevUpperBand or close[1] > prevUpperBand then upBand else prevUpperBand;
    def _direction;
    def superTrend;
    def prevSuperTrend = superTrend[1];
    if isNaN(atr[1]) {
        _direction = 1;
    } else if prevSuperTrend == prevUpperBand {
        _direction = if close > upperBand then -1 else 1;
    } else {
        _direction = if close < lowerBand then 1 else -1;
    }
    superTrend = if _direction == -1 then lowerBand else upperBand;
    plot st = if isNaN(superTrend) then Double.NaN else superTrend;
    plot dir = if isNaN(_direction) then Double.NaN else _direction;
    }

# isBullishReversal {
def isBullLow = fold i = 1 to numBars  with p=low[numBars] while high[i] <= high[numBars] do
                Min(p, low[i]);
def bearCount = fold i1 = 1 to numBars with p1 while high[i1] <= high[numBars] do
                if open[i1] > close[i1] then p1 + 1 else p1 ;
def bullReversal1 = bearCount / (numBars - 1) >= (minBars);
def bullReversal = if isNaN(bullReversal1) then no else bullReversal1;
def bullLow = Min(isBullLow, low);
def isBullish = bullReversal and high > high[numBars];

#isBearishReversal() =>
def isBearHigh = fold j = 1 to numBars with q=high[numBars] while low[j] >= low[numBars] do
                 Max(q, high[j]);
def bullCount = fold j1 = 1 to numBars with q1 while low[j1] >= low[numBars] do
                if open[j1] < close[j1] then q1 + 1 else q1 ;
def bearReversal = bullCount / (numBars -1) >= (minBars);
#def bearReversal = if isNaN(bearReversal1) then no else bearReversal1;
def bearHigh = Max(isBearHigh, high);
def isBearish = bearReversal and low < low[numBars];

#// Calculations - Trend Indicators - Moving Average Cloud
def maFast = movingAverage(movAvgType, close, fastLength);
def maSlow = movingAverage(movAvgType, close, slowLength);
def maColor = maFast > maSlow; # ? trendAC : trendSC
#// Calculations - Trend Indicators - Supertrend
def supertrend = supertrend(supertrendFactor, atrLength).st;
def direction  = supertrend(supertrendFactor, atrLength).dir;
def bodyMid = (open + close) / 2 ;
#// Calculations - Trend Indicators - Donchian Channels
def upp = highest(close, DonchianChannelLength);
def loo = lowest(close, DonchianChannelLength);
def os = if upp > upp[1] then 1 else
         if loo < loo[1] then 0 else os[1];
#// Calculations - 3-Bar Reversal Pattern
def align = FilteringType == FilteringType."Aligned";
def oppo  = FilteringType == FilteringType."Opposite";
def mAvg = trendType == trendType."Moving Average Cloud";
def C_DnTrend; # = true
def C_UpTrend; # = true
def upper;
def lower;
Switch (trendType) {
Case "Moving Average Cloud" :
    upper = maFast;
    lower = maSlow;
    if Align {
        C_DnTrend = close < maFast and maFast < maSlow;
        C_UpTrend = close > maFast and maFast > maSlow;
    } else if Oppo {
        C_DnTrend = close > maFast and maFast > maSlow;
        C_UpTrend = close < maFast and maFast < maSlow;
    } else {
        C_DnTrend = yes;
        C_UpTrend = yes;
    }
Case "Supertrend" :
    upper = if direction < 0 then supertrend else na;
    lower = if direction < 0 then na else supertrend;
   if Align {
        C_DnTrend = direction > 0;
        C_UpTrend   = direction < 0;
    } else if Oppo {
        C_DnTrend = direction < 0;
        C_UpTrend = direction > 0;
    } else {
        C_DnTrend = yes;
        C_UpTrend = yes;
    }
Case "Donchian Channels" :
    lower = if os == 0 then upp else if os[-1] == 0 then upp[-1] else na;
    upper = if os == 1 then loo else if os[-1] == 1 then loo[-1] else na;
   if Align {
        C_DnTrend = os == 0;
        C_UpTrend = os == 1;
    } else if Oppo {
        C_DnTrend = os == 1;
        C_UpTrend = os == 0;
    } else {
        C_DnTrend = yes;
        C_UpTrend = yes;
    }
Default :
    upper = na;
    lower = na;
    C_DnTrend = yes;
    C_UpTrend = yes;
}

def upTrend = if upper then upper else na;
def dnTrend = if lower then lower else na;

AddCloud(if mAvg then na else bodyMid, upTrend, Color.DARK_GREEN, Color.DARK_GREEN, yes);
AddCloud(if mAvg then na else dnTrend, bodyMid, Color.DARK_RED, Color.DARK_RED, yes);
AddCloud(if mAvg then upTrend else na, dnTrend, Color.DARK_GREEN, Color.DARK_RED, yes);

#-- lines
def bullishReversal = isBullish and C_UpTrend;
def bearishReversal = isBearish and C_DnTrend;
def condUp = bullishReversal and !bullishReversal[1] and filterUp;
def condDn = bearishReversal and !bearishReversal[1] and filterDn;
def cntUp = if condUp[-numBars] then 0 else cntUp[1] + 1;
def cntDn = if condDn[-numBars] then 0 else cntDn[1] + 1;


def lnAT; def lnAB; def bullProcess; def bullProcess2; def bullProcess1;
def bxA; def bxA1; def lbAT;
if condUp[-numBars] {
    lbAT = 2;
    bullProcess = yes;
    lnAT = high;
    lnAB = bullLow[-numBars];
    bxA = bxA1[1];
    bullProcess2 = bullProcess1[1];
} else if bullProcess[1] and cntUp>=numBars-1 {
    if (close[1] > lnAT[1]) {
    lbAT = if bullProcess[1] and bullProcess[1] != bullProcess[2] then 0 else 1;
    bullProcess = no;
    bxA = lnAB[1];
    bullProcess2 = yes;
    } else if (close[1] < lnAB[1]) or bearishReversal { #
    lbAT = 0;
    bullProcess = no;
    bxA = bxA1[1];
    bullProcess2 = bullProcess1[1];
    } else {
    lbAT = 0;
    bullProcess = bullProcess[1];
    bxA = bxA1[1];
    bullProcess2 = bullProcess1[1];
    }
    lnAT = if !bullProcess then na else lnAT[1];
    lnAB = if !bullProcess then na else lnAB[1];
} else {
    bullProcess  = bullProcess[1];
    bxA = bxA1[1];
    bullProcess2 = bullProcess1[1];
    lbAT = 0;
    lnAT = if !bullProcess then na else lnAT[1];
    lnAB = if !bullProcess then na else lnAB[1];
}
if (bullProcess2 and !none) {
    if close > bxA {
    bxA1 = bxA;
    bullProcess1 = bullProcess2;
    } else {
    bxA1 = bxA;
    bullProcess1 = no;}
    } else {
    bxA1 = na;
    bullProcess1 = bullProcess2;
}

def lnSB; def lnST; def bearProcess; def bearProcess2; def bearProcess1;
def bxS; def bxS1; def lbST;
if condDn[-numBars] {
    lbST = 2;
    bearProcess = yes;
    lnSB = low;
    lnST = bearHigh[-numBars];
    bxS = bxS1[1];
    bearProcess2 = bearProcess1[1];
} else if bearProcess[1] and cntDn>=numBars-1 {
    if (close[1] > lnST[1]) or bullishReversal {
    lbST = 0;
    bearProcess = no;
    bxS = bxS1[1];
    bearProcess2 = bearProcess1[1];
    } else if (close[1] < lnSB[1]) {
    lbST = if bearProcess[1] and bearProcess[1] != bearProcess[2] then 0 else 1;
    bearProcess = no;
    bxS = lnST[1];
    bearProcess2 = yes;
    } else {
    lbST = 0;
    bearProcess = bearProcess[1];
    bxS = bxS1[1];
    bearProcess2 = bearProcess1[1];
    }
    lnSB = if !bearProcess then na else lnSB[1];
    lnST = if !bearProcess then na else lnST[1];
} else {
    bearProcess  = bearProcess[1];
    bxS = bxS1[1];
    bearProcess2 = bearProcess1[1];
    lbST = 0;
    lnSB = if !bearProcess then na else lnSB[1];
    lnST = if !bearProcess then na else lnST[1];
}
if (bearProcess2 and !none) {
    if close < bxS {
    bxS1 = bxS;
    bearProcess1 = bearProcess2;
    } else {
    bxS1 = bxS;
    bearProcess1 = no;}
    } else {
    bxS1 = na;
    bearProcess1 = bearProcess2;
}


def cloudUp1 = if isNaN(cntUp) then cloudUp1[1] + 1 else cntUp;
def cloudDn1 = if isNaN(cntDn) then cloudDn1[1] + 1 else cntDn;
def cloudUp = cloudUp1;
def cloudDn = cloudDn1;

plot bgBullTop  = if !last and cloudUp <= numBars and lnAT then lnAT else na;
plot bgBullBot  = if !last and cloudUp <= numBars and lnAB then lnAB else na;
plot bgBullTop1 = if !last and cloudUp >= numBars and lnAT==lnAT[1] then lnAT else na;
plot bgBullBot1 = if !last and cloudUp >= numBars and lnAB==lnAB[1] then lnAB else na;
plot bgBearTop  = if !last and cloudDn <= numBars and lnST then lnST else na;
plot bgBearBot  = if !last and cloudDn <= numBars and lnSB then lnSB else na;
plot bgBearTop1 = if !last and cloudDn >= numBars and lnST==lnST[1] then lnST else na;
plot bgBearBot1 = if !last and cloudDn >= numBars and lnSB==lnSB[1] then lnSB else na;

bgBullTop.SetDefaultColor(Color.GREEN);
bgBullBot.SetDefaultColor(Color.GREEN);
bgBullTop1.SetDefaultColor(Color.DARK_GREEN);
bgBullBot1.SetDefaultColor(Color.DARK_GREEN);
bgBearTop.SetDefaultColor(Color.RED);
bgBearBot.SetDefaultColor(Color.RED);
bgBearTop1.SetDefaultColor(Color.DARK_RED);
bgBearBot1.SetDefaultColor(Color.DARK_RED);

plot sigUp = if showSignals and lbAT[numBars]==2 then low else na;
plot sigDn = if showSignals and lbST[numBars]==2 then high else na;
plot ptUp  = if showSignals and lbAT[-1]==1 and lbAT[numBars]!=2 then low - ATR(5)/5 else na;
plot ptDn  = if showSignals and lbST[-1]==1 and lbST[numBars]!=2 then high + ATR(5)/5 else na;
sigUp.SetDefaultColor(Color.CYAN);
sigDn.SetDefaultColor(Color.MAGENTA);
sigUp.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
sigDn.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
ptUp.SetDefaultColor(Color.CYAN);
ptUp.SetPaintingStrategy(PaintingStrategy.SQUARES);
ptDn.SetDefaultColor(Color.MAGENTA);
ptDn.SetPaintingStrategy(PaintingStrategy.SQUARES);

plot lvlUp = if !last and bxA1 then bxA1 else na;
plot lvlDn = if !last and bxS1 then bxS1 else na;
lvlUp.SetDefaultColor(Color.DARK_GREEN);
lvlUp.SetPaintingStrategy(PaintingStrategy.DASHES);
lvlDn.SetDefaultColor(Color.DARK_RED);
lvlDn.SetPaintingStrategy(PaintingStrategy.DASHES);


AddCloud(if cloudUp <= numBars then bgBullTop else na, bgBullBot, Color.DARK_GREEN);
AddCloud(if cloudDn <= numBars then bgBearTop else na, bgBearBot, Color.DARK_RED);

#-- end of code
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
213 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top