Skip to content

Free TradingView indicator

Premium and Discount Zones

Splits the dealing range between the latest swing high and low into premium, equilibrium and discount zones with alerts.

Smart moneyv1.0TradingView (Pine Script v6) Non-repainting signals Alerts

What it does

The indicator takes the latest swing high and swing low as a dealing range and splits it in two. The upper half is the premium zone, the lower half is the discount zone, and a thin band around the 50% level marks equilibrium. The idea is simple: within a range, buying is relatively cheap in the lower half and selling is relatively expensive in the upper half.

How it works

  1. Swing highs and lows are confirmed pivots, using the swing length on each side.
  2. The most recent swing high is the top of the range and the most recent swing low is the bottom. If price trades beyond either end before a new swing confirms, that end moves with price straight away.
  3. Equilibrium = (range top + range bottom) ÷ 2. The equilibrium band extends the set percentage of the range height above and below that level.
  4. Premium runs from the top of the band to the range top. Discount runs from the range bottom to the bottom of the band.
  5. The zones are drawn from the older of the two swings to a few bars past the last candle, with the prices printed in the labels. A plotted line records where equilibrium was on each past bar, so you can see how the range evolved.

For example, with an illustrative range from 1.0800 to 1.0900, equilibrium is 1.0850 and a 5% band covers 1.0845 to 1.0855.

How to use it

  • In an uptrend, many traders prefer to look for long setups only when price pulls back into discount, and avoid buying in premium. In a downtrend the opposite applies.
  • Pair the zones with a structure or trend tool so you know which side of the range matters. Zones alone do not tell you the trend.
  • A larger swing length (15 to 30) gives a broader range suited to swing trading. A smaller one tracks short intraday ranges.
  • Combine with Fibonacci retracement levels: the 50% level is the same in both tools.

Alerts: price closed in premium, price closed in discount, price crossed equilibrium.

Settings

InputDefaultWhat it changes
Swing length10Which swings define the range
Equilibrium band5%Width of the neutral band
Extend zones right20 barsProjection past the last candle
Plot equilibrium historyOnHistorical 50% line
Show prices in labelsOnPrices next to zone names
Colors and zone transparencyRed / gray / teal, 88Appearance only

Limitations

The range depends on swings that confirm late, and it changes whenever a new swing forms, so the zones you see today will not stay fixed. The historical equilibrium line shows only what was known on each bar. In strong trends price can stay in premium (or discount) for a long time, so "expensive" does not mean "about to fall". Premium and discount describe location, not timing.

Pine Script source

In TradingView open Pine Editor, paste the code, click Save and then Add to chart.

FXP_PremiumDiscountZones.pine

98 lines

// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/premium-discount-zones/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
// Builds a dealing range from the latest confirmed swing high and swing low and splits it
// into premium (upper half), equilibrium (50% band) and discount (lower half). The range
// expands immediately if price trades beyond either end.
indicator("FXP Premium Discount Zones", shorttitle = "FXP P/D Zones", overlay = true, max_boxes_count = 10, max_lines_count = 10, max_labels_count = 10)

// ── Inputs ─────────────────────────────────────────────────────────────
grpRange   = "Dealing range"
swingLen   = input.int(10, "Swing length (bars each side)", minval = 2, maxval = 100, group = grpRange)
eqBandPct  = input.float(5.0, "Equilibrium band (% of range, each side)", minval = 0.0, maxval = 25.0, step = 0.5, group = grpRange)

