Reversal Trap Probability Bands [BigBeluga]

BigBeluga · study · 235 行 · 点赞 6,362 · TradingView 原页

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

Pine Script

// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International  
// https://creativecommons.org/licenses/by-nc-sa/4.0/
// © BigBeluga
 
//@version=6
indicator("Reversal Trap Probability Bands [BigBeluga]", overlay=true, max_labels_count=100, max_lines_count=500)
 
// INPUTS ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
 
envelope_len  = input.int(55, "Envelope Smoothness", minval=1, group="Envelope Settings", tooltip="Changes the length of the central moving average line. Higher values create a smoother, slower channel.")
multiplier    = input.float(4.0, "Envelope Width", minval=0.1, step=0.1, group="Envelope Settings", tooltip="Determines how far the outer bands stretch away from the center baseline based on market volatility.")
 
trap_window   = input.int(10, "Trap Window (Candles)", minval=1, group="Strategy Settings", tooltip="The maximum number of candles allowed to close completely outside the bands before a reversal is disqualified as a fakeout trap.")
signal_gap    = input.int(10, "Minimum Bars Between Signals", minval=1, group="Strategy Settings", tooltip="Cooldown period. The minimum number of bars required between signal triggers to avoid cluttering your charts.")
rsi_len       = 20
stop_mult     = input.float(0.5, "ATR Stop Multiplier", minval=0.1, step=0.1, group="Strategy Settings", tooltip="Multiplies the Average True Range (ATR) value to add safety padding above or below structural key levels.")
target_source = "Basis Line"
 
max_bars      = input.int(5000, "Max Lookback Bars", minval=1, group="Database Limits", tooltip="Limits the script's historical memory. It will only search and record trades from the last X number of bars.")
max_trades    = input.int(500, "Max Total Trades", minval=1, group="Database Limits", tooltip="Database limit guardrail. Stops saving new trades to memory once the total historical trade counter hits this number.")
 
colorDn       = input.color(color.rgb(236, 51, 51), "Bearish Theme Color", group="Color Styling", tooltip="Changes the color of the upper envelope boundary, bearish labels, and shading effects.")
colorUp       = input.color(color.rgb(18, 175, 159), "Bullish Theme Color", group="Color Styling", tooltip="Changes the color of the lower envelope boundary, bullish labels, and shading effects.")
colormid      = input.color(color.rgb(120, 123, 134, 50), "MidLine Color", group="Color Styling", tooltip="Changes the color of the middle envelope boundary")
 
label_size_setting = input.string("Small", "Label Size", options=["Auto", "Tiny", "Small", "Normal", "Large", "Huge"], group="Color Styling", tooltip="Adjusts the size of the signal labels displayed on the chart.")
 
// }
// CALCULATIONS――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
 
basis = ta.ema(close, envelope_len)
vola  = ta.atr(envelope_len)
rsi   = ta.rsi(close, rsi_len)
 
upper_band = basis + (multiplier * vola)
lower_band = basis - (multiplier * vola)
 
rsi_bucket = math.max(0, math.min(10, math.round(rsi / 10)))
atr        = ta.atr(100) * stop_mult
 
// Convert label size input to TradingView size type
get_label_size(size_str) =>
    switch size_str
        "Auto"   => size.auto
        "Tiny"   => size.tiny
        "Small"  => size.small
        "Normal" => size.normal
        "Large"  => size.large
        "Huge"   => size.huge
        => size.small
 
selected_label_size = get_label_size(label_size_setting)
 
// Historical Database Trackers
var int[] bull_total = array.new_int(11, 0)
var int[] bull_wins  = array.new_int(11, 0)
var int[] bear_total = array.new_int(11, 0)
var int[] bear_wins  = array.new_int(11, 0)
 
var int total_trades_count = 0
bars_from_live = last_bar_index - bar_index
allowed_by_limits = (bars_from_live <= max_bars) and (total_trades_count < max_trades)
 
