Market Memory Levels
A Higher-Timeframe Volume Acceptance Map for Identifying Historical Areas of Market Interest.Market Memory Levels is a higher-timeframe volume distribution indicator designed to identify price areas where the market has historically spent the greatest amount of time and volume. Rather than attempting to predict future price action, it highlights the levels that the market itself has repeatedly recognized as important.
Change the timeframe in settings based on your trading timeframe. WEEKLY is by default. If you're trading on a 30 minute or less chart, use DAILY. If you're trading on a daily chart, use MONTHLY.
The indicator builds a rolling volume profile within a selected higher timeframe (such as a week) and converts those areas of concentrated participation into horizontal "memory levels." These levels often act as natural support and resistance because they represent prices where buyers and sellers previously found agreement. The colors of the levels indicate strength of the retest. Red is a weak pullback, yellow is an average pullback, green is strong and cyan is an extreme pullback.
Key Observations
- High-volume areas tend to attract future price action. Markets frequently revisit these levels before deciding on the next directional move.
- Strong trends often pause or consolidate near Market Memory Levels. What appears to be random hesitation is often the market interacting with a prior area of heavy participation.
- The most significant levels often become magnets. Price may accelerate toward them from a distance, then either reject sharply or consolidate before continuing.
- Memory Levels are dynamic. As each higher timeframe period develops, the distribution evolves, allowing new areas of market acceptance to emerge while older structures gradually lose relevance.
- The indicator works best as a context tool rather than a standalone signal generator. Combining Market Memory Levels with trend analysis, price action, or momentum studies can help identify higher-probability trading opportunities.
CODE:
Code:
#========================
# Market_Memory_Levels
# Created by Chewie 6/7/2026
#========================
declare upper;
#========================
# INPUTS
#========================
input Aggregation = {default Weekly, Daily, Monthly};
input ATRLength = 100;
input ATRMultiplier = 0.25;
input LookbackBars = 200;
#========================
# HTF PERIOD
#========================
def newPeriod =
if Aggregation == Aggregation.Weekly then GetWeek() <> GetWeek()[1]
else if Aggregation == Aggregation.Daily then GetDay() <> GetDay()[1]
else GetMonth() <> GetMonth()[1];
#========================
# FIXED HTF RANGE
#========================
rec hi =
if newPeriod then high
else Max(high, hi[1]);
rec lo =
if newPeriod then low
else Min(low, lo[1]);
def range = hi - lo;
#========================
# ATR BIN SIZE
#========================
def atr = Average(TrueRange(high, close, low), ATRLength);
def bin = Max(atr * ATRMultiplier, TickSize());
#========================
# PRE-COMPUTE BIN LEVELS
#========================
def b1l = lo;
def b1h = b1l + bin;
def b2l = b1h;
def b2h = b2l + bin;
def b3l = b2h;
def b3h = b3l + bin;
def b4l = b3h;
def b4h = b4l + bin;
def b5l = b4h;
def b5h = b5l + bin;
#========================
# RAW VOLUME (ISOLATED DEFINITIONS)
#========================
def v1 =
fold i1 = 0 to LookbackBars
with a1 = 0
do a1 + (if close[i1] >= b1l and close[i1] < b1h then volume[i1] else 0);
def v2 =
fold i2 = 0 to LookbackBars
with a2 = 0
do a2 + (if close[i2] >= b2l and close[i2] < b2h then volume[i2] else 0);
def v3 =
fold i3 = 0 to LookbackBars
with a3 = 0
do a3 + (if close[i3] >= b3l and close[i3] < b3h then volume[i3] else 0);
def v4 =
fold i4 = 0 to LookbackBars
with a4 = 0
do a4 + (if close[i4] >= b4l and close[i4] < b4h then volume[i4] else 0);
def v5 =
fold i5 = 0 to LookbackBars
with a5 = 0
do a5 + (if close[i5] >= b5l and close[i5] < b5h then volume[i5] else 0);
#========================
# MAX VOLUME (SAFE REDUCTION)
#========================
def maxV1 = Max(v1, v2);
def maxV2 = Max(v3, v4);
def maxV3 = Max(maxV1, maxV2);
def maxVol = Max(maxV3, v5);
#========================
# NORMALIZED SCORES
#========================
def p1 = if maxVol > 0 then v1 / maxVol else 0;
def p2 = if maxVol > 0 then v2 / maxVol else 0;
def p3 = if maxVol > 0 then v3 / maxVol else 0;
def p4 = if maxVol > 0 then v4 / maxVol else 0;
def p5 = if maxVol > 0 then v5 / maxVol else 0;
#========================
# VISUAL OUTPUT
#========================
plot L1 = if p1 > 0.6 then (b1h + b1l) / 2 else Double.NaN;
L1.SetPaintingStrategy(PaintingStrategy.POINTS);
L1.SetDefaultColor(Color.YELLOW);
plot L2 = if p2 > 0.6 then (b2h + b2l) / 2 else Double.NaN;
L2.SetPaintingStrategy(PaintingStrategy.POINTS);
L2.SetDefaultColor(Color.CYAN);
plot L3 = if p3 > 0.6 then (b3h + b3l) / 2 else Double.NaN;
L3.SetPaintingStrategy(PaintingStrategy.POINTS);
L3.SetDefaultColor(Color.GREEN);
#========================================================
# PART 2 — HEATMAP LAYERS
#========================================================
input showHeatmap = yes;
#========================
# COLORS
#========================
DefineGlobalColor("Low", Color.BLUE);
DefineGlobalColor("Mid", Color.CYAN);
DefineGlobalColor("High", Color.YELLOW);
DefineGlobalColor("Extreme", Color.RED);
#========================================================
# BIN 1
#========================================================
AddCloud(
if showHeatmap and p1 > 0.25 then b1h else Double.NaN,
if showHeatmap and p1 > 0.25 then b1l else Double.NaN,
GlobalColor("Low"),
GlobalColor("Low"));
#========================================================
# BIN 2
#========================================================
AddCloud(
if showHeatmap and p2 > 0.30 then b2h else Double.NaN,
if showHeatmap and p2 > 0.30 then b2l else Double.NaN,
GlobalColor("Low"),
GlobalColor("Mid"));
#========================================================
# BIN 3
#========================================================
AddCloud(
if showHeatmap and p3 > 0.40 then b3h else Double.NaN,
if showHeatmap and p3 > 0.40 then b3l else Double.NaN,
GlobalColor("Mid"),
GlobalColor("Mid"));
#========================================================
# BIN 4
#========================================================
AddCloud(
if showHeatmap and p4 > 0.50 then b4h else Double.NaN,
if showHeatmap and p4 > 0.50 then b4l else Double.NaN,
GlobalColor("Mid"),
GlobalColor("High"));
#========================================================
# BIN 5
#========================================================
AddCloud(
if showHeatmap and p5 > 0.60 then b5h else Double.NaN,
if showHeatmap and p5 > 0.60 then b5l else Double.NaN,
GlobalColor("High"),
GlobalColor("High"));
#========================================================
# EXTENSION BIN 6
#========================================================
def b6l = b5h;
def b6h = b6l + bin;
def v6 =
fold i6 = 0 to LookbackBars
with a6 = 0
do a6 + (if close[i6] >= b6l and close[i6] < b6h then volume[i6] else 0);
def p6 = if maxVol > 0 then v6 / maxVol else 0;
AddCloud(
if showHeatmap and p6 > 0.55 then b6h else Double.NaN,
if showHeatmap and p6 > 0.55 then b6l else Double.NaN,
GlobalColor("High"),
GlobalColor("Extreme"));
#========================================================
# EXTENSION BIN 7
#========================================================
def b7l = b6h;
def b7h = b7l + bin;
def v7 =
fold i7 = 0 to LookbackBars
with a7 = 0
do a7 + (if close[i7] >= b7l and close[i7] < b7h then volume[i7] else 0);
def p7 = if maxVol > 0 then v7 / maxVol else 0;
AddCloud(
if showHeatmap and p7 > 0.65 then b7h else Double.NaN,
if showHeatmap and p7 > 0.65 then b7l else Double.NaN,
GlobalColor("Extreme"),
GlobalColor("Extreme"));
#========================================================
# PART 3 — LIQUIDITY LEVELS ENGINE
#========================================================
input showLevels = yes;
input levelStrength = 0.65;
#========================
# STRENGTH CONDITIONS
#========================
def st1 = p1 > levelStrength;
def st2 = p2 > levelStrength;
def st3 = p3 > levelStrength;
def st4 = p4 > levelStrength;
def st5 = p5 > levelStrength;
def st6 = p6 > levelStrength;
def st7 = p7 > levelStrength;
#========================
# LEVEL MIDPOINTS
#========================
def mid1 = (b1h + b1l) / 2;
def mid2 = (b2h + b2l) / 2;
def mid3 = (b3h + b3l) / 2;
def mid4 = (b4h + b4l) / 2;
def mid5 = (b5h + b5l) / 2;
def mid6 = (b6h + b6l) / 2;
def mid7 = (b7h + b7l) / 2;
#========================
# BREAK CONDITIONS
#========================
def br1 = close < mid1;
def br2 = close < mid2;
def br3 = close < mid3;
def br4 = close < mid4;
def br5 = close < mid5;
def br6 = close < mid6;
def br7 = close < mid7;
#========================
# PERSISTENT LEVELS
#========================
rec lvlA1 =
if newPeriod then Double.NaN
else if st1 and !br1 then mid1
else if br1 then Double.NaN
else lvlA1[1];
rec lvlA2 =
if newPeriod then Double.NaN
else if st2 and !br2 then mid2
else if br2 then Double.NaN
else lvlA2[1];
rec lvlA3 =
if newPeriod then Double.NaN
else if st3 and !br3 then mid3
else if br3 then Double.NaN
else lvlA3[1];
rec lvlA4 =
if newPeriod then Double.NaN
else if st4 and !br4 then mid4
else if br4 then Double.NaN
else lvlA4[1];
rec lvlA5 =
if newPeriod then Double.NaN
else if st5 and !br5 then mid5
else if br5 then Double.NaN
else lvlA5[1];
rec lvlA6 =
if newPeriod then Double.NaN
else if st6 and !br6 then mid6
else if br6 then Double.NaN
else lvlA6[1];
rec lvlA7 =
if newPeriod then Double.NaN
else if st7 and !br7 then mid7
else if br7 then Double.NaN
else lvlA7[1];
#========================
# PLOTS
#========================
plot Liquidity_A1 =
if showLevels then lvlA1 else Double.NaN;
Liquidity_A1.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A1.SetDefaultColor(Color.YELLOW);
Liquidity_A1.SetLineWeight(2);
plot Liquidity_A2 =
if showLevels then lvlA2 else Double.NaN;
Liquidity_A2.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A2.SetDefaultColor(Color.CYAN);
Liquidity_A2.SetLineWeight(2);
plot Liquidity_A3 =
if showLevels then lvlA3 else Double.NaN;
Liquidity_A3.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A3.SetDefaultColor(Color.GREEN);
Liquidity_A3.SetLineWeight(2);
plot Liquidity_A4 =
if showLevels then lvlA4 else Double.NaN;
Liquidity_A4.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A4.SetDefaultColor(Color.BLUE);
Liquidity_A4.SetLineWeight(2);
plot Liquidity_A5 =
if showLevels then lvlA5 else Double.NaN;
Liquidity_A5.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A5.SetLineWeight(2);
Liquidity_A5.SetDefaultColor(Color.GRAY);
plot Liquidity_A6 =
if showLevels then lvlA6 else Double.NaN;
Liquidity_A6.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A6.SetDefaultColor(Color.MAGENTA);
Liquidity_A6.SetLineWeight(2);
plot Liquidity_A7 =
if showLevels then lvlA7 else Double.NaN;
Liquidity_A7.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Liquidity_A7.SetDefaultColor(Color.RED);
Liquidity_A7.SetLineWeight(2);
#========================================================
# PART 4 — FILTERED LIQUIDITY EVENTS
#========================================================
input showSignals = yes;
input minStrength = 0.70;
#========================
# ONLY HIGH-QUALITY LEVELS
#========================
def strongZone =
(p1 > minStrength or
p2 > minStrength or
p3 > minStrength or
p4 > minStrength or
p5 > minStrength or
p6 > minStrength or
p7 > minStrength);
#========================
# TRUE MAX LIQUIDITY SELECTION
#========================
def maxP = Max(p1,
Max(p2,
Max(p3,
Max(p4,
Max(p5,
Max(p6, p7))))));#
def keyLevel =
if p1 == maxP then mid1
else if p2 == maxP then mid2
else if p3 == maxP then mid3
else if p4 == maxP then mid4
else if p5 == maxP then mid5
else if p6 == maxP then mid6
else mid7;
#========================
# SWEEP ONLY AT KEY LEVEL
#========================
def sweepUp =
high > keyLevel and close < keyLevel;
def sweepDown =
low < keyLevel and close > keyLevel;
#========================
# CONFIRMATION FILTER
# must be at strong zone
#========================
def validSweepUp = sweepUp and strongZone;
def validSweepDown = sweepDown and strongZone;
#========================
# SINGLE CLEAN SIGNAL PLOTS
#========================
plot SellSignal =
if showSignals and validSweepUp then high else Double.NaN;
SellSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SellSignal.SetDefaultColor(Color.RED);
SellSignal.SetLineWeight(3);
plot BuySignal =
if showSignals and validSweepDown then low else Double.NaN;
BuySignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BuySignal.SetDefaultColor(Color.GREEN);
BuySignal.SetLineWeight(3);
#========================
# OPTIONAL: ALERT FILTER
#========================
def signal =
validSweepUp or validSweepDown;
Alert(signal, "Liquidity Sweep at Key Level", Alert.BAR, Sound.Ding);
input showPOC = yes;
input pocLineWeight = 4;
#========================================================
# PART 5 - DOMINANT LIQUIDITY NODE
#========================================================
def maxP1 =
Max(p1,
Max(p2,
Max(p3,
Max(p4,
Max(p5,
Max(p6, p7))))));
def POC =
if p1 == maxP1 then mid1
else if p2 == maxP1 then mid2
else if p3 == maxP1 then mid3
else if p4 == maxP1 then mid4
else if p5 == maxP1 then mid5
else if p6 == maxP1 then mid6
else mid7;
plot PointOfControl =
if showPOC then POC else Double.NaN;
PointOfControl.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PointOfControl.SetDefaultColor(Color.WHITE);
PointOfControl.SetLineWeight(pocLineWeight);
Here is a picture of a one minute chart. Notice the arrows where price breaks down. These could be good areas to short on a continued downtrend.
Here is a 5 min. chart of /GC. Price uses the levels as support until it breaks much lower.
Last edited: