Candlestick Chart

Financial OHLC visualisation highlighting open, high, low, and close for trading periods.

npm install @plocks/charts

Basics

Visualizes financial OHLC price movements over time.

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { PRICE_SERIES } from './data'; export function Demo() { return ( <CandlestickChart title="AAPL daily candles" subtitle="Includes 3 & 5-day moving averages" h={360} series={[ { id: 'apple', name: 'Apple Inc.', data: PRICE_SERIES, colorBull: '#34C38F', colorBear: '#F56565', wickColor: '#6B7280', }, ]} movingAveragePeriods={[3, 5]} xAxis={{ show: true, labelFormatter: (value) => new Date(value).toLocaleDateString('en-US', { month: 'short', day: 'numeric', }), title: 'Trading day', }} yAxis={{ show: true, title: 'Price (USD)', labelFormatter: (value) => `$${value.toFixed(0)}`, }} grid={{ show: true, color: '#E5EAF7' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => `O: $${candle.open.toFixed(2)} • H: $${candle.high.toFixed(2)} • L: $${candle.low.toFixed(2)} • C: $${candle.close.toFixed(2)}`, }} enableCrosshair liveTooltip animation={{ duration: 400 }} enablePanZoom zoomMode="both" minZoom={0.2} resetOnDoubleTap clampToInitialDomain xScaleType="time" /> ); }

Battery Material Pricing

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { LITHIUM_SERIES, NICKEL_SERIES, negotiationMarkers } from './data'; const formatWeek = (value: number) => new Date(value).toLocaleDateString('en-US', { month: 'short', day: 'numeric', }); export function Demo() { return ( <CandlestickChart title="Battery Material Pricing" subtitle="Negotiation window tracked across lithium and nickel contracts" h={420} series={[ { id: 'lithium', name: 'Lithium carbonate (USD/ton)', data: LITHIUM_SERIES, colorBull: '#0ea5e9', colorBear: '#bfdbfe', wickColor: '#1d4ed8', }, { id: 'nickel', name: 'Nickel sulfate (USD/ton)', data: NICKEL_SERIES, colorBull: '#facc15', colorBear: '#fef08a', wickColor: '#ca8a04', }, ]} movingAveragePeriods={[3]} movingAverageColors={['#6366f1']} annotations={negotiationMarkers} grid={{ show: true, color: '#E3E8F4' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => `Open $${candle.open.toLocaleString('en-US')} • Close $${candle.close.toLocaleString('en-US')} \nRange $${candle.low.toLocaleString('en-US')} – $${candle.high.toLocaleString('en-US')}`, }} xAxis={{ show: true, title: 'Week of shipment', labelFormatter: formatWeek, }} yAxis={{ show: true, title: 'Spot price (USD per metric ton)', labelFormatter: (value) => `$${value.toLocaleString('en-US')}`, }} enableCrosshair liveTooltip multiTooltip xScaleType="time" /> ); }

Cloud Infra Cost Swings

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { COST_SERIES, CloudCandle, annotations } from './data'; export function Demo() { return ( <CandlestickChart title="Cloud Spend Volatility" subtitle="Optimization window captured a 4.7% cost reduction" h={420} series={[ { id: 'cloud-costs', name: 'Daily infrastructure cost', data: COST_SERIES, colorBull: '#10b981', colorBear: '#ef4444', wickColor: '#475569', }, ]} movingAveragePeriods={[3, 5, 8]} movingAverageColors={['#38bdf8', '#6366f1', '#f97316']} showMovingAverages showVolume volumeHeightRatio={0.24} annotations={annotations} grid={{ show: true, color: '#E3E8F4' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => { const delta = candle.close - candle.open; const deltaLabel = `${delta >= 0 ? '+' : ''}$${delta.toLocaleString('en-US', { maximumFractionDigits: 0 })}`; const note = (candle as CloudCandle).note ? `\n• ${ (candle as CloudCandle).note }` : ''; return [ `Start: $${candle.open.toLocaleString('en-US', { maximumFractionDigits: 0 })}`, `End: $${candle.close.toLocaleString('en-US', { maximumFractionDigits: 0 })} (${deltaLabel})`, `Compute hours: ${(candle.volume ?? 0).toLocaleString('en-US')}`, ].join(' • ') + note; }, }} xAxis={{ show: true, title: 'Billing day', labelFormatter: (value) => new Date(value).toLocaleDateString('en-US', { month: 'short', day: 'numeric', }), }} yAxis={{ show: true, title: 'Daily cloud cost (USD)', labelFormatter: (value) => `$${value.toLocaleString('en-US', { maximumFractionDigits: 0 })}`, }} enableCrosshair liveTooltip xScaleType="time" /> ); }

