Indicator · Pine Script v6 · Own pane

Permutation Entropy Regime [Jayadev Rana]

by jayadevrana

This indicator classifies market conditions into five regimes using Bandt-Pompe permutation entropy on price closes.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code166
Settings15inputs
LicenceCustom licencefile: MPL-2.0
Last update2 months ago7 Aug 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

166 lines of Pine Script v6 from permutation_entropy_regime.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

permutation_entropy_regime.pine
//@version=6
// Permutation Entropy Regime [Jayadev Rana]
// This source code is subject to the terms of the Mozilla Public License 2.0.
//
// Concept: classify the market into a "predictability regime" using the
// permutation entropy (Bandt-Pompe, embedding dimension 3) of recent closes.
// Low entropy = ordered / structured price (clean trend or clean oscillation);
// high entropy = disordered / random-walk chop. A drift-bias term splits
// structured regimes into Up / Down / Range. Computed on confirmed bars only.

indicator("Permutation Entropy Regime [Jayadev Rana]", shorttitle="PER", overlay=false, max_bars_back=200)

//------------------------------------------------------------------------------
// Inputs
//------------------------------------------------------------------------------
grpCore   = "Core"
winLen    = input.int(50, "Entropy Window (bars)", minval=10, maxval=150, group=grpCore, tooltip="Number of ordinal patterns used to estimate permutation entropy. Larger = smoother and slower to react; smaller = more responsive and noisier. Embedding dimension is 3 (compares 3 consecutive closes).")
smoothLen = input.int(3, "Predictability Smoothing", minval=1, maxval=50, group=grpCore, tooltip="EMA length applied to the raw predictability score to reduce single-bar jitter. Set 1 to disable.")

grpReg    = "Regime"
rankLb    = input.int(200, "Structure Rank Lookback", minval=20, maxval=500, group=grpReg, tooltip="History window used to percentile-rank the current predictability against its own past, so the regime cutoff adapts per instrument and timeframe.")
structLv  = input.int(60, "Structured Level", minval=50, maxval=95, group=grpReg, tooltip="A Structure Rank at or above this value marks a structured (predictable) regime.")
chopLv    = input.int(40, "Chop Level", minval=5, maxval=50, group=grpReg, tooltip="A Structure Rank at or below this value marks a random / chop regime. Between the two levels is Neutral.")
driftTh   = input.float(0.15, "Drift Bias Threshold", minval=0.0, maxval=1.0, step=0.05, group=grpReg, tooltip="Minimum absolute drift bias (net share of up vs down closes over the window, -1..+1) needed to call a structured regime Up or Down rather than Range.")

grpVis    = "Visuals"
colorBars = input.bool(true, "Color price bars by regime", group=grpVis, tooltip="Recolor the main chart candles using the current regime color.")
showBg    = input.bool(true, "Shade this pane by regime", group=grpVis)
showDash  = input.bool(true, "Show dashboard", group=grpVis)
dashPos   = input.string("Top Right", "Dashboard position", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group=grpVis)

