Market Structure- Zig Zag, BoS, Supply/Demand and Inflection Zones

The_Forex_Steward · study · 271 行 · 点赞 6,010 · 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/
// © The_Forex_Steward
 
//@version=6
indicator("Market Structure- ZigZag, Break of Structure & Order Blocks", overlay=true)
 
// === User Inputs ===
showBullishOrderBlocks = input.bool(true, title="Show Bullish Order Blocks (Green)")
showBearishOrderBlocks = input.bool(true, title="Show Bearish Order Blocks (Red)")
orderBlockDuration = 20
deleteMitigatedBoxes = input.bool(true, title="Delete Mitigated Boxes")
internalShiftMode = input.string("High/Low", title="Calculate Internal Shift By", options=["Open", "High/Low"])
bullishBlockColor = input.color(color.rgb(76, 175, 79, 75), title="Bullish Order Block Fill Color")
bearishBlockColor = input.color(color.rgb(255, 82, 82, 75), title="Bearish Order Block Fill Color")
bullishBorderColor = input.color(color.rgb(76, 175, 79), title="Bullish Order Block Border Color")
bearishBorderColor = input.color(color.rgb(255, 82, 82), title="Bearish Order Block Border Color")
 
// === Variables to Track State ===
var float lastBearishHigh = na
var float lastBearishLow = na
var int lastBearishBarIndex = na
var bool bearishBroken = true
 
var float lastBullishHigh = na
var float lastBullishLow = na
var int lastBullishBarIndex = na
var bool bullishBroken = true
 
isBearish = close < open
isBullish = close > open
 
// === Track latest box objects ===
var box[] bullishBoxes = array.new<box>()
var box[] bearishBoxes = array.new<box>()
 
// === Capture Candle State ===
if isBearish
    lastBearishHigh := high
    lastBearishLow := low
    lastBearishBarIndex := bar_index
    bearishBroken := false
 
if isBullish
    lastBullishLow := low
    lastBullishHigh := high
    lastBullishBarIndex := bar_index
    bullishBroken := false
 
// === Break Conditions ===
bullishBreak = not bearishBroken and close > lastBearishHigh
bearishBreak = not bullishBroken and close < lastBullishLow
 
if bullishBreak
    bearishBroken := true
if bearishBreak
    bullishBroken := true
 
// === Plot Engulfment Triangles ===
plotshape(bullishBreak, title="Bullish Engulfment", location=location.belowbar, color=color.rgb(76, 175, 79), style=shape.triangleup, size=size.tiny)
plotshape(bearishBreak, title="Bearish Engulfment", location=location.abovebar, color=color.rgb(255, 82, 82), style=shape.triangledown, size=size.tiny)
 
// === Delete invalidated boxes ===
if array.size(bullishBoxes) > 0
    for i = array.size(bullishBoxes) - 1 to 0
        boxItem = array.get(bullishBoxes, i)
        if low < box.get_bottom(boxItem)
            box.delete(boxItem)
            array.remove(bullishBoxes, i)
 
if array.size(bearishBoxes) > 0
    for i = array.size(bearishBoxes) - 1 to 0
        boxItem = array.get(bearishBoxes, i)
        if high > box.get_top(boxItem)
            box.delete(boxItem)
            array.remove(bearishBoxes, i)
 
// === Delete mitigated boxes (optional) ===
var bool bullishMitigated = false
var bool bearishMitigated = false
 
bullishMitigated := false
bearishMitigated := false
 
if deleteMitigatedBoxes
    if array.size(bullishBoxes) > 0
        for i = array.size(bullishBoxes) - 1 to 0
            boxItem = array.get(bullishBoxes, i)
            if low < box.get_top(boxItem)
                bullishMitigated := true
                box.delete(boxItem)
                array.remove(bullishBoxes, i)
    if array.size(bearishBoxes) > 0
        for i = array.size(bearishBoxes) - 1 to 0
            boxItem = array.get(bearishBoxes, i)
            if high > box.get_bottom(boxItem)
                bearishMitigated := true
                box.delete(boxItem)
                array.remove(bearishBoxes, i)
 
