CUCKOOTRADE
Guide

How to mock the Alpha Vantage API, including intraday

The same numbered-key JSON, the same newest-first maps, the same errors-as-200 quirk — without a key, without the daily request cap, and with intraday history that is a paid feature on the real thing.

Any language REST 6 minutes

The base URL swap

Replace https://www.alphavantage.co/query with https://cuckootrade.com/api/v1/alphavantage/query. The function-switched interface is unchanged:

shell — daily series, no key
curl 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_DAILY&symbol=IBM'
json — the familiar shape
{
  "Meta Data": {
    "1. Information": "Daily Prices (open, high, low, close) and Volumes",
    "2. Symbol": "IBM",
    "3. Last Refreshed": "2026-08-19",
    "4. Output Size": "Compact",
    "5. Time Zone": "US/Eastern"
  },
  "Time Series (Daily)": {
    "2026-08-19": {
      "1. open": "241.8300",
      "2. high": "244.1900",
      "3. low": "240.5500",
      "4. close": "243.0700",
      "5. volume": "3814227"
    }
  }
}
Everything is a string, and that is the point. Prices and volumes are quoted, keys are numbered, and series are maps keyed newest-first rather than arrays. Parsers that assume JSON numbers break here — which is a large part of why this surface is worth testing against rather than around.

Intraday, free

On the real API, intraday history sits behind a premium plan. Here it is generated on demand, so it costs nothing:

shell — five-minute bars
curl 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min'

# a specific month of history
curl 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=1min&month=2026-07&outputsize=full'
functionNotes
TIME_SERIES_INTRADAYinterval= 1min, 5min, 15min, 30min, 60min. month=YYYY-MM selects a month.
TIME_SERIES_DAILYKeyed YYYY-MM-DD.
TIME_SERIES_WEEKLYKeyed by the last trading day of the week.
TIME_SERIES_MONTHLYKeyed by the last trading day of the month.
GLOBAL_QUOTEThe single-quote shape.

outputsize=compact (100 rows, the default) and full both behave as documented. apikey, adjusted and extended_hours are accepted and ignored.

Timestamp conventions differ per function, exactly as upstream. Intraday rows are keyed by the bar’s close in US/Eastern local time — the opposite convention to the Alpaca surface’s UTC open timestamps. If your code has an off-by-one-bar bug, this is where it shows up.

Errors arrive as HTTP 200

The real API reports failures with a success status line, and its client libraries sniff for the Error Message key rather than checking the status. That is faithfully reproduced here, because code that gets this wrong fails silently in production:

python — check the key, not the status
import requests

r = requests.get("https://cuckootrade.com/api/v1/alphavantage/query",
                 params={"function": "TIME_SERIES_DAILY",
                         "symbol": "IBM"}).json()

# Errors arrive as 200. r.raise_for_status() would never fire.
if "Error Message" in r:
    raise SystemExit(r["Error Message"])

series = r["Time Series (Daily)"]
for day, ohlcv in list(series.items())[:5]:      # newest first
    print(day, float(ohlcv["4. close"]))         # values are strings

The one deliberate exception is scenario=status:503: you explicitly asked for a status code, so the request wins over the mimicry. That gives you both behaviors to test against.

Scenario tickers and fault injection

All three provider surfaces read from the same deterministic engine, so scenario tickers work here identically — only the wire format differs:

shell — a crash, in Alpha Vantage’s format
curl 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_DAILY&symbol=CRASH'

# and a transport that fails twice before it works
curl -i 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_DAILY&symbol=IBM&scenario=flap:2'

The full scenario ticker catalogue →

Deviations, stated plainly

  • Completed bars only. There is no partial current day, week, or month row — determinism requires it.
  • Regular session only. 09:30–16:00 ET; extended hours are not modeled.
  • No rate limit worth planning around. 60 requests/minute per address rather than the real API’s daily cap.
  • Fundamentals, FX, and crypto functions are not implemented. Time series and GLOBAL_QUOTE are.
All data is synthetic and every response says so via X-Cuckoo-Synthetic: true. For exercising code paths, not for validating trading strategies.

Next