Video: PRICE ACTION: Once You Learn It, Trading Becomes Ridiculously Simple
Creator: Trading Notes
Original Video: Watch the original video
Difficulty: Advanced
The Big Idea
A simpler chart becomes useful when it supports a clear decision process. Trading Notes organizes that process around direction, confirmation, and invalidation: choose the side to consider, specify the event required for entry, and define what would disprove the trade.
The source applies those checks across two timeframes. A 15-minute chart supplies the directional map, while a one-minute chart supplies a structure shift and a fair value gap retest. This guide turns the framework into a decision sequence, clarifies the evidence behind its terminology, and provides a mechanical research approximation.
“Reacting” still involves a forecast: the trader expects the observed reaction to lead to continuation. The benefit is that the forecast has explicit conditions and a failure point. It does not remove uncertainty.
Direction: Establish a Map Before an Entry
For a bullish map, the video looks for higher highs and higher lows, followed by a close above an earlier high. It draws a trend line through two preceding lows and identifies the pullback area before that breakout. The bearish case reverses those relationships.
A break of structure describes a price event relative to a selected reference. It does not prove that buyers or sellers will retain control. Two traders can choose different swing points and label the same chart differently, especially when one uses small internal swings and another uses larger ones.
Choose the reference before seeing the outcome. Record the relevant swing prices, when each became identifiable, and whether a wick or a close counts as a break. If a pivot requires several subsequent bars for confirmation, the pivot was not available at its apparent turning point.
Trend lines also depend on selected anchors. A third touch can provide information about that particular line, but it does not turn the line into a physical barrier. Treat the mapped area as a place to observe a response.
Confirmation: Wait for a Defined Response
The source’s bullish sequence begins with a short-term decline into the mapped area. A one-minute close above a recent lower high signals a possible shift toward the higher-timeframe direction. A bullish fair value gap forms on the move, and price later returns to that gap.
The presenter waits for a bullish candle on the return rather than entering simply because the gap exists or is touched. The bearish example uses a short-term upward move, a downside structure shift, a bearish gap, and a bearish retest candle.
| Decision | Bullish example | Bearish example |
|---|---|---|
| 15-minute direction | Upward structure break | Downward structure break |
| One-minute shift | Close above a recent lower high | Close below a recent higher low |
| Three-candle gap | Third low exceeds first high | Third high is below first low |
| Retest confirmation | Return into the gap followed by a bullish close | Return into the gap followed by a bearish close |
| Failure planning | Protection beneath the defined setup | Protection above the defined setup |
The rejection candle must occur after the gap becomes identifiable. Using the gap’s third candle as its own historical retest would use a level that did not yet exist during that candle’s earlier trading.
What a Fair Value Gap Actually Shows
A bullish three-candle gap exists when the first candle’s high is below the third candle’s low. The interval between those prices is the marked zone. A bearish gap exists when the first candle’s low exceeds the third candle’s high.
This is non-overlap between the outer candles. The middle candle may have traded through the entire zone, so the pattern does not establish an absence of transactions or a price region that the market literally skipped.
The source interprets the pattern as evidence of momentum and a possible continuation area. That is a testable interpretation. Candle geometry alone cannot identify unfilled institutional orders, determine a “fair” price, or guarantee that the same participants will defend a retest. Some gaps are revisited, some fail, and some are never revisited.
For an original bullish example, suppose candle one has a $100.20 high and candle three a $100.50 low. The gap spans $100.20–$100.50. A later candle trades down to $100.35 and closes at $100.60 above its $100.42 open. That supplies a visible bullish response. A later close below $100.20 instead weakens the proposed gap-hold thesis.
Invalidation: Separate the Idea From the Order
The video describes both a stop beyond the candle creating the gap and a close through the full gap as failure information. Those are different exit mechanisms. A price-based stop may trigger intrabar; a close-based exit waits until a candle finishes and then submits an order.
Choose the intended mechanism before trading. “The candle that created the gap” is also ambiguous without the chart: it might refer to the middle displacement candle or another candle in the formation. A test needs an explicit choice rather than quietly selecting whichever stop would have survived.
A higher-timeframe change of character can undermine the broader directional idea, but that does not require allowing an individual trade to run until such a change appears. The trade’s protective stop and the map’s structural invalidation can operate at different scales.
In the example above, an assumed $100.60 entry and a $100.05 stop create $0.55 of price risk per share. A target at $101.70 offers $1.10, or 2R, before costs. An actual fill at $100.70 with unchanged levels produces $0.65 risk and $1.00 reward, about 1.54R. Entry slippage changes the trade even though the chart setup is identical.
Tools Can Draw the Pattern; They Cannot Validate the Edge
The source uses Price Action Toolkit by Flux Charts to draw market-structure labels and gap boxes, and promotes a discount. Those conveniences do not establish profitable expectancy. The transcript does not supply the toolkit’s complete structure algorithm, settings, or independently audited results.
Compare manual and automated labels using the same swing definitions and decision times. A label placed on an earlier candle can be visually persuasive even when the information required to confirm it arrived later. Keep the distinction between a label’s displayed location and its availability time.
Pine Script Research Strategy
Expand the complete Pine Script research strategy
//@version=6
strategy("Direction + FVG rejection - research proxy", overlay=true,
initial_capital=25000, pyramiding=0, margin_long=100, margin_short=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)
htfBars = input.int(20, "15-minute breakout lookback", minval=2)
localBars = input.int(5, "1-minute shift lookback", minval=2)
gapDelay = input.int(3, "Maximum bars from shift to gap", minval=0)
expiry = input.int(20, "Gap expiry in chart bars", minval=1)
minGapTicks = input.int(2, "Minimum gap size, ticks", minval=1)
reward = input.float(2, "Target / actual entry-to-stop distance", minval=0.1)
cashRisk = input.float(100, "Estimated cash risk before costs", minval=1)
lotStep = input.float(1, "Quantity increment", minval=0.000001)
maxQty = input.float(1000, "Maximum quantity", minval=0.000001)
useBias = input.bool(true, "Require 15-minute direction")
allowShorts = input.bool(true, "Allow shorts; verify actual borrow")
startMinute = input.int(570, "Entry start: NY minutes after midnight", minval=0, maxval=1439)
endMinute = input.int(660, "Entry end: NY minutes after midnight", minval=1, maxval=1440)
flattenMinute = input.int(960, "Flatten: NY minutes after midnight", minval=1, maxval=1440)
if barstate.isfirst and (not timeframe.isminutes or timeframe.multiplier != 1)
runtime.error("Use standard one-minute candles.")
if barstate.isfirst and endMinute <= startMinute
runtime.error("Entry end must be later than entry start.")
// Rolling-range breaks are our proxy, not a swing-labeling algorithm.
// Returned state is offset INSIDE the higher-timeframe context.
f_confirmedBias() =>
upper = ta.highest(high, htfBars)[1]
lower = ta.lowest(low, htfBars)[1]
var int direction = 0
if close > upper
direction := 1
else if close < lower
direction := -1
direction[1]
bias = request.security(syminfo.tickerid, "15", f_confirmedBias(),
gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
localHigh = ta.highest(high, localBars)[1]
localLow = ta.lowest(low, localBars)[1]
bullShift = close > localHigh and close[1] <= localHigh
bearShift = close < localLow and close[1] >= localLow
bullGap = low > high[2] and low - high[2] >= minGapTicks * syminfo.mintick
bearGap = high < low[2] and low[2] - high >= minGapTicks * syminfo.mintick
varip float seenPosition = 0.0
fillPass = strategy.position_size != seenPosition
seenPosition := strategy.position_size
varip int dayKey = na
varip bool usedToday = false
varip int shiftDirection = 0
varip int shiftBar = na
varip int zoneDirection = 0
varip int zoneBar = na
varip float zoneLow = na
varip float zoneHigh = na
varip float zoneStop = na
varip float tradeStop = na
varip float tradeTarget = na
// Fill passes read actual fill price and previously frozen stop only.
// They do not select setups using the fill bar's OHLC.
if fillPass and strategy.position_size != 0
distance = strategy.position_size > 0 ? strategy.position_avg_price - tradeStop : tradeStop - strategy.position_avg_price
if distance > 0
tradeTarget := strategy.position_avg_price + (strategy.position_size > 0 ? 1 : -1) * reward * distance
else
strategy.close_all(comment="Fill beyond stop", immediately=true)
if not fillPass and barstate.isconfirmed
key = year(time, "America/New_York") * 10000 + month(time, "America/New_York") * 100 + dayofmonth(time, "America/New_York")
if na(dayKey) or key != dayKey
dayKey := key
usedToday := false
shiftDirection := 0
zoneDirection := 0
minutesOpen = hour(time, "America/New_York") * 60 + minute(time, "America/New_York")
minutesClose = hour(time_close, "America/New_York") * 60 + minute(time_close, "America/New_York")
entryWindow = minutesOpen >= startMinute and minutesClose < endMinute
if strategy.position_size == 0 and not usedToday
if not entryWindow
zoneDirection := 0
shiftDirection := 0
else
if zoneDirection != 0
invalid = bar_index - zoneBar > expiry or
(zoneDirection == 1 ? close < zoneLow : close > zoneHigh) or
(useBias and bias != zoneDirection)
if invalid
zoneDirection := 0
if zoneDirection == 0
if bullShift and (not useBias or bias == 1)
shiftDirection := 1
shiftBar := bar_index
else if bearShift and allowShorts and (not useBias or bias == -1)
shiftDirection := -1
shiftBar := bar_index
if shiftDirection != 0 and bar_index - shiftBar <= gapDelay
if shiftDirection == 1 and bullGap
zoneDirection := 1
zoneLow := high[2]
zoneHigh := low
zoneStop := math.min(low[1], zoneLow) - syminfo.mintick
zoneBar := bar_index
shiftDirection := 0
else if shiftDirection == -1 and bearGap
zoneDirection := -1
zoneLow := high
zoneHigh := low[2]
zoneStop := math.max(high[1], zoneHigh) + syminfo.mintick
zoneBar := bar_index
shiftDirection := 0
if zoneDirection != 0 and bar_index > zoneBar
touched = low <= zoneHigh and high >= zoneLow
rejection = zoneDirection == 1 ? close > open and close > zoneHigh : close < open and close < zoneLow
distance = zoneDirection == 1 ? close - zoneStop : zoneStop - close
if touched and rejection and distance > 0
unitRisk = distance * syminfo.pointvalue
quantity = math.floor(math.min(maxQty, cashRisk / unitRisk) / lotStep) * lotStep
if quantity >= lotStep
tradeStop := zoneStop
tradeTarget := na
usedToday := true
if zoneDirection == 1
strategy.entry("L", strategy.long, qty=quantity)
strategy.exit("L-bracket", "L", stop=tradeStop)
else
strategy.entry("S", strategy.short, qty=quantity)
strategy.exit("S-bracket", "S", stop=tradeStop)
zoneDirection := 0
if minutesClose == flattenMinute
strategy.cancel_all()
strategy.close_all(comment="Session flatten", immediately=true)
if strategy.position_size > 0 and not na(tradeTarget)
strategy.exit("L-bracket", "L", stop=tradeStop, limit=tradeTarget)
if strategy.position_size < 0 and not na(tradeTarget)
strategy.exit("S-bracket", "S", stop=tradeStop, limit=tradeTarget)
plot(zoneDirection != 0 ? zoneLow : na, "Active gap low", color=color.orange, style=plot.style_linebr)
plot(zoneDirection != 0 ? zoneHigh : na, "Active gap high", color=color.orange, style=plot.style_linebr)
plot(strategy.position_size != 0 ? tradeStop : na, "Frozen stop", color=color.red, style=plot.style_linebr)
plot(strategy.position_size != 0 ? tradeTarget : na, "Fill-based target", color=color.green, style=plot.style_linebr)
The following strategy tests a reduced sequence on standard one-minute candles: a confirmed 15-minute directional state, a local range break, a same-direction three-candle gap, and a subsequent retest that closes beyond the gap in the trade direction.
The following choices are our research definitions: a 15-minute close beyond the prior 20-bar range changes the directional state; a one-minute close beyond the prior five-bar range supplies the local shift; a gap must appear within three bars, span at least two ticks, and receive its retest within 20 bars. The local break is a proxy, not a complete change-of-character algorithm requiring a preceding countertrend.
The rejection rule is stricter than the source’s candle-color description: a long retest must close above the gap’s upper edge; a short must close below its lower edge. The stop uses the middle candle’s extreme or the gap’s far boundary, whichever places it farther outside the zone, plus one tick.
One active gap is retained until used, invalidated, or expired. New gaps do not replace a valid active one. Entry is restricted to 9:30–11:00 New York time, with at most one submitted entry per calendar day. These time and frequency limits are ours. The target defaults to 2R from the actual simulated entry and frozen stop, replacing the source’s discretionary next 15-minute level.
Execution Checks That Affect the Result
Higher-timeframe direction uses the previous completed 15-minute state. The offset is applied inside the higher-timeframe calculation before requesting it with lookahead enabled. This follows TradingView’s documented confirmed higher-timeframe approach (paid link); an unshifted request would expose future information in historical tests.
Entries are market orders after a confirmed rejection candle, normally filled at the next bar’s open. A frozen protective stop is submitted with the entry. On the fill recalculation, the strategy reads the actual entry price and frozen stop to establish its target; it does not use the fill bar’s completed high, low, or close to select another setup. A fill beyond the stop prompts an immediate simulated exit, rather than creating an inverted bracket.
Position quantity is estimated at the rejection close. A gap at entry can exceed the intended cash risk even though the target is recalculated correctly. Commission defaults to 0.01% per fill and slippage to two ticks, adjustable in Strategy Properties. Borrow availability, borrow fees, spreads that vary through the session, and order rejection are not modeled. The 100% margin setting can prevent an otherwise plotted setup from receiving a fill.
The strategy flattens at the configured session close using an immediate simulated close. That assumes an obtainable closing fill and requires cost stress. Use 780 minutes after midnight for a 13:00 early close; the default is 960 for 16:00. The script does not automatically identify holiday sessions. Use a consistent chart session across comparisons because it affects the ranges and gaps.
Same-bar stop and target outcomes depend on TradingView’s broker emulator. Use Bar Magnifier where available and inspect ambiguous trades. Code logic has been reviewed, but this script has not been compiled or backtested in TradingView. No profitability or fill-quality result is claimed.
Backtest Lab: Find Out Which Check Helps
| Experiment | Change | Evaluate |
|---|---|---|
| Directional context | Toggle the 15-minute bias filter | Net expectancy, drawdown, and trade count |
| Gap freshness | Compare short and long expiry periods | Whether delayed retests perform differently |
| Structure definition | Change the five-bar local lookback | Stability rather than one best setting |
| Execution sensitivity | Increase slippage and commissions | How much of the result survives realistic friction |
Keep instruments and dates consistent, change one assumption at a time, and reserve an untouched period for validation. Include losing trades and record gaps that never produced entries. Selected chart winners do not establish a win rate.
This test does not reproduce the drawn trend line, the selected 15-minute pullback area, the toolkit’s proprietary labels, or its next-level targets. Its higher-timeframe bias can update while waiting; the source describes holding its map fixed during the trade. A useful manual comparison is to annotate the omitted context before seeing each outcome and check whether it improves the mechanical baseline.
Final Takeaway
Direction, confirmation, and invalidation make a trade easier to describe and review. Their value depends on definitions available at the time, realistic fills, and evidence across many opportunities. A fair value gap can mark a candidate retest area; a subsequent response supplies additional information, while the stop limits planned exposure when the idea fails.
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. Short selling adds borrow and potentially unlimited-loss 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 Trading Notes or Flux Charts.