Source

70 chart lines · 2 files · 2.0 kBBenchmark harness excluded · shared/mount.ts

Apple daily stock prices1,260 records · CSV · 92.4 kB
@charts-poc/demo-data/aapl

Selection: Complete published snapshot

Date
Date
Open
number
High
number
Low
number
Close
number
Adj Close
number
Volume
number

Yahoo! Finance@observablehq/sample-datasets@1.0.1 · revision 732c0148de74 · aapl.csv · ISC distribution; upstream source credited · SHA-256 18dc8bf6542dPinned snapshot

cases/28-candlestick/tanstack.ts62 lines · entry
cases/28-candlestick/tanstack.ts
import { defineChart, link } from '@tanstack/charts'
import { aapl } from '@charts-poc/demo-data/aapl'
import { scaleLinear, scaleUtc } from 'd3-scale'
import { selectCandleData } from './selection'
import { tanstackMount } from '../../shared/mount'
import type { ConformanceInput } from '../../types'

const candleDate = new Intl.DateTimeFormat('en-US', {
  month: 'short',
  day: 'numeric',
  year: 'numeric',
  timeZone: 'UTC',
})
const price = new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
})

const definition = (input: ConformanceInput) => {
  const rows = selectCandleData(aapl, input.revision)
  const gains = rows.filter((row) => row.Close >= row.Open)
  const losses = rows.filter((row) => row.Close < row.Open)
  return defineChart({
    marks: [
      link(rows, {
        x1: 'Date',
        y1: 'Low',
        x2: 'Date',
        y2: 'High',
        stroke: '#64748b',
        strokeWidth: 1,
      }),
      link(gains, {
        x1: 'Date',
        y1: 'Open',
        x2: 'Date',
        y2: 'Close',
        stroke: '#10b981',
        strokeWidth: 5,
      }),
      link(losses, {
        x1: 'Date',
        y1: 'Open',
        x2: 'Date',
        y2: 'Close',
        stroke: '#ef4444',
        strokeWidth: 5,
      }),
    ],
    x: { scale: scaleUtc },
    y: { scale: scaleLinear, grid: true, axis: { label: 'Price' } },
  })
}

export const mount = tanstackMount(
  definition,
  'Apple daily candlestick chart',
  {
    format: (point) =>
      `${candleDate.format(point.datum.Date)} · Open: ${price.format(point.datum.Open)} · High: ${price.format(point.datum.High)} · Low: ${price.format(point.datum.Low)} · Close: ${price.format(point.datum.Close)}`,
  },
)
cases/28-candlestick/selection.ts8 lines · support
cases/28-candlestick/selection.ts
import type { AaplRow } from '@charts-poc/demo-data/aapl'

const sessionsPerView = 30

export function selectCandleData(rows: readonly AaplRow[], revision = 0) {
  const start = Math.abs(revision % 2) * sessionsPerView
  return rows.slice(start, start + sessionsPerView)
}