Indicator · Pine Script v6 · Own pane

Market Pressure Scale [WavesUnchained]

by casoon

Market Pressure Scale plots two oscillator curves in a separate pane.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code431
Settings21inputs
LicenceMIT
Last update3 days ago27 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

431 lines of Pine Script v6 from indicators/momentum/market_pressure_scale/market_pressure_scale.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

market_pressure_scale.pine
//@version=6
// ============================================================================
// Market Pressure Scale [WavesUnchained]
// Version: 2.4.4
// Author: WavesUnchained
// Build: 2026-10-12
// ============================================================================
// Two-component oscillator separating setup pressure (compression + S/R proximity)
// from impulse pressure (range expansion + volume + body + trend), with phase
// classification, a Move Strength column gauge for the expected magnitude
// of the eventual move, and a DMI-free Reversal signal.
//
// Features:
//   ✓ Setup Pressure — ATR/BB compression, S/R proximity, volume drying up
//   ✓ Impulse Pressure — range expansion, volume, body size
//   ✓ Range Chop Filter — ADX/DMI regime detection suppresses Failed Coil /
//     Reversal signals inside dead mid-range chop
//   ✓ Phase classification: Sideways/Chop / Impulse Running / Sideways / Neutral
//   ✓ Move Strength — expected magnitude of the eventual move (compression depth +
//     range-edge location + ADX), plotted as blue columns behind the two curves
//   ✓ Reversal — Impulse exhaustion + rejection wick + candle confirmation at a
//     range extreme, weighted by Setup compression; direction-native, does not rely on DMI
//   ✓ Failed Coil requires price to actually fall back toward the middle of the range
//   ✓ Naked Impulse requires ADX to still be weak (a real trend doesn't count as "naked")
//   ✓ Directional bias via configurable fast/slow MA cross
//   ✓ Range position (close relative to N-bar range)
//   ✓ Dashboard table with phase, bias, range position, move strength, plain-language action (off by default)
//   ✓ Configurable output smoothing — EMA / RMA / SMA / WMA / HMA / JMA
//   ✓ Alerts for all phase transitions and signal markers
//   ✓ Debug: Pine Logs output of full Reversal context per bar at a range extreme (off by default)
//
// Data Contract:
//   Price:     REQUIRED   chart symbol
//   Volume:    OPTIONAL   real trade volume only — Setup/Impulse Pressure volume sub-weights renormalize onto remaining components when not real
//   OI:        NO
//   Reference: NO
//   Verdict:   CFD-degraded
//
// ============================================================================

indicator("Market Pressure Scale [WavesUnchained]", format=format.price, precision=2, shorttitle="MPS", overlay=false, max_labels_count=500)

// Inputs
normLen   = input.int(100,  "Normalisation",    minval=20)
atrLen    = input.int(14,   "ATR Length")
bbLen     = input.int(20,   "BB Length")
bbMult    = input.float(2.0, "BB Multiplier")
volLen    = input.int(20,   "Volume MA")
srLen     = input.int(50,   "Range / S/R Lookback")

biasGR       = "Bias"
biasType     = input.string("HMA", "Type",
     options=["EMA", "RMA", "SMA", "WMA", "HMA", "JMA"], group=biasGR)
biasFastLen  = input.int(9,  "Fast Length", minval=1, group=biasGR)
biasSlowLen  = input.int(21, "Slow Length", minval=1, group=biasGR)

smGR       = "Smoothing"
smoothLen  = input.int(3,     "Length", minval=1, maxval=50, group=smGR)
smoothType = input.string("EMA", "Type",
     options=["EMA", "RMA", "SMA", "WMA", "HMA", "JMA"], group=smGR)
jmaPhase   = input.int(50,    "  JMA Phase", minval=-100, maxval=100,            group=smGR)
jmaPower   = input.float(2.0, "  JMA Power", minval=1.0,  maxval=4.0, step=0.25, group=smGR)

dashGR    = "Dashboard"
showTable = input.bool(false, "Show Table", group=dashGR)

