{"slug":"dividend-yield-traps","qid":"denominator_math","label":"How each yield band got there: median price and dividend change over the prior 12 months","post_title":"Dividend Yield Traps: How to Spot One","post_url":"/blog/dividend-yield-traps#q-denominator_math","columns":["yield_band","names","median_yield_pct","median_price_change_pct","median_dividend_change_pct"],"rows":[{"yield_band":"under 2%","names":1220,"median_yield_pct":1.08,"median_price_change_pct":11.9,"median_dividend_change_pct":5.5},{"yield_band":"2-4%","names":836,"median_yield_pct":2.88,"median_price_change_pct":8.1,"median_dividend_change_pct":4.2},{"yield_band":"4-6%","names":403,"median_yield_pct":4.91,"median_price_change_pct":5.1,"median_dividend_change_pct":1.9},{"yield_band":"6-8%","names":394,"median_yield_pct":6.74,"median_price_change_pct":-0.4,"median_dividend_change_pct":0},{"yield_band":"8% and up","names":304,"median_yield_pct":9.69,"median_price_change_pct":-2.4,"median_dividend_change_pct":0}],"shape":"table","sql":"WITH px_base AS (\n    SELECT ticker,\n           argMax(toFloat64(close), window_start) AS price\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE toDate(toTimeZone(window_start, 'America/New_York')) = toDate('2025-06-30')\n      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60\n           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959\n    GROUP BY ticker\n    HAVING price >= 5\n),\npx_prior AS (\n    SELECT ticker,\n           argMax(toFloat64(close), window_start) AS price\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE toDate(toTimeZone(window_start, 'America/New_York')) = toDate('2024-06-28')\n      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60\n           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959\n    GROUP BY ticker\n    HAVING price > 0\n),\nrate_base AS (\n    SELECT ticker,\n           argMax(toFloat64(cash_amount) * frequency, ex_dividend_date) AS annual_rate\n    FROM global_markets.stocks_dividends\n    WHERE distribution_type = 'recurring'\n      AND frequency = 4\n      AND cash_amount > 0\n      AND ex_dividend_date > toDate('2024-06-30')\n      AND ex_dividend_date <= toDate('2025-06-30')\n    GROUP BY ticker\n),\nrate_prior AS (\n    SELECT ticker,\n           argMax(toFloat64(cash_amount) * frequency, ex_dividend_date) AS annual_rate\n    FROM global_markets.stocks_dividends\n    WHERE distribution_type = 'recurring'\n      AND frequency = 4\n      AND cash_amount > 0\n      AND ex_dividend_date > toDate('2023-06-30')\n      AND ex_dividend_date <= toDate('2024-06-28')\n    GROUP BY ticker\n)\nSELECT multiIf(100 * rb.annual_rate / b.price >= 8, '8% and up',\n               100 * rb.annual_rate / b.price >= 6, '6-8%',\n               100 * rb.annual_rate / b.price >= 4, '4-6%',\n               100 * rb.annual_rate / b.price >= 2, '2-4%',\n               'under 2%') AS yield_band,\n       count() AS names,\n       round(quantileDeterministic(0.5)(100 * rb.annual_rate / b.price, cityHash64(b.ticker)), 2) AS median_yield_pct,\n       round(quantileDeterministic(0.5)(100 * (b.price / p.price - 1), cityHash64(b.ticker)), 1) AS median_price_change_pct,\n       round(quantileDeterministic(0.5)(100 * (rb.annual_rate / rp.annual_rate - 1), cityHash64(b.ticker)), 1) AS median_dividend_change_pct\nFROM px_base AS b\nINNER JOIN px_prior AS p ON b.ticker = p.ticker\nINNER JOIN rate_base AS rb ON b.ticker = rb.ticker\nINNER JOIN rate_prior AS rp ON b.ticker = rp.ticker\nGROUP BY yield_band\nORDER BY median_yield_pct","computed_at":"2026-08-22T04:04:31.130582+00:00","elapsed":2.797249108}