//@version=6 // ============================================================================ // M2 / Inflation Lens — weight, re-adjust, lead/lag & accel-decel // Works on ANY chart symbol (uses the chart's own price). // Four modes (dropdown): // 1. Adjusted price (real) -> the equity RE-ADJUSTED for inflation or M2 // 2. Weighted ratio -> weight the ticker by M2/inflation, 3 ways // 3. Lead/Lag compare -> offset M2/inflation in TIME to see it lead price // 4. Accel-Decel oscillator -> 2nd-derivative of M2 & inflation (+ offset) // ============================================================================ indicator("M2 / Inflation Lens", shorttitle="M2·CPI Lens", overlay=false, precision=2) // ── Data sources (swap M2 for FRED:M2SL or a global-M2 composite if you like) ── gS = "Data sources" m2Sym = input.symbol("ECONOMICS:USM2", "M2 money supply", group=gS) cpiSym = input.symbol("ECONOMICS:USCPI", "CPI index (deflator)", group=gS) infSym = input.symbol("ECONOMICS:USIRYY", "Inflation rate YoY %", group=gS) // ── Mode ── gM = "Mode" mode = input.string("Adjusted price (real)", "Mode", options=["Adjusted price (real)", "Weighted ratio", "Lead/Lag compare", "Accel-Decel oscillator"], group=gM) factor = input.string("M2", "Adjust / weight by", options=["M2", "Inflation (CPI)"], group=gM) method = input.string("Real deflated", "Weighting method (the 'two ways')", options=["Ratio (price / factor)", "Real deflated", "Relative perf (price - factor growth)"], group=gM, tooltip="Ratio = price denominated in M2/CPI units. Real deflated = nominal price rebased to constant money/prices (the TRUE real trajectory). Relative perf = does the ticker BEAT money-supply / inflation growth.") // ── Time offset (lead / lag) ── gO = "Time offset (lead / lag)" offBars = input.int(0, "Offset M2/CPI by N bars (+ shifts it forward => it LEADS price)", group=gO, tooltip="Slide the M2 / inflation series in time to find where it best leads (or lags) price. M2 commonly leads risk assets by months — try positive offsets on a weekly/daily chart.") // ── Accel / Decel oscillator ── gA = "Accel / Decel oscillator" rocLen = input.int(12, "Growth lookback (bars)", minval=1, group=gA, tooltip="Bars over which M2 / inflation growth is measured; acceleration = the CHANGE in that growth (2nd derivative).") showM2A = input.bool(true, "M2 accel/decel", group=gA) showInfA = input.bool(true, "Inflation accel/decel", group=gA) // ── Compare normalization ── gN = "Compare normalization" normMode = input.string("Z-score", "Normalize (compare mode)", options=["Z-score", "% from start", "Raw"], group=gN) normLen = input.int(252, "Z-score lookback", minval=20, group=gN) // ── Pull series (no lookahead bias) ── px = close m2 = request.security(m2Sym, timeframe.period, close, lookahead=barmerge.lookahead_off) cpi = request.security(cpiSym, timeframe.period, close, lookahead=barmerge.lookahead_off) inf = request.security(infSym, timeframe.period, close, lookahead=barmerge.lookahead_off) fSeries = factor == "M2" ? m2 : cpi // first non-na values = bases for deflation / %-from-start var float fBase = na var float pxBase = na if na(fBase) and not na(fSeries) fBase := fSeries if na(pxBase) and not na(px) pxBase := px // ── Weighting math (the two/three ways) ── ratio = fSeries != 0 ? px / fSeries : na // price in M2/CPI units realDef = (fSeries != 0 and not na(fBase)) ? px * (fBase / fSeries) : na // real / deflated price pxG = ta.roc(px, rocLen) fG = ta.roc(fSeries, rocLen) relPerf = pxG - fG // does price beat factor growth weighted = method == "Ratio (price / factor)" ? ratio : method == "Real deflated" ? realDef : relPerf // ── Normalize helper (compare mode) ── normalize(s, baseV) => r = s if normMode == "Z-score" mu = ta.sma(s, normLen) sd = ta.stdev(s, normLen) r := sd != 0 ? (s - mu) / sd : 0.0 else if normMode == "% from start" r := (not na(baseV) and baseV != 0) ? (s / baseV - 1.0) * 100.0 : na r // ── Accel / Decel (2nd derivative) ── m2G = ta.roc(m2, rocLen) // M2 growth-rate % (1st derivative) m2Acc = m2G - m2G[rocLen] // change in growth = acceleration infAcc = inf - inf[rocLen] // inflation is already a rate -> its change = its acceleration // ── Mode flags ── isAdj = mode == "Adjusted price (real)" isRat = mode == "Weighted ratio" isCmp = mode == "Lead/Lag compare" isOsc = mode == "Accel-Decel oscillator" // ── Plots ── // 1 & 2: the ticker re-adjusted / weighted (its real trajectory in the pane) plot(isAdj ? realDef : na, "Real / adjusted price", color=color.new(color.teal, 0), linewidth=2) plot(isRat ? weighted : na, "Weighted ticker", color=color.new(color.orange, 0), linewidth=2) // 3: lead/lag — price fixed, M2/CPI shifted by offBars (positive = it leads) plot(isCmp ? normalize(px, pxBase) : na, "Price (norm)", color=color.new(color.gray, 0), linewidth=2) plot(isCmp ? normalize(fSeries, fBase) : na, "M2/CPI (norm, offset)", color=color.new(color.blue, 0), linewidth=2, offset=offBars) // 4: accel/decel oscillator (also offsettable) hline(isOsc ? 0 : na, "zero", color=color.new(color.gray, 60)) m2Col = m2Acc >= 0 ? color.new(color.green, 0) : color.new(color.red, 0) plot(isOsc and showM2A ? m2Acc : na, "M2 accel/decel", color=m2Col, style=plot.style_columns, offset=offBars) plot(isOsc and showInfA ? infAcc : na, "Inflation accel/decel", color=color.new(color.purple,0), linewidth=2, offset=offBars)