TanStack
Catalog

Bollinger band

trend

84 lines · 2 files · 2.2 kB

cases/22-bollinger-band/example.tsx78 lines · entry
cases/22-bollinger-band/example.tsx
import { Chart } from '@tanstack/charts/react/tooltip'
import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip'

import {
  areaY,
  defineChart,
  deviation,
  lineY,
  rollingWindow,
} from '@tanstack/charts'
import { scaleLinear, scaleUtc } from 'd3-scale'
import { aapl } from '@tanstack/charts-data/aapl'
import { selectBollingerData } from './selection'

const windowSize = 20
const deviationMultiplier = 2

function bollingerRows(input: ChartOptions) {
  const rows = rollingWindow(selectBollingerData(aapl, input.revision), {
    size: windowSize,
    orderBy: 'Date',
    anchor: 'end',
    partial: false,
    outputs: {
      meanClose: { value: 'Close', reduce: 'mean' },
      closeDeviation: { value: 'Close', reduce: deviation },
    },
  })
  return rows
}

export const createExampleChart = (input: ChartOptions) => {
  const rows = bollingerRows(input)

  return defineChart(
    {
      marks: [
        areaY(rows, {
          id: 'bollinger-band',
          x: 'Date',
          y1: (row) => row.meanClose - row.closeDeviation * deviationMultiplier,
          y2: (row) => row.meanClose + row.closeDeviation * deviationMultiplier,
          fill: '#7c3aed',
          fillOpacity: 0.18,
        }),
        lineY(rows, {
          id: 'bollinger-mean',
          x: 'Date',
          y: 'meanClose',
          stroke: '#7c3aed',
          strokeWidth: 2.25,
        }),
      ],
      scales: {
        x: { scale: scaleUtc, axis: { label: 'Date' } },
        y: {
          scale: scaleLinear,
          grid: true,
          axis: { label: 'Apple close (USD)' },
        },
      },
    },
    { keyboard: true, tooltip: exampleTooltip },
  )
}
export interface ChartOptions {
  revision: number
}

export const exampleAriaLabel = 'Twenty-day Apple Bollinger band'

export const chart = createExampleChart({
  revision: 0,
})

export default function Example() {
  return <Chart ariaLabel={exampleAriaLabel} definition={chart} height={480} />
}
cases/22-bollinger-band/selection.ts6 lines · dependency
cases/22-bollinger-band/selection.ts
import type { AaplRow } from '@tanstack/charts-data/aapl'

export function selectBollingerData(rows: readonly AaplRow[], revision = 0) {
  const offset = Math.abs(revision) % 2
  return rows.slice(offset)
}