Candlestick Chart

Financial OHLC candlestick chart for stock and crypto data visualization

Installation

pnpm dlx shadcn@latest add "https://vritti.thesatyajit.com/r/candlestick-chart"

Dependencies

pnpm add @visx/responsive @visx/scale @visx/shape @visx/group @visx/event @visx/grid @visx/gradient @visx/pattern d3-array motion react-use-measure

Examples

Bitcoin

"use client"
import CandlestickChart, {
  Candlestick,
  ChartTooltip,
  Grid,
  XAxis,
  YAxis,
} from "@/components/vritti/candlestick-chart"

// BTC/USD daily data — January 2026
// Confirmed reference points: Jan 1 ~$88k, Jan 5 ~$94k, mid-Jan peak ~$95–97k,
// Jan 20 ~$95k, Jan 29 crash low ~$81k, Jan 30 ~$82.7k
const data = [
  { date: new Date(2026, 0, 1),  open: 87800, high: 89500, low: 85200, close: 88100, volume: 28400000000 },
  { date: new Date(2026, 0, 2),  open: 88100, high: 91200, low: 87400, close: 90500, volume: 31200000000 },
  { date: new Date(2026, 0, 3),  open: 90500, high: 92100, low: 88800, close: 89700, volume: 27800000000 },
  { date: new Date(2026, 0, 4),  open: 89700, high: 91800, low: 88500, close: 91200, volume: 29500000000 },
  { date: new Date(2026, 0, 5),  open: 91200, high: 94600, low: 90800, close: 93800, volume: 38700000000 },
  { date: new Date(2026, 0, 6),  open: 93800, high: 95400, low: 92100, close: 94500, volume: 35200000000 },
  { date: new Date(2026, 0, 7),  open: 94500, high: 96800, low: 93200, close: 96100, volume: 41500000000 },
  { date: new Date(2026, 0, 8),  open: 96100, high: 97200, low: 94500, close: 95400, volume: 36800000000 },
  { date: new Date(2026, 0, 9),  open: 95400, high: 96500, low: 93800, close: 94800, volume: 33100000000 },
  { date: new Date(2026, 0, 10), open: 94800, high: 96200, low: 93500, close: 95900, volume: 31700000000 },
  { date: new Date(2026, 0, 11), open: 95900, high: 97100, low: 94200, close: 95200, volume: 34500000000 },
  { date: new Date(2026, 0, 12), open: 95200, high: 96800, low: 93100, close: 94100, volume: 35900000000 },
  { date: new Date(2026, 0, 13), open: 94100, high: 95400, low: 91800, close: 92500, volume: 37200000000 },
  { date: new Date(2026, 0, 14), open: 92500, high: 94200, low: 90500, close: 91800, volume: 39400000000 },
  { date: new Date(2026, 0, 15), open: 91800, high: 93500, low: 90200, close: 93100, volume: 34800000000 },
  { date: new Date(2026, 0, 16), open: 93100, high: 94800, low: 91500, close: 92300, volume: 32100000000 },
  { date: new Date(2026, 0, 17), open: 92300, high: 94100, low: 90800, close: 93500, volume: 33500000000 },
  { date: new Date(2026, 0, 18), open: 93500, high: 95200, low: 92100, close: 93800, volume: 35800000000 },
  { date: new Date(2026, 0, 19), open: 93800, high: 95800, low: 92500, close: 94900, volume: 37200000000 },
  { date: new Date(2026, 0, 20), open: 94900, high: 96100, low: 93200, close: 95100, volume: 40100000000 },
  { date: new Date(2026, 0, 21), open: 95100, high: 96500, low: 91200, close: 91800, volume: 52300000000 },
  { date: new Date(2026, 0, 22), open: 91800, high: 93100, low: 88400, close: 89200, volume: 58700000000 },
  { date: new Date(2026, 0, 23), open: 89200, high: 90500, low: 86800, close: 87900, volume: 48900000000 },
  { date: new Date(2026, 0, 24), open: 87900, high: 89400, low: 85100, close: 86200, volume: 51200000000 },
  { date: new Date(2026, 0, 29), open: 86200, high: 87800, low: 80800, close: 81200, volume: 72400000000 },
]

