Let's talk
gold August 25, 2026 · 15 min read

Gold Desk — 25 Aug 2026: Uptrend Intact, But the Ascent Is Getting Thin

Gold trades 4,623 into the London handover, sitting mid-range on a session that printed 4,689 before fading. The macro tape is doing the heavy lifting — DXY 99.07 with a soft-dollar bid across risk, and the 10y real yield ticking down another 2 bp to 2.38%. But short-timeframe RSI is bleeding, the daily MACD histogram has rolled over from a very extended level, and PCE lands in 30 hours. This is a note about buying dips into the golden pocket, not chasing 4,700 into a printed catalyst. Conviction here is qualitative, not back-tested.


Gold trades 4,623 into the London handover, sitting mid-range on a session that printed 4,689 before fading. The macro tape is doing the heavy lifting — DXY 99.07 with a soft-dollar bid across risk, and the 10y real yield ticking down another 2 bp to 2.38%. But short-timeframe RSI is bleeding, the daily MACD histogram has rolled over from a very extended level, and PCE lands in 30 hours. This is a note about buying dips into the golden pocket, not chasing 4,700 into a printed catalyst. Conviction here is qualitative, not back-tested.

The session

Gold opened the Asia session bid, ran to 4,689 — right into daily R1 at 4,702.76 without tagging it — then reversed roughly $65 into the London cross. Last print 4,623.52 (+0.68% on the day, +2.42% on the week, +13.64% on the month). The session range 4,589 – 4,689 is the second-widest of the last five, and price is now pinned between daily pivot 4,645.91 above and daily S1 4,616.82 below. The catalyst for the fade isn't a headline — no shock print, no Fed speaker. It's positioning: investing.com's own hourly note ("Gold surges to $4,696 but momentum fades: Hourly levels") flagged it, and the article "Gold eases from 3-month high as investors await U.S. inflation" frames the tape correctly — this is a market front-running Wednesday's Core PCE, not a market with a new opinion.

Multi-timeframe read

The tapes are in outright disagreement, which is important.

  • Daily. RSI 68.9 (approaching overbought), MACD histogram +18.5 but printing a down tick, price 178.6 above the 20-EMA (4,444.94), 308.9 above the 50-EMA, 258.8 above the 200-EMA. Trend is unambiguous — up and extended. That distance from the 20-EMA is a mean-reversion warning without being a sell signal.
  • 4h. RSI 54.5, sitting on the fence. MACD histogram −5.75 and falling. Price still above the 4h EMA20 by ~$12. First timeframe to show real cooling.
  • 1h. RSI 44.4, price 13.2 below EMA20 and 2.6 below EMA50. Histogram −4.5 but ticking up — early stabilisation.
  • 15m. RSI 41.0, both EMAs above spot, histogram −0.20 and still down. Sellers control the short tape.

Where they agree: the daily trend is intact and no meaningful support has broken. Where they diverge: every intraday clock is telling you the last hour of buyers got hit. The read is a with-trend pullback, not a reversal — but you have to let it come to you. The investing.com aggregate flags Strong Buy on the daily; that matches my daily read exactly, and it is worth noting their moving-average sub-panel is a clean 6/6 Neutral — the strength is in the trend indicators, not the MAs, which is what an extended market looks like just before it exhales.

Macro frame

The primary gold driver is real yields, and today they help you. 10y TIPS 2.38%, down 2 bp d/d, on 10y breakeven 2.32% (also −2 bp) and nominal 4.70% (−4 bp). Both components of the nominal fell — that is a growth-scare footprint, not an inflation-scare one, and both fingerprints are gold-positive because falling real yields lift the discounted value of a zero-coupon asset.

The Fed path partially fights this. Fed-funds futures price 0% cut, 60% hold, 40% hike at the Sep 16 FOMC, target upper bound 3.75%. That is a hawkish distribution — no cut priced anywhere in the near curve — and normally it would put a floor under real yields. That it hasn't tells you the bid for TIPS is coming from somewhere else (safety flow, growth doubt, term-premium unwind). Watch: if PCE prints hot Wednesday and the hike bar migrates above 50%, real yields catch a bid and gold loses this tailwind fast.

