N Bar Reversal Detector [LuxAlgo]

LuxAlgo · study · 305 行 · 点赞 7,247 · TradingView 原页

本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。

Pine Script

// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © LuxAlgo
//@version=5
 
indicator("N Bar Reversal Detector [LuxAlgo]", 'LuxAlgo - N Bar Reversal Detector', true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
 
//---------------------------------------------------------------------------------------------------------------------
// Settings 
//---------------------------------------------------------------------------------------------------------------------{
 
display  = display.all - display.status_line
 
brpGroup = 'Pattern Detection'
brpTypeTT = 'Selects the type of reversal pattern to detect:\n\n' +
             ' *Normal: Detects standard reversal patterns based on the high and low prices of the sequence.\n\n' +
             ' *Enhanced: Detects advanced reversal patterns where the most recent closing price must exceed or fall below the high or low of the first candle.\n\n' +
             ' *All: Includes both normal and enhanced patterns.'
brpType = input.string("All", "Pattern Type", options = ["Normal", "Enhanced", "All"], group = brpGroup, display = display, tooltip = brpTypeTT)
numBarsTT = 'Specifies the number of candles in the sequence used to identify a reversal pattern. The length N includes the initial N-1 candles plus the most recent candle (Nth) for pattern detection.'
numBars = input.int(7, 'Reversal Pattern Sequence Length', minval = 2, group = brpGroup, display = display, tooltip = numBarsTT)
minBrasTT = 'Sets the minimum percentage of the first N-1 candles that must be bullish (for a bearish reversal) or bearish (for a bullish reversal) to qualify as a valid reversal pattern. This setting helps adjust the sensitivity of the pattern detection.'
minBars = input.int(50, 'Min Percentage of Required Candles', minval = 0, maxval = 100, group = brpGroup, display = display, tooltip = minBrasTT) / 100
 
brpSRTT = 'Shows horizontal support and resistance lines based on the highest high or lowest low of the pattern'
brpSR  = input.string("Level", "Derived Support and Resistance", options = ["Level", "None"], group = brpGroup, display = display, tooltip = brpSRTT)
brpAC  = input.color(#089981, 'Bullish Reversal Patterns', group = brpGroup)
brpSC  = input.color(#f23645, 'Bearish Reversal Patterns', group = brpGroup)
 
trendIndiGroup = 'Trend Filtering'
trendTT = 'Selects the trend filtering method for detecting reversal patterns and specifies the alignment with the trend.'
trendType = input.string("None", "Filtering", options = ["Moving Average Cloud", "Supertrend", "Donchian Channels", "None"], group = trendIndiGroup, inline = 'flt', display = display, tooltip = trendTT)
trendFilt = input.string("Aligned", "", options = ["Aligned", "Opposite"], group = trendIndiGroup, inline = 'flt', display = display)
trendAC  = input.color(#089981, 'Bullish Trend', inline = 'trnd')
trendSC  = input.color(#f23645, ' Bearish Trend', inline = 'trnd')
 
ma_Group  = 'Moving Average Settings'
maType    = input.string("HMA", "Type", options = ["SMA", "EMA", "HMA", "RMA", "WMA", "VWMA"], group = ma_Group, display = display)
maFLength  = input.int(50, 'Fast Length', minval = 1, maxval = 100, group = ma_Group, display = display)
maSLength  = input.int(200, 'Slow Length', minval = 100, group = ma_Group, display = display)
 
st_Group  = 'Supertrend Settings'
atrPeriod = input.int(10, 'ATR Length', minval=1, group = st_Group, display = display)
factor = input.float(3, 'Factor', minval = 2, step = 0.1, group = st_Group, display = display)
 
dc_Group  = 'Donchian Channel Settings'
length = input.int(13, 'Length', minval = 1, group = dc_Group, display = display)
 
//---------------------------------------------------------------------------------------------------------------------}
// Functions / Methods
//---------------------------------------------------------------------------------------------------------------------{
 
movingAverage(source, length, maType) => 
    switch maType
        "SMA"  => ta.sma (source, length)
        "EMA"  => ta.ema (source, length)
        "HMA"  => ta.hma (source, length)
        "RMA"  => ta.rma (source, length)
        "WMA"  => ta.wma (source, length)
        "VWMA" => ta.vwma(source, length)
 
donchian(len) => math.avg(ta.lowest(len), ta.highest(len))
 
isBullishReversal() =>
    var bool bullReversal = na
    float bullLow = low[numBars]
    int bearCount = 0
 
    for i = 1 to numBars - 1
        if high[i] > high[numBars]
            bullReversal := false
            break
        else 
            bullReversal := true
            bullLow := math.min(bullLow, low[i])
            if open[i] > close[i]
                bearCount += 1
    
    if bearCount / (numBars-1) >= minBars
        bullReversal := true
    else
        bullReversal := false
 
    [math.min(bullLow, low), bullReversal and high > high[numBars]] 
 
isBearishReversal() =>
    var bool bearReversal = na
    float bearHigh = high[numBars]
    int bullCount = 0
 
    for i = 1 to numBars - 1
        if low[i] < low[numBars]
            bearReversal := false
            break
        else 
            bearReversal := true
            bearHigh := math.max(bearHigh, high[i])
            if open[i] < close[i]
                bullCount += 1
    
    if bullCount / (numBars-1) >= minBars
        bearReversal := true
    else
        bearReversal := false
 
    [math.max(bearHigh, high), bearReversal and low < low[numBars]]
 
//---------------------------------------------------------------------------------------------------------------------}
// Calculations - Trend Indicators - Moving Average Cloud
//---------------------------------------------------------------------------------------------------------------------{
 
maFast = movingAverage(close, maFLength, maType) 
maSlow = movingAverage(close, maSLength, maType) 
 
maColor = maFast > maSlow ? trendAC : trendSC
ma1 = plot(trendType == 'Moving Average Cloud' ? maFast : na, "ma fast", color.new(maColor, 81), 1, plot.style_linebr, display = display, editable = false)
ma2 = plot(trendType == 'Moving Average Cloud' ? maSlow : na, "ma slow", color.new(maColor, 73), 1, plot.style_linebr, display = display, editable = false)
 
fill(ma1, ma2, math.max(maFast, maSlow), math.min(maFast, maSlow), color.new(maColor, maFast > maSlow ? 99 : 81), color.new(maColor, maFast > maSlow ? 81 : 99))
 
//---------------------------------------------------------------------------------------------------------------------}
// Calculations - Trend Indicators - Supertrend
//---------------------------------------------------------------------------------------------------------------------{
 
[supertrend, direction] = ta.supertrend(factor, atrPeriod)
 
supertrend := barstate.isfirst ? na : supertrend
upTrend     = plot(direction < 0 ? trendType == 'Supertrend' ? supertrend : na : na, "Up Trend", color.new(trendAC, 73), style = plot.style_linebr, display = display, editable = false)
downTrend   = plot(direction < 0 ? na : trendType == 'Supertrend' ? supertrend : na, "Down Trend", color.new(trendSC, 73),   style = plot.style_linebr, display = display, editable = false)
bodyMiddle  = plot(barstate.isfirst ? na : trendType == 'Supertrend' ? (open + close) / 2 : na, "Body Middle", display = display.none, editable = false)
 
fill(bodyMiddle, upTrend  , supertrend, (open + close) / 2, color.new(trendAC, 81), color.new(chart.bg_color, 100), fillgaps = false)
fill(bodyMiddle, downTrend, (open + close) / 2, supertrend, color.new(chart.bg_color, 100), color.new(trendSC, 81), fillgaps = false)
 
//---------------------------------------------------------------------------------------------------------------------}
// Calculations - Trend Indicators - Donchian Channels
//---------------------------------------------------------------------------------------------------------------------{
 
var os = 0
upper = ta.highest(close, length)
lower = ta.lowest(close, length)
os := upper > upper[1] ? 1 : lower < lower[1] ? 0 : os
 
dcUpper = plot(trendType == 'Donchian Channels' ? upper : na, color = os == 1 ? color.new(trendAC, 99) : color.new(trendSC, 73), display = display, editable = false)
dcLower = plot(trendType == 'Donchian Channels' ? lower : na, color = os == 1 ? color.new(trendAC, 73) : color.new(trendSC, 99), display = display, editable = false)
 
fill(dcUpper, dcLower, upper, lower, os == 1 ? color.new(chart.bg_color, 100) : color.new(trendSC, 81) , os == 0 ? color.new(chart.bg_color, 100) : color.new(trendAC, 81))
 
//---------------------------------------------------------------------------------------------------------------------}
// Calculations - 3-Bar Reversal Pattern
//---------------------------------------------------------------------------------------------------------------------{
 
C_DownTrend = true
C_UpTrend = true
 
if trendType == 'Moving Average Cloud'
    if trendFilt == 'Aligned'
	    C_DownTrend := close < maFast and maFast < maSlow
	    C_UpTrend := close > maFast and maFast > maSlow
    else if trendFilt == 'Opposite'
	    C_DownTrend := close > maFast and maFast > maSlow
	    C_UpTrend := close < maFast and maFast < maSlow
    else
        C_DownTrend := true
        C_UpTrend := true
 
if trendType == 'Supertrend'
    if trendFilt == 'Aligned'
        C_DownTrend := direction > 0 
        C_UpTrend := direction < 0 
    else if trendFilt == 'Opposite'
        C_DownTrend := direction < 0 
        C_UpTrend := direction > 0 
    else
        C_DownTrend := true
        C_UpTrend := true
 
if trendType == 'Donchian Channels'
    if trendFilt == 'Aligned'
        C_DownTrend := os == 0 
        C_UpTrend := os == 1 
    else if trendFilt == 'Opposite'
        C_DownTrend := os == 1
        C_UpTrend := os == 0 
    else
        C_DownTrend := true
        C_UpTrend := true
 
[bullLow, isBullish] = isBullishReversal()
bullishReversal = isBullish and C_UpTrend
 
[bearHigh, isBearish] = isBearishReversal()
bearishReversal = isBearish and C_DownTrend
 
var line lnAT = na
var line lnAB = na
var line lnAT2 = na
var line lnAB2 = na
var label lbAT = na
var box bxA = na
var bool bullProcess = false
var bool bullProcess2 = false
var float bullHigh = na
 
if bullishReversal and not bullishReversal[1] and (brpType == 'All' ? true : brpType == 'Enhanced' ? close > high[numBars] ? true : false : brpType == 'Normal' ? close < high[numBars] ? true : false : false)
    bullProcess := true
 
    lbAT := label.new(bar_index, low, '▲', color = color(na), textcolor = color.new(brpAC, 07), style = label.style_label_up, size = size.small, tooltip = 'new bullish pattern detected' + (close > high[2] ? ' (enchanced)' : ' (normal)'))
 
    lnAT2 := line.new(bar_index[numBars], high[numBars], bar_index, high[numBars], color = color.new(brpAC, 53))
    lnAB2 := line.new(bar_index[numBars], bullLow, bar_index, bullLow, color = color.new(brpAC, 53))
    linefill.new(lnAT2, lnAB2, color.new(brpAC, 73))
 
    lnAT := line.new(bar_index[numBars], high[numBars], bar_index, high[numBars], color = color.new(brpAC, 53))
    lnAB := line.new(bar_index[numBars], bullLow, bar_index, bullLow, color = color.new(brpAC, 53))
 
    bullHigh := brpSR == 'Zone' ? math.max(low[1], low) : bullLow
 
if bullProcess 
    if close[1] > lnAT.get_price(bar_index)
        if bullProcess[1] and bullProcess[1] != bullProcess[2]
            lbAT.set_tooltip('enchanced pattern (confirmed at detection)\nprice activity above the pattern high')
        else
            lbAT.set_tooltip('pattern confirmed ' + str.tostring(bar_index[1] - lbAT.get_x()) + ' bar(s) later')
            label.new(bar_index[1], low[1], '⦁', color = color(na), textcolor = color.new(brpAC, 07), style = label.style_label_up, size = size.small, tooltip = 'confirmation bar\nprice activity above the pattern high')
        
        bullProcess := false
 
        bxA := box.new(bar_index, bullHigh, bar_index, lnAB.get_price(bar_index), color.new(brpAC, brpSR == 'Zone' ? 73 : 53), bgcolor = color.new(brpAC, 73))
        bullProcess2 := true
 
    if close[1] < lnAB.get_price(bar_index) or bearishReversal
        lbAT.set_tooltip('pattern failed\nthe low of the pattern breached')
        bullProcess := false
 
    if not bullProcess 
        lnAT.set_x2(bar_index[1])
        lnAB.set_x2(bar_index[1])
    else
        lnAT.set_x2(bar_index)
        lnAB.set_x2(bar_index)
 
if bullProcess2 and brpSR != 'None'
    if close > bxA.get_bottom()
        bxA.set_right(bar_index)
    else
        bxA.set_right(bar_index)
        bullProcess2 := false
 
 
var line lnST = na
var line lnSB = na
var line lnST2 = na
var line lnSB2 = na
var label lbST = na
var box bxS = na
var bool bearProcess = false
var bool bearProcess2 = false
var float bearLow = na
 
if bearishReversal and not bearishReversal[1] and (brpType == 'All' ? true : brpType == 'Enhanced' ? close < low[numBars] ? true : false : brpType == 'Normal' ? close > low[numBars] ? true : false : false)
    bearProcess := true
 
    lbST := label.new(bar_index, high, '▼', color = color(na), textcolor = color.new(brpSC, 07), style = label.style_label_down, size = size.small, tooltip = 'new bearish pattern detected' + (close < low[2] ? ' (enchanced)' : ' (normal)'))
 
    lnSB2 := line.new(bar_index[numBars], low[numBars], bar_index, low[numBars], color = color.new(brpSC, 53))
    lnST2 := line.new(bar_index[numBars], bearHigh, bar_index, bearHigh, color = color.new(brpSC, 53))
    linefill.new(lnST2, lnSB2, color.new(brpSC, 89))
 
    lnSB := line.new(bar_index[numBars], low[numBars], bar_index, low[numBars], color = color.new(brpSC, 53))
    lnST := line.new(bar_index[numBars], bearHigh, bar_index, bearHigh, color = color.new(brpSC, 53))
 
    bearLow := brpSR == 'Zone' ? math.min(high[1], high) : bearHigh
 
if bearProcess 
    if close[1] > lnST.get_price(bar_index) or bullishReversal
        lbST.set_tooltip('pattern failed\nthe high of the pattern breached')
        bearProcess := false
 
    if close[1] < lnSB.get_price(bar_index) 
        if bearProcess[1] and bearProcess[1] != bearProcess[2]
            lbST.set_tooltip('enchanced pattern (confirmed at detection)\nprice activity below the pattern low')
        else
            lbST.set_tooltip('pattern confirmed ' + str.tostring(bar_index[1] - lbST.get_x()) + ' bar(s) later')
            label.new(bar_index[1], high[1], '⦁', color = color(na), textcolor = color.new(brpSC, 07), style = label.style_label_down, size = size.small, tooltip = 'confirmation bar\nprice activity blow the pattern low')
 
        bearProcess := false
 
        bxS := box.new(bar_index, lnST.get_price(bar_index), bar_index, bearLow, color.new(brpSC, brpSR == 'Zone' ? 89 : 53), bgcolor = color.new(brpSC, 89))
        bearProcess2 := true
 
    if not bearProcess 
        lnST.set_x2(bar_index[1])
        lnSB.set_x2(bar_index[1])
    else
        lnST.set_x2(bar_index)
        lnSB.set_x2(bar_index)
 
if bearProcess2 and brpSR != 'None'
    if close < bxS.get_top()
        bxS.set_right(bar_index)
    else
        bxS.set_right(bar_index)
        bearProcess2 := false
 
//---------------------------------------------------------------------------------------------------------------------}

← 返回列表