Arc VWAP Supertrend [BOSWaves]

BOSWaves · study · 310 行 · 点赞 3,315 · TradingView 原页

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

Pine Script

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BOSWaves
 
//@version=6
indicator("Arc VWAP Supertrend [BOSWaves]", overlay = true,
     max_lines_count = 500, max_labels_count = 500)
 
// ┌───────────────────────────── BOSWaves ─ Arc Settings ────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
float accelRate   = input.float(0.12, "Arc Speed", step = 0.01, minval = 0.01,
                        tooltip = "Base acceleration rate of the arc. Higher values make the arc chase price more aggressively. Scales up automatically when price is extended from VWAP.")
float startMult   = input.float(2.0,  "Start Distance (ATR×)", step = 0.1,
                        tooltip = "How far the arc is placed from price when a new trend begins, measured in multiples of the slow ATR. Higher = more breathing room before a flip.")
int   smooth      = input.int(3, "Smoothing", minval = 1, maxval = 10,
                        tooltip = "Number of bars used to smooth the arc and candle gradient. Higher values reduce noise but add lag.")
bool  showLevels  = input.bool(true,  "Show Flip Levels",
                        tooltip = "Draw a horizontal level at each trend flip point. Lines extend forward until price closes through them.")
bool  showCloud   = input.bool(true,  "Show Cloud Fill",
                        tooltip = "Fill the area between the arc and price with a semi-transparent cloud. Color reflects current trend direction.")
bool  showCandles = input.bool(true,  "Color Candles",
                        tooltip = "Override candle colors with a gradient based on trend direction and distance from the arc. Brighter = further from arc.")
int   maxLevels   = input.int(10, "Max Levels", 5, 50,
                        tooltip = "Maximum number of unbroken flip levels kept on the chart at once. Oldest levels are removed first when the limit is reached.")
color colUp       = input.color(#1ac200, "Bull Color", inline = "c",
                        tooltip = "Color used for bullish trend elements: arc, candles, flip markers, and cloud fill.")
color colDn       = input.color(#ff4040, "Bear Color", inline = "c",
                        tooltip = "Color used for bearish trend elements: arc, candles, flip markers, and cloud fill.")
 
float arrowOffset = input.float(1.2, "Arrow Offset (ATR×)", step = 0.1, minval = 0.1,
                        tooltip = "How far the flip arrows are pushed away from the arc, in multiples of ATR. Increase if arrows overlap candle wicks.")
 
// ┌───────────────────────────── BOSWaves ─ Flip Level Style ────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
string levelStyle  = input.string("Dashed", "Level Style",
                         options = ["Solid", "Dashed", "Dotted"],
                         group   = "Flip Levels",
                         tooltip = "Line style for active flip levels.")
int    levelWidth  = input.int(1, "Level Width", minval = 1, maxval = 4,
                         group   = "Flip Levels",
                         tooltip = "Stroke width of active flip level lines.")
int    levelTransp = input.int(20, "Level Transparency", minval = 0, maxval = 90,
                         group   = "Flip Levels",
                         tooltip = "Transparency of active flip level lines. 0 = fully opaque, 90 = nearly invisible.")
bool   levelLabel  = input.bool(true, "Show Price Label",
                         group   = "Flip Levels",
                         tooltip = "Show a small price label at the right edge of each active flip level.")
string levelLabelSize = input.string("tiny", "Label Size",
                         options = ["auto", "tiny", "small", "normal", "large", "huge"],
                         group   = "Flip Levels",
                         tooltip = "Size of the price label shown at the right edge of each flip level.")
 
// ┌───────────────────────────── BOSWaves ─ VWAP Settings ───────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
string filterPeriod  = input.string("Session", "Signal Filter Period",
                           options = ["Session", "Week", "Month", "Any", "All"],
                           group   = "VWAP",
                           tooltip = "Which VWAP must agree with the flip direction for a confirmed alert.\n\nSession = daily VWAP\nWeek = rolling weekly VWAP\nMonth = rolling monthly VWAP\nAny = at least one VWAP agrees\nAll = every VWAP must agree")
 
float vwapAccelBoost = input.float(1.5, "VWAP Distance Speed Boost",
                           minval = 1.0, maxval = 5.0, step = 0.1,
                           group   = "VWAP",
                           tooltip = "How much faster the arc accelerates when price is extended from the reference VWAP.\n\n1.0 = no boost (flat acceleration)\n5.0 = up to 5× faster when price is 4+ ATRs from VWAP")
 
// ┌───────────────────────────── BOSWaves ─ VWAP Calculation ────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
bool  newSession  = timeframe.change("D")
var float cumPvS  = 0.0
var float cumVolS = 0.0
if newSession
    cumPvS  := 0.0
    cumVolS := 0.0