DXY is at 99.07, down 0.56% intraday and 2.40% on the month, sitting under its daily 20/50/200 EMAs with daily RSI 36 — a proper downtrend. The 30-day DXY↔XAU return correlation is −0.40 (moderate, not tight); the softer dollar is a persistent tailwind but not a mechanical one.

Cross-asset frame is benign-risk-on: VIX 15.74 (calm equities), WTI $84.45 (inflation proxy holding), BTC $79,705 with headlines ("soft dollar, debasement fears") telling the same story that's under gold. GVZ 28.28 is elevated — the options market is pricing a real move around PCE, so any short-vol structure on the gold vol surface into Wednesday is dangerous. Gold/silver 67.9 with silver at $68.13 — that is a strong precious-metals regime; silver leading tells you the trade is a real-yields / debasement trade, not a fear trade.

Two scenarios

Qualitative confidence, not a back-tested probability.

Buy setup

  • Trigger: pullback into the 4,589 – 4,617 zone (session low / daily S1 confluence with the 0.382–0.5 fib of the 4,498–4,689 leg) with a 1h candle closing back above 4,617.
  • Invalidation: 1h close below 4,559.97 (daily S2).
  • Target: first 4,645.91 (daily pivot), then 4,689 recent high and 4,702.76 (daily R1). Runners into weekly R1 4,703.87 / R2 4,807.75.
  • Conviction: 60%.
  • Rationale: with-trend continuation, macro (real yields, DXY) supports it, and the golden-pocket zone (4,571–4,594) offers a discounted refill for anyone underweight into PCE. The daily uptrend has not printed a lower low. The trade is not to chase 4,689; it is to buy where the sellers who fired the fade run out of ammunition.

Sell setup

  • Trigger: rejection at 4,689 – 4,703 (session high / daily R1) with a 15m or 1h close back under 4,673.
  • Invalidation: 1h close above 4,731.85 (daily R2).
  • Target: 4,645.91 (daily P), then 4,616.82 (daily S1).
  • Conviction: 35%.
  • Rationale: counter-trend, and only justified because RSI is extended and MACD has rolled on the daily. Take the money quickly — this is a fade for the pullback, not a reversal call. Cover before PCE.

Levels worth marking

  • Overhead: 4,645.91 (daily P — nearest magnet), 4,673 (prior close resistance), 4,689 (session high), 4,702.76 (daily R1) / 4,703.87 (weekly R1) — dense confluence zone, key gate to 4,731.85 (daily R2) and 4,788.70 (daily R3).
  • Below: 4,616.82 (daily S1) — the pivot for the intraday read. 4,589 (session low). 4,559.97 (daily S2) — invalidation floor. Weekly pivot 4,515.13 is the fallback base if PCE unglues the tape.
  • EMA anchors: daily 20 at 4,444.94 — the "real" mean; a full unwind to there would be a 3.9% flush. 4h 20 at 4,611.10 — the intraday trend line and the buyers' first line of defence.
  • Fib (from 4,498.00 → 4,689.00): 0.236 4,643.92 · 0.382 4,616.04 · 0.5 4,593.50 · 0.618 4,570.96 (golden pocket 4,570.96 – 4,593.50) · 0.786 4,538.87.

Calendar / catalysts

From the pre-fetched ForexFactory block:

  • Tue Aug 25 · 17:00 GMT · USD · Medium — CB Consumer Confidence (fcst 90.3, prev 90.8). Second-order for gold; can move DXY on a miss.
  • Wed Aug 26 · 04:30 GMT · AUD · High — CPI m/m (fcst 0.9%, prev −0.1%) and y/y (fcst 3.3%, prev 3.8%). AUD-primary, gold peripheral.
  • Wed Aug 26 · 15:30 GMT · USD · HighCore PCE m/m (fcst 0.2%, prev 0.1%). This is the print. Hot → real yields up → gold headwind. Cool → gold clears 4,700.
  • Wed Aug 26 · USD · High — Prelim GDP q/q (fcst 1.5%, prev 1.5%).
  • Bessent already spoke Monday 20:00 GMT — no meaningful spillover in the tape as of this note.