export function CandlestickBitcoinDemo() {
  const fmtK = (v: number) => `$${(v / 1000).toFixed(1)}k`

  return (
    <div className="w-full p-4">
      <CandlestickChart data={data} candleGap={0.15}>
        <Grid horizontal />
        <Candlestick />
        <XAxis />
        <YAxis formatValue={fmtK} />
        <ChartTooltip
          showDatePill
          showCrosshair
          showDots={false}
          rows={(point) => {
            const p = point as {
              open: number
              high: number
              low: number
              close: number
              volume: number
            }
            return [
              { color: "var(--muted-foreground)", label: "Open",   value: fmtK(p.open) },
              { color: "hsl(142 71% 45%)",        label: "High",   value: fmtK(p.high) },
              { color: "hsl(0 84% 60%)",          label: "Low",    value: fmtK(p.low) },
              { color: "var(--muted-foreground)", label: "Close",  value: fmtK(p.close) },
              {
                color: "var(--muted-foreground)",
                label: "Volume",
                value: `${(p.volume / 1_000_000_000).toFixed(1)}B`,
              },
            ]
          }}
        />
      </CandlestickChart>
    </div>
  )
}

Ohlv

"use client"
import CandlestickChart, {
  Candlestick,
  ChartTooltip,
  Grid,
  XAxis,
  YAxis,
} from "@/components/vritti/candlestick-chart"

const data = [
  { date: new Date(2026, 0, 2),  open: 272.26, high: 277.84, low: 269.00, close: 271.01, volume: 37838054 },
  { date: new Date(2026, 0, 5),  open: 270.64, high: 271.51, low: 266.14, close: 267.26, volume: 45647190 },
  { date: new Date(2026, 0, 6),  open: 267.00, high: 267.55, low: 262.12, close: 262.36, volume: 52352090 },
  { date: new Date(2026, 0, 7),  open: 263.20, high: 263.68, low: 259.81, close: 260.33, volume: 48309804 },
  { date: new Date(2026, 0, 8),  open: 257.02, high: 259.29, low: 255.70, close: 259.04, volume: 50419337 },
  { date: new Date(2026, 0, 9),  open: 259.08, high: 260.21, low: 256.22, close: 259.37, volume: 39996967 },
  { date: new Date(2026, 0, 12), open: 259.16, high: 261.30, low: 256.80, close: 260.25, volume: 45263767 },
  { date: new Date(2026, 0, 13), open: 258.72, high: 261.81, low: 258.39, close: 261.05, volume: 45730847 },
  { date: new Date(2026, 0, 14), open: 259.49, high: 261.82, low: 256.71, close: 259.96, volume: 40019421 },
  { date: new Date(2026, 0, 15), open: 260.65, high: 261.04, low: 257.05, close: 258.21, volume: 39388564 },
  { date: new Date(2026, 0, 16), open: 257.90, high: 258.90, low: 254.93, close: 255.53, volume: 72142773 },
  { date: new Date(2026, 0, 20), open: 252.73, high: 254.79, low: 243.42, close: 246.70, volume: 80267517 },
  { date: new Date(2026, 0, 21), open: 248.70, high: 251.56, low: 245.18, close: 247.65, volume: 54641725 },
  { date: new Date(2026, 0, 22), open: 249.20, high: 251.00, low: 248.15, close: 248.35, volume: 39708340 },
  { date: new Date(2026, 0, 23), open: 247.32, high: 249.41, low: 244.68, close: 248.04, volume: 41688982 },
  { date: new Date(2026, 0, 26), open: 251.48, high: 256.56, low: 249.80, close: 255.41, volume: 55969234 },
  { date: new Date(2026, 0, 27), open: 259.17, high: 261.95, low: 258.21, close: 258.27, volume: 49648271 },
  { date: new Date(2026, 0, 28), open: 257.65, high: 258.86, low: 254.51, close: 256.44, volume: 41287971 },
  { date: new Date(2026, 0, 29), open: 258.00, high: 259.65, low: 254.41, close: 258.28, volume: 67253009 },
  { date: new Date(2026, 0, 30), open: 255.17, high: 261.90, low: 252.18, close: 259.48, volume: 92443408 },
  { date: new Date(2026, 1, 2),  open: 260.03, high: 270.49, low: 259.21, close: 270.01, volume: 73913425 },
  { date: new Date(2026, 1, 3),  open: 269.20, high: 271.88, low: 267.61, close: 269.48, volume: 64394655 },
  { date: new Date(2026, 1, 4),  open: 272.29, high: 278.95, low: 272.29, close: 276.49, volume: 90545710 },
  { date: new Date(2026, 1, 5),  open: 278.13, high: 279.50, low: 273.23, close: 275.91, volume: 52977441 },
  { date: new Date(2026, 1, 6),  open: 277.12, high: 280.91, low: 276.93, close: 278.12, volume: 50453414 },
  { date: new Date(2026, 1, 9),  open: 277.91, high: 278.20, low: 271.70, close: 274.62, volume: 44623396 },
  { date: new Date(2026, 1, 10), open: 274.89, high: 275.37, low: 272.94, close: 273.68, volume: 34376898 },
  { date: new Date(2026, 1, 11), open: 274.70, high: 280.18, low: 274.45, close: 275.50, volume: 51931283 },
  { date: new Date(2026, 1, 12), open: 275.59, high: 275.72, low: 260.18, close: 261.73, volume: 81077229 },
  { date: new Date(2026, 1, 13), open: 262.01, high: 262.23, low: 255.45, close: 255.78, volume: 56290673 },
]

