Power Order Blocks [ChartPrime]

ChartPrime · study · 282 行 · 点赞 2,844 · 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/
// © ChartPrime
//@version=6
 
indicator("Power Order Blocks [ChartPrime]", overlay=true, max_boxes_count=500, max_labels_count=500, max_lines_count=500)
 
// --------------------------------------------------------------------------------------------------------------------}
// 📌 𝙐𝙎𝙀𝙍 𝙄𝙉𝙋𝙐𝙏𝙎
// --------------------------------------------------------------------------------------------------------------------{
grp1 = "Order Block Settings"
maxBlocks   = 10
dispThresh  = input.float(0.5, title="Displacement Multiplier", step=0.1, group=grp1, tooltip="How much larger the engulfing candle must be to validate an OB.")
strLookback = 100
 
grp2 = "Styling"
bullColor   = input.color(#1bd37a, title="Bullish OB Color",  group=grp2)
bearColor   = input.color(#bc14e6, title="Bearish OB Color",  group=grp2)
borderColor = color.new(#ffffff, 100)
textColor   = input.color(color.new(#ffffff, 0),  title="Text Color",   group=grp2)
showEqLine  = input.bool(true, title="Show Equilibrium Line", group=grp2, tooltip="Draws a dashed midpoint line inside each Order Block.")
powerFade   = input.bool(true, title="Power Intensity",       group=grp2, tooltip="Higher power OBs appear more vivid; weaker OBs are more transparent.")
 
grp3 = "Signals"
showRetests = input.bool(true, title="Show Retest Labels", group=grp3, tooltip="Plots an arrow label when price taps into an active Order Block.")
 
// --------------------------------------------------------------------------------------------------------------------}
// 📌 𝙏𝙔𝙋𝙀𝙎
// --------------------------------------------------------------------------------------------------------------------{
type OBBlock
    box   bx
    box   infoBox
    line  eqLine
    int   touches
    int   birthBar
    float obTop
    float obBtm
    float powerPct
 
// --------------------------------------------------------------------------------------------------------------------}
// 📌 𝙄𝙉𝘿𝙄𝘾𝘼𝙏𝙊𝙍 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
// --------------------------------------------------------------------------------------------------------------------{
var OBBlock[] bullBlocks = array.new<OBBlock>()
var OBBlock[] bearBlocks = array.new<OBBlock>()
 
var int lastBullRetestBar = na
var int lastBearRetestBar = na
 
bool isBearishCandle = close[1] < open[1]
bool isBullishDisp   = close > open and close > high[1] and (close - open) > (high[1] - low[1]) * dispThresh
bool bullOB          = isBearishCandle and isBullishDisp
 
bool isBullishCandle = close[1] > open[1]
bool isBearishDisp   = close < open and close < low[1] and (open - close) > (high[1] - low[1]) * dispThresh
bool bearOB          = isBullishCandle and isBearishDisp
 
float maxCandleSize = ta.highest(high - low, strLookback)
float atr           = ta.atr(14) * 0.2
 
// Power % drives transparency: high power = low transp (vivid), low power = high transp (faded)
// Power 100% -> transp 60, Power 0% -> transp 92
calcPowerTransp(float powerPct) =>
    int transp = math.round(92 - (powerPct / 100.0) * 32)
    transp
 
buildLabel(int touches, float pct) =>
    "Power: " + str.tostring(math.round(pct)) + "%  |  Touches: " + str.tostring(touches)
 
bool bullRetestRaw = false
bool bearRetestRaw = false
 
// --- Update bullish blocks ---
int bullSize = array.size(bullBlocks)
if bullSize > 0
    for i = bullSize - 1 to 0
        OBBlock ob  = array.get(bullBlocks, i)
        float   btm = ob.obBtm
        float   top = ob.obTop
 
        if close < btm
            box.delete(ob.bx)
            box.delete(ob.infoBox)
            if not na(ob.eqLine)
                line.delete(ob.eqLine)
            array.remove(bullBlocks, i)
        else
            int transp = powerFade ? calcPowerTransp(ob.powerPct) : 80
            box.set_bgcolor(ob.bx, color.new(bullColor, transp))
            box.set_right(ob.bx, bar_index + 25)
 
            box.set_left(ob.infoBox,   bar_index)
            box.set_right(ob.infoBox,  bar_index + 25)
            box.set_top(ob.infoBox,    top)
            box.set_bottom(ob.infoBox, btm)
 
            if showEqLine and not na(ob.eqLine)
                line.set_x2(ob.eqLine, bar_index)
 
            if low[1] <= top and low >= top and bar_index > box.get_left(ob.bx)
                bullRetestRaw := true
                ob.touches    += 1
                float pct      = maxCandleSize > 0 ? ((top - btm) / maxCandleSize) * 100 : 0
                box.set_text(ob.infoBox, "Bullish OB\n" + buildLabel(ob.touches, pct))
 
// --- Update bearish blocks ---
int bearSize = array.size(bearBlocks)
if bearSize > 0
    for i = bearSize - 1 to 0
        OBBlock ob  = array.get(bearBlocks, i)
        float   top = ob.obTop
        float   btm = ob.obBtm
 
        if close > top
            box.delete(ob.bx)
            box.delete(ob.infoBox)
            if not na(ob.eqLine)
                line.delete(ob.eqLine)
            array.remove(bearBlocks, i)
        else
            int transp = powerFade ? calcPowerTransp(ob.powerPct) : 80
            box.set_bgcolor(ob.bx, color.new(bearColor, transp))
            box.set_right(ob.bx, bar_index + 25)
 
            box.set_left(ob.infoBox,   bar_index)
            box.set_right(ob.infoBox,  bar_index + 25)
            box.set_top(ob.infoBox,    top)
            box.set_bottom(ob.infoBox, btm)
 
            if showEqLine and not na(ob.eqLine)
                line.set_x2(ob.eqLine, bar_index)
 
            if high[1] >= btm and high <= btm and bar_index > box.get_left(ob.bx)
                bearRetestRaw := true
                ob.touches    += 1
                float pct      = maxCandleSize > 0 ? ((top - btm) / maxCandleSize) * 100 : 0
                box.set_text(ob.infoBox, "Bearish OB\n" + buildLabel(ob.touches, pct))
 
// Apply 10-bar gap filter
bool bullRetest = bullRetestRaw and (na(lastBullRetestBar) or bar_index - lastBullRetestBar >= 10)
bool bearRetest = bearRetestRaw and (na(lastBearRetestBar) or bar_index - lastBearRetestBar >= 10)
 
if bullRetest
    lastBullRetestBar := bar_index
if bearRetest
    lastBearRetestBar := bar_index
 
// --------------------------------------------------------------------------------------------------------------------}
// 📌 𝙑𝙄𝙎𝙐𝘼𝙇𝙄𝙕𝘼𝙏𝙄𝙊𝙉
// --------------------------------------------------------------------------------------------------------------------{
if bullOB
    float  obTop  = high[1]
    float  obBtm  = low[1]
    float  obMid  = math.avg(obTop, obBtm)
    int    obLeft = bar_index[1]
    float  pct    = maxCandleSize > 0 ? ((obTop - obBtm) / maxCandleSize) * 100 : 0
    string lbl    = "Bullish OB\n" + buildLabel(0, pct)
    int    transp = powerFade ? calcPowerTransp(pct) : 80
 
    if array.size(bullBlocks) > 0
        for i = array.size(bullBlocks) - 1 to 0
            OBBlock old = array.get(bullBlocks, i)
            if obTop >= old.obBtm and obBtm <= old.obTop
                box.delete(old.bx)
                box.delete(old.infoBox)
                if not na(old.eqLine)
                    line.delete(old.eqLine)
                array.remove(bullBlocks, i)
 
    box newBx = box.new(obLeft, obTop, bar_index, obBtm,
         border_color = borderColor,
         border_style = line.style_dashed,
         bgcolor      = color.new(bullColor, transp))
 
    box infoBx = box.new(bar_index, obTop, bar_index + 25, obBtm,
         border_color = color.new(bullColor, 40),
         border_style = line.style_solid,
         bgcolor      = color.new(bullColor, 92),
         text         = lbl,
         text_color   = textColor,
         text_size    = size.auto,
         text_halign  = text.align_center,
         text_valign  = text.align_center)
 
    line eqL = na
    if showEqLine
        eqL := line.new(obLeft, obMid, bar_index, obMid,
             color = color.new(bullColor, 40),
             style = line.style_solid,
             width = 1)
 
    array.push(bullBlocks, OBBlock.new(newBx, infoBx, eqL, 0, bar_index, obTop, obBtm, pct))
 
    int bullCount = array.size(bullBlocks)
    if bullCount > maxBlocks
        int trim = bullCount - maxBlocks
        for _i = 0 to trim - 1
            if array.size(bullBlocks) > 0
                OBBlock old = array.shift(bullBlocks)
                box.delete(old.bx)
                box.delete(old.infoBox)
                if not na(old.eqLine)
                    line.delete(old.eqLine)
 
if bearOB
    float  obTop  = high[1]
    float  obBtm  = low[1]
    float  obMid  = math.avg(obTop, obBtm)
    int    obLeft = bar_index[1]
    float  pct    = maxCandleSize > 0 ? ((obTop - obBtm) / maxCandleSize) * 100 : 0
    string lbl    = "Bearish OB\n" + buildLabel(0, pct)
    int    transp = powerFade ? calcPowerTransp(pct) : 80
 
    if array.size(bearBlocks) > 0
        for i = array.size(bearBlocks) - 1 to 0
            OBBlock old = array.get(bearBlocks, i)
            if obTop >= old.obBtm and obBtm <= old.obTop
                box.delete(old.bx)
                box.delete(old.infoBox)
                if not na(old.eqLine)
                    line.delete(old.eqLine)
                array.remove(bearBlocks, i)
 
    box newBx = box.new(obLeft, obTop, bar_index, obBtm,
         border_color = borderColor,
         border_style = line.style_dashed,
         bgcolor      = color.new(bearColor, transp))
 
    box infoBx = box.new(bar_index, obTop, bar_index + 25, obBtm,
         border_color = color.new(bearColor, 40),
         border_style = line.style_solid,
         bgcolor      = color.new(bearColor, 92),
         text         = lbl,
         text_color   = textColor,
         text_size    = size.auto,
         text_halign  = text.align_center,
         text_valign  = text.align_center)
 
    line eqL = na
    if showEqLine
        eqL := line.new(obLeft, obMid, bar_index, obMid,
             color = color.new(bearColor, 40),
             style = line.style_solid,
             width = 1)
 
    array.push(bearBlocks, OBBlock.new(newBx, infoBx, eqL, 0, bar_index, obTop, obBtm, pct))
 
    int bearCount = array.size(bearBlocks)
    if bearCount > maxBlocks
        int trim = bearCount - maxBlocks
        for _i = 0 to trim - 1
            if array.size(bearBlocks) > 0
                OBBlock old = array.shift(bearBlocks)
                box.delete(old.bx)
                box.delete(old.infoBox)
                if not na(old.eqLine)
                    line.delete(old.eqLine)
 
// --- Retest labels ---
if showRetests and bullRetest
    label.new(
         x         = bar_index,
         y         = low - atr,
         text      = "⇡",
         style     = label.style_label_up,
         color     = color.new(bullColor, 100),
         textcolor = bullColor,
         size      = size.large)
 
if showRetests and bearRetest
    label.new(
         x         = bar_index,
         y         = high + atr,
         text      = "⇣",
         style     = label.style_label_down,
         color     = color.new(bearColor, 100),
         textcolor = bearColor,
         size      = size.large)
 
// --- Alerts ---
alertcondition(bullRetest, title="Bullish OB Retest", message="Price retested a Bullish Order Block.")
alertcondition(bearRetest, title="Bearish OB Retest", message="Price retested a Bearish Order Block.")
 
// --------------------------------------------------------------------------------------------------------------------}

← 返回列表