grpDisp    = "Display"
extendBars = input.int(20, "Extend zones right (bars)", minval = 0, maxval = 200, group = grpDisp)
showHist   = input.bool(true, "Plot equilibrium history", group = grpDisp)
showPrices = input.bool(true, "Show prices in labels", group = grpDisp)
colPrem    = input.color(#ef5350, "Premium", group = grpDisp)
colEq      = input.color(color.gray, "Equilibrium", group = grpDisp)
colDisc    = input.color(#26a69a, "Discount", group = grpDisp)
fillTransp = input.int(88, "Zone transparency", minval = 0, maxval = 100, group = grpDisp)

// ── Range ──────────────────────────────────────────────────────────────
ph = ta.pivothigh(high, swingLen, swingLen)
pl = ta.pivotlow(low, swingLen, swingLen)

var float rTop    = na
var int   rTopBar = na
var float rBot    = na
var int   rBotBar = na

if not na(ph)
    rTop    := ph
    rTopBar := bar_index - swingLen
if not na(pl)
    rBot    := pl
    rBotBar := bar_index - swingLen
if not na(rTop) and high > rTop
    rTop    := high
    rTopBar := bar_index
if not na(rBot) and low < rBot
    rBot    := low
    rBotBar := bar_index

float rng    = rTop - rBot
bool  valid  = not na(rTop) and not na(rBot) and rng > 0
float eq     = (rTop + rBot) / 2
float half   = rng * eqBandPct / 100
float eqTop  = eq + half
float eqBot  = eq - half

// 1 = premium, -1 = discount, 0 = equilibrium band or no range
int zone = not valid ? 0 : close > eqTop ? 1 : close < eqBot ? -1 : 0

// ── Drawing (last bar only) ────────────────────────────────────────────
var box   premBox = na
var box   discBox = na
var box   eqBox   = na
var line  eqLine  = na

fmt(float v) =>
    showPrices ? "  " + str.tostring(v, format.mintick) : ""

if barstate.islast and valid
    int left  = math.min(rTopBar, rBotBar)
    int right = bar_index + extendBars
    string premTxt = "Premium" + fmt(rTop)
    string discTxt = "Discount" + fmt(rBot)
    string eqTxt   = "Equilibrium" + fmt(eq)
    if na(premBox)
        premBox := box.new(left, rTop, right, eqTop, border_color = color.new(colPrem, 60), bgcolor = color.new(colPrem, fillTransp), text = premTxt, text_color = colPrem, text_size = size.small, text_halign = text.align_right, text_valign = text.align_top)
        discBox := box.new(left, eqBot, right, rBot, border_color = color.new(colDisc, 60), bgcolor = color.new(colDisc, fillTransp), text = discTxt, text_color = colDisc, text_size = size.small, text_halign = text.align_right, text_valign = text.align_bottom)
        eqBox   := box.new(left, eqTop, right, eqBot, border_color = color.new(colEq, 100), bgcolor = color.new(colEq, math.min(fillTransp + 4, 100)), text = eqTxt, text_color = colEq, text_size = size.small, text_halign = text.align_right, text_valign = text.align_center)
        eqLine  := line.new(left, eq, right, eq, color = colEq, style = line.style_dashed, width = 1)
    else
        premBox.set_lefttop(left, rTop)
        premBox.set_rightbottom(right, eqTop)
        premBox.set_text(premTxt)
        discBox.set_lefttop(left, eqBot)
        discBox.set_rightbottom(right, rBot)
        discBox.set_text(discTxt)
        eqBox.set_lefttop(left, eqTop)
        eqBox.set_rightbottom(right, eqBot)
        eqBox.set_text(eqTxt)
        eqLine.set_xy1(left, eq)
        eqLine.set_xy2(right, eq)

plot(showHist and valid ? eq : na, "Equilibrium", color = color.new(colEq, 40), style = plot.style_linebr)

// ── Alerts ─────────────────────────────────────────────────────────────
bool enterPrem = barstate.isconfirmed and zone == 1 and zone[1] != 1
bool enterDisc = barstate.isconfirmed and zone == -1 and zone[1] != -1
bool crossEq   = barstate.isconfirmed and valid and ((close > eq and close[1] <= eq[1]) or (close < eq and close[1] >= eq[1]))

alertcondition(enterPrem, "Price entered premium", "{{ticker}} {{interval}}: price closed in the premium zone at {{close}}")
alertcondition(enterDisc, "Price entered discount", "{{ticker}} {{interval}}: price closed in the discount zone at {{close}}")
alertcondition(crossEq, "Price crossed equilibrium", "{{ticker}} {{interval}}: price crossed the dealing-range equilibrium at {{close}}")

Key inputs

Key inputs of Premium and Discount Zones
InputDefaultDescription
Swing length10Bars on each side that confirm the range's swing high and low.
Equilibrium band5% each sideWidth of the neutral band around the 50% level.
Extend zones right20 barsHow far the zones project past the last candle.
Plot equilibrium historyOnDraws a line showing how the 50% level moved over time.

Educational tools, not advice. Indicators and Expert Advisors describe price; they do not predict it, and past behaviour does not guarantee future results. Test everything on a demo account first and never risk money you cannot afford to lose. See our disclaimer.

Keep exploring

Related tradingview indicators