export function CandlestickOHLVDemo() {
  return (
    <div className="w-full p-4">
      <CandlestickChart data={data}>
        <Grid horizontal />
        <Candlestick />
        <XAxis />
        <YAxis formatValue={(v) => `$${v.toFixed(0)}`} />
        <ChartTooltip
          showDatePill
          showCrosshair
          showDots={false}
          indicatorColor={(point) => {
            const p = point as { close: number; open: number }
            return p.close >= p.open
              ? "var(--color-emerald-500)"
              : "var(--color-red-500)"
          }}
          rows={(point) => {
            const p = point as {
              open: number
              high: number
              low: number
              close: number
              volume: number
            }
            return [
              {
                color: "var(--muted-foreground)",
                label: "Open",
                value: `$${p.open.toFixed(2)}`,
              },
              {
                color: "hsl(142 71% 45%)",
                label: "High",
                value: `$${p.high.toFixed(2)}`,
              },
              {
                color: "hsl(0 84% 60%)",
                label: "Low",
                value: `$${p.low.toFixed(2)}`,
              },
              {
                color: "var(--muted-foreground)",
                label: "Close",
                value: `$${p.close.toFixed(2)}`,
              },
              {
                color: "var(--muted-foreground)",
                label: "Volume",
                value: `${(p.volume / 1_000_000).toFixed(1)}M`,
              },
            ]
          }}
        />
      </CandlestickChart>
    </div>
  )
}

Weekly

"use client"
import CandlestickChart, {
  Candlestick,
  ChartTooltip,
  Grid,
  XAxis,
  YAxis,
} from "@/components/vritti/candlestick-chart"

