Practical guide

Build a time series chart from JSON

A time-series chart needs ordered observations and a stable relationship between every timestamp and value. Sorting only the dates, dropping a null from one side, or treating seconds as milliseconds can produce a believable line with the wrong story.

This example uses a compact set of 2024 month-end S&P 500 closing index observations. It is a charting exercise, not live market data, a price forecast, or investment advice.

Fix the source and time window

I pulled this sample from FRED's SP500 table, which names S&P Dow Jones Indices LLC as the source. Each number is the index at that day's market close. Dividends are not included, so do not read the series as total return.

The guide keeps one 2024 month-end observation per month. Record the series, retrieval date, transformation rule, and time window when you prepare your own fixture; do not quietly mix daily closes, monthly averages, ETF prices, and total-return values.

  • Source: FRED SP500 table data.
  • Frequency in the source series: daily close; this fixture selects month-end observations.
  • Unit: index points, not USD and not an ETF share price.
2024 month-end close samplejson
[
  { "date": "2024-01-31", "close": 4845.65 },
  { "date": "2024-02-29", "close": 5096.27 },
  { "date": "2024-03-28", "close": 5254.35 },
  { "date": "2024-04-30", "close": 5035.69 },
  { "date": "2024-05-31", "close": 5277.51 },
  { "date": "2024-06-28", "close": 5460.48 },
  { "date": "2024-07-31", "close": 5522.30 },
  { "date": "2024-08-30", "close": 5648.40 },
  { "date": "2024-09-30", "close": 5762.48 },
  { "date": "2024-10-31", "close": 5705.45 },
  { "date": "2024-11-29", "close": 6032.38 },
  { "date": "2024-12-31", "close": 5881.63 }
]

Keep timestamps and values paired

Filter and sort the records before extracting either series. Repeating the same preparation in both chart expressions is deliberate: it keeps a missing close from removing a Y value while leaving its date behind on X.

ISO dates sort correctly as strings in this fixture. If your source uses Unix timestamps, first establish whether they are seconds or milliseconds and which timezone defines a reporting day.

paired observationsjq
map(select(.date != null and (.close | type) == "number"))
| sort_by(.date)

Create the line chart

Choose Line, put the sorted dates on X, and take the closes from the very same rows for Y. Call the Y axis S&P 500 close and set its unit to index points; these values are not dollars.

You can switch the same inputs to Area without changing the numbers. The fill mainly adds visual weight, so Line is the clearer first look at movement between observations.

X expressionjq
map(select(.date != null and (.close | type) == "number"))
| sort_by(.date)[]
| .date
Y expressionjq
map(select(.date != null and (.close | type) == "number"))
| sort_by(.date)[]
| .close
A source-to-chart walkthrough using a dated S&P 500 fixture: inspect missing observations, preserve timestamp/value pairs, sort the records, build a line chart, and verify selected points against the JSON.Watch on YouTube

Treat missing observations honestly

A market holiday is not a zero index value. A missing close can mean no observation, a delayed source, or a malformed record. Filter it out or apply a documented domain rule before charting; do not insert zero merely to keep the arrays the same length.

If you resample daily values into weeks or months, state whether you selected the last available close, calculated an average, or used another rule. Each method answers a different question.

Trace points back to JSON

Do a quick spot check instead of trusting the curve. January and December anchor the ends; April should fall below March, while November should rise above October. A different picture means the filter or ordering needs another look.

The result is a local visualization of a fixed fixture. It does not update itself, calculate returns, include dividends, or provide financial advice. Return to How to create a chart from JSON for the general chart-shape checklist.