Video: FREE VWAP Volume Profile You’re INSANE For Not Using
Creator: ChartPrime
Original Video: Watch the original video
Difficulty: Beginner
The Big Idea
ChartPrime introduces its Heat Map VWAP Profile as a way to organize a VWAP reference, surrounding deviation levels, and highlighted areas of activity. The display is intended to make certain price areas easier to monitor.
The video is a product demonstration with selected reactions. Phrases such as perfect entries and large gains do not establish an expected return. The useful lesson is how to separate the chart’s components and ask what information each actually contains.
If You Remember Only One Thing
A bright heatmap level is useful only when you understand its calculation and know it existed before the reaction.
60-Second Summary
- Anchor choice changes the period being summarized.
- Core VWAP, deviation bands, and a control label are different components.
- A custom control level is not automatically a conventional volume-profile POC.
- Inspect when colors and levels update, including after reload.
- Define the reaction, invalidation, and target separately from the display.
Start With the Anchor
VWAP is a volume-weighted average price over a chosen interval. Its interpretation depends on where the calculation starts. A session-based average and an average anchored to an earlier event answer different questions.
The source says increasing or decreasing the anchor changes the scope of analysis, but does not provide exact settings in the transcript. Record the actual anchor and confirm whether it is time-based, event-based, or a rolling lookback before comparing charts.
Calling VWAP fair price is shorthand for an average of observed activity, not a finding about fundamental value. A market can trade persistently above or below it.
Distinguish the Components
| Component | Role in the demonstration | What to verify |
|---|---|---|
| Core VWAP | A central reference shown in orange | Anchor and price source |
| Deviation levels | Additional areas around the average | Formula and multipliers |
| Heatmap | Highlights selected regions of activity or reactions | What the color measures and when it updates |
| Control label | A highlighted level called PC in the transcript | The indicator’s own definition |
Do not assume the control label equals a conventional volume-profile POC. A standard profile groups volume by price; a VWAP is a weighted average. A hybrid display can combine ideas, but its precise calculation must be checked in its documentation or source.
Use a Level to Ask a Question
The video illustrates price returning to highlighted areas and bouncing or rejecting. An operational plan needs another step: decide what constitutes a reaction before acting.
For example, a hypothetical support study might require a completed candle to trade below a pre-existing level and close back above it. The stop could then be assessed against that reaction’s low, with a previously known obstacle as the target. Those are original research rules, not rules established by this promotional walkthrough.
A touch without rejection, repeated trading through a band, and a sustained break are different observations. A bright color does not resolve those differences.
Keep the Historical View Honest
Ask whether a level was already highlighted before the reaction. A heatmap that incorporates later activity can make past bounces appear predictable. Likewise, changing the anchor after seeing the result changes the question being studied.
Save screenshots or record values as they appear during replay and forward observation. Keep developing references separate from completed ones. If the underlying study revises historical levels, use only the information that was available at the proposed entry.
Risk Still Depends on the Entry
Suppose a hypothetical long enters at 100, its invalidation is 99, and the next planned target is 102. That is 2R before costs. If price has already bounced to 101, the same references offer only 0.5R. The highlighted zone may remain relevant even when the trade no longer offers enough reward.
Allow for spread, slippage, and the instrument’s value per point. A stop order does not guarantee a fill at the stop price. Size from the risk plan rather than from confidence in the heatmap’s color.
Separate the Indicator From the Promotion
The transcript also mentions a paid trend assistant and automated configurations. Those are distinct features, and their promotion does not supply a testable strategy for this article. Verify availability and terms directly if investigating them.
The original heatmap weighting and control formula are absent from the transcript. The original Pine indicator below therefore supplies explicit alternative definitions rather than presenting itself as a clone.
A Worked Anchor Comparison
Imagine two original hypothetical charts of the same morning. A session VWAP is near 100 because it includes the full session’s volume. Another calculation anchored after a news release is near 103 because its sample starts later. Price at 102 is above the first reference and below the second. The two readings are not a contradiction; they summarize different observations.
That also means changing the anchor until a bounce aligns with a bright level is not a neutral display choice. It changes the hypothesis after seeing the answer. Record the anchor before evaluating the reaction, then keep it fixed.
Research Exercise: Was the Highlight Available?
Begin with a chronological replay or forward-observation sample. Before price reaches a highlighted level, save the timestamp, level value, anchor, timeframe, and color state. At a later timestamp, record whether the level moved, changed intensity, or disappeared. Reload the chart and compare the historical display with the saved observation.
The purpose is not to accuse the indicator of a flaw. A developing calculation can legitimately change. The question is whether a reader could have acted on the exact historical picture being used as evidence.
Next, define a reaction before collecting outcomes. One original measurement is whether price moves half a previously available ATR away from the first touch within five bars before moving half an ATR through the level. If both thresholds occur in the same bar and sequence is unknown, classify the case as ambiguous rather than selecting a favorable result.
Compare Against a Plain Reference
Use the same touch and reaction rules for the core VWAP and the heatmap’s highlighted levels. Keep the market, anchor interval, observation window, volatility measure, and sample dates constant. This asks whether the added display contributes information beyond the central average.
| Study | Change one input | Measure |
|---|---|---|
| Anchor scope | Two preselected anchor conventions | Touch frequency, reactions, and level movement |
| Display layer | Core VWAP versus eligible highlighted levels | Outcomes per recorded touch, including failures |
| Reaction timing | 3, 5, 10 bars | How quickly the claimed effect appears |
A reaction rate is not yet strategy profitability. To make it a trading test, add an entry, stop, target, position rule, and realistic costs, then evaluate those rules on another period. A level that often reacts by a few ticks may still be uneconomic after spread and slippage.
Check Your Understanding
Can two VWAP values differ on the same chart? Yes, if their anchors or inputs differ. Does brighter mean a verified probability? Not without a defined calibration study. Is a custom control label automatically POC? No; verify the formula. What makes a historical bounce useful evidence? A level recorded before the bounce, a fixed outcome definition, and inclusion of failures. What does a positive reaction study establish? At most the measured relationship under those conditions, not a complete profitable execution method.
Pine Script: An Original VWAP Heat Map Profile
Show Pine Script v6 — VWAP Heat Map Profile
//@version=6
// Article: https://candlechasers.com/vwap-heatmap-anchor-bands-levels/
// Original CandleChasers approximation; not ChartPrime's code or formula.
// Profile estimates volume uniformly across each chart bar's low-high range.
indicator("CandleChasers - VWAP Heat Map Profile", overlay=true,
max_boxes_count=150, max_lines_count=10, max_labels_count=10)
if not timeframe.isintraday or not chart.is_standard
runtime.error("Use standard intraday candles and a symbol with volume.")
mode = input.string("Day", "Anchor mode",
options=["Day", "Week", "Month", "Rolling Bars", "Manual Time"])
anchorTime = input.time(timestamp("01 Jan 2026 00:00 +0000"), "Manual anchor")
cap = input.int(400, "Maximum stored chart bars / rolling length", minval=20, maxval=1000)
rows = input.int(32, "Price rows", minval=8, maxval=64)
width = input.int(45, "Maximum profile width in bars", minval=10, maxval=100)
offset = input.int(3, "Right offset in bars", minval=1, maxval=30)
showBands = input.bool(true, "Show deviation bands")
showProfile = input.bool(true, "Show heat map and profile")
float src = hlc3
bool dayReset = timeframe.change("1D")
bool weekReset = timeframe.change("1W")
bool monthReset = timeframe.change("1M")
bool manualReset = time >= anchorTime and (na(time[1]) or time[1] < anchorTime)
bool reset = switch mode
"Day" => dayReset
"Week" => weekReset
"Month" => monthReset
"Manual Time" => manualReset
=> false
bool eligible = mode != "Manual Time" or time >= anchorTime
var array<float> prices = array.new<float>()
var array<float> highs = array.new<float>()
var array<float> lows = array.new<float>()
var array<float> vols = array.new<float>()
var bool capped = false
var bool observedBoundary = false
var float mean = na
var float sigma = na
var float total = 0.0
var int missing = 0
if barstate.isconfirmed
if reset
array.clear(prices)
array.clear(highs)
array.clear(lows)
array.clear(vols)
capped := false
observedBoundary := not barstate.isfirst
if mode == "Manual Time"
observedBoundary := not na(time[1]) and time[1] < anchorTime
if eligible
array.push(prices, src)
array.push(highs, high)
array.push(lows, low)
array.push(vols, math.max(nz(volume, 0.0), 0.0))
if array.size(prices) > cap
array.shift(prices)
array.shift(highs)
array.shift(lows)
array.shift(vols)
capped := true
total := 0.0
float weighted = 0.0
missing := 0
int count = array.size(prices)
if count > 0
for i = 0 to count - 1
float v = array.get(vols, i)
total += v
weighted += array.get(prices, i) * v
if v <= 0
missing += 1
mean := total > 0 ? weighted / total : na
float deviations = 0.0
if count > 0 and total > 0
for i = 0 to count - 1
float difference = array.get(prices, i) - mean
deviations += difference * difference * array.get(vols, i)
sigma := total > 0 ? math.sqrt(math.max(deviations / total, 0.0)) : na
// Current realtime bar does not enter the sample until it closes.
bool gapBar = reset
plot(gapBar ? na : mean, "Confirmed chart-bar VWAP", color=color.orange,
linewidth=2, style=plot.style_linebr)
u1 = plot(showBands and not gapBar ? mean + sigma : na, "+1 weighted SD",
color=color.new(color.aqua, 35), style=plot.style_linebr)
l1 = plot(showBands and not gapBar ? mean - sigma : na, "-1 weighted SD",
color=color.new(color.aqua, 35), style=plot.style_linebr)
plot(showBands and not gapBar ? mean + 2.0 * sigma : na, "+2 weighted SD",
color=color.new(color.blue, 30), style=plot.style_linebr)
plot(showBands and not gapBar ? mean - 2.0 * sigma : na, "-2 weighted SD",
color=color.new(color.blue, 30), style=plot.style_linebr)
fill(u1, l1, color=color.new(color.aqua, 95))
var array<box> drawings = array.new<box>()
var line controlLine = na
var label controlLabel = na
var table info = table.new(position.top_right, 1, 3, border_width=1)
if barstate.islast
while array.size(drawings) > 0
box.delete(array.pop(drawings))
if not na(controlLine)
line.delete(controlLine)
controlLine := na
if not na(controlLabel)
label.delete(controlLabel)
controlLabel := na
int n = array.size(prices)
// On the first unclosed bar of an anchor, hide the previous anchor's snapshot.
bool awaitingReset = reset and not barstate.isconfirmed
if showProfile and n > 0 and total > 0 and not awaitingReset
float floorPrice = array.min(lows)
float ceilingPrice = array.max(highs)
if ceilingPrice <= floorPrice
floorPrice -= syminfo.mintick * 0.5
ceilingPrice += syminfo.mintick * 0.5
float step = (ceilingPrice - floorPrice) / rows
array<float> bins = array.new<float>(rows, 0.0)
for i = 0 to n - 1
float bh = array.get(highs, i)
float bl = array.get(lows, i)
float bv = array.get(vols, i)
if bv > 0
if bh > bl
for j = 0 to rows - 1
float lower = floorPrice + j * step
float upper = lower + step
float overlap = math.max(math.min(bh, upper) - math.max(bl, lower), 0.0)
array.set(bins, j, array.get(bins, j) + bv * overlap / (bh - bl))
else
int row = int(math.floor((bl - floorPrice) / step))
row := math.max(0, math.min(rows - 1, row))
array.set(bins, row, array.get(bins, row) + bv)
float peak = array.max(bins)
if peak > 0
int pocRow = array.indexof(bins, peak)
float poc = floorPrice + (pocRow + 0.5) * step
int left = bar_index + offset
for j = 0 to rows - 1
float ratio = array.get(bins, j) / peak
float bottom = floorPrice + j * step
float top = bottom + step
color heat = color.from_gradient(ratio, 0.0, 1.0,
color.rgb(20, 45, 95), color.rgb(255, 145, 0))
// Fixed-width heat strip, followed by proportional volume bars.
array.push(drawings, box.new(left=left, top=top, right=left + 5,
bottom=bottom, border_width=0, bgcolor=color.new(heat, 25)))
if ratio > 0
int length = math.max(1, int(math.round(ratio * width)))
array.push(drawings, box.new(left=left + 7, top=top,
right=left + 7 + length, bottom=bottom, border_width=0,
bgcolor=color.new(heat, 20)))
controlLine := line.new(x1=left, y1=poc, x2=left + 7 + width,
y2=poc, color=color.orange, width=2)
controlLabel := label.new(x=left + 8 + width, y=poc,
text="Estimated POC " + str.tostring(poc, format.mintick),
style=label.style_label_left, textcolor=color.white,
color=color.rgb(135, 70, 0), size=size.small)
string scope = mode == "Rolling Bars" ? "Rolling chart-bar sample" :
capped ? "CAP REACHED: truncated rolling tail, not full anchor" :
observedBoundary ? "Observed anchor boundary; feed may contain gaps" :
"Partial loaded history: anchor boundary not observed"
string state = total <= 0 ? "NO POSITIVE VOLUME: choose another feed or load history" :
"Closed bars: " + str.tostring(n) + " | zero/missing volume: " + str.tostring(missing)
if mode == "Manual Time" and time < anchorTime
state := "Waiting for manual anchor time"
if awaitingReset
state := "New anchor: waiting for first bar close"
table.cell(info, 0, 0, "CandleChasers VWAP Heat Map | " + mode,
text_color=color.white, bgcolor=color.rgb(20, 30, 45))
table.cell(info, 0, 1, scope,
text_color=color.white, bgcolor=color.rgb(20, 30, 45))
table.cell(info, 0, 2, state,
text_color=color.white, bgcolor=color.rgb(20, 30, 45))
The indicator below implements the article’s broad idea using original, disclosed calculations. It is not ChartPrime’s indicator, formula, or a claim of equivalent results. It combines a volume-weighted average of each completed chart bar’s typical price, weighted deviation bands, and an estimated volume-by-price distribution over the same stored sample.
What This Code Actually Shows
- Orange VWAP: sum of typical price × volume divided by total volume. Typical price is (high + low + close) / 3.
- Deviation bands: one and two volume-weighted population standard deviations of those representative bar prices. They are not prediction intervals or probabilities.
- Heat strip: fixed-width price rows colored from blue to orange according to estimated row volume relative to the largest row.
- Right-side profile: the same rows with horizontal lengths proportional to estimated volume.
- Estimated POC: the midpoint of the highest-volume row in this approximation. Equal-volume ties select the lower row; this is our rule, not ChartPrime’s control-level formula.
To estimate volume at price, each bar’s reported volume is spread uniformly across its low-to-high range in proportion to overlap with each row. A zero-range bar places its volume into one row. This conserves the allocated volume but cannot reproduce actual transactions at individual prices. It does not measure bid/ask delta, resting orders, or institutional activity.
Choose the Sample Before Interpreting It
Day, Week, and Month reset on the symbol’s exchange-based period boundaries. They use the chart’s included sessions, so changing between regular and extended hours changes the data. These modes are not a custom New York session filter. Rolling Bars uses the latest selected number of completed chart bars. Manual Time starts with the first chart bar opening at or after the selected timestamp; it cannot split a candle that straddles that timestamp.
The stored-bar limit defaults to 400. When an anchored sample exceeds that limit, both VWAP and the profile become calculations over the retained tail, not the full original anchor. The table reports this explicitly. Raise the limit up to 1,000 or choose a suitable timeframe if a longer complete sample is needed. An anchor boundary not observed in loaded history is labeled partial. Observing a boundary does not establish that the feed contains every transaction.
Setup and Troubleshooting
- Open a symbol with reported volume on a standard intraday candlestick chart; five-minute candles are a practical starting point.
- Paste the complete code into Pine Editor, save, and add it to the chart.
- Start with Day anchoring, 32 rows, and the 400-bar limit. Check the table’s sample status.
- Leave space to the right of the latest candle. The colored heat strip and profile are deliberately placed in the right margin. Adjust width or right offset if necessary.
- If volume is unavailable or always zero, use an appropriate symbol/feed. The script does not fabricate volume or silently substitute equal weights.
- For Manual Time, select a timestamp within loaded history and before the latest completed bar. A future anchor correctly displays no sample.
The indicator processes completed bars only. During an open candle, the sample remains at its last confirmed state; a new anchor waits for its first bar to close. The first bar of a new period is omitted from the VWAP line to prevent a misleading connecting segment between anchors. The right-side profile remains available when positive volume exists.
Developing Profile Versus Historical Signals
The profile is a current snapshot. New extremes can change its row boundaries, redistribute the estimated rows, and move its POC. The script deletes and redraws that right-side snapshot rather than painting the latest profile across past candles. Its placement beside the chart is a display choice, not a forecast.
The plotted VWAP and band history uses only the sample available at each completed bar. No higher-timeframe requests or future bars are used. Feed revisions, changed inputs, session changes, or different loaded history can still alter the result. Use replay and saved observations when testing whether a level existed before a reaction.
What This Code Does Not Test
This is an indicator, so it generates no Strategy Tester trades, entry arrows, profit estimates, or automatic orders. It does not reproduce ChartPrime’s proprietary weighting, heatmap rules, trend assistant, or control-level calculation. The weighted band calculation uses bar typical prices, not tick-by-tick price variance. Volume may represent different units across instruments and feeds.
Offline checks covered volume conservation, nonnegative row allocation, weighted mean and deviation calculations, flat-price bars, prefix causality, and the stored-bar limit. The script has not been compiled or run inside TradingView here. Check its displayed values and behavior on your intended chart before using it for analysis. TradingView’s drawing documentation (paid link) explains the boxes and lines used for the display.
Three Useful Comparisons
Compare 16, 32, and 64 rows while keeping the sample fixed: a useful area should not owe its entire appearance to one bin width. Next compare Day and Rolling Bars anchoring without treating them as the same dataset. Finally, compare the heatmap with the core VWAP under a predefined reaction rule, retaining failures. Record the sample status, row settings, level value, and timestamp before the touch. These are observational exercises; they do not establish a profitable execution strategy.
Final Takeaway
Know the anchor, understand what each layer measures, and confirm that highlighted levels existed before the reaction. Use the display to organize analysis, then apply explicit entry and risk rules.
Risk Disclosure
This article is for educational purposes only and is not financial advice or a recommendation to buy or sell any security. Trading involves substantial risk, including loss of capital. Leverage can magnify losses, and stop orders do not guarantee an execution price. Examples and historical results do not predict future performance. Account for fees, spread, slippage, and your own financial circumstances before trading.
CandleChasers is independent of the video creator. This article provides educational analysis of the source material; it does not verify the creator’s earnings or endorse paid products.