Also Like

IZAKI 0.618 TRADING ZONE
Advertisement

Modjoy-Adaptive Support and Resistance Zones [BigBeluga]

Modjoy-Adaptive Support and Resistance Zones: A Revolutionary Trading Strategy by BigBeluga

The foreign exchange market is a complex and dynamic environment where traders need to adapt quickly to changing market conditions. One of the most effective ways to navigate this landscape is by using support and resistance zones, which can help traders identify potential areas of buying and selling opportunities. In this article, we will explore the Modjoy-Adaptive Support and Resistance Zones strategy developed by BigBeluga, a renowned trading expert.

Introduction to Support and Resistance Zones

Support and resistance zones are areas on a chart where the price of an asset has historically bounced back or reversed direction. These zones can be used to identify potential areas of buying and selling opportunities, as well as to set stop-loss and take-profit levels. However, traditional support and resistance zones can be limited by their static nature, failing to account for changing market conditions and volatility.

The Modjoy-Adaptive Approach

The Modjoy-Adaptive Support and Resistance Zones strategy developed by BigBeluga addresses the limitations of traditional support and resistance zones by incorporating adaptive and dynamic elements. This approach uses a combination of technical indicators and algorithms to identify and adjust support and resistance zones in real-time, taking into account changes in market volatility, trend direction, and other factors.

Key Components of the Modjoy-Adaptive Strategy

The Modjoy-Adaptive Support and Resistance Zones strategy consists of the following key components:

  • Adaptive Zone Calculation: The strategy uses a proprietary algorithm to calculate support and resistance zones based on historical price data and market volatility.
  • Dynamic Zone Adjustment: The zones are adjusted in real-time to reflect changes in market conditions, such as shifts in trend direction or changes in volatility.
  • Multi-Time Frame Analysis: The strategy incorporates analysis of multiple time frames to provide a more comprehensive view of market conditions and to identify potential trading opportunities.

Benefits of the Modjoy-Adaptive Strategy

The Modjoy-Adaptive Support and Resistance Zones strategy offers several benefits to traders, including:

  • Improved Accuracy: The adaptive and dynamic nature of the strategy allows for more accurate identification of support and resistance zones.
  • Increased Flexibility: The strategy can be applied to various markets and time frames, making it a versatile tool for traders.
  • Enhanced Risk Management: The strategy provides traders with a more effective way to manage risk by identifying potential areas of support and resistance.

Conclusion

The Modjoy-Adaptive Support and Resistance Zones strategy developed by BigBeluga is a powerful tool for traders looking to improve their trading performance. By incorporating adaptive and dynamic elements, this strategy provides a more accurate and effective way to identify support and resistance zones, ultimately leading to better trading decisions and improved risk management. Whether you are a seasoned trader or just starting out, the Modjoy-Adaptive strategy is definitely worth considering as part of your trading arsenal.


Exclusive Source Code: Modjoy-Adaptive Support and Resistance Zones [BigBeluga]

MODJOY-ADAPTIVE SUPPORT AND RESISTANCE ZONES [BIGBELUGA] SOURCE CODE
// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International  

//@version=6
indicator("Modjoy-Adaptive Support and Resistance Zones [BigBeluga]", shorttitle="Adaptive S/R [BigBeluga]", overlay=true, max_lines_count=500, max_labels_count=200, max_boxes_count=200)

// INPUTS ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{

var grpSwing = "Swing Detection"
pivotLen     = input.int(5,   "Pivot Length",      minval=2, maxval=50,   group=grpSwing, tooltip="The number of bars on each side of a high or low to confirm a pivot point.")
minStrength  = input.float(0.1, "Min ATR Strength", minval=0.0, maxval=5.0, step=0.05, group=grpSwing, tooltip="Minimum distance required between the pivot and its neighbors.")
maxAgeBars   = input.int(300, "Max Level Age (bars)", minval=20, maxval=2000, group=grpSwing, tooltip="Maximum bars a level exists before removal. Also used to calculate longevity scaling.")