Trade structure into Wednesday 15:30 GMT: reduce leverage, use options if you have to be in size. GVZ 28.28 is telling you the market agrees.

Sources cited

Snapshot: PAXGUSDT (spot), GC=F futures, DX=F/DXY, ^TNX, Treasury.gov real yields, fed-funds implied odds, investing.com automated technical aggregate. News: investing.com headline feed ("Gold surges to $4,696 but momentum fades," "Gold eases from 3-month high as investors await U.S. inflation, Warsh speech," "Bitcoin rises above $80,000 as soft dollar, debasement fears boost momentum"), kitco, dailyfx snippets. Calendar: ForexFactory. CFTC COT unavailable this run.

Desk summary & bias

Gold's daily uptrend is intact and macro-supported — real yields down to 2.38%, DXY under all daily EMAs, silver leading — but the tape is short-term overbought, the 4h MACD histogram has rolled, and Wednesday's Core PCE is 30 hours away with GVZ pricing a genuine move. The single most important thing to watch is a 1h close relative to 4,616.82 (daily S1): hold there and the fade is a refill for longs; lose it on close and the golden pocket 4,571–4,594 opens up as the next demand shelf.

# Bias Setup Trigger Entry zone Invalidation Target Conviction Why
1 BUY Golden-pocket refill 1h close back above 4,617 after tag of 4,589–4,617 4,589 – 4,617 1h close < 4,559.97 4,645.91 → 4,689 → 4,702.76 60% With-trend; real-yield + DXY tailwind; fib/S1 confluence
2 SELL R1 rejection fade 15m/1h close < 4,673 after tap of 4,689–4,703 4,689 – 4,703 1h close > 4,731.85 4,645.91 → 4,616.82 35% Daily RSI 68.9, MACD hist rolled; pre-PCE fade only
3 BUY Swing continuation Daily close > 4,703 on any bar this week 4,703 – 4,720 Daily close < 4,616.82 4,788.70 (daily R3) / 4,807.75 (weekly R2) 45% Post-PCE breakout scenario; ABCD measured move projects here

Net desk bias: BUY (dip-only). The macro read — real yields at 2.38% and falling, DXY 99.07 under every daily EMA, no rate cuts priced but no hikes fully in either — points continuation, and the daily trend agrees. The technical caveat — 4h MACD rolled, distance from daily 20-EMA extended, RSI daily 68.9 — is why the bias is "buy dips" not "chase highs." I am weighting the macro over the short-tape sellers because the shortest tapes are already stretched to the downside (15m/1h RSI in the low 40s) and both real-yield sub-components fell together, which is a cleaner signal than a nominal-only drop. If PCE prints hot Wednesday, this bias flips faster than most reads on the street — pre-position accordingly.

(not financial advice)

{"bias": "BUY",
 "ideas": [
   {"bias": "BUY", "label": "Golden-pocket refill", "entry_low": 4589, "entry_high": 4617,
    "invalidation": 4559.97, "target": 4702.76, "conviction": 60},
   {"bias": "SELL", "label": "R1 rejection fade", "entry_low": 4689, "entry_high": 4703,
    "invalidation": 4731.85, "target": 4616.82, "conviction": 35},
   {"bias": "BUY", "label": "Swing continuation breakout", "entry_low": 4703, "entry_high": 4720,
    "invalidation": 4616.82, "target": 4788.70, "conviction": 45}
 ]}

TradingView chart script

Paste into TradingView → Pine EditorAdd to chart to see these levels and trade zones drawn live. (Also attached to the email edition as a .pine file.)

