OPEN-SOURCE SCRIPT
Structure-Anchored VWAP [WillyAlgoTrader]

📐 Structure-Anchored VWAP is an overlay indicator that anchors a true volume-weighted average price to market structure and re-anchors it automatically at every confirmed swing pivot, structure break, fast extreme, or one manual date — combining a pivot-based structure engine, an O(1) prefix-sum VWAP core, volume-weighted sigma bands, a retest entry model with ATR risk management, and a sectioned dashboard with session statistics.
The core insight: a VWAP anchored to the start of the current structural leg tells you the average price at which volume actually changed hands since this move began. That is the level participants in this leg are collectively break-even at. Session VWAP resets at midnight and ignores structure. Manual anchored VWAP requires you to drag it and re-drag it. This indicator keeps the anchor synchronised with the structure itself, and measures how stretched price is from that anchor in the leg's own volume-weighted standard deviations rather than in generic ATR units.
It works on any market and any timeframe. On instruments with no volume feed it falls back to time weighting automatically and says so in the dashboard.
🧩 WHY THESE COMPONENTS WORK TOGETHER
A VWAP alone has no memory of structure — it does not know whether the market is making higher highs or lower lows, so it cannot know when its own anchor has gone stale. A structure detector alone tells you HH / HL / LH / LL but gives you no price level to trade against. Deviation bands built on ATR describe candle size, not participation, so they say nothing about where volume was actually transacted. And an entry signal without a fixed stop and target is not a trade, it is an opinion.
This indicator connects all four into one chain:
Pivot structure engine → anchor selection → prefix-sum anchored VWAP → volume-weighted sigma bands → retest detection → ATR risk model → session statistics
The structure engine finds confirmed swing highs and lows, filters them by ATR amplitude and enforces strict high/low alternation, so every anchor is a real structural turn rather than a passing wick. Anchor selection decides which of those turns starts a new leg, with four different policies for four trading styles. The prefix-sum core then computes the anchored VWAP for that leg — and because it also accumulates the sum of squared prices, the same pass produces the leg's own volume-weighted standard deviation, so the bands are derived from the same data as the line instead of being bolted on. The retest engine watches the distance between price and that line, requires price to leave and come back, and only then produces an entry. The risk model turns the entry into a fixed stop and three targets, and the statistics layer records what happened to each of them.
Remove any link and the chain stops working. Without structure anchoring, the VWAP measures a leg that ended days ago. Without the ATR amplitude filter, every minor wick creates a new anchor and the line resets constantly. Without the sigma bands, "far from VWAP" has no unit. Without the retest rule, every touch of the line is a signal, including the fifty touches that happen while price is glued to it. Without the risk layer, you know where to enter but not where you are wrong.
🔍 WHAT MAKES IT ORIGINAL
1️⃣ Prefix-sum VWAP core — any anchor evaluated in O(1), including a decayed one.
Three running totals are maintained on every bar, where p is the price source and w is the bar weight:
— S_w(t) = lam × S_w(t−1) + w(t)
— S_pw(t) = lam × S_pw(t−1) + p(t) × w(t)
— S_p2(t) = lam × S_p2(t−1) + p(t)² × w(t)
The sum over any leg [a..t] is then recovered without looping:
— sum[a..t] = S(t) − lam^(t−a+1) × S(a−1)
With lam = 1 this is an exact cumulative anchored VWAP — every bar of the leg keeps its full weight, the same quantity the built-in Anchored VWAP tool computes. With lam < 1 the same identity still holds, which is what makes the optional Half-life mode possible without a second engine.
Why this matters: re-anchoring becomes cheap. Moving the anchor does not require replaying the whole leg bar by bar, so the indicator can afford four anchor modes and legs up to 4000 bars long without a performance penalty.
2️⃣ Volume-weighted sigma bands — dispersion of the leg, not size of the candle.
Because the squared-price sum is already accumulated, the leg's variance comes out of the same pass:
— VWAP = sum_pw / sum_w
— sigma = sqrt( max( sum_p2 / sum_w − VWAP², 0 ) )
Bands are drawn at VWAP ± multiplier × sigma. Band 1 defaults to 0.5 sigma (the value-area edge of this leg), Band 2 to 2.0 sigma and is off by default.
Why this matters: an ATR band tells you how big recent candles were. A volume-weighted sigma band tells you how widely the volume of this specific leg was distributed around its own average price. Two markets with identical ATR but different participation profiles get different bands, and the "Premium / Fair value / Discount" classification in the dashboard becomes comparable across instruments.
3️⃣ Four anchor modes — one engine, four trading styles.
— Swing (default): a new leg starts at every confirmed pivot. The anchor is the opposite extreme, so a bullish leg is anchored at the swing low that preceded it.
— Structure break: a new leg starts only when price closes beyond the previous swing. The anchor is then the extreme that preceded the break, found by scanning back from that swing. Fewer legs, each tied to an actual break of structure.
— Fast: no confirmation delay. The bar printing the highest high or lowest low of the last N bars (default 30) is treated as a new extreme, and the leg flips the moment an extreme opposite to the previous one appears. When a bar prints both a new high and a new low, the candle direction decides which one is taken.
— Manual: a single leg from a chosen date and time, which reproduces the behaviour of the built-in Anchored VWAP tool inside the same framework — useful for comparing against a manual anchor or pinning a level.
4️⃣ Structure engine with ATR amplitude filter and strict alternation.
Pivots come from equal left/right lookback (default 55/55). A new pivot of the opposite type is only accepted when it clears an ATR-scaled amplitude:
— accept a new high when: pivotHigh − lastSwingLow ≥ minSwing × ATR(atrLen)
— accept a new low when: lastSwingHigh − pivotLow ≥ minSwing × ATR(atrLen)
Default minSwing 1.5, ATR length 13. A pivot of the same type as the last one does not create a new structural point — it only supersedes the previous extreme if it is more extreme. This enforces a clean alternating high-low-high-low sequence instead of clusters of adjacent highs.
Classification against the previous extreme of the same type, with an equality tolerance (default 0.1 × ATR):
— |current − previous| ≤ eqTol × ATR → EQH or EQL
— current > previous → HH or HL
— current < previous → LH or LL
5️⃣ Retest entry model — price must leave before it can come back.
Every bar the engine measures the relationship between the bar range and the anchored VWAP:
— tol = sigma × touchTolerance (default 0.25), or ATR × 0.1 while sigma is still zero
— touch = low ≤ VWAP + tol and high ≥ VWAP − tol
— outside = bullish leg ? low > VWAP + tol : high < VWAP − tol
An "away" counter increments on every outside bar and resets to zero on every touch. A retest fires only when a touch happens while the committed away counter has already reached the threshold (default 5 bars).
Why this matters: a raw "price touched VWAP" condition fires continuously in the chop that surrounds every mean. Requiring a genuine departure first converts an omnipresent condition into a discrete, countable event.
6️⃣ Volume balance — who controlled this leg.
While the leg accumulates, every bar's weight is assigned to one of two buckets by where it closed relative to the VWAP at that moment:
— close ≥ VWAP → volUp += w
— close < VWAP → volDn += w
— balance = volUp / (volUp + volDn) × 100
The dashboard shows this as a percentage with a bar gauge, and relabels it "Bars above VWAP" automatically when the instrument has no volume data. Above 50 % means most of the leg's participation happened above its own average price.
7️⃣ Signal strength — a transparent 0-100 context score.
Four independent components, published in full so the number is auditable rather than a black box:
— 40 pts × (volume balance aligned with leg direction, 0..1). For a bearish leg the balance is inverted before scoring.
— 25 pts if price sits on the leg's own side of the VWAP.
— 20 pts if price is not stretched beyond Band 2, i.e. |distance in sigma| ≤ band 2 multiplier.
— 15 pts if the leg has already produced at least one retest.
The score is clamped to 100 and shown with a gauge. This is a context filter, not a proven edge — it says how coherent the current leg is, nothing more.
8️⃣ VWAP memory levels — dead legs leave a level behind.
When a leg ends on a genuine direction flip, its final VWAP value is written to the chart as a dashed horizontal line. That line extends forward until price trades through it, then it is either removed or faded to dotted, depending on a setting. Up to four such levels are kept (configurable), and the newest push out the oldest.
When a level is created, the bars between the anchor and the current bar are scanned first, so a level that was already traded through is never shown as untouched.
9️⃣ Single-position trade model with break-even and outcome tracking.
A retest signal opens a trade only while flat — signals never stack. On entry, the levels are fixed once and never recalculated:
— slDistance = ATR(riskAtrLen) × slMultiplier
— long: SL = entry − slDistance, TP(n) = entry + slDistance × tpMult(n)
— short: SL = entry + slDistance, TP(n) = entry − slDistance × tpMult(n)
Presets set all four multipliers at once — Conservative 2.5 / 1R / 2R / 4R, Balanced 1.5 / 1R / 2R / 3R, Aggressive 1.0 / 1.5R / 2.5R / 4R, Scalping 0.8 / 0.8R / 1.5R / 2R, or Custom.
Break-even is optional and on by default: the first touch of TP1 moves the stop to the entry price, the entry label changes to show it now acts as the stop, and the stop line dims. TP1 still counts as a win. Hit checks begin only on the bar after entry and only on confirmed bars, so the entry bar's own range cannot close the trade it just opened.
🔟 Persistent trade forensics — the chart keeps the last result.
SL and TP lines are not deleted when the trade closes. They stay until the next entry, so the last trade remains readable on the chart: any target that was reached is redrawn as a solid teal line and its label gets a check mark, while untouched targets keep their original dashed style. Labels can show the distance from entry in percent, for example "SL 78120.5 (-0.36%)".
1️⃣1️⃣ Realtime correctness — ring buffers and a commit/undo pattern.
Functions that only run on some bars cannot use the [ ] history operator safely, because the history they see is sparse and does not correspond to chart bars. All per-bar values this indicator needs later are therefore written to explicit ring buffers on every single bar, and read back by index.
On top of that, the live leg uses a commit/undo pattern: statistics are always recomputed from the last confirmed state, and the provisional point for the forming bar is popped before a new one is pushed. A bar being formed can therefore never be counted twice, no matter how many ticks arrive.
1️⃣2️⃣ Continuous curve across anchor changes.
When a new anchor appears, the previous leg is not erased — it is cut exactly at the new anchor bar and frozen. The curve therefore has no gaps at handover points, including the case where a stronger extreme of the same type supersedes the previous one.
⚙️ HOW IT WORKS — CALCULATION FLOW
Step 1 — Structure: On each confirmed bar the engine evaluates pivot highs and lows with equal left/right lookback, applies the ATR amplitude filter, enforces high/low alternation and classifies the result as HH, HL, LH, LL, EQH or EQL.
Step 2 — Weighting: The bar weight is volume, or 1.0 when the instrument has no volume. If spike clamping is on, the weight is capped at N × the 50-bar median volume so a single print cannot dominate the average.
Step 3 — Accumulation: The three running totals of weight, price × weight and price² × weight are advanced, decayed by lam if Half-life weighting is selected.
Step 4 — Buffering: The totals plus high, low, close and ATR are appended to ring buffers, one entry per bar, with the current bar's provisional entry overwritten rather than duplicated on repeat ticks.
Step 5 — Anchor decision: The active anchor mode decides whether this bar starts a new leg and where that leg's anchor sits.
Step 6 — Leg build: On a new anchor the previous leg is trimmed to the anchor bar, frozen and archived, a memory level is created if the direction actually flipped, and the new leg is replayed once from the anchor to the current bar. On every other bar the live leg simply advances by one point.
Step 7 — Readouts: VWAP, sigma, distance in sigma and percent, zone, volume balance, leg age and the strength score are computed for the current bar.
Step 8 — Signal: The retest rule is evaluated. A qualifying retest, on a confirmed and warmed-up bar, while flat, becomes an entry.
Step 9 — Risk: On entry the stop and three targets are fixed. On later confirmed bars they are tested for hits, break-even is applied after TP1, and the trade is closed by stop or final target.
Step 10 — Reporting: Lines, labels, markers, the dashboard and alerts are updated. Closed trades update the win/loss counters and the form strip.
📖 HOW TO USE
🎯 Quick start:
1. Add the indicator. Defaults are tuned for 15m to 4H swing structure.
2. Watch the coloured curve — it is the anchored VWAP of the leg the market is currently in.
3. Wait for a Long ▲ or Short ▼ marker. That is a retest of the VWAP in the direction of the leg.
4. Read the Trade section of the dashboard for the stop, the three targets and the R:R.
5. If signals are too frequent, raise "Bars away before a retest counts". If legs are too frequent, raise pivot strength or the minimum swing size.
👁️ Reading the chart:
— 🟢 Green curve = bullish leg, anchored at the swing low that started it.
— 🔴 Red curve = bearish leg, anchored at the swing high that started it.
— Shaded band around the curve = ± sigma of this leg. Price inside it is at fair value for the leg.
— 🟢 Long ▲ / 🔴 Short ▼ marker = a retest entry was taken on that bar.
— Dotted blue line = entry. Solid red line = stop. Dashed green lines = TP1, TP2, TP3.
— A target that turns solid teal with a ✓ in its label was reached.
— An orange entry label reading "→ SL (BE)" means the stop has been moved to break-even.
— Dashed horizontal level far from the curve = a memory level, the final VWAP of a finished leg.
— HH / HL / LH / LL / EQH / EQL tags mark every confirmed pivot.
📊 Dashboard fields:
— Trend: direction of the current leg.
— Signal: LONG, SHORT or Wait. A new trade can only open while flat.
— Strength: the 0-100 context score with a gauge.
— Last event: the most recent new leg or retest.
— Timeframe: the chart resolution.
— Mode: active anchor mode and weighting, plus a note when the symbol has no volume.
— Anchor: structure tag and price of the bar the leg is anchored to.
— Leg age: bars since the anchor and the price move from it.
— VWAP: the anchored VWAP on the current bar.
— Price vs VWAP: distance in sigma and in percent.
— Zone: Premium above Band 2, Discount below it, Fair value in between.
— Vol above VWAP: share of the leg's weight transacted above the VWAP, with a gauge.
— SL / TP1 / TP2 / TP3: the fixed levels of the open trade. A ✓ marks a reached target, "BE @" marks a stop moved to entry.
— R:R (TP1) and SL Dist %: reward-to-risk at the first target and the stop distance as a percentage of entry.
— Trades / W / L / Win rate / Form: closed trades in the loaded history, the win-loss split, the win rate with a gauge and the last ten outcomes as ▰ and ▱.
🔧 Tuning guide:
— Too many legs, the line resets constantly: raise pivot strength (55/55 → 80/80) or the minimum swing size (1.5 → 3.0).
— Legs appear too late: lower pivot strength, or switch the anchor mode to Fast for immediate flips.
— Too many entries: raise "Bars away before a retest counts" and lower the touch tolerance.
— The line drifts too far from price on long legs: switch Weighting to Half-life. This is no longer a textbook VWAP, and the dashboard says so.
— Comparing against the built-in Anchored VWAP tool: set the mode to Manual with the same anchor time, price source to hl2, weighting to Cumulative, and turn volume clamping off.
— Stops feel too tight or too wide: change the Risk Preset before touching individual multipliers.
⚙️ KEY SETTINGS
⚙️ Main Settings:
— Pivot strength left / right (default 55 / 55): bars required on each side of a swing. Right is the confirmation delay.
— Minimum swing size (default 1.5 × ATR): amplitude filter for new pivots. 0 disables it.
— ATR Length (default 13): ATR used by the swing filter and the equality tolerance.
— Re-anchor on (default Swing): Swing, Structure break, Fast or Manual.
— Fast mode: extreme lookback (default 30): lookback for the Fast mode only.
— Equal high/low tolerance (default 0.1 × ATR): threshold for EQH and EQL tags.
— Manual anchor: date and time for the Manual mode, shown in the chart's timezone.
📐 Anchored VWAP:
— Price source (default hl2): hl2 matches the built-in tool, hlc3 weights closes more, close is the most reactive.
— Weighting (default Cumulative): Cumulative is a true VWAP, Half-life fades older bars.
— Half-life (default 21 bars): only used by Half-life weighting.
— Clamp volume spikes (default on, 4 × median): caps outlier volume bars.
— Max leg length (default 4000 bars): keeps very old anchors bounded.
📏 Deviation Bands:
— Band 1 (default on, 0.5 sigma): inner band.
— Band 2 (default off, 2.0 sigma): outer band, also defines the Premium and Discount zones.
— Fill transparency (default 90).
🎯 Signals & Levels:
— Bars away before a retest counts (default 5).
— Touch tolerance (default 0.25 sigma).
— VWAP memory levels (default on, max 4, crossed levels removed).
🛡️ Risk Management:
— Risk Preset (default Balanced): Conservative, Balanced, Aggressive, Scalping or Custom.
— ATR Length (SL) (default 13).
— SL ×ATR / TP1 / TP2 / TP3 ×Risk (defaults 1.5 / 1.0 / 2.0 / 3.0): used by the Custom preset.
— Break-Even After TP1 (default on).
— Show SL/TP Lines, Labels, % Distance (all on by default).
— Entry / SL / TP Line Style (defaults Dotted / Solid / Dashed).
🎨 Visual:
— Theme (default Auto): Auto detects the chart background, Dark and Light force it.
— Show Buy/Sell Signals, HH/HL/LH/LL, Leg Background, Watermark.
— SL/TP Label Font Size (default Small).
— Finished legs kept on chart (default 30).
📊 Dashboard:
— Position (default Top Right) and four independent section switches: Market, VWAP, Trade, Stats.
🔔 ALERTS
— 🟢 LONG — VWAP retest entry, with price, VWAP, SL, TP1, TP2, TP3 and R:R
— 🔴 SHORT — same payload, short side
— 🛑 SL HIT — entry and stop price. Reported as 🛡️ BE STOP-OUT when the stop had already been moved to break-even
— 🛡️ BREAK-EVEN — stop moved to entry after TP1 (optional)
— 🎯 TP1 HIT, 🎯🎯 TP2 HIT, 🏆 TP3 HIT — first touch of each target (optional)
— 🟢 New bullish leg / 🔴 New bearish leg — a new anchor was set (optional)
— 🔵 Close above VWAP / 🔵 Close below VWAP — the close crossed the anchored VWAP (optional)
Entry alerts support both plain text and a JSON webhook payload. All alerts fire on bar close.
⚠️ IMPORTANT NOTES
— 🚫 No repainting of confirmed values. Every structure event, entry, stop, target and alert is evaluated only when barstate.isconfirmed is true. Pivots use equal left and right lookback, so the swing point is in the past by the "right" value at the moment it becomes known — that is delayed confirmation, not a look into the future. Stop and target hits are tested only from the bar after entry. Alerts fire once per bar close.
— 📐 What does update intrabar. The VWAP value of the leg currently in progress moves while the bar is forming, because that is what an anchored average does. Values on closed bars never change. A commit/undo pattern makes sure a forming bar is never counted twice in the statistics.
— 📐 The unfinished leg can be shortened. When a stronger extreme of the same type is confirmed, the current leg is cut at that point and a new leg starts there. Legs that have already been archived are never modified.
— 📊 The statistics are not a backtest. Trades, win rate and the form strip are counted over the history currently loaded on the chart and reset when the chart reloads or a setting changes. They describe how this rule set behaved on the visible data. Past performance does not guarantee future results.
— 🧮 The strength score is a context filter. Its four components and weights are published above precisely so it can be judged on its merits. It measures the internal coherence of the current leg, not the probability of any outcome.
— ⚖️ Half-life weighting is not a VWAP. When that mode is selected the line is an exponentially weighted average, useful on instruments without volume, but it is no longer the textbook volume-weighted average price. The dashboard states the active mode at all times.
— 🌐 Universal compatibility. Works on stocks, futures, forex, crypto and indices, on every timeframe. Where no volume data exists the weighting falls back to time and the dashboard relabels the volume-balance row accordingly.
— 🛠️ Decision support, not automation. This is an anchored VWAP and structure analysis tool with a risk framework attached. It marks anchors, measures distance in the leg's own units, detects retests and lays out stops and targets — trade decisions remain yours.
The core insight: a VWAP anchored to the start of the current structural leg tells you the average price at which volume actually changed hands since this move began. That is the level participants in this leg are collectively break-even at. Session VWAP resets at midnight and ignores structure. Manual anchored VWAP requires you to drag it and re-drag it. This indicator keeps the anchor synchronised with the structure itself, and measures how stretched price is from that anchor in the leg's own volume-weighted standard deviations rather than in generic ATR units.
It works on any market and any timeframe. On instruments with no volume feed it falls back to time weighting automatically and says so in the dashboard.
🧩 WHY THESE COMPONENTS WORK TOGETHER
A VWAP alone has no memory of structure — it does not know whether the market is making higher highs or lower lows, so it cannot know when its own anchor has gone stale. A structure detector alone tells you HH / HL / LH / LL but gives you no price level to trade against. Deviation bands built on ATR describe candle size, not participation, so they say nothing about where volume was actually transacted. And an entry signal without a fixed stop and target is not a trade, it is an opinion.
This indicator connects all four into one chain:
Pivot structure engine → anchor selection → prefix-sum anchored VWAP → volume-weighted sigma bands → retest detection → ATR risk model → session statistics
The structure engine finds confirmed swing highs and lows, filters them by ATR amplitude and enforces strict high/low alternation, so every anchor is a real structural turn rather than a passing wick. Anchor selection decides which of those turns starts a new leg, with four different policies for four trading styles. The prefix-sum core then computes the anchored VWAP for that leg — and because it also accumulates the sum of squared prices, the same pass produces the leg's own volume-weighted standard deviation, so the bands are derived from the same data as the line instead of being bolted on. The retest engine watches the distance between price and that line, requires price to leave and come back, and only then produces an entry. The risk model turns the entry into a fixed stop and three targets, and the statistics layer records what happened to each of them.
Remove any link and the chain stops working. Without structure anchoring, the VWAP measures a leg that ended days ago. Without the ATR amplitude filter, every minor wick creates a new anchor and the line resets constantly. Without the sigma bands, "far from VWAP" has no unit. Without the retest rule, every touch of the line is a signal, including the fifty touches that happen while price is glued to it. Without the risk layer, you know where to enter but not where you are wrong.
🔍 WHAT MAKES IT ORIGINAL
1️⃣ Prefix-sum VWAP core — any anchor evaluated in O(1), including a decayed one.
Three running totals are maintained on every bar, where p is the price source and w is the bar weight:
— S_w(t) = lam × S_w(t−1) + w(t)
— S_pw(t) = lam × S_pw(t−1) + p(t) × w(t)
— S_p2(t) = lam × S_p2(t−1) + p(t)² × w(t)
The sum over any leg [a..t] is then recovered without looping:
— sum[a..t] = S(t) − lam^(t−a+1) × S(a−1)
With lam = 1 this is an exact cumulative anchored VWAP — every bar of the leg keeps its full weight, the same quantity the built-in Anchored VWAP tool computes. With lam < 1 the same identity still holds, which is what makes the optional Half-life mode possible without a second engine.
Why this matters: re-anchoring becomes cheap. Moving the anchor does not require replaying the whole leg bar by bar, so the indicator can afford four anchor modes and legs up to 4000 bars long without a performance penalty.
2️⃣ Volume-weighted sigma bands — dispersion of the leg, not size of the candle.
Because the squared-price sum is already accumulated, the leg's variance comes out of the same pass:
— VWAP = sum_pw / sum_w
— sigma = sqrt( max( sum_p2 / sum_w − VWAP², 0 ) )
Bands are drawn at VWAP ± multiplier × sigma. Band 1 defaults to 0.5 sigma (the value-area edge of this leg), Band 2 to 2.0 sigma and is off by default.
Why this matters: an ATR band tells you how big recent candles were. A volume-weighted sigma band tells you how widely the volume of this specific leg was distributed around its own average price. Two markets with identical ATR but different participation profiles get different bands, and the "Premium / Fair value / Discount" classification in the dashboard becomes comparable across instruments.
3️⃣ Four anchor modes — one engine, four trading styles.
— Swing (default): a new leg starts at every confirmed pivot. The anchor is the opposite extreme, so a bullish leg is anchored at the swing low that preceded it.
— Structure break: a new leg starts only when price closes beyond the previous swing. The anchor is then the extreme that preceded the break, found by scanning back from that swing. Fewer legs, each tied to an actual break of structure.
— Fast: no confirmation delay. The bar printing the highest high or lowest low of the last N bars (default 30) is treated as a new extreme, and the leg flips the moment an extreme opposite to the previous one appears. When a bar prints both a new high and a new low, the candle direction decides which one is taken.
— Manual: a single leg from a chosen date and time, which reproduces the behaviour of the built-in Anchored VWAP tool inside the same framework — useful for comparing against a manual anchor or pinning a level.
4️⃣ Structure engine with ATR amplitude filter and strict alternation.
Pivots come from equal left/right lookback (default 55/55). A new pivot of the opposite type is only accepted when it clears an ATR-scaled amplitude:
— accept a new high when: pivotHigh − lastSwingLow ≥ minSwing × ATR(atrLen)
— accept a new low when: lastSwingHigh − pivotLow ≥ minSwing × ATR(atrLen)
Default minSwing 1.5, ATR length 13. A pivot of the same type as the last one does not create a new structural point — it only supersedes the previous extreme if it is more extreme. This enforces a clean alternating high-low-high-low sequence instead of clusters of adjacent highs.
Classification against the previous extreme of the same type, with an equality tolerance (default 0.1 × ATR):
— |current − previous| ≤ eqTol × ATR → EQH or EQL
— current > previous → HH or HL
— current < previous → LH or LL
5️⃣ Retest entry model — price must leave before it can come back.
Every bar the engine measures the relationship between the bar range and the anchored VWAP:
— tol = sigma × touchTolerance (default 0.25), or ATR × 0.1 while sigma is still zero
— touch = low ≤ VWAP + tol and high ≥ VWAP − tol
— outside = bullish leg ? low > VWAP + tol : high < VWAP − tol
An "away" counter increments on every outside bar and resets to zero on every touch. A retest fires only when a touch happens while the committed away counter has already reached the threshold (default 5 bars).
Why this matters: a raw "price touched VWAP" condition fires continuously in the chop that surrounds every mean. Requiring a genuine departure first converts an omnipresent condition into a discrete, countable event.
6️⃣ Volume balance — who controlled this leg.
While the leg accumulates, every bar's weight is assigned to one of two buckets by where it closed relative to the VWAP at that moment:
— close ≥ VWAP → volUp += w
— close < VWAP → volDn += w
— balance = volUp / (volUp + volDn) × 100
The dashboard shows this as a percentage with a bar gauge, and relabels it "Bars above VWAP" automatically when the instrument has no volume data. Above 50 % means most of the leg's participation happened above its own average price.
7️⃣ Signal strength — a transparent 0-100 context score.
Four independent components, published in full so the number is auditable rather than a black box:
— 40 pts × (volume balance aligned with leg direction, 0..1). For a bearish leg the balance is inverted before scoring.
— 25 pts if price sits on the leg's own side of the VWAP.
— 20 pts if price is not stretched beyond Band 2, i.e. |distance in sigma| ≤ band 2 multiplier.
— 15 pts if the leg has already produced at least one retest.
The score is clamped to 100 and shown with a gauge. This is a context filter, not a proven edge — it says how coherent the current leg is, nothing more.
8️⃣ VWAP memory levels — dead legs leave a level behind.
When a leg ends on a genuine direction flip, its final VWAP value is written to the chart as a dashed horizontal line. That line extends forward until price trades through it, then it is either removed or faded to dotted, depending on a setting. Up to four such levels are kept (configurable), and the newest push out the oldest.
When a level is created, the bars between the anchor and the current bar are scanned first, so a level that was already traded through is never shown as untouched.
9️⃣ Single-position trade model with break-even and outcome tracking.
A retest signal opens a trade only while flat — signals never stack. On entry, the levels are fixed once and never recalculated:
— slDistance = ATR(riskAtrLen) × slMultiplier
— long: SL = entry − slDistance, TP(n) = entry + slDistance × tpMult(n)
— short: SL = entry + slDistance, TP(n) = entry − slDistance × tpMult(n)
Presets set all four multipliers at once — Conservative 2.5 / 1R / 2R / 4R, Balanced 1.5 / 1R / 2R / 3R, Aggressive 1.0 / 1.5R / 2.5R / 4R, Scalping 0.8 / 0.8R / 1.5R / 2R, or Custom.
Break-even is optional and on by default: the first touch of TP1 moves the stop to the entry price, the entry label changes to show it now acts as the stop, and the stop line dims. TP1 still counts as a win. Hit checks begin only on the bar after entry and only on confirmed bars, so the entry bar's own range cannot close the trade it just opened.
🔟 Persistent trade forensics — the chart keeps the last result.
SL and TP lines are not deleted when the trade closes. They stay until the next entry, so the last trade remains readable on the chart: any target that was reached is redrawn as a solid teal line and its label gets a check mark, while untouched targets keep their original dashed style. Labels can show the distance from entry in percent, for example "SL 78120.5 (-0.36%)".
1️⃣1️⃣ Realtime correctness — ring buffers and a commit/undo pattern.
Functions that only run on some bars cannot use the [ ] history operator safely, because the history they see is sparse and does not correspond to chart bars. All per-bar values this indicator needs later are therefore written to explicit ring buffers on every single bar, and read back by index.
On top of that, the live leg uses a commit/undo pattern: statistics are always recomputed from the last confirmed state, and the provisional point for the forming bar is popped before a new one is pushed. A bar being formed can therefore never be counted twice, no matter how many ticks arrive.
1️⃣2️⃣ Continuous curve across anchor changes.
When a new anchor appears, the previous leg is not erased — it is cut exactly at the new anchor bar and frozen. The curve therefore has no gaps at handover points, including the case where a stronger extreme of the same type supersedes the previous one.
⚙️ HOW IT WORKS — CALCULATION FLOW
Step 1 — Structure: On each confirmed bar the engine evaluates pivot highs and lows with equal left/right lookback, applies the ATR amplitude filter, enforces high/low alternation and classifies the result as HH, HL, LH, LL, EQH or EQL.
Step 2 — Weighting: The bar weight is volume, or 1.0 when the instrument has no volume. If spike clamping is on, the weight is capped at N × the 50-bar median volume so a single print cannot dominate the average.
Step 3 — Accumulation: The three running totals of weight, price × weight and price² × weight are advanced, decayed by lam if Half-life weighting is selected.
Step 4 — Buffering: The totals plus high, low, close and ATR are appended to ring buffers, one entry per bar, with the current bar's provisional entry overwritten rather than duplicated on repeat ticks.
Step 5 — Anchor decision: The active anchor mode decides whether this bar starts a new leg and where that leg's anchor sits.
Step 6 — Leg build: On a new anchor the previous leg is trimmed to the anchor bar, frozen and archived, a memory level is created if the direction actually flipped, and the new leg is replayed once from the anchor to the current bar. On every other bar the live leg simply advances by one point.
Step 7 — Readouts: VWAP, sigma, distance in sigma and percent, zone, volume balance, leg age and the strength score are computed for the current bar.
Step 8 — Signal: The retest rule is evaluated. A qualifying retest, on a confirmed and warmed-up bar, while flat, becomes an entry.
Step 9 — Risk: On entry the stop and three targets are fixed. On later confirmed bars they are tested for hits, break-even is applied after TP1, and the trade is closed by stop or final target.
Step 10 — Reporting: Lines, labels, markers, the dashboard and alerts are updated. Closed trades update the win/loss counters and the form strip.
📖 HOW TO USE
🎯 Quick start:
1. Add the indicator. Defaults are tuned for 15m to 4H swing structure.
2. Watch the coloured curve — it is the anchored VWAP of the leg the market is currently in.
3. Wait for a Long ▲ or Short ▼ marker. That is a retest of the VWAP in the direction of the leg.
4. Read the Trade section of the dashboard for the stop, the three targets and the R:R.
5. If signals are too frequent, raise "Bars away before a retest counts". If legs are too frequent, raise pivot strength or the minimum swing size.
👁️ Reading the chart:
— 🟢 Green curve = bullish leg, anchored at the swing low that started it.
— 🔴 Red curve = bearish leg, anchored at the swing high that started it.
— Shaded band around the curve = ± sigma of this leg. Price inside it is at fair value for the leg.
— 🟢 Long ▲ / 🔴 Short ▼ marker = a retest entry was taken on that bar.
— Dotted blue line = entry. Solid red line = stop. Dashed green lines = TP1, TP2, TP3.
— A target that turns solid teal with a ✓ in its label was reached.
— An orange entry label reading "→ SL (BE)" means the stop has been moved to break-even.
— Dashed horizontal level far from the curve = a memory level, the final VWAP of a finished leg.
— HH / HL / LH / LL / EQH / EQL tags mark every confirmed pivot.
📊 Dashboard fields:
— Trend: direction of the current leg.
— Signal: LONG, SHORT or Wait. A new trade can only open while flat.
— Strength: the 0-100 context score with a gauge.
— Last event: the most recent new leg or retest.
— Timeframe: the chart resolution.
— Mode: active anchor mode and weighting, plus a note when the symbol has no volume.
— Anchor: structure tag and price of the bar the leg is anchored to.
— Leg age: bars since the anchor and the price move from it.
— VWAP: the anchored VWAP on the current bar.
— Price vs VWAP: distance in sigma and in percent.
— Zone: Premium above Band 2, Discount below it, Fair value in between.
— Vol above VWAP: share of the leg's weight transacted above the VWAP, with a gauge.
— SL / TP1 / TP2 / TP3: the fixed levels of the open trade. A ✓ marks a reached target, "BE @" marks a stop moved to entry.
— R:R (TP1) and SL Dist %: reward-to-risk at the first target and the stop distance as a percentage of entry.
— Trades / W / L / Win rate / Form: closed trades in the loaded history, the win-loss split, the win rate with a gauge and the last ten outcomes as ▰ and ▱.
🔧 Tuning guide:
— Too many legs, the line resets constantly: raise pivot strength (55/55 → 80/80) or the minimum swing size (1.5 → 3.0).
— Legs appear too late: lower pivot strength, or switch the anchor mode to Fast for immediate flips.
— Too many entries: raise "Bars away before a retest counts" and lower the touch tolerance.
— The line drifts too far from price on long legs: switch Weighting to Half-life. This is no longer a textbook VWAP, and the dashboard says so.
— Comparing against the built-in Anchored VWAP tool: set the mode to Manual with the same anchor time, price source to hl2, weighting to Cumulative, and turn volume clamping off.
— Stops feel too tight or too wide: change the Risk Preset before touching individual multipliers.
⚙️ KEY SETTINGS
⚙️ Main Settings:
— Pivot strength left / right (default 55 / 55): bars required on each side of a swing. Right is the confirmation delay.
— Minimum swing size (default 1.5 × ATR): amplitude filter for new pivots. 0 disables it.
— ATR Length (default 13): ATR used by the swing filter and the equality tolerance.
— Re-anchor on (default Swing): Swing, Structure break, Fast or Manual.
— Fast mode: extreme lookback (default 30): lookback for the Fast mode only.
— Equal high/low tolerance (default 0.1 × ATR): threshold for EQH and EQL tags.
— Manual anchor: date and time for the Manual mode, shown in the chart's timezone.
📐 Anchored VWAP:
— Price source (default hl2): hl2 matches the built-in tool, hlc3 weights closes more, close is the most reactive.
— Weighting (default Cumulative): Cumulative is a true VWAP, Half-life fades older bars.
— Half-life (default 21 bars): only used by Half-life weighting.
— Clamp volume spikes (default on, 4 × median): caps outlier volume bars.
— Max leg length (default 4000 bars): keeps very old anchors bounded.
📏 Deviation Bands:
— Band 1 (default on, 0.5 sigma): inner band.
— Band 2 (default off, 2.0 sigma): outer band, also defines the Premium and Discount zones.
— Fill transparency (default 90).
🎯 Signals & Levels:
— Bars away before a retest counts (default 5).
— Touch tolerance (default 0.25 sigma).
— VWAP memory levels (default on, max 4, crossed levels removed).
🛡️ Risk Management:
— Risk Preset (default Balanced): Conservative, Balanced, Aggressive, Scalping or Custom.
— ATR Length (SL) (default 13).
— SL ×ATR / TP1 / TP2 / TP3 ×Risk (defaults 1.5 / 1.0 / 2.0 / 3.0): used by the Custom preset.
— Break-Even After TP1 (default on).
— Show SL/TP Lines, Labels, % Distance (all on by default).
— Entry / SL / TP Line Style (defaults Dotted / Solid / Dashed).
🎨 Visual:
— Theme (default Auto): Auto detects the chart background, Dark and Light force it.
— Show Buy/Sell Signals, HH/HL/LH/LL, Leg Background, Watermark.
— SL/TP Label Font Size (default Small).
— Finished legs kept on chart (default 30).
📊 Dashboard:
— Position (default Top Right) and four independent section switches: Market, VWAP, Trade, Stats.
🔔 ALERTS
— 🟢 LONG — VWAP retest entry, with price, VWAP, SL, TP1, TP2, TP3 and R:R
— 🔴 SHORT — same payload, short side
— 🛑 SL HIT — entry and stop price. Reported as 🛡️ BE STOP-OUT when the stop had already been moved to break-even
— 🛡️ BREAK-EVEN — stop moved to entry after TP1 (optional)
— 🎯 TP1 HIT, 🎯🎯 TP2 HIT, 🏆 TP3 HIT — first touch of each target (optional)
— 🟢 New bullish leg / 🔴 New bearish leg — a new anchor was set (optional)
— 🔵 Close above VWAP / 🔵 Close below VWAP — the close crossed the anchored VWAP (optional)
Entry alerts support both plain text and a JSON webhook payload. All alerts fire on bar close.
⚠️ IMPORTANT NOTES
— 🚫 No repainting of confirmed values. Every structure event, entry, stop, target and alert is evaluated only when barstate.isconfirmed is true. Pivots use equal left and right lookback, so the swing point is in the past by the "right" value at the moment it becomes known — that is delayed confirmation, not a look into the future. Stop and target hits are tested only from the bar after entry. Alerts fire once per bar close.
— 📐 What does update intrabar. The VWAP value of the leg currently in progress moves while the bar is forming, because that is what an anchored average does. Values on closed bars never change. A commit/undo pattern makes sure a forming bar is never counted twice in the statistics.
— 📐 The unfinished leg can be shortened. When a stronger extreme of the same type is confirmed, the current leg is cut at that point and a new leg starts there. Legs that have already been archived are never modified.
— 📊 The statistics are not a backtest. Trades, win rate and the form strip are counted over the history currently loaded on the chart and reset when the chart reloads or a setting changes. They describe how this rule set behaved on the visible data. Past performance does not guarantee future results.
— 🧮 The strength score is a context filter. Its four components and weights are published above precisely so it can be judged on its merits. It measures the internal coherence of the current leg, not the probability of any outcome.
— ⚖️ Half-life weighting is not a VWAP. When that mode is selected the line is an exponentially weighted average, useful on instruments without volume, but it is no longer the textbook volume-weighted average price. The dashboard states the active mode at all times.
— 🌐 Universal compatibility. Works on stocks, futures, forex, crypto and indices, on every timeframe. Where no volume data exists the weighting falls back to time and the dashboard relabels the volume-balance row accordingly.
— 🛠️ Decision support, not automation. This is an anchored VWAP and structure analysis tool with a risk framework attached. It marks anchors, measures distance in the leg's own units, detects retests and lays out stops and targets — trade decisions remain yours.
開源腳本
秉持TradingView一貫精神,這個腳本的創作者將其設為開源,以便交易者檢視並驗證其功能。向作者致敬!您可以免費使用此腳本,但請注意,重新發佈代碼需遵守我們的社群規範。
10 years in trading. For all inquiries, contact me on my Telegram channel: t.me/WillyAlgoTrader or Instagram: @willytraderbtc
免責聲明
這些資訊和出版物並非旨在提供,也不構成TradingView提供或認可的任何形式的財務、投資、交易或其他類型的建議或推薦。請閱讀使用條款以了解更多資訊。
開源腳本
秉持TradingView一貫精神,這個腳本的創作者將其設為開源,以便交易者檢視並驗證其功能。向作者致敬!您可以免費使用此腳本,但請注意,重新發佈代碼需遵守我們的社群規範。
10 years in trading. For all inquiries, contact me on my Telegram channel: t.me/WillyAlgoTrader or Instagram: @willytraderbtc
免責聲明
這些資訊和出版物並非旨在提供,也不構成TradingView提供或認可的任何形式的財務、投資、交易或其他類型的建議或推薦。請閱讀使用條款以了解更多資訊。