Gráficos y Estadísticaschartsvgzero-dependencycandlestickohlcfinancetrading
Candlestick Chart
Gráfico de velas OHLC con velas alcistas huecas y bajistas rellenas para no depender del color.
Vista Previa en Vivo
Daily candles
$196.19+7.80%
- Up (hollow)
- Down (filled)
View data
| Date | Open | High | Low | Close |
|---|---|---|---|---|
| Oct 6 | $182.00 | $183.00 | $178.60 | $182.60 |
| Oct 7 | $182.60 | $184.45 | $180.16 | $183.09 |
| Oct 8 | $183.09 | $187.52 | $181.50 | $185.31 |
| Oct 9 | $185.31 | $189.72 | $184.39 | $186.84 |
| Oct 10 | $186.84 | $190.13 | $184.13 | $184.64 |
| Oct 11 | $184.64 | $188.04 | $182.49 | $182.89 |
| Oct 12 | $182.89 | $189.90 | $182.28 | $186.71 |
| Oct 13 | $186.71 | $193.95 | $185.60 | $191.26 |
| Oct 14 | $191.26 | $193.21 | $187.23 | $189.08 |
| Oct 15 | $189.08 | $190.13 | $181.66 | $184.41 |
| Oct 16 | $184.41 | $187.36 | $181.33 | $186.64 |
| Oct 17 | $186.64 | $194.82 | $184.49 | $193.17 |
| Oct 18 | $193.17 | $196.11 | $191.83 | $193.65 |
| Oct 19 | $193.65 | $196.70 | $187.75 | $188.50 |
| Oct 20 | $188.50 | $191.86 | $187.36 | $187.80 |
| Oct 21 | $187.80 | $196.52 | $187.36 | $193.16 |
| Oct 22 | $193.16 | $199.02 | $192.42 | $195.96 |
| Oct 23 | $195.96 | $198.43 | $191.97 | $193.30 |
| Oct 24 | $193.30 | $194.97 | $189.47 | $191.60 |
| Oct 25 | $191.60 | $194.60 | $188.54 | $193.86 |
| Oct 26 | $193.86 | $197.04 | $191.09 | $196.01 |
| Oct 27 | $196.01 | $198.13 | $194.15 | $196.19 |
Uso
Copia y pega este código directamente en tu componente React:
tsx
import { CandlestickChart } from 'react-component-kit-ui/charts';
<CandlestickChart title="ACME / USD" candles={[
{ label: 'Oct 1', open: 182, high: 186, low: 180, close: 185 },
{ label: 'Oct 2', open: 185, high: 187, low: 181, close: 182 },
]} />Instalación Manual
Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/CandlestickChart.tsx + CandlestickChart.css:
CandlestickChart.tsx
'use client';
import ChartFrame from './ChartFrame';
import { scaleLinear, niceTicks, POSITIVE, NEGATIVE } from './chart-utils';
interface Candle { label: string; open: number; high: number; low: number; close: number }
const demo: Candle[] = (() => {
let p = 182;
return Array.from({ length: 22 }, (_, i) => {
const r1 = Math.sin(i * 4.7) * 0.5 + Math.sin(i * 1.3) * 0.5;
const r2 = Math.abs(Math.sin(i * 9.1));
const open = p;
const close = Math.round((p + r1 * 6 + 0.6) * 100) / 100;
const high = Math.round((Math.max(open, close) + r2 * 3 + 0.4) * 100) / 100;
const low = Math.round((Math.min(open, close) - (1 - r2) * 3 - 0.4) * 100) / 100;
p = close;
return { label: `Oct ${i + 6}`, open, high, low, close };
});
})();
/**
* CandlestickChart — OHLC price chart. Bodies span open→close, wicks span
* low→high. Up candles are hollow, down candles filled, so direction is
* readable without color.
*
* @param {Array<{label: string, open: number, high: number, low: number, close: number}>} candles - OHLC data.
* @param {string} prefix - Price prefix.
* @param {number} height - SVG height in viewBox units (width is 640).
* @param {string} variant - Card style (glass|solid|ghost).
* @param {string} size - Density (sm|md|lg).
*/
export interface CandlestickChartProps {
title?: string;
subtitle?: string;
candles?: Candle[];
prefix?: string;
height?: number;
variant?: 'glass' | 'solid' | 'ghost';
size?: 'sm' | 'md' | 'lg';
className?: string;
}
export function CandlestickChart({
title = 'ACME / USD',
subtitle = 'Daily candles',
candles = demo,
prefix = '$',
height = 300,
variant = 'glass',
size = 'md',
className = '',
}: CandlestickChartProps) {
const W = 640;
const H = height;
const m = { t: 12, r: 52, b: 28, l: 12 };
const ticks = niceTicks(Math.min(...candles.map((c) => c.low)), Math.max(...candles.map((c) => c.high)), 5);
const y = scaleLinear(ticks[0], ticks[ticks.length - 1], H - m.b, m.t);
const band = (W - m.l - m.r) / candles.length;
const bw = Math.max(3, band * 0.6);
const f = (v: number) => `${prefix}${v.toFixed(2)}`;
const last = candles[candles.length - 1];
const first = candles[0];
const change = ((last.close - first.open) / first.open) * 100;
const labelEvery = Math.ceil(candles.length / 6);
return (
<>
<ChartFrame title={title} subtitle={subtitle} value={f(last.close)} delta={`${change >= 0 ? '+' : ''}${change.toFixed(2)}%`} deltaPositive={change >= 0} variant={variant} size={size} className={className} legend={[{ label: 'Up (hollow)', color: POSITIVE }, { label: 'Down (filled)', color: NEGATIVE }]} table={{ headers: ['Date', 'Open', 'High', 'Low', 'Close'], rows: candles.map((c) => [c.label, f(c.open), f(c.high), f(c.low), f(c.close)]) }}>
<svg viewBox={`0 0 ${W} ${H}`} role="img" aria-label={`${title}: candlestick chart, ${candles.length} periods, ${change.toFixed(1)}% change`}>
{ticks.map((t, __i: number) => (
<g key={__i}>
<line className="cf-grid" x1={m.l} x2={W - m.r} y1={y(t)} y2={y(t)} />
<text className="cf-label" x={W - m.r + 8} y={y(t) + 4}>{f(t)}</text>
</g>
))}
{candles.map((c, i) => {
const cx = m.l + i * band + band / 2;
const up = c.close >= c.open;
const col = up ? POSITIVE : NEGATIVE;
const top = y(Math.max(c.open, c.close));
const h = Math.max(1.5, Math.abs(y(c.open) - y(c.close)));
return (
<g className="cf-mark cf-dim" tabIndex={0} role="img" aria-label={`${c.label}: open ${f(c.open)}, high ${f(c.high)}, low ${f(c.low)}, close ${f(c.close)}`} data-tip-title={c.label} data-tip={`${col}::${up ? 'Up' : 'Down'} ${(((c.close - c.open) / c.open) * 100).toFixed(2)}%|O ${f(c.open)} · H ${f(c.high)}|L ${f(c.low)} · C ${f(c.close)}`}>
<rect x={cx - band / 2} y={m.t} width={band} height={H - m.t - m.b} fill="transparent" />
<line x1={cx} x2={cx} y1={y(c.high)} y2={y(c.low)} stroke={col} strokeWidth="1.5" />
<rect x={cx - bw / 2} y={top} width={bw} height={h} rx="1.5" fill={up ? 'var(--chart-surface, #0d0d0f)' : col} stroke={col} strokeWidth="1.5" />
{i % labelEvery === 0 && <text className="cf-label" x={cx} y={H - 8} textAnchor="middle">{c.label}</text>}
</g>
);
})}
<line x1={m.l} x2={W - m.r} y1={y(last.close)} y2={y(last.close)} stroke="var(--c-text-1, #fff)" strokeOpacity="0.3" strokeDasharray="3 4" aria-hidden="true" />
</svg>
</ChartFrame>
</>
);
}
export default CandlestickChart;Información Rápida
- Categoría
- Gráficos y Estadísticas
- Nombre de archivo
CandlestickChart.tsx- Dependencias
- Ninguna — React + CSS puro
- Etiquetas
- chartsvgzero-dependencycandlestickohlcfinancetrading