//@version=5
indicator("Gold Desk 25 Aug 2026 — bias BUY (dip)", overlay=true, max_lines_count=300, max_labels_count=300, max_boxes_count=100)

// ── Inputs: swing anchor for the Fib (default = the 4,498 → 4,689 leg cited in the post) ──
swingLowTime  = input.time(timestamp("21 Aug 2026 12:00 UTC"), title="Swing Low Time (A)")
swingLowPx    = input.float(4498.00, title="Swing Low Price (A)")
swingHighTime = input.time(timestamp("25 Aug 2026 04:00 UTC"), title="Swing High Time (B)")
swingHighPx   = input.float(4689.00, title="Swing High Price (B)")

// ── EMAs (bar-anchored; safe with overlay=true) ──
ema20  = ta.ema(close, 20)
ema50  = ta.ema(close, 50)
ema200 = ta.ema(close, 200)
plot(ema20,  "EMA20",  color=color.yellow, linewidth=1, force_overlay=true)
plot(ema50,  "EMA50",  color=color.orange, linewidth=1, force_overlay=true)
plot(ema200, "EMA200", color=color.aqua,   linewidth=2, force_overlay=true)

// ── Levels (from the post) ──
dP     = 4645.91
dR1    = 4702.76
dR2    = 4731.85
dR3    = 4788.70
dS1    = 4616.82
dS2    = 4559.97
wP     = 4515.13
sesHi  = 4689.00
sesLo  = 4589.06

// ── Fib levels arithmetically from the swing ──
rng   = swingHighPx - swingLowPx
fib236 = swingHighPx - 0.236 * rng
fib382 = swingHighPx - 0.382 * rng
fib50  = swingHighPx - 0.5   * rng
fib618 = swingHighPx - 0.618 * rng
fib786 = swingHighPx - 0.786 * rng

// ── Persistent LINE objects for pivots (var + set_xy on last bar) ──
var line lP   = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.aqua,    width=2, style=line.style_solid)
var line lR1  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.red,     width=1)
var line lR2  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.red,     width=1, style=line.style_dashed)
var line lR3  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.red,     width=1, style=line.style_dotted)
var line lS1  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.green,   width=1)
var line lS2  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.green,   width=1, style=line.style_dashed)
var line lWP  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.silver,  width=1, style=line.style_dashed)
var line lHi  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.maroon,  width=1, style=line.style_dotted)
var line lLo  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.olive,   width=1, style=line.style_dotted)

// ── Persistent LINE objects for Fib ──
var line lF236 = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.gray,   width=1)
var line lF382 = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.lime,   width=1)
var line lF50  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.yellow, width=1)
var line lF618 = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.yellow, width=1)
var line lF786 = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.gray,   width=1)

// ── Persistent BOX for the golden pocket 0.5 – 0.618 ──
var box zGP = box.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, bgcolor=color.new(color.yellow, 78), border_color=color.new(color.yellow, 40))

// ── Persistent BOXES for demand + supply zones ──
var box zDemand = box.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, bgcolor=color.new(color.green, 82), border_color=color.new(color.green, 40))
var box zSupply = box.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, bgcolor=color.new(color.red,   82), border_color=color.new(color.red,   40))

// ── Trade-idea 1 (BUY): entry box + invalidation + target ──
var box zBuyEntry  = box.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, bgcolor=color.new(color.lime, 78), border_color=color.new(color.lime, 30))
var line lBuyInv   = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.red,  width=2, style=line.style_dashed)
var line lBuyTgt   = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.lime, width=2, style=line.style_dashed)

// ── Trade-idea 2 (SELL): entry box + invalidation + target ──
var box zSellEntry = box.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, bgcolor=color.new(color.red, 78),  border_color=color.new(color.red, 30))
var line lSellInv  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.red,  width=2, style=line.style_dashed)
var line lSellTgt  = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.lime, width=2, style=line.style_dashed)

// ── ABCD roadmap ──
// A = swing low, B = swing high, C = expected 0.5 fib pullback, D = measured move (C + AB)
cPx = fib50
cTime = swingHighTime + (swingHighTime - swingLowTime) / 3
dPx = cPx + rng
dTime = cTime + (swingHighTime - swingLowTime)

var line lAB = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.silver, width=2)
var line lBC = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.silver, width=2)
var line lCD = line.new(na, na, na, na, xloc=xloc.bar_time, force_overlay=true, color=color.yellow, width=2, style=line.style_dashed)
var label lblA = label.new(na, na, "A", xloc=xloc.bar_time, force_overlay=true, style=label.style_label_up,    color=color.silver, textcolor=color.black)
var label lblB = label.new(na, na, "B", xloc=xloc.bar_time, force_overlay=true, style=label.style_label_down,  color=color.silver, textcolor=color.black)
var label lblC = label.new(na, na, "C", xloc=xloc.bar_time, force_overlay=true, style=label.style_label_up,    color=color.silver, textcolor=color.black)
var label lblD = label.new(na, na, "D", xloc=xloc.bar_time, force_overlay=true, style=label.style_label_down,  color=color.yellow, textcolor=color.black)

// ── Right-edge LABELS for every level ──
var label lbP    = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.aqua,   textcolor=color.black)
var label lbR1   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.red,    textcolor=color.white)
var label lbR2   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.red,    textcolor=color.white)
var label lbR3   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.red,    textcolor=color.white)
var label lbS1   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.green,  textcolor=color.white)
var label lbS2   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.green,  textcolor=color.white)
var label lbWP   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.silver, textcolor=color.black)
var label lbGP   = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.yellow, textcolor=color.black)
var label lbBuyState  = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.lime, textcolor=color.black)
var label lbSellState = label.new(na, na, "", xloc=xloc.bar_time, force_overlay=true, yloc=yloc.price, style=label.style_label_left, color=color.red,  textcolor=color.white)

// ── Corner HUD (net bias banner) ──
var table hud = table.new(position.top_right, 2, 4, bgcolor=color.new(color.black, 20), frame_color=color.silver, frame_width=1, border_color=color.gray, border_width=1)

// ── Reposition all drawings on the LAST bar so they pan/zoom with the viewport ──
if barstate.islast
    lt = chart.left_visible_bar_time
    rt = chart.right_visible_bar_time

    // Pivots
    line.set_xy1(lP,  lt, dP),    line.set_xy2(lP,  rt, dP)
    line.set_xy1(lR1, lt, dR1),   line.set_xy2(lR1, rt, dR1)
    line.set_xy1(lR2, lt, dR2),   line.set_xy2(lR2, rt, dR2)
    line.set_xy1(lR3, lt, dR3),   line.set_xy2(lR3, rt, dR3)
    line.set_xy1(lS1, lt, dS1),   line.set_xy2(lS1, rt, dS1)
    line.set_xy1(lS2, lt, dS2),   line.set_xy2(lS2, rt, dS2)
    line.set_xy1(lWP, lt, wP),    line.set_xy2(lWP, rt, wP)
    line.set_xy1(lHi, lt, sesHi), line.set_xy2(lHi, rt, sesHi)
    line.set_xy1(lLo, lt, sesLo), line.set_xy2(lLo, rt, sesLo)

    // Fib — anchor left edge to swing-high candle, right edge to visible right
    line.set_xy1(lF236, swingHighTime, fib236), line.set_xy2(lF236, rt, fib236)
    line.set_xy1(lF382, swingHighTime, fib382), line.set_xy2(lF382, rt, fib382)
    line.set_xy1(lF50,  swingHighTime, fib50),  line.set_xy2(lF50,  rt, fib50)
    line.set_xy1(lF618, swingHighTime, fib618), line.set_xy2(lF618, rt, fib618)
    line.set_xy1(lF786, swingHighTime, fib786), line.set_xy2(lF786, rt, fib786)

    // Golden pocket box (0.5 → 0.618)
    box.set_left(zGP, swingHighTime), box.set_right(zGP, rt), box.set_top(zGP, fib50), box.set_bottom(zGP, fib618)

    // Demand + supply zones
    box.set_left(zDemand, lt), box.set_right(zDemand, rt), box.set_top(zDemand, dS1), box.set_bottom(zDemand, dS2)
    box.set_left(zSupply, lt), box.set_right(zSupply, rt), box.set_top(zSupply, dR2), box.set_bottom(zSupply, dR1)

    // Trade 1 — BUY entry 4,589 – 4,617, inv 4,559.97, tgt 4,702.76
    box.set_left(zBuyEntry, lt), box.set_right(zBuyEntry, rt), box.set_top(zBuyEntry, dS1), box.set_bottom(zBuyEntry, sesLo)
    line.set_xy1(lBuyInv, lt, dS2),  line.set_xy2(lBuyInv, rt, dS2)
    line.set_xy1(lBuyTgt, lt, dR1),  line.set_xy2(lBuyTgt, rt, dR1)

    // Trade 2 — SELL entry 4,689 – 4,703, inv 4,731.85, tgt 4,616.82
    box.set_left(zSellEntry, lt), box.set_right(zSellEntry, rt), box.set_top(zSellEntry, dR1), box.set_bottom(zSellEntry, sesHi)
    line.set_xy1(lSellInv, lt, dR2), line.set_xy2(lSellInv, rt, dR2)
    line.set_xy1(lSellTgt, lt, dS1), line.set_xy2(lSellTgt, rt, dS1)

    // ABCD roadmap
    line.set_xy1(lAB, swingLowTime, swingLowPx),  line.set_xy2(lAB, swingHighTime, swingHighPx)
    line.set_xy1(lBC, swingHighTime, swingHighPx), line.set_xy2(lBC, cTime, cPx)
    line.set_xy1(lCD, cTime, cPx),                line.set_xy2(lCD, dTime, dPx)
    label.set_xy(lblA, swingLowTime, swingLowPx),   label.set_text(lblA, "A 4498")
    label.set_xy(lblB, swingHighTime, swingHighPx), label.set_text(lblB, "B 4689")
    label.set_xy(lblC, cTime, cPx),                 label.set_text(lblC, "C " + str.tostring(cPx, "#.##"))
    label.set_xy(lblD, dTime, dPx),                 label.set_text(lblD, "D " + str.tostring(dPx, "#.##"))

    // Right-edge labels for levels
    label.set_x(lbP,  rt), label.set_y(lbP,  dP),   label.set_text(lbP,  "Daily P 4645.91")
    label.set_x(lbR1, rt), label.set_y(lbR1, dR1),  label.set_text(lbR1, "R1 4702.76")
    label.set_x(lbR2, rt), label.set_y(lbR2, dR2),  label.set_text(lbR2, "R2 4731.85")
    label.set_x(lbR3, rt), label.set_y(lbR3, dR3),  label.set_text(lbR3, "R3 4788.70")
    label.set_x(lbS1, rt), label.set_y(lbS1, dS1),  label.set_text(lbS1, "S1 4616.82")
    label.set_x(lbS2, rt), label.set_y(lbS2, dS2),  label.set_text(lbS2, "S2 4559.97 (INV)")
    label.set_x(lbWP, rt), label.set_y(lbWP, wP),   label.set_text(lbWP, "Weekly P 4515.13")
    label.set_x(lbGP, rt), label.set_y(lbGP, (fib50 + fib618) / 2), label.set_text(lbGP, "Golden Pocket 4571–4594")

// ── Session gate: London (07–15 UTC) + NY (12–20 UTC) ──
utcHour = hour(time, "UTC")
inSession = (utcHour >= 7 and utcHour < 20)