// === Draw New Order Blocks ===
if showBullishOrderBlocks and bullishBreak and not na(lastBearishBarIndex)
    bullishBox = box.new(left=lastBearishBarIndex, right=bar_index + orderBlockDuration, top=lastBearishHigh, bottom=lastBearishLow, border_color=bullishBorderColor, bgcolor=bullishBlockColor)
    array.push(bullishBoxes, bullishBox)
 
if showBearishOrderBlocks and bearishBreak and not na(lastBullishBarIndex)
    bearishBox = box.new(left=lastBullishBarIndex, right=bar_index + orderBlockDuration, top=lastBullishHigh, bottom=lastBullishLow, border_color=bearishBorderColor, bgcolor=bearishBlockColor)
    array.push(bearishBoxes, bearishBox)
 
// === Internal Structure Logic ===
var int bullishCount = 0
var int bearishCount = 0
var float lowestBullishPrice = na
var float highestBearishPrice = na
var float firstBullishOpen = na
var float firstBearishOpen = na
var int lastInternalShift = 0
 
if isBullish
    bullishCount += 1
    bearishCount := 0
    if bullishCount == 1 or low < lowestBullishPrice
        lowestBullishPrice := low
    if bullishCount == 1
        firstBullishOpen := open
else if isBearish
    bearishCount += 1
    bullishCount := 0
    if bearishCount == 1 or high > highestBearishPrice
        highestBearishPrice := high
    if bearishCount == 1
        firstBearishOpen := open
else
    bullishCount := 0
    bearishCount := 0
    lowestBullishPrice := na
    highestBearishPrice := na
 
// === Determine Internal Shift Based on User Input ===
internalShiftBearish = internalShiftMode == "Open" ? close < firstBullishOpen : close < lowestBullishPrice
internalShiftBullish = internalShiftMode == "Open" ? close > firstBearishOpen : close > highestBearishPrice
 
allowInternalShiftBearish = internalShiftBearish and lastInternalShift != -1
allowInternalShiftBullish = internalShiftBullish and lastInternalShift != 1
 
var bool plotBearishInternalShift = false
var bool plotBullishInternalShift = false
plotBearishInternalShift := false
plotBullishInternalShift := false
 
if allowInternalShiftBearish
    plotBearishInternalShift := true
    lastInternalShift := -1
 
if allowInternalShiftBullish
    plotBullishInternalShift := true
    lastInternalShift := 1
 
// === Plot internal shift markers ===
plotshape(plotBullishInternalShift, title="Bullish Internal Shift", location=location.belowbar, color=color.black, style=shape.triangleup, size=size.tiny)
plotshape(plotBearishInternalShift, title="Bearish Internal Shift", location=location.abovebar, color=color.black, style=shape.triangledown, size=size.tiny)
 
// === Persistent variables for multiple line handling ===
var line[] zigzagLines = array.new<line>()
var int lastBearishShiftBar = na
var int lastBullishShiftBar = na
var float lastZigzagPrice = na  // Keeps track of the last plotted price for zigzag
var int lastLowIndex = na       // Stores index of last low in zigzag
var int lastHighIndex = na      // Stores index of last high in zigzag
var float lastSwingHigh = na
var float lastSwingLow = na
 
// Save shift bar indices
if plotBearishInternalShift
    lastBearishShiftBar := bar_index
if plotBullishInternalShift
    lastBullishShiftBar := bar_index
 
// Bearish shift followed by Bullish shift → Track lowest low
if plotBullishInternalShift and not na(lastBearishShiftBar)
    shiftLength = bar_index - lastBearishShiftBar
    if shiftLength <= 10000
        lowest = low
        lowIndex = bar_index
        for i = 0 to shiftLength
            if low[i] < lowest
                lowest := low[i]
                lowIndex := bar_index - i
 
        // Plot zigzag line
        if not na(lastZigzagPrice)
            zigzagLine = line.new(x1=lastHighIndex, y1=lastZigzagPrice, x2=lowIndex, y2=lowest, color=color.black, width=3)
            array.push(zigzagLines, zigzagLine)
 
        lastZigzagPrice := lowest
        lastSwingLow := lowest  // Save last swing low
        lastBearishShiftBar := bar_index
        lastLowIndex := lowIndex
 
 