var grpLevels = "Levels"
showSupport  = input.bool(true,  "Show Support Levels",    group=grpLevels)
showResist   = input.bool(true,  "Show Resistance Levels", group=grpLevels)
maxLevels    = input.int(5,      "Max Active Levels Each", minval=1, maxval=20, group=grpLevels)
mergeThresh  = input.float(0.5,  "Merge Threshold (ATR x)", minval=0.0, maxval=3.0, step=0.05, group=grpLevels)
showZones    = input.bool(true,  "Show Level Zones",       group=grpLevels)
zoneWidth    = input.float(0.25, "Zone Width (ATR x)",     minval=0.05, maxval=2.0, step=0.05, group=grpLevels)

var grpBreak = "Breakouts"
showBroken   = input.bool(true,  "Show Broken Levels",         group=grpBreak)
breakSens    = input.float(0.1,  "Break Sensitivity (ATR x)",  minval=0.0, maxval=2.0, step=0.05, group=grpBreak)
showBreakLbl = input.bool(true,  "Show Break Labels",          group=grpBreak)
maxBroken    = input.int(4,      "Max Broken Levels Shown",    minval=0, maxval=20, group=grpBreak)

var grpVis = "Visuals"
supColor     = input.color(color.new(#22bac5, 0),  "Support Color",         group=grpVis)
resColor     = input.color(color.new(#ff6f43, 0),  "Resistance Color",      group=grpVis)
brokenColor  = input.color(color.new(#94a3b8, 0),  "Broken Level Color",    group=grpVis)
lineWidth    = input.int(2, "Base Line Width",     minval=1, maxval=5,      group=grpVis, tooltip="Used when Longevity Scaling is OFF.")

//  NEW LONGEVITY INPUTS 
useDynamicWidth = input.bool(true, "Enable Longevity Width", group=grpVis, tooltip="When enabled, older levels become thicker over time.")
maxLineWidth    = input.int(7, "Max Longevity Width", minval=1, maxval=10, group=grpVis, tooltip="The maximum thickness an old level can reach.")

showDash     = input.bool(true, "Show Dashboard",   group=grpVis)
showPriceLbl = input.bool(true, "Show Price Labels on Active Levels", group=grpVis)

var grpDash = "Dashboard"
dashPos      = input.string("Bottom Right", "Dashboard Position", options=["Top Right","Bottom Right","Top Left","Bottom Left"], group=grpDash)

// }
// CALCULATIONS――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{

type SRLevel
    float  price
    int    barStart
    int    levelType
    bool   active
    bool   broken
    int    breakBar
    bool   retested
    line   mainLine
    box    zoneBox
    label  breakLabel
    label  priceLabel

var array activeLevels = array.new()
var array brokenLevels = array.new()
var string         lastBreakDir = "—"
var int            lastBreakBar = na

atrVal  = ta.atr(14)
atrSafe = na(atrVal) or atrVal == 0 ? syminfo.mintick * 10 : atrVal

ph = ta.pivothigh(high, pivotLen, pivotLen)
pl = ta.pivotlow(low,   pivotLen, pivotLen)

f_isTooClose(_price, _type) =>
    bool tooClose = false
    int  sz = array.size(activeLevels)
    if sz > 0
        for i = 0 to sz - 1
            lvl = array.get(activeLevels, i)
            if lvl.levelType == _type and lvl.active
                if math.abs(lvl.price - _price) < mergeThresh * atrSafe
                    tooClose := true
                    break
    tooClose

f_addLevel(_price, _type, _barIdx) =>
    if not f_isTooClose(_price, _type)
        int sz  = array.size(activeLevels)
        int cnt = 0
        if sz > 0
            for i = 0 to sz - 1
                lvl = array.get(activeLevels, i)
                if lvl.levelType == _type and lvl.active
                    cnt += 1

        if cnt < maxLevels
            _baseColor = _type == 1 ? resColor : supColor
            _zoneTop   = _price + zoneWidth * atrSafe * 0.5
            _zoneBot   = _price - zoneWidth * atrSafe * 0.5

            newLine = line.new(
                 x1     = _barIdx,
                 y1     = _price,
                 x2     = _barIdx + 1,
                 y2     = _price,
                 extend = extend.right,
                 color  = color.new(_baseColor, 0),
                 width  = lineWidth,
                 style  = line.style_solid
             )

            newBox = showZones ? box.new(
                 left         = _barIdx,
                 top          = _zoneTop,
                 right        = _barIdx + 1,
                 bottom       = _zoneBot,
                 border_color = color.new(_baseColor, 90),
                 bgcolor      = color.new(_baseColor, 88),
                 extend       = extend.right
             ) : na

            newPriceLbl = showPriceLbl ? label.new(
                 x         = bar_index + 20,
                 y         = _price,
                 text      = str.tostring(_price, format.mintick),
                 style     = label.style_label_center,
                 textcolor = _baseColor,
                 color     = color.new(chart.bg_color, 0),
                 size      = size.small
             ) : na

            array.push(activeLevels, SRLevel.new(
                 price      = _price,
                 barStart   = _barIdx,
                 levelType  = _type,
                 active     = true,
                 broken     = false,
                 breakBar   = na,
                 retested   = false,
                 mainLine   = newLine,
                 zoneBox    = newBox,
                 breakLabel = na,
                 priceLabel = newPriceLbl
             ))

f_pivotStrong(_price, _type) =>
    bool strong = true
    if minStrength > 0
        if _type == 1
            nearHigh = math.max(high[pivotLen - 1], high[pivotLen + 1])
            if (_price - nearHigh) < minStrength * atrSafe
                strong := false
        else
            nearLow = math.min(low[pivotLen - 1], low[pivotLen + 1])
            if (nearLow - _price) < minStrength * atrSafe
                strong := false
    strong

// Prune old levels
int pruneSize = array.size(activeLevels)
if pruneSize > 0
    for i = pruneSize - 1 to 0
        if i < array.size(activeLevels)
            lvl = array.get(activeLevels, i)
            if lvl.active and (bar_index - lvl.barStart) > maxAgeBars
                line.delete(lvl.mainLine)
                if not na(lvl.zoneBox)
                    box.delete(lvl.zoneBox)
                if not na(lvl.priceLabel)
                    label.delete(lvl.priceLabel)
                array.remove(activeLevels, i)

// Add new pivots
if not na(ph) and showResist
    if f_pivotStrong(ph, 1)
        f_addLevel(ph, 1, bar_index - pivotLen)

if not na(pl) and showSupport
    if f_pivotStrong(pl, -1)
        f_addLevel(pl, -1, bar_index - pivotLen)

// Breakout logic
int activeSize = array.size(activeLevels)
if activeSize > 0
    for i = activeSize - 1 to 0
        if i >= array.size(activeLevels)
            continue
        lvl = array.get(activeLevels, i)
        if not lvl.active
            continue

        breakBuffer = breakSens * atrSafe

        if lvl.levelType == 1 and close > lvl.price + breakBuffer
            lvl.active   := false
            lvl.broken   := true
            lvl.breakBar := bar_index
            lastBreakDir := "Bullish"
            lastBreakBar := bar_index

            if not na(lvl.priceLabel)
                label.delete(lvl.priceLabel)
                lvl.priceLabel := na

            line.set_color(lvl.mainLine,  color.new(brokenColor, 0))
            line.set_style(lvl.mainLine,  line.style_dotted)
            line.set_width(lvl.mainLine,  1)
            line.set_extend(lvl.mainLine, extend.none)
            line.set_x2(lvl.mainLine,     bar_index)

            if not na(lvl.zoneBox)
                box.set_bgcolor(lvl.zoneBox,       color.new(brokenColor, 93))
                box.set_border_color(lvl.zoneBox,  color.new(brokenColor, 100))
                box.set_extend(lvl.zoneBox,        extend.none)
                box.set_right(lvl.zoneBox,         bar_index)
                mid = math.avg(lvl.zoneBox.get_top(), lvl.zoneBox.get_bottom())
                lvl.zoneBox.set_top(mid + breakBuffer)
                lvl.zoneBox.set_bottom(mid - breakBuffer)
                
            if showBreakLbl
                lvl.breakLabel := label.new(
                     x         = bar_index,
                     y         = lvl.price,
                     text      = "< Break",
                     style     = label.style_label_left,
                     textcolor = supColor,
                     color     = color.new(#22c55e, 100),
                     size      = size.small
                 )

            if showBroken
                array.push(brokenLevels, lvl)
                if array.size(brokenLevels) > maxBroken and array.size(brokenLevels) > 0
                    old = array.shift(brokenLevels)
                    if not na(old.mainLine)
                        line.delete(old.mainLine)
                    if not na(old.zoneBox)
                        box.delete(old.zoneBox)
                    if not na(old.breakLabel)
                        label.delete(old.breakLabel)
            else
                line.delete(lvl.mainLine)
                
                if not na(lvl.zoneBox)
                    box.delete(lvl.zoneBox)

            array.remove(activeLevels, i)

        else if lvl.levelType == -1 and close < lvl.price - breakBuffer
            lvl.active   := false
            lvl.broken   := true
            lvl.breakBar := bar_index
            lastBreakDir := "Bearish"
            lastBreakBar := bar_index

            if not na(lvl.priceLabel)
                label.delete(lvl.priceLabel)
                lvl.priceLabel := na

            line.set_color(lvl.mainLine,  color.new(brokenColor, 0))
            line.set_style(lvl.mainLine,  line.style_dotted)
            line.set_width(lvl.mainLine,  1)
            line.set_extend(lvl.mainLine, extend.none)
            line.set_x2(lvl.mainLine,     bar_index)

            if not na(lvl.zoneBox)
                box.set_bgcolor(lvl.zoneBox,       color.new(brokenColor, 93))
                box.set_border_color(lvl.zoneBox,  color.new(brokenColor, 100))
                box.set_extend(lvl.zoneBox,        extend.none)
                box.set_right(lvl.zoneBox,         bar_index)
                mid = math.avg(lvl.zoneBox.get_top(), lvl.zoneBox.get_bottom())
                lvl.zoneBox.set_top(mid + breakBuffer)
                lvl.zoneBox.set_bottom(mid - breakBuffer)
                
            if showBreakLbl
                lvl.breakLabel := label.new(
                     x         = bar_index,
                     y         = lvl.price,
                     text      = "< Break",
                     style     = label.style_label_left,
                     textcolor = resColor,
                     color     = color.new(#ef4444, 100),
                     size      = size.small
                 )

            if showBroken
                array.push(brokenLevels, lvl)
                if array.size(brokenLevels) > maxBroken and array.size(brokenLevels) > 0
                    old = array.shift(brokenLevels)
                    if not na(old.mainLine)
                        line.delete(old.mainLine)
                    if not na(old.zoneBox)
                        box.delete(old.zoneBox)
                    if not na(old.breakLabel)
                        label.delete(old.breakLabel)
            else
                line.delete(lvl.mainLine)
                if not na(lvl.zoneBox)
                    box.delete(lvl.zoneBox)

            array.remove(activeLevels, i)

// }
// PLOT ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{

// Extend visuals on active levels
int extSize = array.size(activeLevels)
if extSize > 0
    for i = 0 to extSize - 1
        lvl = array.get(activeLevels, i)
        if lvl.active
            //  DYNAMIC LONGEVITY WIDTH CALCULATION 
            if useDynamicWidth
                age = bar_index - lvl.barStart
                // Scale width from 1 to maxLineWidth based on maxAgeBars
                calcWidth = math.min(maxLineWidth, 1 + math.floor((age / maxAgeBars) * (maxLineWidth - 1)))
                line.set_width(lvl.mainLine, int(calcWidth))
            else
                line.set_width(lvl.mainLine, lineWidth)

            line.set_x2(lvl.mainLine, bar_index + 1)
            if not na(lvl.zoneBox)
                box.set_right(lvl.zoneBox, bar_index + 1)
            if showPriceLbl and not na(lvl.priceLabel)
                label.set_x(lvl.priceLabel, bar_index + 10)

var float nearestSup = na
var float nearestRes = na

nearestSup := na
nearestRes := na

// Dashboard scanning
int dashScanSize = array.size(activeLevels)
if dashScanSize > 0
    for i = 0 to dashScanSize - 1
        lvl = array.get(activeLevels, i)
        if not lvl.active
            continue
        if lvl.levelType == -1 and lvl.price < close
            if na(nearestSup) or lvl.price > nearestSup
                nearestSup := lvl.price
        if lvl.levelType == 1 and lvl.price > close
            if na(nearestRes) or lvl.price < nearestRes
                nearestRes := lvl.price

// Draw Dashboard
var table dashTable = na

if showDash
    tablePos = switch dashPos
        "Top Right"    => position.top_right
        "Bottom Right" => position.bottom_right
        "Top Left"     => position.top_left
        "Bottom Left"  => position.bottom_left
        => position.bottom_right

    if barstate.isfirst
        dashTable := table.new(
             position     = tablePos,
             columns      = 2,
             rows         = 5,
             bgcolor      = color.new(#0d1117, 5),
             border_color = color.new(#30363d, 40),
             border_width = 1,
             frame_color  = color.new(#30363d, 20),
             frame_width  = 1
         )

    if barstate.islast and not na(dashTable)
        table.cell(dashTable, 0, 0, "S/R Dashboard", text_color=color.new(#f0f6fc, 0), text_size=size.normal, bgcolor=color.new(#161b22, 0), text_halign=text.align_center)
        table.merge_cells(dashTable, 0, 0, 1, 0)

        table.cell(dashTable, 0, 1, "Resistance", text_color=color.new(#8b949e, 0), text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_left)
        table.cell(dashTable, 1, 1,
             na(nearestRes) ? "—" : str.tostring(nearestRes, format.mintick),
             text_color  = na(nearestRes) ? color.new(#484f58, 0) : resColor,
             text_size   = size.normal,
             bgcolor     = color.new(#0d1117, 10),
             text_halign = text.align_right
         )

        table.cell(dashTable, 0, 2, "Support", text_color=color.new(#8b949e, 0), text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_left)
        table.cell(dashTable, 1, 2,
             na(nearestSup) ? "—" : str.tostring(nearestSup, format.mintick),
             text_color  = na(nearestSup) ? color.new(#484f58, 0) : supColor,
             text_size   = size.normal,
             bgcolor     = color.new(#0d1117, 10),
             text_halign = text.align_right
         )

        table.cell(dashTable, 0, 3, "Last Break", text_color=color.new(#8b949e, 0), text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_left)
        breakDirColor = lastBreakDir == "Bullish" ? supColor : lastBreakDir == "Bearish" ? resColor : color.new(#484f58, 0)
        table.cell(dashTable, 1, 3, lastBreakDir, text_color=breakDirColor, text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_right)

        activeCnt = array.size(activeLevels)
        table.cell(dashTable, 0, 4, "Active Levels", text_color=color.new(#8b949e, 0), text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_left)
        table.cell(dashTable, 1, 4, str.tostring(activeCnt), text_color=color.new(#f0f6fc, 0), text_size=size.normal, bgcolor=color.new(#0d1117, 10), text_halign=text.align_right)

// }