Crypto Treasury Balances

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { TREASURY_SERIES, TreasuryCandle, annotations } from './data'; const formatWeek = (value: number) => new Date(value).toLocaleDateString('en-US', { month: 'short', day: 'numeric', }); export function Demo() { return ( <CandlestickChart title="Crypto Treasury Balances" subtitle="Weekly BTC position changes with treasury policy markers" h={420} series={[ { id: 'btc', name: 'BTC holdings (USD equivalent)', data: TREASURY_SERIES, colorBull: '#0ea5e9', colorBear: '#f97316', wickColor: '#1f2937', }, ]} movingAveragePeriods={[2, 4, 6]} movingAverageColors={['#38bdf8', '#6366f1', '#facc15']} showMovingAverages showVolume volumeHeightRatio={0.2} annotations={annotations} grid={{ show: true, color: '#E3E8F4' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => { const delta = candle.close - candle.open; const deltaLabel = `${delta >= 0 ? '+' : '-'}$${Math.abs(delta).toLocaleString('en-US', { maximumFractionDigits: 0 })}`; const note = (candle as TreasuryCandle).note ? `\n• ${(candle as TreasuryCandle).note}` : ''; return [ `Open $${candle.open.toLocaleString('en-US', { maximumFractionDigits: 0 })}`, `Close $${candle.close.toLocaleString('en-US', { maximumFractionDigits: 0 })} (${deltaLabel})`, `Flow: ${(candle.volume ?? 0).toLocaleString('en-US')} BTC`, ].join(' • ') + note; }, }} xAxis={{ show: true, title: 'Week of', labelFormatter: formatWeek, }} yAxis={{ show: true, title: 'USD value (thousands)', labelFormatter: (value) => `$${value.toLocaleString('en-US')}`, }} enableCrosshair liveTooltip multiTooltip xScaleType="time" /> ); }

Saas Usage Peaks

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { USAGE_SERIES, UsageCandle, annotations } from './data'; const formatDay = (value: number) => new Date(value).toLocaleDateString('en-US', { month: 'short', day: 'numeric', }); export function Demo() { return ( <CandlestickChart title="SaaS Usage Peaks" subtitle="Daily active sessions during phased launch with capacity guardrails" h={420} series={[ { id: 'active-sessions', name: 'Concurrent sessions', data: USAGE_SERIES, colorBull: '#22c55e', colorBear: '#ef4444', wickColor: '#0f172a', }, ]} movingAveragePeriods={[3, 5]} movingAverageColors={['#0ea5e9', '#f97316']} showMovingAverages showVolume volumeHeightRatio={0.24} annotations={annotations} grid={{ show: true, color: '#E3E8F4' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => { const delta = candle.close - candle.open; const deltaLabel = `${delta >= 0 ? '+' : ''}${delta.toLocaleString('en-US')}`; const note = (candle as UsageCandle).note ? `\n• ${(candle as UsageCandle).note}` : ''; return [ `Start ${candle.open.toLocaleString('en-US')} sessions`, `End ${candle.close.toLocaleString('en-US')} (${deltaLabel})`, `Peak ${candle.high.toLocaleString('en-US')} • Floor ${candle.low.toLocaleString('en-US')}`, `Requests ${(candle.volume ?? 0).toLocaleString('en-US')}`, ].join(' • ') + note; }, }} xAxis={{ show: true, title: 'Day', labelFormatter: formatDay, }} yAxis={{ show: true, title: 'Concurrent sessions', labelFormatter: (value) => value.toLocaleString('en-US'), }} enableCrosshair liveTooltip multiTooltip xScaleType="time" /> ); }

Subscription Mrr Dynamics

Loading demo…

import { CandlestickChart } from '@plocks/charts'; import { MRR_SERIES, MrrCandle, annotations } from './data'; const formatMonth = (value: number) => new Date(value).toLocaleDateString('en-US', { month: 'short', year: 'numeric', }); export function Demo() { return ( <CandlestickChart title="Subscription MRR Momentum" subtitle="Expansion revenue outpaced churn across a pricing refresh" h={420} series={[ { id: 'mrr', name: 'Monthly recurring revenue', data: MRR_SERIES, colorBull: '#22c55e', colorBear: '#ef4444', wickColor: '#0f172a', }, ]} movingAveragePeriods={[2, 3]} movingAverageColors={['#14b8a6', '#6366f1']} showMovingAverages showVolume volumeHeightRatio={0.22} annotations={annotations} grid={{ show: true, color: '#E3E8F4' }} legend={{ show: true }} tooltip={{ show: true, formatter: (candle) => { const net = candle.close - candle.open; const netLabel = `${net >= 0 ? '+' : '-'}$${Math.abs(net).toLocaleString('en-US')}`; const note = (candle as MrrCandle).note ? `\n• ${(candle as MrrCandle).note}` : ''; return [ `Open $${candle.open.toLocaleString('en-US')}`, `Close $${candle.close.toLocaleString('en-US')} (${netLabel})`, `Net expansions: ${(candle.volume ?? 0).toLocaleString('en-US')} accounts`, ].join(' • ') + note; }, }} xAxis={{ show: true, title: 'Month', labelFormatter: formatMonth, }} yAxis={{ show: true, title: 'MRR (USD)', labelFormatter: (value) => `$${value.toLocaleString('en-US')}`, }} enableCrosshair liveTooltip multiTooltip xScaleType="time" /> ); }
Scan to open this page on your phoneplocks.dev/charts/CandlestickChart

Related charts