sigGR       = "Signal Markers"
showMarkers = input.bool(true,  "Show Markers",     group=sigGR)
showFailed  = input.bool(true,  "  Failed Coil",    group=sigGR,
              tooltip="Setup was high but Impulse never confirmed — stalled breakout, likely range continues.")
showNaked   = input.bool(true,  "  Naked Impulse",  group=sigGR,
              tooltip="Impulse > 70 but Setup collapses below 40 — move running without structural backing.")
showReversal = input.bool(true, "  Reversal",       group=sigGR,
              tooltip="At a range extreme: the recent Impulse is fading from its own high AND there's a rejection wick against the extreme, weighted by Setup compression. Direction-native — does not use DMI.")

strengthGR    = "Move Strength"
showStrengthBg = input.bool(true, "Show Columns", group=strengthGR,
                 tooltip="Blue columns (5 opacity bands) tracking the expected magnitude of the eventual move: compression depth + range-edge location + ADX, suppressed while the Range Chop Filter is active. Plotted behind Setup/Impulse Pressure instead of a full-pane background.")

debugGR      = "Debug"
showDebugLog = input.bool(false, "Log Reversal Context (Pine Logs)", group=debugGR,
               tooltip="Writes two things to Pine Logs: 1) rangePos/chop/setup/impulse/exhaustion/wick/score on every confirmed bar at a range extreme, for diagnosing Reversal signals. 2) every raw ingredient (atr/volume/volRel/compression/srProximity/etc.) whenever Setup or Impulse Pressure comes back na, for diagnosing feeds whose volume series carries no usable turnover.")

// Helpers
clamp(x, lo, hi) =>
    math.max(lo, math.min(hi, x))

norm100(src, len) =>
    hi = ta.highest(src, len)
    lo = ta.lowest(src, len)
    hi == lo ? 50.0 : 100.0 * (src - lo) / (hi - lo)

f_jma(src, length, phase, power) =>
    var float jma = na
    var float e0  = na
    var float e1  = na
    var float e2  = na
    _pr    = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100.0 + 1.5
    _beta  = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
    _alpha = math.pow(_beta, power)
    e0    := (1 - _alpha) * src + _alpha * nz(e0[1], src)
    e1    := (src - e0) * (1 - _beta) + _beta * nz(e1[1], 0)
    e2    := (e0 + _pr * e1 - nz(jma[1], src)) * math.pow(1 - _alpha, 2) + math.pow(_alpha, 2) * nz(e2[1], 0)
    jma   := nz(jma[1], src) + e2
    jma

f_smooth(src, length, mode) =>
    switch mode
        'SMA' => ta.sma(src, length)
        'RMA' => ta.rma(src, length)
        'HMA' => ta.hma(src, length)
        'WMA' => ta.wma(src, length)
        'JMA' => f_jma(src, length, jmaPhase, jmaPower)
        =>       ta.ema(src, length)