// Bullish shift followed by Bearish shift → Track highest high
if plotBearishInternalShift and not na(lastBullishShiftBar)
    shiftLength = bar_index - lastBullishShiftBar
    if shiftLength <= 10000
        highest = high
        highIndex = bar_index
        for i = 0 to shiftLength
            if high[i] > highest
                highest := high[i]
                highIndex := bar_index - i
 
        // Plot zigzag line
        if not na(lastZigzagPrice)
            zigzagLine = line.new(x1=lastLowIndex, y1=lastZigzagPrice, x2=highIndex, y2=highest, color=color.black, width=3)
            array.push(zigzagLines, zigzagLine)
 
        lastZigzagPrice := highest
        lastSwingHigh := highest  // Save last swing high
        lastBullishShiftBar := bar_index
        lastHighIndex := highIndex
 
// === Track Break of Structure (BOS) markers ===
// Initialize flags as mutable `var` variables
var bool plotBullishBOS = false
var bool plotBearishBOS = false
 
// === Conditions to plot the BOS markers ===
// Bullish BOS (Only plot the first candle breaking the swing high)
if not na(lastSwingHigh) and close > lastSwingHigh and not plotBullishBOS
    plotBullishBOS := true  // Set the flag to true after the first BOS
    // No need for plotshape here since we plot it below in the global scope
 
// Bearish BOS (Only plot the first candle breaking the swing low)
if not na(lastSwingLow) and close < lastSwingLow and not plotBearishBOS
    plotBearishBOS := true  // Set the flag to true after the first BOS
    // No need for plotshape here since we plot it below in the global scope
 
// === Plot Break of Structure (BOS) with horizontal lines ===
 
// Modify these flags
var line bullishBOSLine = na
var line bearishBOSLine = na
 
// === Plot Break of Structure (BOS) with horizontal lines ===
 
// === Conditions to plot the BOS markers ===
// Bullish BOS (Only plot the first candle breaking the swing high)
if not na(lastSwingHigh) and close > lastSwingHigh and na(bullishBOSLine)
    // Draw horizontal line from the last swing high to the current price (breaking candle)
    bullishBOSLine := line.new(x1=lastHighIndex, y1=lastSwingHigh, x2=bar_index, y2=lastSwingHigh, color=color.green, width=3, style=line.style_dotted)
    
// Bearish BOS (Only plot the first candle breaking the swing low)
if not na(lastSwingLow) and close < lastSwingLow and na(bearishBOSLine)
    // Draw horizontal line from the last swing low to the current price (breaking candle)
    bearishBOSLine := line.new(x1=lastLowIndex, y1=lastSwingLow, x2=bar_index, y2=lastSwingLow, color=color.red, width=3, style=line.style_dotted)
 
// Optionally reset lines after new swings are formed, if needed
if close < lastSwingHigh
    bullishBOSLine := na  // Reset bullish BOS line when a new swing high is formed
 
if close > lastSwingLow
    bearishBOSLine := na  // Reset bearish BOS line when a new swing low is formed
 
// === Alerts ===
alertcondition(bullishBreak, title="Bullish Engulfment", message="Bullish engulfment! New order block available.")
alertcondition(bearishBreak, title="Bearish Engulfment", message="Bearish engulfment! New order block available.")
alertcondition(plotBullishInternalShift, title="Bullish Internal Shift", message="Bullish Internal Shift detected! Update your swing low.")
alertcondition(plotBearishInternalShift, title="Bearish Internal Shift", message="Bearish Internal Shift detected! Update your swing high.")
alertcondition(not na(lastSwingHigh) and close > lastSwingHigh, title="Bullish Break of Structure", message="Bullish Break of Structure detected!")
alertcondition(not na(lastSwingLow) and close < lastSwingLow, title="Bearish Break of Structure", message="Bearish Break of Structure detected!")
alertcondition(bullishMitigated, title="Bullish Order Block Mitigated", message="Bullish Order Block has been mitigated!")
alertcondition(bearishMitigated, title="Bearish Order Block Mitigated", message="Bearish Order Block has been mitigated!")

← 返回列表