grpCol    = "Colors"
cUp       = input.color(#26a69a, "Structured Up", group=grpCol)
cDn       = input.color(#ef5350, "Structured Down", group=grpCol)
cRange    = input.color(#42a5f5, "Structured Range", group=grpCol)
cNeutral  = input.color(#b0bec5, "Neutral", group=grpCol)
cChop     = input.color(#ffa726, "Random / Chop", group=grpCol)

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
// Ordinal pattern id (0..5) of three values using strict rank comparison.
patternId(float a, float b, float c) =>
    int ra = (a > b ? 1 : 0) + (a > c ? 1 : 0)
    int rb = (b > a ? 1 : 0) + (b > c ? 1 : 0)
    int rc = (c > a ? 1 : 0) + (c > b ? 1 : 0)
    int id = ra * 2 + (rb > rc ? 1 : 0)
    id := id < 0 ? 0 : id > 5 ? 5 : id
    id

f1(float x) => na(x) ? "-" : str.tostring(x, "#.0")
f2(float x) => na(x) ? "-" : str.tostring(x, "#.00")

//------------------------------------------------------------------------------
// Permutation entropy (embedding dimension 3, delay 1)
//------------------------------------------------------------------------------
var array<float> hist = array.new<float>(6, 0.0)

float He        = na
float predRaw   = na
float driftBias = na

enoughBars = bar_index > winLen + 3
if enoughBars
    for k = 0 to 5
        array.set(hist, k, 0.0)
    float driftSum = 0.0
    for i = 0 to winLen - 1
        float a = close[i]
        float b = close[i + 1]
        float c = close[i + 2]
        int id = patternId(a, b, c)
        array.set(hist, id, array.get(hist, id) + 1.0)
        driftSum += math.sign(a - b)
    float total = winLen
    float ent = 0.0
    for k = 0 to 5
        float p = array.get(hist, k) / total
        if p > 0.0
            ent -= p * math.log(p)
    He        := ent / math.log(6)
    predRaw   := (1.0 - He) * 100.0
    driftBias := driftSum / winLen

float predScore = ta.ema(predRaw, smoothLen)
float sRank     = ta.percentrank(predScore, rankLb)

//------------------------------------------------------------------------------
// Regime classification
//------------------------------------------------------------------------------
bool hasRank    = not na(sRank)
bool structured = hasRank and sRank >= structLv
bool chop       = hasRank and sRank <= chopLv

color regimeColor = cNeutral
string regime = "Neutral"
if chop
    regime := "Random / Chop"
    regimeColor := cChop
else if structured
    if driftBias > driftTh
        regime := "Structured Up"
        regimeColor := cUp
    else if driftBias < -driftTh
        regime := "Structured Down"
        regimeColor := cDn
    else
        regime := "Structured Range"
        regimeColor := cRange

var string prevRegime = ""
bool regimeChanged = prevRegime != "" and regime != prevRegime
var int barsInRegime = 0
barsInRegime := prevRegime == regime ? barsInRegime + 1 : 1

//------------------------------------------------------------------------------
// Alerts (bar close)
//------------------------------------------------------------------------------
bool aUp    = barstate.isconfirmed and regime == "Structured Up" and barsInRegime == 1
bool aDn    = barstate.isconfirmed and regime == "Structured Down" and barsInRegime == 1
bool aRange = barstate.isconfirmed and regime == "Structured Range" and barsInRegime == 1
bool aChop  = barstate.isconfirmed and regime == "Random / Chop" and barsInRegime == 1
bool aChg   = barstate.isconfirmed and regimeChanged
alertcondition(aUp, "Entered Structured Up", "Permutation Entropy Regime: Structured Up")
alertcondition(aDn, "Entered Structured Down", "Permutation Entropy Regime: Structured Down")
alertcondition(aRange, "Entered Structured Range", "Permutation Entropy Regime: Structured Range")
alertcondition(aChop, "Entered Random / Chop", "Permutation Entropy Regime: Random / Chop")
alertcondition(aChg, "Regime Changed", "Permutation Entropy Regime: regime changed")

//------------------------------------------------------------------------------
// Visuals
//------------------------------------------------------------------------------
plot(predScore, "Predictability", color=color.new(color.gray, 40), linewidth=1)
plot(sRank, "Structure Rank", color=regimeColor, linewidth=2)
hline(structLv, "Structured Level", color=color.new(color.green, 60), linestyle=hline.style_dashed)
hline(chopLv, "Chop Level", color=color.new(color.orange, 60), linestyle=hline.style_dashed)
hline(50, "Mid", color=color.new(color.gray, 80))

bgcolor(showBg and hasRank ? color.new(regimeColor, 90) : na, title="Regime background")
barcolor(colorBars and hasRank ? regimeColor : na, title="Regime bar color")

//------------------------------------------------------------------------------
// Dashboard
//------------------------------------------------------------------------------
tablePos = dashPos == "Top Right" ? position.top_right : dashPos == "Top Left" ? position.top_left : dashPos == "Bottom Right" ? position.bottom_right : position.bottom_left
var table dash = table.new(tablePos, 2, 8, border_width=1, frame_width=1, frame_color=color.new(color.gray, 50))

if showDash and barstate.islast
    table.cell(dash, 0, 0, "Permutation Entropy Regime", text_color=color.white, bgcolor=color.new(color.black, 20), text_size=size.small)
    table.cell(dash, 1, 0, "", bgcolor=color.new(color.black, 20))
    table.cell(dash, 0, 1, "Regime", text_color=color.white, bgcolor=color.new(color.black, 40), text_size=size.small)
    table.cell(dash, 1, 1, regime, text_color=color.white, bgcolor=color.new(regimeColor, 10), text_size=size.small)
    table.cell(dash, 0, 2, "Structure Rank", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 2, f1(sRank), text_color=regimeColor, text_size=size.small)
    table.cell(dash, 0, 3, "Predictability", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 3, f1(predScore), text_color=color.white, text_size=size.small)
    table.cell(dash, 0, 4, "Norm. Entropy", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 4, na(He) ? "-" : f1(He * 100) + "%", text_color=color.white, text_size=size.small)
    table.cell(dash, 0, 5, "Drift Bias", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 5, f2(driftBias), text_color=color.white, text_size=size.small)
    table.cell(dash, 0, 6, "Bars in Regime", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 6, str.tostring(barsInRegime), text_color=color.white, text_size=size.small)
    table.cell(dash, 0, 7, "Window / Dim", text_color=color.gray, text_size=size.small)
    table.cell(dash, 1, 7, str.tostring(winLen) + " / 3", text_color=color.white, text_size=size.small)

prevRegime := regime

Overview

Permutation Entropy Regime [Jayadev Rana] calculates an entropy score to assess order versus randomness, smooths it into a predictability metric, and computes an adaptive percentile rank against historical data. A drift-bias calculation further categorizes structured environments into upward, downward, or ranging states, alongside neutral and chop classifications. The indicator plots in a separate pane with threshold guides, an informative metrics dashboard, background pane tinting, and optional candle recoloring on the main chart.

Details

Published by

jayadevrana on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Trend, Volatility & bands, Screeners & dashboards

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

indicatormarket-regimepermutation-entropypine-script-v6pinescripttradingview

Settings

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

SettingTypeDefaultVariable
Entropy Window (bars)int50winLen
Predictability Smoothingint3smoothLen
Structure Rank Lookbackint200rankLb
Structured Levelint60structLv
Chop Levelint40chopLv
Drift Bias Thresholdfloat0.15driftTh
Color price bars by regimebooltruecolorBars
Shade this pane by regimebooltrueshowBg
Show dashboardbooltrueshowDash
Dashboard positionstringTop RightdashPos
Structured Upcolor#26a69acUp
Structured Downcolor#ef5350cDn
Show all 15 settings
SettingTypeDefaultVariable
Structured Rangecolor#42a5f5cRange
Neutralcolor#b0bec5cNeutral
Random / Chopcolor#ffa726cChop
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

This indicator scans a pasted list of symbols and shows matching long and short setups in a table in a separate pane. It uses a Supertrend crossover, then applies an ATR or fixed-point volatility range so quiet, sideways conditions can be skipped. Optional fil

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MPL-2.0 GitHub repository of Trend Following Setup - Sideways Market Skipper Scanner

Strategy-Picker

by hintheman
13 stars

Strategy-Picker evaluates market trend, momentum, and volatility across multiple timeframes (5m, 15m, and 60m) to recommend suitable options trading structures. It combines MACD, an 8-period EMA, and ADX readings with external VIX levels to suggest Put Credit

Indicator v6 TrendVolatility & bands
Updated 2 months ago · Custom licence GitHub repository of Strategy-Picker

The Adaptive Cycle Detector estimates the dominant market cycle from WaveTrend oscillator zero-crossing frequency and applies smoothing to recommend adaptive indicator lengths. Fast markets with frequent crossings receive shorter lengths while slow swing marke

Indicator v6 Oscillators & momentumVolatility & bands
Updated yesterday · MIT GitHub repository of Adaptive Cycle Detector [WavesUnchained]

Manias, Panics and Crashes

by MeridianAlgo
9 stars

Manias, Panics and Crashes is a separate-pane market regime indicator that quantifies market sentiment and systemic risk. It processes technical metrics including RSI, moving averages, and volume alongside optional intermarket data such as VIX volatility and c

Indicator v6 Oscillators & momentumVolatility & bands
Updated 4 months ago · MIT GitHub repository of Manias, Panics and Crashes

Elton's Screener

by eltonaguiar
4 stars

Elton's Screener is an indicator that runs in a separate pane and scores one of twenty selectable strategies, or auto-selects a route from the symbol type. It filters signals by a minimum confidence level and a higher-timeframe EMA trend alignment. ATR multipl

Indicator v6 Screeners & dashboardsOscillators & momentum Repaints
Updated today · None stated GitHub repository of Elton's Screener
4 stars

Meridian - Futures Context is an intraday analysis indicator designed for US index futures. It measures volume participation using relative volume, calculates rolling realized volatility, and evaluates trend context through VWAP slope and EMA structures. Displ

Indicator v6 VolumeVolatility & bands
Updated 7 weeks ago · MPL-2.0 GitHub repository of Meridian - Futures Context

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers