OPEN-SOURCE SCRIPT
Friction Map [NovaLens]

Friction Map reads price structure the way a floor trader reads a room: it finds the price shelves where the market actually spent time, marks which ones are still live versus which the market has abandoned, and measures how much clear air you have to the nearest live shelf in each direction. It is a map of where structure is, how alive it is, and where the open space sits - not a buy or sell signal.
Most support/resistance tools draw static lines and leave them there forever, so the chart fills with levels that stopped mattering 300 bars ago. Friction Map keeps the same structure honest over time: every shelf carries a freshness that decays once the market stops trading at it, so the orange (live) shelves are the ones price has interacted with recently and the gray (fading) ones visibly age out.
═════════════════════════════════════════
◈ HOW TO READ IT
Friction Map draws directly on the price chart. There are two views of the same structure.
The shelves.
The room boxes. On the right edge, a box runs from current price to the nearest LIVE shelf above and below, with a label that reads the distance as a near-to-far range in ATR, for example "1 to 2.1 ATR" - meaning roughly 1 ATR of clear air, then the shelf running out to 2.1 ATR. ATR units make the read comparable on any symbol and timeframe. Teal means clear room; orange means a live shelf sits within about 1 ATR. When there is no live shelf in a direction the label reads "open air".
The breakout badge. On a confirmed close that breaks the recent range, and only at the extremes, the map prints a one-word context badge: CLEAR RUNWAY when there is no live shelf within the runway band ahead, or WALLED (with the distance) when a live shelf stands within about 1 ATR of the path. Only one CLEAR RUNWAY prints per clear-air leg - no repeats while price keeps running in the same open space, and it resets once price pulls back into a shelf. It is breakout context, never a direction call.
The info panel. A compact info panel compiles the read: the structure memory in bars; Room above and Room below as ATR ranges; Price now (open air, on a live shelf, or on a fading shelf); Last breakout (the most recent badge and how many bars ago); Shelves (how many live versus fading); and a one-line Reading takeaway.
The two views (Level view).
═════════════════════════════════════════
◉ HOW IT WORKS
The density field. Across the lookback window, the indicator measures how often each price level sat inside the high-low range of the lookback bars - a time-at-price-style structure read. For every bar it asks which price levels the bar's high-low range covered, and accumulates that into a density field using a difference-array method (O(L+bins) per bar) so the script stays fast even on long charts and heavy lookbacks. Price levels where many bars overlapped are dense; levels price passed through quickly are thin.
Where shelves are born. A shelf forms at a density peak whose strength clears a RELATIVE floor - it must be at least a set fraction of the strongest peak currently on the map. That relative test is self-calibrating: it adapts to each asset and regime instead of relying on a fixed tick count, so the same indicator is designed to read BTC, SPY, EURUSD and gold without constant retuning. A small absolute floor screens out noise on near-empty windows.
Data-driven width. Each shelf's band is not a fixed width. It expands outward from the peak for as long as the neighbouring density holds at least half the peak value, then is capped to a readable range in ATR units. A wide consolidation earns a wide shelf; a tight one stays thin.
Aliveness (freshness). Every shelf carries a freshness equal to an exponential decay of the bars since the band was last traded (2^(-barsSinceTouch / halfLife)). Freshness is 1 while price is in the band and halves every half-life once price leaves. Above the live threshold a shelf renders LIVE (orange); below it the shelf renders FADING (gray) and dims further until it drops off the map.
Causal lifecycle. Shelves are born on confirmed bars and never re-placed. A shelf becomes BROKEN only when price, after arming on one side with real separation, closes through to the other side - the break bar is frozen and the line continues as a faint dotted tail. The ORIGIN anchor (the earliest bar within the lookback where price actually traded that level) and the BREAK anchor are both set once and never rewritten. That frozen history is the trust element: the map cannot quietly redraw the past to look right.
═════════════════════════════════════════
✦ HOW WE USE IT
A common read on a liquid crypto or index chart, default memory: price is pushing toward the top of its recent range. The panel Room above reads "0.4 to 1.6 ATR" in orange - there is a live shelf close overhead, so the map reads the upside as walled in the near term. Room below reads "open air" - nothing live underneath. Price is sitting in open air between an overhead live shelf and abandoned structure far below.
Now price closes through the recent high. Because the nearest live shelf overhead was inside the runway band, the map prints WALLED with the distance, not CLEAR RUNWAY - the break is into immediate structure, not open space. The badge does not say the break fails; it says there is a live shelf standing in the path, which is the context a discretionary trader wants before deciding whether the move has room.
Flip the situation: a confirmed break with Room ahead reading "open air" prints CLEAR RUNWAY. In our testing, clear-runway breakouts travelled further on average than walled ones (the effect was modest and weakest on rates). That is an observation about context, not a guarantee about the next bar.
The point of the map is the same in every case: see where the live structure is, see how much clear air you have to it in ATR, and read the breakout against that structure instead of against a static line.
═════════════════════════════════════════
❖ OTHER APPLICATIONS
═════════════════════════════════════════
⚙ GETTING STARTED
Friction Map ships with pre-tuned memory profiles plus a Custom override. Pick a memory and start reading the map - the default Auto setting matches the chart timeframe for you.
Structure memory:
Core display:
Appearance / Colours (4 pickers):
Advanced (Memory = Custom only): Custom opens on the same defaults as the Medium profile (not a live copy of whichever profile you are currently on), so coming from Medium the switch is seamless; coming from Short or Long the map steps to that baseline first. Then every dial below is yours.
═════════════════════════════════════════
△ LIMITATIONS
═════════════════════════════════════════
🔔 ALERTS
Two alert conditions are built in so you can monitor structure without watching every bar:
Both fire on bar close (gated on `barstate.isconfirmed`) - no intrabar repaint. The indicator also emits a richer alert with a pure-JSON payload for routing to your own automation or webhook stack. The payload carries the brand, the indicator name, the event, the direction, the up and down clearance in ATR, the current price, the ticker, the timeframe and the bar time (the clearance fields are sent as text and read "open" when there is no live shelf that way). Pick ONE mechanism per event - the dropdown alert condition for a simple notification, or the JSON alert for a webhook - so you do not get duplicate notifications. Badges and alerts fire even when the on-chart badge is toggled off; alerts should not require chart clutter.
═════════════════════════════════════════
⌁ NOTES
NovaLens
Most support/resistance tools draw static lines and leave them there forever, so the chart fills with levels that stopped mattering 300 bars ago. Friction Map keeps the same structure honest over time: every shelf carries a freshness that decays once the market stops trading at it, so the orange (live) shelves are the ones price has interacted with recently and the gray (fading) ones visibly age out.
═════════════════════════════════════════
◈ HOW TO READ IT
Friction Map draws directly on the price chart. There are two views of the same structure.
The shelves.
- Orange = LIVE - price traded here recently; this is the current structure context.
- Gray = FADING - price has not returned in a while; the market has moved on and the shelf dims the longer it stays untouched.
- Faint dotted = BROKEN - price closed through it; an x-cross marks the exact bar it failed, and the dotted tail is kept so you can still see it existed.
- KEY LEVEL - the strongest live shelf on the map (boldest line, brightest tag). The eye's anchor.
The room boxes. On the right edge, a box runs from current price to the nearest LIVE shelf above and below, with a label that reads the distance as a near-to-far range in ATR, for example "1 to 2.1 ATR" - meaning roughly 1 ATR of clear air, then the shelf running out to 2.1 ATR. ATR units make the read comparable on any symbol and timeframe. Teal means clear room; orange means a live shelf sits within about 1 ATR. When there is no live shelf in a direction the label reads "open air".
The breakout badge. On a confirmed close that breaks the recent range, and only at the extremes, the map prints a one-word context badge: CLEAR RUNWAY when there is no live shelf within the runway band ahead, or WALLED (with the distance) when a live shelf stands within about 1 ATR of the path. Only one CLEAR RUNWAY prints per clear-air leg - no repeats while price keeps running in the same open space, and it resets once price pulls back into a shelf. It is breakout context, never a direction call.
The info panel. A compact info panel compiles the read: the structure memory in bars; Room above and Room below as ATR ranges; Price now (open air, on a live shelf, or on a fading shelf); Last breakout (the most recent badge and how many bars ago); Shelves (how many live versus fading); and a one-line Reading takeaway.
The two views (Level view).
- Anchored (default): each shelf line starts at its origin diamond, shows its current live (orange) / fading (gray) state from that origin, and marks the x-cross where it broke. An anchored structure story - where structure formed, how it reads now, and where it broke if broken - not a full per-era ledger.
- Zones: every live shelf drawn as a clean full-width band straight across the chart, like a supply/demand map. Instant "where are my levels right now". No origin/break markers; broken shelves drop off.
═════════════════════════════════════════
◉ HOW IT WORKS
The density field. Across the lookback window, the indicator measures how often each price level sat inside the high-low range of the lookback bars - a time-at-price-style structure read. For every bar it asks which price levels the bar's high-low range covered, and accumulates that into a density field using a difference-array method (O(L+bins) per bar) so the script stays fast even on long charts and heavy lookbacks. Price levels where many bars overlapped are dense; levels price passed through quickly are thin.
Where shelves are born. A shelf forms at a density peak whose strength clears a RELATIVE floor - it must be at least a set fraction of the strongest peak currently on the map. That relative test is self-calibrating: it adapts to each asset and regime instead of relying on a fixed tick count, so the same indicator is designed to read BTC, SPY, EURUSD and gold without constant retuning. A small absolute floor screens out noise on near-empty windows.
Data-driven width. Each shelf's band is not a fixed width. It expands outward from the peak for as long as the neighbouring density holds at least half the peak value, then is capped to a readable range in ATR units. A wide consolidation earns a wide shelf; a tight one stays thin.
Aliveness (freshness). Every shelf carries a freshness equal to an exponential decay of the bars since the band was last traded (2^(-barsSinceTouch / halfLife)). Freshness is 1 while price is in the band and halves every half-life once price leaves. Above the live threshold a shelf renders LIVE (orange); below it the shelf renders FADING (gray) and dims further until it drops off the map.
Causal lifecycle. Shelves are born on confirmed bars and never re-placed. A shelf becomes BROKEN only when price, after arming on one side with real separation, closes through to the other side - the break bar is frozen and the line continues as a faint dotted tail. The ORIGIN anchor (the earliest bar within the lookback where price actually traded that level) and the BREAK anchor are both set once and never rewritten. That frozen history is the trust element: the map cannot quietly redraw the past to look right.
═════════════════════════════════════════
✦ HOW WE USE IT
A common read on a liquid crypto or index chart, default memory: price is pushing toward the top of its recent range. The panel Room above reads "0.4 to 1.6 ATR" in orange - there is a live shelf close overhead, so the map reads the upside as walled in the near term. Room below reads "open air" - nothing live underneath. Price is sitting in open air between an overhead live shelf and abandoned structure far below.
Now price closes through the recent high. Because the nearest live shelf overhead was inside the runway band, the map prints WALLED with the distance, not CLEAR RUNWAY - the break is into immediate structure, not open space. The badge does not say the break fails; it says there is a live shelf standing in the path, which is the context a discretionary trader wants before deciding whether the move has room.
Flip the situation: a confirmed break with Room ahead reading "open air" prints CLEAR RUNWAY. In our testing, clear-runway breakouts travelled further on average than walled ones (the effect was modest and weakest on rates). That is an observation about context, not a guarantee about the next bar.
The point of the map is the same in every case: see where the live structure is, see how much clear air you have to it in ATR, and read the breakout against that structure instead of against a static line.
═════════════════════════════════════════
❖ OTHER APPLICATIONS
- Trade-location context: read entries against the nearest live shelf rather than a static S/R line - the orange shelves are the structure price has interacted with most recently.
- Breakout context: CLEAR RUNWAY versus WALLED on a confirmed break, as a read on whether there is open space ahead or a live shelf in the path.
- Stop and target context: the room ranges in ATR give a structure-aware sense of where the nearest live shelves sit above and below, for evaluating whether planned stops or targets sit near recent structure or out in open air, instead of at round numbers.
- Chop filter: many overlapping live shelves with price standing on one ("on a live shelf" in the panel) is a congested read; sustained open air is cleaner trend space.
- Structure classifier: use the Shelves row (live versus fading) and Room rows as a top-down structure filter for any external trade plan, independent of the badges.
- Alert-driven workflow: subscribe to the clear-runway and walled breakout alerts and check the chart only when a confirmed breakout actually changes the structural picture.
═════════════════════════════════════════
⚙ GETTING STARTED
Friction Map ships with pre-tuned memory profiles plus a Custom override. Pick a memory and start reading the map - the default Auto setting matches the chart timeframe for you.
Structure memory:
- Auto (match timeframe) (default): reads the chart - 30-minute and faster get Short, everything slower gets Medium.
- Short (60 bars): about one trading day on 5m, a week on 1H. Faster-moving map.
- Medium (120 bars): about a month on 1H, six months on 1D. Balanced.
- Long (240 bars): slow, full-cycle structure.
- Custom: unlocks the Advanced group for full manual control.
Core display:
- Level view: Anchored (causal story, default) or Zones (clean full-width bands).
- Structure shelves: master toggle for the shelf lines. On by default. Under it, three per-state toggles let you choose which states draw:
- Live shelves (orange), Fading shelves (gray), Broken shelves (dotted) - all on by default. Turn Broken off to declutter when a level has rebuilt live on top of old broken tails.
- Room boxes + labels: the price-to-nearest-live-shelf boxes and ATR range labels. On by default.
- Breakout badge: CLEAR RUNWAY / WALLED context badges on confirmed breakouts. On by default.
- Shelf state tags: a small LIVE / FADING / KEY LEVEL tag at the right end of each shelf. On by default; turn off for a cleaner chart once the colours are familiar.
- Show real shelf width: off by default (live shelves get a thin subtle halo). On draws each live shelf at its true data-driven width as a wider transparent band.
- Info panel: pick where the summary panel anchors - Top Right (default), Top Left, Bottom Right, Bottom Left, Middle Right, or Off to hide it.
- Dark theme panel: panel colours for dark charts; turn off on a light background.
- Level reach (bars): how far back the shelf lines and halos draw, so old structure does not stretch across the whole chart.
Appearance / Colours (4 pickers):
- Live shelf, Fading shelf, Clear air, Broken shelf - each on its own line. The shelf lines, halos, room boxes, tags and badges all reference these inputs, so the palette adapts for colour-blind, light-mode or brand themes without forking the script.
Advanced (Memory = Custom only): Custom opens on the same defaults as the Medium profile (not a live copy of whichever profile you are currently on), so coming from Medium the switch is seamless; coming from Short or Long the map steps to that baseline first. Then every dial below is yours.
- Lookback (bars): structure memory in bars. Larger = more history considered, slower-moving map.
- Freshness half-life: how fast a shelf fades once the market stops trading at it. After this many bars untouched a shelf is at half freshness.
- Breakout lookback: a breakout is a confirmed close that newly breaks beyond the prior N-bar high or low (a fresh cross, so a sustained trend does not re-fire it every bar).
- Min strength (vs strongest): a shelf is born only if its density is at least this fraction of the strongest peak on the map. Raise for fewer, stronger shelves.
- Merge distance (ATR): shelf candidates closer than this to an existing shelf refresh it instead of spawning a duplicate.
- Max shelves: cap on simultaneously tracked (non-broken) shelves; the weakest is pruned when a stronger one is born.
- Live threshold: freshness above this renders a shelf LIVE (orange).
- Runway band (ATR): how far ahead of a breakout to scan for live shelves when deciding CLEAR RUNWAY versus WALLED.
═════════════════════════════════════════
△ LIMITATIONS
- Descriptive, not predictive: Friction Map shows where price spent time and how alive that structure is. It makes no claim that a shelf will hold or that a breakout will follow through. There is no buy or sell signal anywhere in the tool.
- Time-at-price, not volume: the density field is built from how much of the traded range sat at each level, not from volume. That keeps the read universally stable across every asset and data feed (crypto volume is fractured by exchange, FX volume is a tick proxy), but it does not weight a busy bar more than a quiet one.
- Backward-looking by construction: in fast moves and gaps, room can jump to "open air" quickly as price leaps into untraded territory. That is accurate but may not persist.
- Room measures to LIVE shelves only: the room ranges and the badge ignore fading shelves on purpose - the room read focuses on the current (orange) structure. A fading shelf still shows on the chart as a gray line; it just is not counted as room.
- The breakout effect is context, not edge: in testing, clear-runway breakouts travelled further than walled ones on average, but the difference was modest and weakest on rates. Treat the badge as context to read alongside your own plan, not as a validated signal.
- Recency fade: a structurally important level that has not been traded in a long time will fade from the map even if you still consider it important. Lengthen the memory or half-life if you want older structure to persist.
═════════════════════════════════════════
🔔 ALERTS
Two alert conditions are built in so you can monitor structure without watching every bar:
- Clear-runway breakout: a confirmed breakout into clear air (no live shelf within the runway band ahead).
- Walled breakout: a confirmed breakout into nearby live structure (a live shelf within about 1 ATR of the path).
Both fire on bar close (gated on `barstate.isconfirmed`) - no intrabar repaint. The indicator also emits a richer alert with a pure-JSON payload for routing to your own automation or webhook stack. The payload carries the brand, the indicator name, the event, the direction, the up and down clearance in ATR, the current price, the ticker, the timeframe and the bar time (the clearance fields are sent as text and read "open" when there is no live shelf that way). Pick ONE mechanism per event - the dropdown alert condition for a simple notification, or the JSON alert for a webhook - so you do not get duplicate notifications. Badges and alerts fire even when the on-chart badge is toggled off; alerts should not require chart clutter.
═════════════════════════════════════════
⌁ NOTES
- Built on a containment-count density field (time-at-price), with data-driven band width, exponential freshness decay, and a causal frozen lifecycle (origin and break anchors set once and never moved).
- Method lineage: the density field is a time-at-price construction, in the tradition of Market Profile (J. Peter Steidlmayer, popularised at the CBOT in the 1980s), which reads structure from where the market spent time rather than from volume. Friction Map adds the freshness decay and the causal live/fading/broken lifecycle on top of that classical time-at-price idea.
- Repaint: non-repainting on confirmed bars. Births, breaks, clearance, badges and alerts are computed on bar close; the current bar updates in real time. Live/fading colour reflects current state, so a re-traded faded shelf can re-colour live - no past origin or break anchor is ever changed.
- Original construction. The engine is built from first principles for this tool; there is no external reference implementation, so no validation-correlation claim is made.
- Open-source under MPL 2.0. Free to use, fork, study.
NovaLens
Script open-source
Nello spirito di TradingView, l'autore di questo script lo ha reso open source, in modo che i trader possano esaminarne e verificarne la funzionalità. Complimenti all'autore! Sebbene sia possibile utilizzarlo gratuitamente, ricordiamo che la ripubblicazione del codice è soggetta al nostro Regolamento.
NovaLens builds systematic indicators from real quant research - designed for a cleaner market view.
Declinazione di responsabilità
Le informazioni e le pubblicazioni non sono intese come, e non costituiscono, consulenza o raccomandazioni finanziarie, di investimento, di trading o di altro tipo fornite o approvate da TradingView. Per ulteriori informazioni, consultare i Termini di utilizzo.
Script open-source
Nello spirito di TradingView, l'autore di questo script lo ha reso open source, in modo che i trader possano esaminarne e verificarne la funzionalità. Complimenti all'autore! Sebbene sia possibile utilizzarlo gratuitamente, ricordiamo che la ripubblicazione del codice è soggetta al nostro Regolamento.
NovaLens builds systematic indicators from real quant research - designed for a cleaner market view.
Declinazione di responsabilità
Le informazioni e le pubblicazioni non sono intese come, e non costituiscono, consulenza o raccomandazioni finanziarie, di investimento, di trading o di altro tipo fornite o approvate da TradingView. Per ulteriori informazioni, consultare i Termini di utilizzo.