Video: BEST Volume Profile Trading Strategy For Beginners
Creator: Mind Math Money
Original Video: Watch the original video
Difficulty: Intermediate
The Big Idea
Volume profile helps identify where trading activity was concentrated during a chosen period. It does not tell you to buy or sell automatically at those prices.
Mind Math Money proposes a sequence: select a meaningful range or swing, extend the completed profile’s levels, wait for price to return, and enter only after a defined reaction or acceptance. The distinction between a completed profile and later trading is central. A level selected after a successful bounce was not necessarily available before that bounce.
What POC, VAH, and VAL Describe
| Level | Meaning | What it does not promise |
|---|---|---|
| Point of control, POC | The price row with the largest allocated volume | A guaranteed magnet or future reversal |
| Value area high, VAH | The upper boundary of the selected value area | An exact resistance price |
| Value area low, VAL | The lower boundary of the selected value area | An exact support price |
TradingView’s volume-profile documentation (paid link) describes lower-timeframe calculations and a default value-area percentage of 70%. That percentage describes historical volume allocation, not a 70% probability that future price will remain inside the area.
Profile results depend on the instrument’s data feed, selected period, row size, session, and calculation method. Some feeds provide traded volume; others provide tick volume. A Bitcoin profile from one exchange does not necessarily represent the entire crypto market.
Choose the Profile to Answer a Question
The source warns against drawing profiles across arbitrary portions of the chart. A range profile asks where activity concentrated during a balance period. A swing profile asks where activity concentrated during a specific directional move. Those questions can produce different levels.
For an original exercise, identify a consolidation using a rule written before the later move is visible. Record its beginning, ending, and the time at which you recognized it as complete. Calculate the profile from that interval, then evaluate only subsequent returns.
If recognition requires a breakout candle, the profile becomes usable only after that breakout is confirmed. Backdating the levels into the earlier consolidation would use information not yet available.
Also freeze the profile’s price rows and settings. Changing the row count after seeing which POC would have worked is another form of selection.
Why Visible Range Can Move the Goalposts
A visible-range profile changes when the visible chart interval changes. Scrolling or zooming can therefore alter the POC, VAH, and VAL without any change to the historical trades themselves.
That makes it useful for exploration but difficult to reproduce unless the exact interval is recorded. A fixed-range profile with explicit start and end times is easier to evaluate consistently.
A developing profile can also be useful, but it represents a different experiment. Its levels change as new trading arrives. A test of a completed profile must not use its final levels while simulating trades during its formation.
Zones Allow Messy Price Behavior
The presenter treats levels as zones because price can overshoot, fluctuate, and recover around them. A zone gives the trader a defined tolerance; it should not become an excuse to widen the setup after price moves against it.
Suppose an original completed profile has VAL at 100, POC at 106, and VAH at 110. Define the VAL zone as 99.50–100.50 before the retest. A candle that trades to 99.70 and closes at 101.20 has interacted with the zone and recovered above it. A candle closing at 98.80 has a different meaning.
Zone width can be expressed in ticks, absolute price units, or a volatility measure frozen at the profile’s completion. Document the choice and test nearby values. An extremely wide zone can make almost any candle look like a successful interaction.
Reaction and Acceptance Are Different Trades
A reaction trade expects price to turn away from the area. The source mentions a hammer, bullish engulfing candle, or piercing pattern as possible confirmation. An acceptance trade expects price to establish itself beyond the area, more like a breakout.
Choose which you are testing. Two closes beneath VAL followed by a failed retest from below would challenge a bullish reaction thesis; they might instead help define a bearish acceptance setup.
The source’s daily Bitcoin example combines a VAL support area, a bullish two-candle pattern, and RSI divergence. Some transcript wording about above-versus-below is inconsistent, so the exact wick placement cannot be reconstructed confidently without the chart.
Classic piercing-pattern definitions can include an opening gap, which is less natural on a continuously traded crypto market. A crypto adaptation should be labeled explicitly rather than treated as the same rule without qualification.
Confluence Is Useful, but Not Independent Proof
A lower price low with a higher RSI low can show weaker measured downward momentum. It does not ensure a reversal. Pair the RSI readings with the same price swing locations, rather than searching unrelated lows for a convenient comparison.
If swing confirmation requires later bars, the divergence becomes available only after those bars arrive. A test cannot use the later-confirmed divergence at the earlier low.
Support, a VAL zone, a candle pattern, and RSI may all describe aspects of the same price episode. Four labels do not automatically equal four independent pieces of evidence. Compare the base reaction rule against the added RSI condition to see whether it contributes useful information.
Translate the Reaction Into Risk
For the original example above, assume an entry at 101.20 and a stop at 99.40 beneath the rejection low. Price risk is 1.80 units. A 2R target is 104.80; a 3R target is 106.60. The POC at 106 offers approximately 2.67R before costs.
The source discusses both fixed reward/risk targets and POC targets. They are different policies. A POC very close to entry may offer inadequate reward, while a distant POC may be difficult to reach.
Adding “wiggle room” beneath a wick changes the risk distance and therefore position size. At a hypothetical $180 price-risk budget and a $1-per-unit multiplier, 1.80 units of distance permits 100 units before costs. Widening the stop without reducing size raises the potential loss.
Pine Script: Test Reactions at a Real, Completed Profile
Expand the complete Pine Script research strategy
//@version=6
strategy("Fixed VAL reaction - supplied profile levels", overlay=true,
initial_capital=25000, pyramiding=0, margin_long=100,
commission_type=strategy.commission.percent, commission_value=0.01,
slippage=2, calc_on_order_fills=true, calc_on_every_tick=false,
process_orders_on_close=false)
val = input.float(0, "Completed profile VAL (enter actual level)", minval=0)
poc = input.float(0, "Completed profile POC (enter actual level)", minval=0)
vah = input.float(0, "Completed profile VAH (enter actual level)", minval=0)
profileEnd = input.time(timestamp("01 Feb 2024 00:00 +0000"), "First timestamp AFTER completed profile")
tradeEnd = input.time(timestamp("01 Mar 2024 00:00 +0000"), "Last permitted trade window")
zoneHalfWidth = input.float(0.25, "VAL zone half-width, price units", minval=0)
bufferTicks = input.int(2, "Stop buffer, ticks", minval=1)
targetMode = input.string("Fixed R", "Target mode", options=["Fixed R", "POC"])
reward = input.float(2, "Fixed target R", minval=0.1)
cashRisk = input.float(100, "Estimated cash risk before costs", minval=1)
qtyStep = input.float(1, "Quantity increment", minval=0.000001)
maxQty = input.float(1000, "Maximum quantity", minval=0.000001)
maxEntries = input.int(1, "Maximum submitted entries for this profile", minval=1)
pattern = input.string("Any", "Reaction", options=["Any", "Hammer", "Engulfing", "Piercing-style"])
if barstate.isfirst
if not chart.is_standard
runtime.error("Use standard candles.")
if val <= 0 or poc < val or vah < poc or vah <= val
runtime.error("Enter actual ordered profile levels: 0 < VAL <= POC <= VAH, with VAL < VAH.")
if tradeEnd <= profileEnd
runtime.error("Trade window must end after the profile is complete.")
zoneLow = val - zoneHalfWidth
zoneHigh = val + zoneHalfWidth
body = math.abs(close - open)
lowerWick = math.min(open, close) - low
upperWick = high - math.max(open, close)
hammer = close > open and body > 0 and lowerWick >= 2 * body and upperWick <= body
engulf = close > open and close[1] < open[1] and open <= close[1] and close >= open[1]
// Crypto-friendly adaptation: no mandatory overnight opening gap.
piercing = close > open and close[1] < open[1] and low < low[1] and
close > (open[1] + close[1]) / 2 and close < open[1]
reaction = pattern == "Hammer" ? hammer : pattern == "Engulfing" ? engulf :
pattern == "Piercing-style" ? piercing : hammer or engulf or piercing
touch = low <= zoneHigh and high >= zoneLow
reject = close > zoneHigh
window = time >= profileEnd and time_close < tradeEnd
varip float seenPosition = 0.0
varip float fixedStop = na
varip float fixedTarget = na
varip int entries = 0
varip int lastFillBar = na
fillPass = strategy.position_size != seenPosition
seenPosition := strategy.position_size
if fillPass
lastFillBar := bar_index
if strategy.position_size > 0
riskDistance = strategy.position_avg_price - fixedStop
fixedTarget := targetMode == "POC" ? poc : strategy.position_avg_price + reward * riskDistance
if riskDistance <= 0 or fixedTarget <= strategy.position_avg_price or time >= tradeEnd
fixedTarget := na
strategy.close("L", comment="Invalid fill/target", immediately=true)
if not fillPass and barstate.isconfirmed and strategy.position_size == 0 and
(na(lastFillBar) or bar_index > lastFillBar) and entries < maxEntries and
window and touch and reject and reaction
candidateStop = math.min(low, low[1]) - bufferTicks * syminfo.mintick
distance = close - candidateStop
unitRisk = distance * syminfo.pointvalue
quantity = unitRisk > 0 ? math.floor(math.min(maxQty, cashRisk / unitRisk) / qtyStep) * qtyStep : 0
targetValid = targetMode != "POC" or poc > close
if quantity >= qtyStep and targetValid
fixedStop := candidateStop
fixedTarget := na
entries += 1
strategy.entry("L", strategy.long, qty=quantity)
strategy.exit("L-bracket", "L", stop=fixedStop)
if strategy.position_size > 0 and not na(fixedTarget)
strategy.exit("L-bracket", "L", stop=fixedStop, limit=fixedTarget)
if not fillPass and barstate.isconfirmed and time_close >= tradeEnd and strategy.position_size > 0
strategy.cancel_all()
strategy.close("L", comment="Profile window ended")
plot(time >= profileEnd ? val : na, "Frozen VAL", color=color.blue, style=plot.style_linebr)
plot(time >= profileEnd ? poc : na, "Frozen POC", color=color.orange, style=plot.style_linebr)
plot(time >= profileEnd ? vah : na, "Frozen VAH", color=color.purple, style=plot.style_linebr)
plot(time >= profileEnd ? zoneLow : na, "VAL zone low", color=color.new(color.blue, 60), style=plot.style_linebr)
plot(time >= profileEnd ? zoneHigh : na, "VAL zone high", color=color.new(color.blue, 60), style=plot.style_linebr)
plot(strategy.position_size > 0 ? fixedStop : na, "Stop", color=color.red, style=plot.style_linebr)
plot(strategy.position_size > 0 ? fixedTarget : na, "Target", color=color.green, style=plot.style_linebr)
The strategy below takes manually supplied VAL, POC, and VAH from a completed profile. It does not estimate volume-at-price from candle volume or pretend that a moving average is a profile. This lets you test entry and exit rules against the levels you actually recorded.
Enter the actual levels, the first timestamp after the profile is fully known, and the end of the evaluation window. The default dates and zero prices are placeholders; the script will require valid levels before running.
Our test definitions: a long candle must overlap the fixed VAL zone, close above its upper edge, and satisfy a bullish hammer, engulfing, or explicitly adapted piercing-style pattern. The stop is beneath the lower low of the current and previous candles plus a tick buffer. This conservative two-candle stop is ours. RSI divergence, market-structure selection, bearish trades, and acceptance entries are not included.
The default permits one submitted entry per profile. A fixed 2R target is calculated from actual simulated entry and the frozen stop; POC is an alternative target. A POC at or below the entry is rejected.
Execution QA and Limits
Use standard candles and the same instrument, timeframe, session, and data feed used to record the profile. The source example uses daily Bitcoin; lower-timeframe tests answer a different question.
The strategy cannot validate that your entered profile levels were known at the entered time. That is your research record’s responsibility. Do not use a final profile containing later bars, and do not manually choose only profiles that preceded winners.
A reaction is evaluated at candle close, with a market order normally filling at the next bar’s open. The initial stop is submitted alongside the entry. A fill-only recalculation uses the actual entry and frozen stop for its bracket, without using the fill bar’s completed high or low to select another entry. A fill beyond the stop, beyond the trade window, or at or above a POC target prompts an immediate simulated exit.
Quantity is estimated from the signal close, so gap and slippage risk can exceed the intended cash amount. Set quantity increments and limits for the product. The sizing assumes the risk budget and instrument profit-and-loss values use the same currency; currency conversion is not modeled. The 100% margin setting can prevent orders from filling.
Commission defaults to 0.01% per fill and slippage to two ticks, adjustable in Strategy Properties. Spreads, funding, and venue-specific execution are not modeled. At the window’s end, an open trade receives a market-close instruction normally filled on the next available tick. Stops and targets remain price orders, and same-bar outcomes depend on emulator assumptions.
The code has been reviewed for its stated logic but has not been compiled or backtested in TradingView. It tests reactions to supplied levels, not the quality of profile construction. One profile is a case study; a performance estimate needs a consistently selected collection of profiles.
Backtest Lab
| Comparison | Change one assumption | Measure |
|---|---|---|
| Zone width | Narrow versus wider fixed zones | Trade count, adverse excursion, net expectancy |
| Reaction type | Hammer, engulfing, or piercing-style | Whether results depend on one definition |
| Exit policy | 2R, 3R, or frozen POC | Realized payoff and time in trade |
| Repeat touches | One versus several permitted entries | Later-touch performance and accumulated losses |
Retain the same profiles, dates, and cost assumptions. Aggregate results without overlapping the same trade across several profiles, then reserve new profiles for validation. A favorable annotated chart does not establish that a particular pattern or profile boundary has an edge.
Final Takeaway
Volume profile provides historical context. A complete trading rule still needs a purposeful profile interval, levels known before entry, a defined zone, observable confirmation, and an exit policy. Keeping those elements fixed makes it possible to learn from both the reactions that worked and the levels that failed.
Risk Disclosure: This material is for educational and research purposes only and is not financial or investment advice. Trading can result in substantial losses. Backtests are hypothetical, depend heavily on their assumptions, and cannot reproduce every aspect of live execution. Commissions, spreads, slippage, liquidity, gaps, order behavior, market regime changes, and discretionary decision-making can materially affect real-world results. Crypto and leveraged products carry additional volatility, venue, and liquidation risks. Historical results do not guarantee future performance.
This article is an independent educational companion to the video and is not affiliated with, sponsored by, endorsed by, or authorized by Mind Math Money.