Session Sweeps Pro | GainzAlgo

GainzAlgo · study · 276 行 · 点赞 2,810 · TradingView 原页

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

Pine Script

//@version=6
indicator("Session Sweeps Pro | GainzAlgo", overlay = true, max_boxes_count = 500, max_lines_count = 100, max_bars_back = 5000)
 
// rbg colours 
int r1 = 0,   g1 = 242, b1 = 255 
int r2 = 255, g2 = 0,   b2 = 255 
 
// ui
group_hud      = "Profile Settings"
session_type   = input.string("Daily", "Session Period", options = ["Daily", "Weekly", "Monthly"], group=group_hud)
num_rows       = input.int(40, "Rows", minval = 10, maxval = 100, group=group_hud)
glow_width     = input.int(40, "Glow Width", minval = 5, maxval = 100, group=group_hud)
 
group_sweeps   = "Sweep S/R Logic"
lookback_p     = input.int(1000, "Historical Lookback", minval = 100, group=group_sweeps)
risk_threshold = input.int(75, "Risk Score Threshold (%)", group=group_sweeps)
ghost_opacity  = input.int(85, "Ghost S/R Transparency", minval = 0, maxval = 100, group=group_sweeps)
 
group_extra    = "Supplemental Features"
poc_alert_prox = input.float(0.1, "POC Alert Proximity (%)", group=group_extra)
 
// array initalize 
type SweepEvent
    float price
    float top
    float bot
    int   startTime
    bool  isBearish
    box   ghostBox
    label retestLabel
    int   retestCount = 0
    bool  wasRetested = false
    bool  isBroken    = false
 
var sweep_history = array.new<SweepEvent>()
var float s_max = 0.0
var float s_min = 0.0
var int   s_start_time = 0
var float[] sweep_prices = array.new_float()
 
//sessions 
bool is_new = switch session_type
    "Daily"   => timeframe.change("D")
    "Weekly"  => timeframe.change("W")
    "Monthly" => timeframe.change("M")
 
if is_new
    array.clear(sweep_prices)
    s_max := high
    s_min := low
    s_start_time := time
else
    s_max := math.max(s_max, high)
    s_min := math.min(s_min, low)
 
//R:R 
f_get_risk_score() =>
    float atr = ta.atr(14)
    float std = ta.stdev(close, 10)
    na(atr) or atr == 0 ? 50.0 : math.max(0.0, math.min(100.0, 100.0 - (std / atr) * 50.0))
 
ph = ta.pivothigh(high, 20, 20)
pl = ta.pivotlow(low, 20, 20)
atr = ta.atr(14)
 
f_is_overlapping(new_price) =>
    bool overlap = false
    if array.size(sweep_history) > 0
        for i = 0 to array.size(sweep_history) - 1
            if math.abs(array.get(sweep_history, i).price - new_price) < (atr * 1.5)
                overlap := true
                break
    overlap
 
 
var int session_zones = 0
var int total_retests = 0
var int held_zones    = 0
var int broken_zones  = 0
 
if is_new
    session_zones := 0
    total_retests := 0
    held_zones    := 0
    broken_zones  := 0
 
if not na(ph) and not f_is_overlapping(high[20])
    float top = high[20] + (atr*0.2), float bot = high[20]
    c = color.rgb(r2, g2, b2, ghost_opacity)
    gb = box.new(bar_index[20], top, bar_index, bot, bgcolor=c, border_color=color.new(c, 70))
    lb = label.new(bar_index, high[20], "", color=color.new(color.black, 100), textcolor=color.white, size=size.tiny)
    sweep_history.push(SweepEvent.new(high[20], top, bot, s_start_time, true, gb, lb))
    array.push(sweep_prices, high[20]) 
    label.new(bar_index[20], high[20], "▼", style=label.style_label_down, color=color.new(color.red, 20), textcolor=color.white, size=size.tiny)
    alert("New Bearish Sweep Detected at " + str.tostring(high[20]), alert.freq_once_per_bar)
 