cumPvS  += hl2 * volume
cumVolS += volume
float vwapSession = cumVolS > 0 ? cumPvS / cumVolS : hl2
 
bool  newWeek     = timeframe.change("W")
var float cumPvW  = 0.0
var float cumVolW = 0.0
if newWeek
    cumPvW  := 0.0
    cumVolW := 0.0
cumPvW  += hl2 * volume
cumVolW += volume
float vwapWeek = cumVolW > 0 ? cumPvW / cumVolW : hl2
 
bool  newMonth    = timeframe.change("M")
var float cumPvM  = 0.0
var float cumVolM = 0.0
if newMonth
    cumPvM  := 0.0
    cumVolM := 0.0
cumPvM  += hl2 * volume
cumVolM += volume
float vwapMonth = cumVolM > 0 ? cumPvM / cumVolM : hl2
 
// ┌───────────────────────────── BOSWaves ─ VWAP Filter & Speed Logic ───────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
vwapAgrees(bool bullish) =>
    bool s = bullish ? close >= vwapSession : close <= vwapSession
    bool w = bullish ? close >= vwapWeek    : close <= vwapWeek
    bool m = bullish ? close >= vwapMonth   : close <= vwapMonth
    switch filterPeriod
        "Session" => s
        "Week"    => w
        "Month"   => m
        "Any"     => s or w or m
        "All"     => s and w and m
        => true
 
float atr     = ta.atr(14)
float atrSlow = ta.sma(ta.tr, 100)
 
float refVwap = switch filterPeriod
    "Session" => vwapSession
    "Week"    => vwapWeek
    "Month"   => vwapMonth
    => vwapSession
 
float vwapDistNorm   = nz(atr, 1) > 0 ? math.min(math.abs(close - refVwap) / (nz(atr, 1) * 4), 1.0) : 0.0
float effectiveAccel = accelRate * (1.0 + (vwapAccelBoost - 1.0) * vwapDistNorm)
 
// ┌───────────────────────────── BOSWaves ─ Core Calculation ────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
var bool  trend    = true
var float arc      = na
var float velocity = 0.0
var bool  initDone = false
 
if not initDone and not na(atrSlow) and bar_index > 100
    arc      := low - atrSlow * startMult
    trend    := true
    initDone := true
 
if initDone
    if close < arc
        trend := false
    if close > arc
        trend := true
 
bool rawFlipped    = initDone and trend != trend[1]
bool flipConfirmed = rawFlipped and vwapAgrees(trend)
bool flipFiltered  = rawFlipped and not flipConfirmed
 
if rawFlipped and trend
    arc      := low - nz(atrSlow, 1) * startMult
    velocity := 0.0
 
if rawFlipped and not trend
    arc      := high + nz(atrSlow, 1) * startMult
    velocity := 0.0
 
float stepSize = nz(atrSlow, 1) * 0.15
 
if initDone and bar_index % smooth == 0
    velocity += effectiveAccel
    if trend
        arc += stepSize * velocity
    else
        arc -= stepSize * velocity
 
float arcSmooth = ta.sma(arc, smooth)
 
float outerRaw = trend ? arc + nz(atrSlow, 1) * 0.4 : arc - nz(atrSlow, 1) * 0.4
float outer    = ta.sma(outerRaw, smooth)
 
color trendClr = trend ? colUp : colDn
 
// ┌───────────────────────────── BOSWaves ─ Flip Levels ─────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
var flipLines  = array.new<line>()
var flipLevels = array.new<float>()
var flipBull   = array.new<bool>()
var flipLabels = array.new<label>()
 
string resolvedLabelSize = levelLabelSize == "auto"   ? size.auto   :
                           levelLabelSize == "small"  ? size.small  :
                           levelLabelSize == "normal" ? size.normal :
                           levelLabelSize == "large"  ? size.large  :
                           levelLabelSize == "huge"   ? size.huge   : size.tiny
 
if rawFlipped and showLevels
    float _price = trend ? low : high
    color _clr   = color.new(trendClr, levelTransp)
 
    _ln = line.new(bar_index, _price, bar_index + 1, _price,
         color = _clr,
         width = levelWidth,
         style = levelStyle == "Dotted" ? line.style_dotted :
                 levelStyle == "Solid"  ? line.style_solid  :
                 line.style_dashed)
 
    string _labelTxt = levelLabel ? str.tostring(_price, format.mintick) : ""
    _lbl = label.new(bar_index + 1, _price, _labelTxt,
         color     = color.new(trendClr, 80),
         textcolor = trendClr,
         style     = label.style_label_left,
         size      = resolvedLabelSize)
 
    flipLines.push(_ln)
    flipLevels.push(_price)
    flipBull.push(trend)
    flipLabels.push(_lbl)
 
    label.new(bar_index, _price, "◆",
         color     = color(na),
         textcolor = trendClr,
         style     = trend ? label.style_label_up : label.style_label_down,
         size      = size.tiny)
 
if flipLines.size() > 0
    for i = flipLines.size() - 1 to 0
        if i >= flipLines.size()
            break
        ln = flipLines.get(i)
        if na(ln)
            flipLines.remove(i)
            if i < flipLevels.size()
                flipLevels.remove(i)
            if i < flipBull.size()
                flipBull.remove(i)
            if i < flipLabels.size()
                lbl = flipLabels.get(i)
                if not na(lbl)
                    label.delete(lbl)
                flipLabels.remove(i)
            continue
 
        line.set_x2(ln, bar_index)
 
        float lvl   = flipLevels.get(i)
        bool isBull = flipBull.get(i)
 
        if i < flipLabels.size()
            lbl = flipLabels.get(i)
            if not na(lbl)
                label.set_x(lbl, bar_index)
 
        bool broken = isBull ? (close < lvl and barstate.isconfirmed) :
                               (close > lvl and barstate.isconfirmed)
        if broken
            line.delete(ln)
            flipLines.set(i, line(na))
            if i < flipLabels.size()
                lbl = flipLabels.get(i)
                if not na(lbl)
                    label.delete(lbl)
                flipLabels.set(i, label(na))
 
while flipLines.size() > maxLevels
    _old = flipLines.shift()
    if not na(_old)
        line.delete(_old)
    if flipLevels.size() > 0
        flipLevels.shift()
    if flipBull.size() > 0
        flipBull.shift()
    if flipLabels.size() > 0
        _oldLbl = flipLabels.shift()
        if not na(_oldLbl)
            label.delete(_oldLbl)
 
// ┌───────────────────────────── BOSWaves ─ Visualization ───────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
float arcPlotVal = initDone and not rawFlipped ? arcSmooth : na
float priceRef   = ta.sma(hl2, smooth * 5)
 
p1 = plot(arcPlotVal, "Arc", color.new(chart.fg_color, 60), 1, plot.style_linebr)
p2 = plot(priceRef, display = display.none, editable = false)
 
color fillClr = showCloud and initDone ? color.new(trendClr, 65) : na
fill(p1, p2, arcSmooth, priceRef, fillClr, color(na))
 
float distToArc  = not na(arcSmooth) ? math.abs(close - arcSmooth) : 0
float safAtr     = nz(atr, 1)
float distNorm   = safAtr > 0 ? math.min(distToArc / (safAtr * 3), 1.0) : 0.5
color gradCandle = showCandles ?
     color.from_gradient(distNorm, 0, 1, color.new(trendClr, 55), trendClr) : na
 
plotcandle(open, high, low, close, "Candles",
     gradCandle, gradCandle, bordercolor = gradCandle)
 
float arrowAtr   = nz(atr, nz(atrSlow, 1))
float bullArrowY = rawFlipped and trend     ? arcSmooth - arrowAtr * arrowOffset : na
float bearArrowY = rawFlipped and not trend ? arcSmooth + arrowAtr * arrowOffset : na
 
plotshape(bullArrowY, "Bull Flip",
     shape.triangleup, location.absolute, colUp, size = size.tiny)
plotshape(bullArrowY, "Bull Glow",
     shape.triangleup, location.absolute, color.new(colUp, 60), size = size.small)
 
plotshape(bearArrowY, "Bear Flip",
     shape.triangledown, location.absolute, colDn, size = size.tiny)
plotshape(bearArrowY, "Bear Glow",
     shape.triangledown, location.absolute, color.new(colDn, 60), size = size.small)
 
// ┌───────────────────────────── BOSWaves ─ Alerts ──────────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
 
alertcondition(flipConfirmed and trend,     "Bullish Flip (VWAP Confirmed)", "Arc Supertrend — Bullish flip confirmed by VWAP")
alertcondition(flipConfirmed and not trend, "Bearish Flip (VWAP Confirmed)", "Arc Supertrend — Bearish flip confirmed by VWAP")
alertcondition(flipFiltered  and trend,     "Bullish Flip (VWAP Filtered)",  "Arc Supertrend — Bullish flip, VWAP disagrees")
alertcondition(flipFiltered  and not trend, "Bearish Flip (VWAP Filtered)",  "Arc Supertrend — Bearish flip, VWAP disagrees")

← 返回列表