// Trap Counter States
var int close_above_envelope_count = 0
var int close_below_envelope_count = 0
 
 
 
 
bool raw_bear_trap = false
if close < upper_band
    if high > upper_band and close[1] < upper_band and close_above_envelope_count[1] <= trap_window
        raw_bear_trap := true
    else if close[1] > upper_band and close_above_envelope_count[1] <= trap_window
        raw_bear_trap := true
 
 
if high > upper_band
    close_above_envelope_count += 1
else
    close_above_envelope_count := 0
 
 
 
bool raw_bull_trap = false
if close > lower_band
    if low < lower_band and close[1] > lower_band and close_below_envelope_count[1] <= trap_window
        raw_bull_trap := true
    else if close[1] < lower_band and close_below_envelope_count[1] <= trap_window
        raw_bull_trap := true
 
 
if low < lower_band
    close_below_envelope_count += 1
else
    close_below_envelope_count := 0
 
 
var int last_signal_bar = -1000
can_fire = (bar_index - last_signal_bar) >= signal_gap
 
bull_trap = raw_bull_trap and can_fire
bear_trap = raw_bear_trap and can_fire
 
if bull_trap or bear_trap
    last_signal_bar := bar_index
 
// Tracking Engines
var bool active_bull = false
var line bull_target = na
var line bull_stop   = na
var int  bull_bucket = na
var line potentialTarget = na
Bull_Stop = ta.lowest(low, 2) - atr
 
if bull_trap and not active_bull and allowed_by_limits
    active_bull := true
    bull_bucket := rsi_bucket
    total_trades_count += 1
    
    float calculated_target = target_source == "Basis Line" ? basis : upper_band
    
    bull_target     := line.new(bar_index, calculated_target, bar_index + 10, calculated_target, color = colorUp, style = line.style_dashed)
    bull_stop       := line.new(bar_index, Bull_Stop, bar_index + 10, Bull_Stop, color = colorUp, style = line.style_dashed)
    potentialTarget := line.new(x1=bar_index, y1=low, x2=bar_index+10, y2=calculated_target, color=colorUp, style=line.style_arrow_right)
 
    total_attempts = array.get(bull_total, rsi_bucket)
    total_success  = array.get(bull_wins, rsi_bucket)
    string prob_text = "Tracking..."
    rate = 0.0
 
    if total_attempts > 0
        rate := math.round((total_success / total_attempts) * 100)
        prob_text := str.tostring(rate) + "% WIN PROB"
        
    label.new(x=bar_index, y=low-atr, text="⬆\nTRAP\n" + prob_text + "\n(RSI: " + str.tostring(math.round(rsi)) + ")", style=label.style_label_up, color=color.new(colorUp, 100), textcolor=colorUp, size=selected_label_size, tooltip = "Win Probability: " + str.tostring(rate) + "%")
 
if active_bull
    bull_stop.set_x2(bar_index+10)
    bull_target.set_x2(bar_index+10)
    potentialTarget.set_x2(bar_index+10)    
 
    if high >= bull_target.get_price(bar_index) and bar_index - last_signal_bar > 1
        array.set(bull_total, bull_bucket, array.get(bull_total, bull_bucket) + 1)
        array.set(bull_wins,  bull_bucket, array.get(bull_wins,  bull_bucket) + 1)
        active_bull := false
        label.new(bar_index, high, "✓", style = label.style_label_down, color = color.new(colorDn, 100), textcolor = colorUp, size=selected_label_size)
        bull_stop.set_x2(bar_index)
        bull_target.set_x2(bar_index)
        potentialTarget.set_x2(bar_index)    
    else if low < bull_stop.get_price(bar_index) and bar_index - last_signal_bar > 1
        array.set(bull_total, bull_bucket, array.get(bull_total, bull_bucket) + 1)
        active_bull := false
        bull_stop.set_x2(bar_index)
        bull_target.set_x2(bar_index)
        potentialTarget.set_x2(bar_index)    
 