if not na(pl) and not f_is_overlapping(low[20])
    float top = low[20], float bot = low[20] - (atr*0.2)
    c = color.rgb(r1, g1, b1, ghost_opacity)
    gb = box.new(bar_index[20], top, bar_index, bot, bgcolor=c, border_color=color.new(c, 70))
    lb = label.new(bar_index, low[20], "", color=color.new(color.black, 100), textcolor=color.white, size=size.tiny)
    sweep_history.push(SweepEvent.new(low[20], top, bot, s_start_time, false, gb, lb))
    array.push(sweep_prices, low[20])
    label.new(bar_index[20], low[20], "▲", style=label.style_label_up, color=color.new(color.green, 20), textcolor=color.white, size=size.tiny)
    alert("New Bullish Sweep Detected at " + str.tostring(low[20]), alert.freq_once_per_bar)
 
if array.size(sweep_history) > 0
    for i = 0 to array.size(sweep_history) - 1
        SweepEvent s = array.get(sweep_history, i)
        bool in_session = s.startTime == s_start_time
        if in_session
            session_zones += 1
            
        if not s.isBroken
            box.set_right(s.ghostBox, bar_index)
            label.set_x(s.retestLabel, bar_index)
            
  
            bool touching = high >= s.bot and low <= s.top
            if touching and not s.wasRetested
                s.retestCount += 1
                s.wasRetested := true
                total_retests += 1
                label.new(bar_index, s.price, "↺", style=label.style_label_center, color=color.new(color.yellow, 20), textcolor=color.white, size=size.tiny)
                alert("Zone Re-touch: Price returned to sweep at " + str.tostring(s.price))
            else if not touching
                s.wasRetested := false
            
            // Break Logic
            if (s.isBearish and close > s.top) or (not s.isBearish and close < s.bot)
                s.isBroken := true
                broken_zones += in_session ? 1 : 0
            else
                held_zones += in_session ? 1 : 0
            
            if s.retestCount > 0
                label.set_text(s.retestLabel, "R:" + str.tostring(s.retestCount))
 
// stats 
if barstate.islast and array.size(sweep_prices) > 0
    for b in box.all 
        if box.get_left(b) > bar_index 
            box.delete(b) 
    for l in line.all 
        line.delete(l)
    for lb in label.all
        if label.get_x(lb) > bar_index
            label.delete(lb)
 
    float range_size = s_max - s_min
    float step = range_size / num_rows
    float[] counts = array.new_float(num_rows, 0.0)
 
    for p in sweep_prices
        int bin = math.min(num_rows - 1, int((p - s_min) / step))
        if bin >= 0
            array.set(counts, bin, array.get(counts, bin) + 1)
 
    float cumulative = 0.0
    float max_freq = array.max(counts)
    int poc_bin = 0
 
    for i = 0 to num_rows - 1
        float freq = array.get(counts, i) / array.size(sweep_prices)
        if array.get(counts, i) == max_freq
            poc_bin := i
        
        cumulative += freq
        float p_low = s_min + (i * step)
        float p_high = p_low + step
        
        int r = int(r1 + (r2 - r1) * cumulative)
        int g = int(g1 + (g2 - g1) * cumulative)
        int b = int(b1 + (b2 - b1) * cumulative)
        color dyn_color = color.rgb(r, g, b)
        
        box current_box = box.new(bar_index + 2, p_high, bar_index + 2 + int(cumulative * glow_width), p_low,
          bgcolor=color.new(dyn_color, 70), border_color=color.new(dyn_color, 90))
 
        float perc = cumulative * 100
        if perc % 15 <= 2 or perc >= 98
            box.set_text(current_box, str.format("{0,number,#}%", perc))
            box.set_text_size(current_box, size.tiny)
            box.set_text_color(current_box, dyn_color)
            box.set_text_halign(current_box, text.align_left)
 
    float poc_price = s_min + (poc_bin + 0.5) * step
    line.new(s_start_time, poc_price, time + (glow_width * 50000), poc_price,
      color=color.yellow, width=3, style=line.style_dashed, xloc=xloc.bar_time)
    
    label.new(time + (glow_width * 60000), poc_price, "⬥ SWEEP POC", 
      color=color.new(color.black, 100), textcolor=color.yellow, style=label.style_label_left, size=size.normal, xloc=xloc.bar_time)
 
 
    if math.abs(close - poc_price) / poc_price <= (poc_alert_prox / 100)
        alert("Price approaching Session Sweep POC", alert.freq_once_per_bar)
 