// AAPL weekly candles — Jun 2025 → Feb 2026
// ATH $285.92 on Dec 2, 2025. 52-week low $169.21 (Mar 2025). Current $249.68 (Mar 2026).
// Jan–Feb 2026 values are actual data from stockanalysis.com.
const data = [
  { date: new Date(2025, 5, 2),  open: 196.50, high: 200.20, low: 193.80, close: 198.70 },
  { date: new Date(2025, 5, 9),  open: 198.90, high: 203.40, low: 197.10, close: 202.50 },
  { date: new Date(2025, 5, 16), open: 202.20, high: 207.10, low: 200.40, close: 205.80 },
  { date: new Date(2025, 5, 23), open: 205.60, high: 210.30, low: 203.90, close: 209.40 },
  { date: new Date(2025, 5, 30), open: 209.20, high: 213.80, low: 207.60, close: 212.90 },
  { date: new Date(2025, 6, 7),  open: 212.70, high: 217.50, low: 210.80, close: 216.30 },
  { date: new Date(2025, 6, 14), open: 216.10, high: 221.20, low: 214.30, close: 219.80 },
  { date: new Date(2025, 6, 21), open: 219.60, high: 224.40, low: 217.90, close: 222.70 },
  { date: new Date(2025, 6, 28), open: 222.50, high: 227.60, low: 220.30, close: 225.90 },
  { date: new Date(2025, 7, 4),  open: 225.70, high: 230.80, low: 223.50, close: 228.40 },
  { date: new Date(2025, 7, 11), open: 228.20, high: 233.90, low: 226.60, close: 232.10 },
  { date: new Date(2025, 7, 18), open: 232.30, high: 237.50, low: 229.80, close: 235.60 },
  { date: new Date(2025, 7, 25), open: 235.80, high: 241.20, low: 233.40, close: 239.50 },
  { date: new Date(2025, 8, 1),  open: 239.30, high: 244.60, low: 237.10, close: 243.10 },
  { date: new Date(2025, 8, 8),  open: 242.90, high: 248.30, low: 240.60, close: 246.80 },
  { date: new Date(2025, 8, 15), open: 246.50, high: 251.80, low: 244.20, close: 250.40 },
  { date: new Date(2025, 8, 22), open: 250.20, high: 255.40, low: 247.90, close: 253.80 },
  { date: new Date(2025, 8, 29), open: 253.60, high: 258.90, low: 251.40, close: 257.20 },
  { date: new Date(2025, 9, 6),  open: 257.00, high: 262.30, low: 254.80, close: 260.60 },
  { date: new Date(2025, 9, 13), open: 260.40, high: 265.70, low: 257.90, close: 263.90 },
  { date: new Date(2025, 9, 20), open: 263.70, high: 269.10, low: 261.30, close: 267.40 },
  { date: new Date(2025, 9, 27), open: 267.20, high: 272.80, low: 264.90, close: 271.00 },
  { date: new Date(2025, 10, 3), open: 270.80, high: 276.40, low: 268.50, close: 274.60 },
  { date: new Date(2025, 10, 10),open: 274.40, high: 280.10, low: 272.20, close: 278.30 },
  { date: new Date(2025, 10, 17),open: 278.10, high: 283.60, low: 275.80, close: 281.90 },
  { date: new Date(2025, 10, 24),open: 281.70, high: 287.30, low: 279.50, close: 285.10 },
  { date: new Date(2025, 11, 1), open: 284.90, high: 289.20, low: 282.60, close: 287.80 }, // ATH week — Dec 2 ATH $285.92
  { date: new Date(2025, 11, 8), open: 287.60, high: 288.62, low: 278.30, close: 281.10 }, // post-ATH pullback
  { date: new Date(2025, 11, 15),open: 280.90, high: 283.60, low: 271.50, close: 274.20 },
  { date: new Date(2025, 11, 22),open: 273.80, high: 277.10, low: 268.40, close: 275.30 },
  { date: new Date(2025, 11, 29),open: 274.10, high: 278.20, low: 271.60, close: 273.20 },
  { date: new Date(2026, 0, 5),  open: 272.26, high: 277.84, low: 266.14, close: 267.26 }, // actual Jan 2–5
  { date: new Date(2026, 0, 12), open: 259.08, high: 261.82, low: 256.22, close: 260.25 }, // actual Jan 9–12
  { date: new Date(2026, 0, 19), open: 257.90, high: 261.90, low: 243.42, close: 248.04 }, // actual Jan 16–23, Jan 20 low 243.42
  { date: new Date(2026, 0, 26), open: 251.48, high: 261.95, low: 249.80, close: 259.48 }, // actual Jan 26–30
  { date: new Date(2026, 1, 2),  open: 260.03, high: 280.91, low: 259.21, close: 278.12 }, // actual Feb 2–6
  { date: new Date(2026, 1, 9),  open: 277.91, high: 280.18, low: 255.45, close: 255.78 }, // actual Feb 9–13 (sharp drop)
]

export function CandlestickWeeklyDemo() {
  return (
    <div className="w-full p-4">
      <CandlestickChart data={data} aspectRatio="3/1" candleGap={0.1}>
        <Grid horizontal />
        <Candlestick />
        <XAxis />
        <YAxis formatValue={(v) => `$${v.toFixed(0)}`} />
        <ChartTooltip
          showDatePill
          showCrosshair
          showDots={false}
          rows={(point) => {
            const p = point as { open: number; high: number; low: number; close: number }
            return [
              { color: "var(--muted-foreground)", label: "Open",  value: `$${p.open.toFixed(2)}` },
              { color: "hsl(142 71% 45%)",        label: "High",  value: `$${p.high.toFixed(2)}` },
              { color: "hsl(0 84% 60%)",          label: "Low",   value: `$${p.low.toFixed(2)}` },
              { color: "var(--muted-foreground)", label: "Close", value: `$${p.close.toFixed(2)}` },
            ]
          }}
        />
      </CandlestickChart>
    </div>
  )
}