var bool active_bear = false
var line bear_target = na
var line bear_stop   = na
var int  bear_bucket = na
var line potentialTargetBear = na
Bear_Stop = ta.highest(high, 2) + atr
 
if bear_trap and not active_bear and allowed_by_limits
    active_bear := true
    bear_bucket := rsi_bucket
    total_trades_count += 1
    
    float calculated_target = target_source == "Basis Line" ? basis : lower_band
    
    bear_target         := line.new(bar_index, calculated_target, bar_index + 10, calculated_target, color = colorDn, style = line.style_dashed)
    bear_stop           := line.new(bar_index, Bear_Stop, bar_index + 10, Bear_Stop, color = colorDn, style = line.style_dashed)
    potentialTargetBear := line.new(x1=bar_index, y1=high, x2=bar_index+10, y2=calculated_target, color=colorDn, style=line.style_arrow_right)
 
    total_attempts = array.get(bear_total, rsi_bucket)
    total_success  = array.get(bear_wins, rsi_bucket)
    string prob_text = "Tracking..."
    rate = 0.0
 
    if total_attempts > 0
        rate := math.round((total_success / total_attempts) * 100)
        prob_text := str.tostring(rate) + "% WIN PROB"
        
    label.new(x=bar_index, y=high+atr, text=prob_text + "\n(RSI: " + str.tostring(math.round(rsi)) + ")" + "\nTRAP\n⬇", style=label.style_label_down, color=color.new(colorUp, 100), textcolor=colorDn, size=selected_label_size, tooltip = "Win Probability: " + str.tostring(rate) + "%")
 
if active_bear
    bear_stop.set_x2(bar_index+10)
    potentialTargetBear.set_x2(bar_index+10)
    bear_target.set_x2(bar_index+10)
 
    if low <= bear_target.get_price(bar_index) and bar_index - last_signal_bar > 1
        array.set(bear_total, bear_bucket, array.get(bear_total, bear_bucket) + 1)
        array.set(bear_wins,  bear_bucket, array.get(bear_wins,  bear_bucket) + 1)
        active_bear := false
        label.new(bar_index, low, "✓", style = label.style_label_up, color = color.new(colorDn, 100), textcolor = colorDn, size=selected_label_size)
        bear_stop.set_x2(bar_index)
        bear_target.set_x2(bar_index)
        potentialTargetBear.set_x2(bar_index)
    else if high > bear_stop.get_price(bar_index) and bar_index - last_signal_bar > 1
        array.set(bear_total, bear_bucket, array.get(bear_total, bear_bucket) + 1)
        active_bear := false
        bear_stop.set_x2(bar_index)
        bear_target.set_x2(bar_index)
        potentialTargetBear.set_x2(bar_index)
 
// }
// PLOT ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
 
plot_upper = plot(upper_band, "Envelope Ceiling", color=color.new(colorDn, 50), linewidth=3)
plot_lower = plot(lower_band, "Envelope Floor",   color=color.new(colorUp, 50), linewidth=3)
plot_basis = plot(basis, "Envelope Baseline",     color=colormid, linestyle = plot.linestyle_dashed)
 
fill(
     plot1        = plot_upper, 
     plot2        = plot_basis, 
     top_value    = upper_band, 
     bottom_value = basis, 
     top_color    = color.new(colorDn, 90), 
     bottom_color = color.new(colorDn, 100), 
     title        = "Upper Band Gradient"
     )
 
fill(
     plot1        = plot_basis, 
     plot2        = plot_lower, 
     top_value    = basis, 
     bottom_value = lower_band, 
     top_color    = color.new(colorUp, 100), 
     bottom_color = color.new(colorUp, 90), 
     title        = "Lower Band Gradient"
     )
 
// }

← 返回列表