// stats table 
var table risk_tab = table.new(position.top_right, 2, 5, bgcolor=color.rgb(5, 5, 20, 10), border_width=1, border_color=color.rgb(80, 80, 180))
if barstate.islast
    rs = f_get_risk_score(), rc = rs > risk_threshold ? color.red : color.green
    table.cell(risk_tab, 0, 0, "SWEEP RISK", text_color=color.rgb(160,160,255), text_size=size.small)
    table.cell(risk_tab, 1, 0, str.tostring(math.round(rs)) + "%", text_color=rc, text_size=size.large)
    table.cell(risk_tab, 0, 1, "HISTORIC", text_color=color.rgb(160,160,255), text_size=size.small)
    table.cell(risk_tab, 1, 1, str.tostring(array.size(sweep_history)), text_color=color.white)
    table.cell(risk_tab, 0, 2, "SESSION", text_color=color.rgb(160,160,255), text_size=size.small)
    table.cell(risk_tab, 1, 2, str.tostring(session_zones), text_color=color.white)
    table.cell(risk_tab, 0, 3, "RETESTS", text_color=color.rgb(160,160,255), text_size=size.small)
    table.cell(risk_tab, 1, 3, str.tostring(total_retests), text_color=color.white)
    table.cell(risk_tab, 0, 4, "HOLD/BRK", text_color=color.rgb(160,160,255), text_size=size.small)
    table.cell(risk_tab, 1, 4, str.tostring(held_zones) + "/" + str.tostring(broken_zones), text_color=color.white)
 
 
 
if barstate.islast and array.size(sweep_prices) > 0
 
    for b in box.all 
        if box.get_left(b) > bar_index 
            box.delete(b) 
    for l in line.all 
        line.delete(l)
    for lb in label.all
        if label.get_x(lb) > bar_index
            label.delete(lb)
 
    // Binning & Frequency Logic
    float range_size = s_max - s_min
    float step = range_size / num_rows
    float[] counts = array.new_float(num_rows, 0.0)
    
    for p in sweep_prices
        int bin = math.min(num_rows - 1, int((p - s_min) / step))
        if bin >= 0
            array.set(counts, bin, array.get(counts, bin) + 1)
 
    float cumulative = 0.0
    float max_freq = array.max(counts)
    int poc_bin = 0 
 
    for i = 0 to num_rows - 1
        float freq = array.get(counts, i) / array.size(sweep_prices)
        if array.get(counts, i) == max_freq
            poc_bin := i 
        
        cumulative += freq
        float p_low = s_min + (i * step)
        float p_high = p_low + step
        
        color dyn_color = color.rgb(int(r1 + (r2 - r1) * cumulative), int(g1 + (g2 - g1) * cumulative), int(b1 + (b2 - b1) * cumulative))
        box current_box = box.new(bar_index + 2, p_high, bar_index + 2 + int(cumulative * glow_width), p_low, bgcolor=color.new(dyn_color, 70), border_color=color.new(dyn_color, 90))
 
        // HUD Labels
        float perc = cumulative * 100
        if perc % 15 <= 2 or perc >= 98
            box.set_text(current_box, str.format("{0,number,#}%", perc))
            box.set_text_size(current_box, size.tiny)
            box.set_text_color(current_box, dyn_color)
            box.set_text_halign(current_box, text.align_left)
 
   
    float poc_price = s_min + (poc_bin + 0.5) * step 
    
    line.new(s_start_time, poc_price, time + (glow_width * 50000), poc_price,
      color=color.yellow, width=3, style=line.style_dashed, xloc=xloc.bar_time)
    
    label.new(time + (glow_width * 60000), poc_price, "⬥ SWEEP POC", 
      color=color.new(color.black, 100), textcolor=color.yellow, style=label.style_label_left, size=size.normal, xloc=xloc.bar_time) 
 
    // Supplemental Alert Logic
    bool approaching_poc = math.abs(close - poc_price) / poc_price <= 0.001 
    bool hit_poc = ta.cross(close, poc_price)
 
    if approaching_poc
        alert("Price is approaching the Session POC", alert.freq_once_per_bar)
    if hit_poc
        alert("POC Hit at " + str.tostring(close), alert.freq_once_per_bar)

← 返回列表