// Move Strength color — quantized into 5 tiers so consecutive bars read as a
// clear step change instead of a near-uniform continuous gradient
f_strengthColor(v) =>
    _t = v >= 85 ? 10 : v >= 65 ? 35 : v >= 45 ? 58 : v >= 25 ? 80 : 95
    color.new(#2196F3, _t)

// Base values
atr    = ta.atr(atrLen)
atrPct = atr / close

basis    = ta.sma(close, bbLen)
dev      = bbMult * ta.stdev(close, bbLen)
bbUpper  = basis + dev
bbLower  = basis - dev
bbWidth  = (bbUpper - bbLower) / basis

// Echtes Handelsvolumen? Nur "tick" schließt aus; "n/a" zählt, wenn der Feed Volumen liefert (DATA_VALIDITY §2).
bool volumeIsReal = (ta.cum(nz(volume)) > 0 and syminfo.volumetype != "tick") and not na(volume)

_volSma   = ta.sma(volume, volLen)
volRel    = not volumeIsReal or na(_volSma) or _volSma <= 0 ? 1.0 : volume / _volSma
barRange  = high - low
bodySize  = math.abs(close - open)
bodyRatio = bodySize / math.max(barRange, syminfo.mintick)
lowerWick = math.min(close, open) - low
upperWick = high - math.max(close, open)

_biasFast = f_smooth(close, biasFastLen, biasType)
_biasSlow = f_smooth(close, biasSlowLen, biasType)
bullBias  = _biasFast > _biasSlow
bearBias  = _biasFast < _biasSlow

// Range / Support / Resistance
rangeHigh = ta.highest(high, srLen)
rangeLow  = ta.lowest(low,  srLen)
rangeSize = rangeHigh - rangeLow

nearHigh    = math.abs(rangeHigh - close) / math.max(atr, syminfo.mintick)
nearLow     = math.abs(close - rangeLow)  / math.max(atr, syminfo.mintick)
srProximity = clamp(100 - math.min(nearHigh, nearLow) * 50, 0, 100)

rangePosition = rangeSize == 0 ? 50 : 100 * (close - rangeLow) / rangeSize

// Range Chop Filter — ADX/DMI regime detection to keep Failed Coil / Reversal
// from firing on dead mid-range chop, where compression + edge proximity are
// coincidental rather than a genuine squeeze
[diPlus, diMinus, adx] = ta.dmi(14, 14)
chopMarket     = adx < 16 and math.abs(diPlus - diMinus) < 5 and rangePosition > 20 and rangePosition < 80
validSetupZone = rangePosition < 20 or rangePosition > 80

// Setup Pressure — high when volatility is low, BBs tight, price near range
// extreme AND volume is drying up (a genuine squeeze, not a high-volume push)
atrCompression = 100 - norm100(atrPct, normLen)
bbCompression  = 100 - norm100(bbWidth, normLen)
compression    = (atrCompression + bbCompression) / 2
volQuiet       = 100 - norm100(volRel, normLen)

// Volume weight (0.15) drops out when volume isn't real; the remaining two
// weights are renormalized onto the full 1.0 (0.55/0.85, 0.30/0.85) instead
// of just zeroing the term, so Setup Pressure doesn't systematically shrink
// on feeds without real trade volume.
float setupPressure = na
if volumeIsReal
    setupPressure := compression * 0.55 + srProximity * 0.30 + volQuiet * 0.15
else
    setupPressure := compression * (0.55 / 0.85) + srProximity * (0.30 / 0.85)

setupPressure := clamp(setupPressure, 0, 100)

// Impulse Pressure — high when range, body and volume expand
rangeExpansion = norm100(barRange / math.max(atr, syminfo.mintick), normLen)
volumePressure = norm100(volRel,    normLen)
bodyPressure   = norm100(bodyRatio, normLen)

// Same renormalization as Setup Pressure: without real volume the 0.15 volume
// weight drops out and range/body are scaled onto the full 1.0 (0.45/0.85,
// 0.40/0.85) instead of adding a constant mid-value volume term.
float impulsePressure = na
if volumeIsReal
    impulsePressure := rangeExpansion * 0.45 + bodyPressure * 0.40 + volumePressure * 0.15
else
    impulsePressure := rangeExpansion * (0.45 / 0.85) + bodyPressure * (0.40 / 0.85)

impulsePressure := clamp(impulsePressure, 0, 100)

// Smoothing
setupPressure   := f_smooth(setupPressure,   smoothLen, smoothType)
impulsePressure := f_smooth(impulsePressure, smoothLen, smoothType)

// Debug: dump every ingredient when Setup/Impulse comes back na, so a broken
// input can be found from evidence instead of guessing at more zero-division fixes
if showDebugLog and (na(setupPressure) or na(impulsePressure)) and barstate.isconfirmed
    log.info("MPS NAN CTX atr=" + str.tostring(atr) +
         " volume=" + str.tostring(volume) +
         " volSma=" + str.tostring(_volSma) +
         " volRel=" + str.tostring(volRel) +
         " atrPct=" + str.tostring(atrPct) +
         " bbWidth=" + str.tostring(bbWidth) +
         " compression=" + str.tostring(compression) +
         " srProximity=" + str.tostring(srProximity) +
         " volQuiet=" + str.tostring(volQuiet) +
         " rangeExpansion=" + str.tostring(rangeExpansion) +
         " bodyPressure=" + str.tostring(bodyPressure) +
         " volumePressure=" + str.tostring(volumePressure) +
         " setup=" + str.tostring(setupPressure) +
         " impulse=" + str.tostring(impulsePressure))

// Move Strength — expected magnitude of the eventual move once Setup releases:
// compression depth (energy stored) + range-edge location + ADX (trend
// confirmation), suppressed toward zero while chopMarket is active.
adxNorm      = clamp(adx / 50 * 100, 0, 100)
moveStrength = compression * 0.45 + srProximity * 0.35 + adxNorm * 0.20
moveStrength := chopMarket ? moveStrength * 0.35 : moveStrength
moveStrength := clamp(moveStrength, 0, 100)

// Signal detection
var bool inCoil      = false
var bool coilIgnited = false

coilEntry = validSetupZone and not chopMarket and ta.crossover(setupPressure, 65) and impulsePressure < 40
if coilEntry
    inCoil      := true
    coilIgnited := false
if inCoil and impulsePressure >= 45
    coilIgnited := true

backToRange = rangePosition > 25 and rangePosition < 75
sigFailed   = inCoil and not coilIgnited and ta.crossunder(setupPressure, 52) and backToRange
sigNaked    = impulsePressure > 70 and ta.crossunder(setupPressure, 40) and adx < 25

if sigFailed or setupPressure < 40
    inCoil := false

// Reversal — exhaustion of the move that got us here + rejection at a range
// extreme (indicator-design §6.1: regime veto -> exhaustion -> confirmation ->
// quality, combined as one score per direction instead of an AND-chain).
// Direction-native: never touches DMI, so it isn't subject to the lag a
// DMI-based directional read would have at turning points.
impulseHigh10   = ta.highest(impulsePressure, 10)
exhaustionScore = impulseHigh10 > 50 ? clamp(impulseHigh10 - impulsePressure, 0, 100) : 0

lowerWickRatio = lowerWick / math.max(barRange, syminfo.mintick) * 100
upperWickRatio = upperWick / math.max(barRange, syminfo.mintick) * 100

reversalActive     = validSetupZone and not chopMarket
reversalLongScore  = exhaustionScore * 0.45 + lowerWickRatio * 0.30 + setupPressure * 0.25
reversalShortScore = exhaustionScore * 0.45 + upperWickRatio * 0.30 + setupPressure * 0.25

// Candle confirmation — the trigger bar itself must close in the direction of
// the reversal, not just show a rejection wick, so a big wick that closes back
// toward the extreme doesn't count
bullReject = close > open and close > (low + barRange * 0.6)
bearReject = close < open and close < (high - barRange * 0.6)

sigReversalLong  = reversalActive and rangePosition < 20 and bullReject and ta.crossover(reversalLongScore,  60)
sigReversalShort = reversalActive and rangePosition > 80 and bearReject and ta.crossover(reversalShortScore, 60)

// Kept as a short window rather than the single trigger bar, for the
// dashboard's Action row (a one-bar-only flag reads as "nothing" most of the time)
recentRevLong  = ta.barssince(sigReversalLong)  <= 2
recentRevShort = ta.barssince(sigReversalShort) <= 2

if showDebugLog and validSetupZone and barstate.isconfirmed
    log.info("MPS REVERSAL CTX rangePos=" + str.tostring(rangePosition, "#.0") +
         " chop=" + str.tostring(chopMarket) +
         " setup=" + str.tostring(setupPressure, "#.0") +
         " impulse=" + str.tostring(impulsePressure, "#.0") +
         " impulseHigh10=" + str.tostring(impulseHigh10, "#.0") +
         " exhaustion=" + str.tostring(exhaustionScore, "#.0") +
         " lowerWickR=" + str.tostring(lowerWickRatio, "#.0") +
         " upperWickR=" + str.tostring(upperWickRatio, "#.0") +
         " longScore=" + str.tostring(reversalLongScore, "#.0") +
         " shortScore=" + str.tostring(reversalShortScore, "#.0"))

// Phase — priority order: Chop > Impulse > Sideways > Neutral
phase = if chopMarket
    "Sideways / Chop"
else if impulsePressure > 70
    "Impulse Running"
else if setupPressure < 40 and impulsePressure < 40
    "Sideways / Quiet"
else
    "Neutral"

biasText = bullBias ? "Bullish" : bearBias ? "Bearish" : "Flat"

// Colors
setupColor   = setupPressure   > 65 ? color.orange             : color.new(color.orange, 45)
impulseColor = impulsePressure > 70 ? color.lime               : color.new(color.lime,   45)

// Move Strength — columns instead of a full-pane background, so it adds
// information without washing out Setup/Impulse Pressure. Plotted first so it
// sits behind both curves.
plot(showStrengthBg ? moveStrength : na, "Move Strength", color=f_strengthColor(moveStrength), style=plot.style_columns)

plot(setupPressure,   "Setup Pressure",   color=setupColor,   linewidth=3)
plot(impulsePressure, "Impulse Pressure", color=impulseColor, linewidth=4)

hline(40, "Quiet",        color=color.new(color.gray, 55), linestyle=hline.style_dashed)
hline(65, "Setup Zone",   color=color.new(color.gray, 40), linestyle=hline.style_dashed)
hline(70, "Impulse Zone", color=color.new(color.gray, 25), linestyle=hline.style_dashed)

// Signal markers
if showMarkers
    if showFailed and sigFailed
        label.new(bar_index, setupPressure, "FC",
             style=label.style_label_down, color=color.new(#d50000, 15),
             textcolor=color.white, size=size.small,
             tooltip="Failed Coil — Setup was high but Impulse never confirmed.\nBreakout attempt stalled. Expect range continuation or a full reset before the next setup forms.")

    if showNaked and sigNaked
        label.new(bar_index, impulsePressure, "NI",
             style=label.style_label_down, color=color.new(#d50000, 15),
             textcolor=color.white, size=size.small,
             tooltip="Naked Impulse — Impulse > 70 but Setup collapsed below 40.\nMove is running without structural backing. Late-entry risk — momentum may stall or reverse sharply.")

    if showReversal and sigReversalLong
        label.new(bar_index, impulsePressure, "◆",
             style=label.style_label_up, color=color.new(#00c853, 15),
             textcolor=color.white, size=size.small,
             tooltip="Reversal Long — Impulse fading from a recent high, rejection wick at range low, weighted by Setup compression.\nExhaustion + rejection, not DMI-based — an early counter-trend candidate.")

    if showReversal and sigReversalShort
        label.new(bar_index, impulsePressure, "◆",
             style=label.style_label_down, color=color.new(#d50000, 15),
             textcolor=color.white, size=size.small,
             tooltip="Reversal Short — Impulse fading from a recent high, rejection wick at range high, weighted by Setup compression.\nExhaustion + rejection, not DMI-based — an early counter-trend candidate.")

// Table
color tc = color.new(color.gray, 20)
color hd = color.new(color.gray, 90)

setupDir   = setupPressure   > setupPressure[1]   + 0.5 ? "↑" : setupPressure   < setupPressure[1]   - 0.5 ? "↓" : "→"
impulseDir = impulsePressure > impulsePressure[1] + 0.5 ? "↑" : impulsePressure < impulsePressure[1] - 0.5 ? "↓" : "→"

var table t = table.new(position.top_right, 3, 8,
     bgcolor      = color.new(color.white, 5),
     border_color = color.new(color.gray, 60),
     border_width = 1,
     frame_color  = color.new(color.gray, 40),
     frame_width  = 1)

if barstate.islast and showTable
    phaseActive = not chopMarket and impulsePressure > 70
    color phaseBg = color.new(color.gray, 80)
    if phaseActive
        phaseBg := color.new(#00c853, 20)
    phaseTC     = phaseActive ? color.white : tc

    table.cell(t, 0, 0, "Phase",   text_color=tc,      bgcolor=hd,      text_size=size.small)
    table.cell(t, 1, 0, phase,     text_color=phaseTC, bgcolor=phaseBg, text_size=size.small)
    table.cell(t, 2, 0, "",        bgcolor=hd,                          text_size=size.small)

    table.cell(t, 0, 1, "Setup",   text_color=tc, text_size=size.small, tooltip="How much the market is coiling: ATR/BB compression, S/R proximity, relative volume. >65 = strong setup.")
    table.cell(t, 1, 1, str.tostring(setupPressure,   "#.0") + " / 100", text_color=tc,         text_size=size.small)
    table.cell(t, 2, 1, setupDir,                                         text_color=color.new(color.orange, 0), text_size=size.small)

    table.cell(t, 0, 2, "Impulse", text_color=tc, text_size=size.small, tooltip="How much a directional move is underway: range expansion vs ATR, volume, candle body size. >70 = impulse running.")
    table.cell(t, 1, 2, str.tostring(impulsePressure, "#.0") + " / 100", text_color=tc,          text_size=size.small)
    table.cell(t, 2, 2, impulseDir,                                       text_color=color.new(#00c853, 0), text_size=size.small)

    biasTC = bullBias ? color.new(#00c853, 0) : bearBias ? color.new(#d50000, 0) : tc
    table.cell(t, 0, 3, "Bias",       text_color=tc,     text_size=size.small, tooltip="Directional bias from a fast/slow MA cross. Bullish = fast MA above slow MA.")
    table.cell(t, 1, 3, biasText,     text_color=biasTC, text_size=size.small)
    table.cell(t, 2, 3, "",           text_color=tc,     text_size=size.small)

    table.cell(t, 0, 4, "Range Pos.", text_color=tc, text_size=size.small, tooltip="Where the close sits within the N-bar high/low range. 0% = at range low, 100% = at range high.")
    table.cell(t, 1, 4, str.tostring(rangePosition, "#.0") + " %", text_color=tc, text_size=size.small)
    table.cell(t, 2, 4, "",           text_color=tc, text_size=size.small)

    // Separator
    table.cell(t, 0, 5, "", bgcolor=color.new(color.gray, 80))
    table.cell(t, 1, 5, "", bgcolor=color.new(color.gray, 80))
    table.cell(t, 2, 5, "", bgcolor=color.new(color.gray, 80))

    // Move Strength
    strengthTc      = moveStrength > 50 ? color.white : tc
    color strengthBg = f_strengthColor(moveStrength)
    table.cell(t, 0, 6, "Move Str.", text_color=tc,        bgcolor=na,          text_size=size.small, tooltip="Expected magnitude of the eventual move: compression depth + range-edge proximity + ADX trend confirmation, suppressed during chop.")
    table.cell(t, 1, 6, str.tostring(moveStrength, "#.0") + " / 100", text_color=strengthTc, bgcolor=strengthBg, text_size=size.small)
    table.cell(t, 2, 6, "",          text_color=tc,        bgcolor=na,          text_size=size.small)

    // Action — a plain-language read of the same priority order as the signals above
    string actionText = "Wait"
    color  actionBg    = color.new(color.gray, 80)
    color  actionTc    = tc
    if chopMarket
        actionText := "Ignore / Chop"
    else if setupPressure > 65 and impulsePressure < 45
        actionText := "Watch Setup"
        actionBg   := color.new(#ffd600, 30)
    else if impulsePressure > 70
        actionText := "Trend Running"
        actionBg   := color.new(#00c853, 20)
        actionTc   := color.white
    else if recentRevLong
        actionText := "Long Reversal"
        actionBg   := color.new(#00c853, 20)
        actionTc   := color.white
    else if recentRevShort
        actionText := "Short Reversal"
        actionBg   := color.new(#d50000, 20)
        actionTc   := color.white
    table.cell(t, 0, 7, "Action", text_color=tc,       bgcolor=na,      text_size=size.small, tooltip="Plain-language read of the current state, same priority order as the phase/signals above.")
    table.cell(t, 1, 7, actionText, text_color=actionTc, bgcolor=actionBg, text_size=size.small)
    table.cell(t, 2, 7, "",        text_color=tc,       bgcolor=na,      text_size=size.small)

// Alerts
bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed
alertcondition(alertOk and (impulsePressure > 70),                                       "Impulse Running", "MPS · IMPULSE RUNNING · {{ticker}} {{interval}}")
alertcondition(alertOk and (setupPressure < 40 and impulsePressure < 40),                "Sideways / Quiet", "MPS · SIDEWAYS QUIET · {{ticker}} {{interval}}")
alertcondition(alertOk and (sigFailed), "Signal: Failed Coil",     "MPS · FAILED COIL · {{ticker}} {{interval}}")
alertcondition(alertOk and (sigNaked),  "Signal: Naked Impulse",   "MPS · NAKED IMPULSE · {{ticker}} {{interval}}")
alertcondition(alertOk and (sigReversalLong),  "Signal: Reversal Long",  "MPS · REVERSAL LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (sigReversalShort), "Signal: Reversal Short", "MPS · REVERSAL SHORT · {{ticker}} {{interval}}")

Overview

Setup pressure combines ATR and Bollinger compression, support and resistance proximity, and drying volume. Impulse pressure combines range expansion, volume, and candle body size. A range-chop filter uses ADX and DMI to suppress failed-coil and reversal markers in mid-range chop. Move strength appears as columns. Fast and slow moving-average bias, output smoothing, and an optional dashboard change how phases and markers are shown. Volume weights drop out when volume is not real trade volume.

Details

Published by

casoon on GitHub

Draws

Separate pane below the chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Normalisationint100normLen
ATR Lengthint14atrLen
BB Lengthint20bbLen
BB Multiplierfloat2.0bbMult
Volume MAint20volLen
Range / S/R Lookbackint50srLen
TypestringHMAbiasType
Fast Lengthint9biasFastLen
Slow Lengthint21biasSlowLen
Lengthint3smoothLen
TypestringEMAsmoothType
JMA Phaseint50jmaPhase
Show all 21 settings
SettingTypeDefaultVariable
JMA Powerfloat2.0jmaPower
Show TableboolfalseshowTable
Show MarkersbooltrueshowMarkers
Failed CoilbooltrueshowFailed
Naked ImpulsebooltrueshowNaked
ReversalbooltrueshowReversal
Show ColumnsbooltrueshowStrengthBg
Log Reversal Context (Pine Logs)boolfalseshowDebugLog
Alerts only on bar close (confirmed)booltruealertsOnBarClose
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

114 stars

This indicator standardizes price inputs using z-score normalization before calculating a relative strength index (RSI). It generates trade signals when standardized price components cross over or under the standardized RSI feature. Signals can be filtered by

Indicator v4 Oscillators & momentumVolatility & bands Repaints
Updated 1 year ago · None stated GitHub repository of Preprosessed & Standardized RSI

PPO ATR Bands

by cryptorife
75 stars

PPO ATR Bands plots a percentage price oscillator in a separate pane. It compares a Hull average of typical price with a volume-weighted exponential average of Parabolic SAR, then scales three true-range bands around the slow average into matching oscillator l

Indicator v4 Oscillators & momentumMoving averages
Updated 3 years ago · GPL-3.0 GitHub repository of PPO ATR Bands

CCI DC

by be-thomas
65 stars

This indicator plots the Commodity Channel Index in a separate pane and surrounds it with a Donchian channel whose lookback length changes with volatility. It measures volatility as a ratio of short and long ATR values, then ranks that ratio and shortens or le

Indicator v5 Oscillators & momentumVolatility & bands
Updated 6 days ago · GPL-3.0 GitHub repository of CCI DC

This indicator calculates the Relative Strength Index (RSI) alongside a simple moving average to generate directional momentum signals in a separate pane. It supports Break Flip and Break Continuous scanning modes for long and short setups. A wide array of opt

Indicator v5 Oscillators & momentumVolatility & bands
Updated 1 year ago · None stated GitHub repository of Momentum Setup: RSI Direction Confirmation

NFI v6

by koradiyakaushal
12 stars

This Pine v4 study ports early NostalgiaForInfinity V6 conditions onto the price chart. It computes two Bollinger setups, several EMAs and SMAs, RSI, MFI, a percent SMA spread labeled EWO, a 14-period choppiness value, and short and longer volume medians. Fixe

Indicator v4 Moving averagesVolatility & bands
Updated 5 years ago · MIT GitHub repository of NFI v6

More Oscillators & momentum scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers