gdpnow_anchor
gdpnow_anchor is a master switch wired to the Atlanta Fed's running guess at how fast the economy is growing right now. Once a day we ask for the latest GDPNow nowcast — the Fed's Atlanta branch re-estimates this quarter's GDP growth every few days as new data lands — and you pick a condition off it: "only when GDPNow is above 2.5%", "only when it's below 1%". While your condition holds the bot trades; while it doesn't, the bot places no trades at all that cycle, in any market.
Two things about it matter more than anything else on this page, so they go first. The backtester does not apply this gate. Put it in a bot, run a backtest, and the backtest runs without the rule and hands you an equity curve anyway. You can tune a strategy that was never tested with the switch you are about to ship it with. And the history we store is the answer, not the question. Our table keeps one number per quarter — the last nowcast of that quarter, published the week the quarter ended — filed under the quarter's start date. Nobody could have known it on day one. Anyone replaying our table is reading the economy's report card while pretending to sit the exam.
- Bots using it
- 0 none live, none out-of-sample, none archived, none ever
- Data source
- FRED GDPNOW (the Atlanta Fed's number, republished)
- Refresh
- Daily 05:30 UTC (30 5 * * *)
- Rows stored
- 61 one per quarter, 2011 Q3 → 2026 Q3
- Backtest-replayable
- No — see catch #1
- Anchor module
- quants/gdpnow_anchor.py
What a GDP nowcast actually is
Official GDP is slow. The Bureau of Economic Analysis publishes its first estimate — the "advance" estimate — about a month after a quarter has finished. For the three months in between, the single most important number in macroeconomics simply does not exist yet.
GDPNow fills that gap. It is a model run by the Federal Reserve Bank of Atlanta that assembles a running estimate of the current quarter's real GDP growth out of the monthly data that has arrived — retail sales, trade, construction, inventories and the rest. FRED's own description of the series puts it this way: it "forecasts GDP growth by aggregating 13 subcomponents that make up GDP with the chain-weighting methodology used by the US Bureau of Economic Analysis." Every time a relevant release lands, the model re-runs and the number moves. When the BEA finally publishes, GDPNow stops for that quarter and starts over on the next one.
The units are percent change at a seasonally adjusted annual rate, which is how American GDP is always quoted: 2.5 means "if this quarter's pace held for a year, the economy would grow 2.5%." Everything on this page is in those units, and one unit is called a percentage point (pp). For scale, the number we hold right now is 5.833 for 2026 Q3, and the deepest and highest readings in our own table are −32.084 (2020 Q2) and +36.971 (2020 Q3).
Two distinctions worth keeping straight, because they get mixed up constantly. GDPNow is not a forecast of the future — it is an estimate of a quarter that is currently happening. And it is not the official number — it is a model's guess at what the official number will say. How good a guess is measured further down; it is a real question with a real answer.
Where the data comes from
The signal's ultimate source is the Atlanta Fed, but we do not call the Atlanta Fed. We call FRED — the St. Louis Fed's data warehouse — and read its GDPNOW series: https://api.stlouisfed.org/fred/series/observations?series_id=GDPNOW. It is free; it needs an API key, which is free too, and ours sits in the production environment file. Called live from the production server while this page was written it returned HTTP 200 in 0.14 seconds.
That indirection is worth naming because a republisher can lag its source. Today it does not. We checked the Atlanta Fed's own page directly, and it says: "5.8% Third-Quarter GDPNow Estimate for 2026:Q3 — Updated: August 06, 2026. Next update: August 14, 2026." FRED's metadata for the series reports last_updated: 2026-08-06, and our stored value is 5.833. Same number, same day, no lag. Take that for what it is, though — it shows the most recent fetch matches the public figure. It says nothing about the shape of the history behind it, which is where the real problem lives.
The poller is predictive/gdpnow_poller.py, on cron 30 5 * * * — once a day at 05:30 UTC. It asks FRED for the whole series and re-writes every row, so a single run refreshes all 61 rows at once. They land in macro_nowcast in predictive.db: one row per quarter, 2011 Q3 through 2026 Q3, each carrying the observation date, the value, and the time we fetched it.
Once a day is the right cadence, and it is worth saying so plainly since so many things on this page are not. GDPNow does not update daily. Across the ten years of revision history FRED will serve, the median gap between updates is 4 days and the mean is 4.7 — roughly 80 updates a year. A daily poll catches every one of them inside 24 hours. (The two docstrings involved both describe it as "weekly", which is a little slower than the truth but errs in the safe direction.)
Then there is the date. FRED files each observation under the first day of the quarter it describes — 2026 Q3 is stored as 2026-07-01 — and it overwrites that row in place every time the Atlanta Fed publishes a new estimate. The anchor's own comments are alert to the first half of this and say so. The second half is the one that does the damage, and it gets catch #2 to itself.
How the gate decides
quants/gdpnow_anchor.py reads the newest row in the table (ORDER BY date DESC LIMIT 1) and applies two staleness rules before it will even look at your threshold:
- _STALE_OBS_DAYS = 100 — the observation must be for a recent quarter. If the newest row's date is more than 100 days ago, the gate is shut no matter what the value says.
- _STALE_POLL_DAYS = 3 — the poller must be alive. If we have not successfully fetched in more than 3 days, the gate is shut.
Both fail closed, and both are written correctly — the timestamps are parsed into real Python dates rather than compared as text, which is a bug three other signals in this dictionary do have. Only then does it compare the value to your above and below. Both comparisons are strict.
What it means for your bot
This is a whole-bot master switch, not a filter on economics markets. The engine evaluates it before it looks at any market at all: if the condition fails, the bot does nothing that cycle — no weather trades, no sports trades, nothing. That is worth saying because the two configurations this site ships both attach it to a bot restricted to the economics category, which hides the fact. Point it at a bot that trades everything and it will silence the lot.
What it buys you is a macro regime filter: the idea that contracts about rate cuts, inflation prints, recession calls and election-year economics behave differently when growth is accelerating than when it is stalling, and that you would rather only be in the market during one of those states. That is a real hypothesis. It is not a small one, and this signal will not test it for you — see catch #1.
Practically, the thresholds behave like this over the last ten years, measured as the share of calendar days on which the gate would have been open (which is not the same as the share of time GDP was above a level — dark days count as shut, because that is what your bot experiences):
| Setting | Where it appears | Gate open |
|---|---|---|
| above 2.0 | starter bot "Macro Nowcast Rider" | 55.91% |
| above 2.5 | builder field default · recipe "Hot-growth macro" · docstring | 45.74% |
| below 1.0 | docstring example | 7.52% |
Those are good numbers, and after nine of these pages it is a pleasure to write that. A gate that is open roughly half the time is doing the job a regime filter is supposed to do. Several signals in this dictionary ship defaults that have literally never been satisfied; this one does not. The problems here are elsewhere.
The catch
Ordered worst first.
1. A backtest that includes this signal is not testing this signal
gdpnow_anchor appears nowhere in quants/backtest.py — not in the supported list, not even in the documentary "unsupported" list that records why things can't be replayed. It is caught only by the catch-all, which flags any entry key that isn't explicitly supported. The consequence is the one that matters: the backtest runs your strategy without the gate and returns an equity curve anyway.
The result does name the rule in its unsupported_rules output, and the interface does print "advanced rule(s) not yet replayed" — so this is a lie by omission rather than a lie. But the curve is the thing people look at. If you tune entry prices and sizing against that curve and then activate the bot, you have optimised a strategy that never had the switch and shipped one that does, and you have no idea which direction that moves you.
2. The history we store is the end-of-quarter answer, not what anyone could see
FRED files each GDPNow reading under the first day of the quarter it describes and overwrites it every time the Atlanta Fed publishes. Our poller does INSERT OR REPLACE on the same key. So macro_nowcast holds, for every past quarter, the final nowcast — the one published the week the quarter ended — stamped with a date thirteen weeks earlier.
The poller's own docstring says the opposite in as many words: "FRED serves full history, so this backfills on first run → the signal is backtest-replayable from day one." The backfill is real. The replayability is not, and the reason is not that the data is missing — it is that the wrong object was stored.
We measured the gap using FRED's revision archive, which keeps every version of every observation. Comparing what our table holds against what was genuinely published on each of 806 revision dates:
- mean absolute difference 1.414 pp, median 0.643, 90th percentile 3.455;
- worst single case 25.086 pp — on 3 August 2020 the live nowcast read +11.88; our table stores +36.97 for that quarter;
- the sign of growth differs between the first reading and the stored one in 3 of 61 quarters (2020 Q1, 2022 Q2, 2025 Q1).
A mean error of 1.4 pp is not a rounding issue when the thresholds on offer are 2.0 and 2.5. But error in percentage points is the wrong unit for a switch, so we measured the switch instead: how often would a replay of our table have disagreed with reality about whether the gate was open?
| Threshold | Replay OPEN, live SHUT | Replay SHUT, live OPEN | Total | Worst run |
|---|---|---|---|---|
| above 2.0 | 22.49% | 15.29% | 37.78% | 81 days |
| above 2.5 | 22.52% | 15.07% | 37.59% | 81 days |
| below 1.0 | 12.37% | 2.71% | 15.07% | 99 days |
Read the first column. At every threshold the bias runs the same way — toward the replay trading on days the real signal would have blocked — and the worst single unbroken stretch of that is 81 consecutive days at the starter bot's setting, 99 at below 1.0. That is the direction that flatters a backtest, and it is not a small edge case: on the days where the two disagree, the median gap between stored and live is 1.471 pp against 0.947 pp across all days. The disagreements happen precisely where the number is doing something interesting.
The fix exists and is one query parameter away. The same endpoint we already call accepts realtime_start and realtime_end and will serve 803 archived vintages back to 17 May 2016 — every version of the number, with the date it became true. Everything in bands 2, 3 and 4 of the diagram above was computed from it. The "we don't have the historical series" excuse that covers several other signals in this dictionary does not apply here. The one honest limit: the vintage archive starts in 2016, so the first nineteen quarters in our table (2011 Q3 – 2016 Q1) have no revision record and are finals only.
3. The gate is dark about 94 days a year, and nothing tells you
This one needs care, because the behaviour is defensible and the silence is not.
The Atlanta Fed does not start nowcasting a quarter on day one. It waits for source data: the first estimate for a quarter has landed 29 or 30 days after the quarter began in each of the last several years (Q1 2025 on 31 January, Q2 2026 on 30 April, Q3 2026 on 30 July). Meanwhile the previous quarter's row — dated about 92 days earlier — crosses the anchor's _STALE_OBS_DAYS = 100 line roughly 8 days into the new quarter. Between those two moments there is no observation the gate will accept, so it is shut regardless of what you configured.
Over the 3,695 days modelled that is 948 days — 25.66% of the calendar, 93.7 days a year. Recent windows: 19 days in July 2026, 18 in April 2026, 18 in April 2025, 27 in July 2025.
Is that a bug? No — refusing to treat a 92-day-old quarter's final figure as a description of "now" is the right call, and the alternative (carry the last known number forward indefinitely) is how you end up gating August on data about April. The defect is that nobody is told. The builder renders your rule as "only when GDPNow > 2.5%" and stops there. There is no note in the field description, no warning at save time, no line on the signals page, and no log entry when the gate shuts for this reason rather than because your condition failed. A user reading the duty-cycle table above would reasonably expect roughly 46% open; a user reading the builder would expect "whenever growth is hot". Both are missing a structural third of the shut days.
4. Early-quarter readings are five times less reliable, and the threshold treats them identically
A nowcast published 30 days into a quarter is built from one month of source data. One published on day 90 has almost everything. They are not the same quality of evidence, and the gate cannot tell them apart — it compares a number to a number.
Measured against each quarter's own final figure, from the revision archive:
| Published this far into the quarter | Readings | Mean gap to the final figure |
|---|---|---|
| 30–44 days | 152 | 2.433 pp |
| 45–59 days | 119 | 1.900 pp |
| 60–74 days | 139 | 1.556 pp |
| 75–89 days | 116 | 1.611 pp |
| 90+ days | 280 | 0.502 pp |
The first reading of a quarter is off by 2.4 pp on average — more than the entire distance between the two thresholds this site recommends. By the end it is off by 0.5. If you use this signal, the useful mental model is that it gets sharper as the quarter ages, and that a gate flipping in week five means much less than the same flip in week twelve.
5. The nowcast itself misses the official print by 0.87 pp on average
Everything above is about our handling. This is about the number itself, and it is the question the dictionary is supposed to answer: is it any good?
We compared each quarter's final GDPNow reading against the BEA's advance estimate for the same quarter — the first official print, pulled from FRED's revision archive for A191RL1Q225SBEA so that we are using the number as first published rather than as later revised. Over 60 quarters: mean absolute error 0.869 pp, median 0.549, 90th percentile 2.444, worst 3.871. From 2021 Q1 onward, which drops the pandemic quarters, the mean is 0.761 pp over 22 quarters.
That is genuinely good for a model with no inside information — but it is not tight enough to treat a threshold as a bright line. Two of the last six quarters missed by more than 2.4 pp in opposite directions: 2025 Q1 came in at −2.732 against an advance print of −0.300, and 2025 Q4 at +4.237 against +1.400. A bot gated on above 2.5 was open through the second of those on the strength of a number that overstated growth by nearly three points.
6. The feed went dark for 68 days this year, and the gate went dark with it
The Atlanta Fed published nothing at all between 29 January and 7 April 2026 — 68 days. When it resumed, the first nowcast for Q1 2026 arrived on 7 April, after the quarter it describes had already ended. There were two shorter silences before it: 20 days in October 2025 and 13 in November 2025. The knock-on is visible in band 2 of the diagram: November 2025, February 2026 and March 2026 had no current nowcast on any day of the month, and the forced-shut windows for those quarters ran 75 and 87 days instead of the usual 18 to 27.
We are not going to guess why — the reason is not in our data and we did not find a primary source stating it, so it stays unstated. The point for a bot builder is the exposure: this is a signal whose publisher can stop for months, and when it does, a gate built on it is off, silently, for a quarter. Our staleness rules handle that correctly — they fail closed — but "correctly off for 87 days" is still 87 days your bot did not trade, and nothing anywhere tells you that is what happened.
7. The poller dies on our own database lock — and the gate is slow to notice
The poller crashed on sqlite3.OperationalError: database is locked on both 10 and 11 August 2026, leaving the table three days stale. Lifetime: 53 successful runs, 3 crashes, two of them those. Nothing was wrong with FRED — the fetch had already succeeded; the write is what failed, against our own predictive.db. This is the same contention that has hit six other pollers documented elsewhere in this dictionary.
Two honest qualifications, both of which cut against making too much of it. First, we watched the next run succeed: at 05:30:04 UTC on 12 August the poller wrote all 61 rows normally. The ticker_index job that had been holding the write lock for the full ~119 seconds of its scan was rewritten at 02:47 that morning and now holds it for between 0.16 and 7.8 seconds. One successful run is not proof, but the sequence is what you would expect if that were the cause. Second, the gate never actually shut: _STALE_POLL_DAYS = 3 is compared with .days > 3, so it takes four consecutive missed daily polls to fail closed. We used two of them.
The watchdog is the weaker link. signal_health.py carries a row for this feed with a 36-hour threshold, which those two missed days comfortably breached — but its log's most recent entry is 10 August 06:00, and its entries are spaced a week apart despite a daily cron. So the alarm that was configured for exactly this did not sound. That is a platform issue rather than a signal issue, and it is noted here because it is why the outage was found by writing a dictionary page instead of by the monitoring.
8. Two smaller things: a range that can't describe 2020, and contradictions that validate
validate_config requires the threshold to be between −20 and 20. Our own table contains −32.084 (2020 Q2) and +36.971 (2020 Q3). So {"below": −30} — a rule meaning "only when the economy is in genuine freefall" — is rejected as invalid even though the series has been there, twice, inside the history we ship. The bound is sensible for ordinary use and wrong at exactly the moment you would most want it.
And {"above": 3, "below": 1} validates cleanly, can never be true, and to_english renders it as "only when GDPNow > 3% (growth running hot) and GDPNow < 1% (growth cooling)" — which is at least honest enough to be obviously absurd on the page, unlike the equivalent bug on funding_anchor, which silently hides the second condition. Nothing warns you either way.
The case for the defence
Five things this signal gets right, several of which its neighbours in this dictionary do not:
- The shipped thresholds are well calibrated. 2.0 and 2.5 sit in the middle of the real distribution and produce gates open 56% and 46% of the time. Four other signals documented here ship defaults that have never once been satisfied. This one shipped sensible numbers.
- Both staleness checks are written correctly. They parse timestamps into real dates instead of comparing ISO strings against SQLite's format — the bug that silently defeats the freshness check on finance_anchor, tropical_anchor and funding_anchor. And the comment explaining why two separate checks are needed — one for the observation, one for the poller — is the clearest piece of reasoning in the anchor set.
- The polling cadence is right and the vendor is excellent. Daily against a series that moves every 4 days; FRED is free, fast, historically complete and has never failed us. The one thing we asked of it that it does not do — serving the vintage path by default — it will do on request.
- The registry describes it accurately. Source, poller, cron, table, replayability and bot count all resolve correctly, with no correction needed on this page. That has been true for only a handful of the signals documented so far.
- The underlying idea is sound. "Don't trade macro contracts when the growth regime is against you" is a reasonable hypothesis, the input is the best real-time growth estimate publicly available, and it is free. The problems on this page are almost all about how we store and replay it, not about whether the number is worth having.
The real record
There isn't one. No bot has ever used this signal. Zero of the 76 strategy configurations on the platform mention gdpnow_anchor — not the 21 live, not the 15 out-of-sample, not the 36 archived, not the 4 drafts — and zero of the 88 saved strategy versions. No trades, no fills, no evaluations, no profit or loss. There is no track record to quote and none is invented here.
That is worth stating carefully rather than treating as a verdict. Nobody using a signal is evidence about adoption, and adoption has several possible causes — the backtester not supporting it is an obvious candidate, since a builder who attaches it and sees "advanced rule(s) not yet replayed" has little reason to continue. We cannot rank those causes from a count of zero, so we won't.
Two things do exist and are ready to use. The builder ships a "GDP nowcast" field with a default of above 2.5 and a recipe called "Hot-growth macro" at the same level; and there is a starter bot, "Macro Nowcast Rider" — buy YES on economics markets priced 30¢–60¢, only when GDPNow is above 2%, $5 a trade. Neither has ever been activated by anyone.
There is also a live reading on the site that has nothing to do with the table. The /api/tools/gdpnow endpoint behind the economics signals page calls FRED directly rather than reading macro_nowcast, so it kept showing the correct current figure throughout the two days the poller was down. Right now it returns the nowcast 5.833 for Q3 2026, as of 2026-08-06, against a prior actual of 1.5 for Q2 2026. The page a human reads is more reliable than the table a bot reads, which is a strange way round for a trading platform.
How to actually use it
- Do not trust a backtest of a bot containing this rule. The gate was not applied. Check the result for unsupported_rules and treat the curve as the ungated strategy — because that is exactly what it is.
- Expect it to be shut about a quarter of the time for reasons unrelated to your threshold, concentrated in the first month of each quarter. If your strategy needs continuous exposure, this is the wrong switch.
- Prefer wide, slow thresholds. With a mean error of 2.4 pp on early-quarter readings and 0.87 pp against the official print, a threshold you sit within a point of will flip on noise. The two shipped defaults are reasonable starting points precisely because they are round and central.
- Match the horizon. GDPNow describes a three-month window that resolves weeks later. It is a poor input for a contract settling this afternoon and a plausible one for a contract about the quarter, the rate path, or a recession call.
- Remember it silences the whole bot. If you only want it to govern economics markets, set the bot's category filter too — otherwise a macro condition is deciding your weather trades.
- If you want the honest historical version of this signal, it exists — FRED's vintage archive, described in catch #2. It is just not what our table holds today.
Where to go next
The closest relative is gdp_surprise_anchor, which reads the same table from the same poller and gates on the nowcast minus the last official print — growth accelerating or decelerating rather than high or low. It has no page yet; when it gets one, catches #2, #3, #6 and #7 here apply to it wholesale, because it is the same row from the same feed.
For a signal that gates on a market level rather than an economic one, see finance_anchor, which also reads FRED — and whose freshness check, unlike this one's, does not work. For the other time-based macro switch, see eco_anchor, which opens a window around scheduled releases rather than reacting to a value. For what happens when a gate does work exactly as designed and the bot loses money anyway, see funding_anchor.
Everything on this page traces to one of four places: the source of
quants/gdpnow_anchor.py and predictive/gdpnow_poller.py; the production database and
crontab; the FRED API including its vintage archive, called live from the production server; and the Atlanta
Fed's own GDPNow page, read directly. Where a claim could not be traced to one of those it is marked as
unverified or left out — the 68-day publication gap in catch #6 is stated as measured and its cause is not
guessed at. No performance figures appear on this page because none exist. Duty-cycle and disagreement figures
cover 3,695 calendar days, 1 July 2016 to 12 August 2026, and describe gate open rate, not the
behaviour of the economy. Verified 2026-08-12. All TinyCorp bots trade simulated money.