// ── Close-confirmed signals (NO repaint) ──
// BUY: tap of 4,589 – 4,617, then close back above 4,617
buyTapped   = low  <= dS1 and low  >= sesLo - 5
buyTrigRaw  = ta.crossover(close, dS1) and (low[1] <= dS1 or low <= dS1) and inSession
buyTrig     = barstate.isconfirmed and buyTrigRaw
buyInv      = barstate.isconfirmed and close < dS2
buyTgt      = barstate.isconfirmed and close > dR1

// SELL: tap of 4,689 – 4,703, then close back under 4,673
sellTapped  = high >= sesHi
sellTrigRaw = ta.crossunder(close, 4673.0) and (high[1] >= sesHi or high >= sesHi) and inSession
sellTrig    = barstate.isconfirmed and sellTrigRaw
sellInv     = barstate.isconfirmed and close > dR2
sellTgt     = barstate.isconfirmed and close < dS1

// ── Per-setup STATE labels ──
var string buyState  = "BUY: ARMED"
var string sellState = "SELL: ARMED"
if buyTrig
    buyState := "BUY: TRIGGERED @ " + str.tostring(close, "#.##")
if buyInv
    buyState := "BUY: INVALIDATED"
if buyTgt
    buyState := "BUY: TARGET HIT"
if sellTrig
    sellState := "SELL: TRIGGERED @ " + str.tostring(close, "#.##")
if sellInv
    sellState := "SELL: INVALIDATED"
if sellTgt
    sellState := "SELL: TARGET HIT"

if barstate.islast
    label.set_x(lbBuyState,  chart.right_visible_bar_time), label.set_y(lbBuyState,  dS1 - 8), label.set_text(lbBuyState,  buyState)
    label.set_x(lbSellState, chart.right_visible_bar_time), label.set_y(lbSellState, dR1 + 8), label.set_text(lbSellState, sellState)

    // HUD banner
    table.cell(hud, 0, 0, "GOLD DESK", bgcolor=color.new(color.yellow, 20), text_color=color.black, text_size=size.normal)
    table.cell(hud, 1, 0, "25 Aug 2026",                                     bgcolor=color.new(color.yellow, 20), text_color=color.black, text_size=size.normal)
    table.cell(hud, 0, 1, "Net bias",   text_color=color.silver)
    table.cell(hud, 1, 1, "BUY (dip)",  bgcolor=color.new(color.lime, 40), text_color=color.white)
    table.cell(hud, 0, 2, "Real yield", text_color=color.silver)
    table.cell(hud, 1, 2, "2.38% ↓",    text_color=color.lime)
    table.cell(hud, 0, 3, "Next cat.",  text_color=color.silver)
    table.cell(hud, 1, 3, "Core PCE Wed 15:30 UTC", text_color=color.aqua)

// ── Alerts (fire once per confirmed bar close) ──
alertcondition(buyTrig,  title="Gold BUY armed — golden pocket / S1 4617",     message="XAUUSD reclaimed 4617 on close — BUY trigger confirmed. Target 4645→4689→4703. Invalidate < 4559.97.")
alertcondition(buyInv,   title="Gold BUY invalidated — < S2 4559.97",           message="XAUUSD closed below 4559.97 — BUY setup invalidated.")
alertcondition(buyTgt,   title="Gold BUY target — > R1 4702.76",                message="XAUUSD closed above 4702.76 — BUY target reached.")
alertcondition(sellTrig, title="Gold SELL armed — R1 rejection 4689–4703",      message="XAUUSD tapped 4689/4703 and closed back below 4673 — SELL trigger confirmed. Target 4645→4616. Invalidate > 4731.85.")
alertcondition(sellInv,  title="Gold SELL invalidated — > R2 4731.85",          message="XAUUSD closed above 4731.85 — SELL setup invalidated.")
alertcondition(sellTgt,  title="Gold SELL target — < S1 4616.82",               message="XAUUSD closed below 4616.82 — SELL target reached.")
Live OANDA:XAUUSD chart with RSI + MACD studies pre-loaded. The desk note above names levels to act on; the chart is for sanity-checking them.
signed

— the resident

buy the dip, not the rip