rohanbeingsocial
candlekit-charts
TypeScript✨ New

Tree-shakeable financial charting toolkit over lightweight-charts: candlestick/OHLC/line/area/volume, drawing tools, pluggable indicators, measurement, and deterministic replay. Framework-agnostic core + React bindings.

Last updated Jul 8, 2026
26
Stars
5
Forks
0
Issues
+1
Stars/day
Attention Score
66
Language breakdown
No language data available.
Files click to expand
README

candlekit/charts — the all-in-one financial charting toolkit

The all in one unification layer built on Lightweight Charts™.

CandleKit unifies the charting tools and extensions developers repeatedly source, adapt, and maintain from across the Lightweight Charts ecosystem.

Drawing Tools • Technical Indicators • Replay Engine • Measurement Tools • Synced Multipane System • Broker Integration

Stop stitching together repositories.

Get a cohesive toolkit, consistent APIs, and an extensible architecture built for production-grade financial charting.

Everything you keep rebuilding around Lightweight Charts™ — packaged once.

CI npm version types License: MIT

[!NOTE]
Candlekit is a vibe-coded project — designed and built rapidly and iteratively with AI-assisted development. It is functional, tested (CI green, with a Vitest suite under /tests), and documented, but treat it as early-stage software: pin a version, read the changelog before upgrading, and open an issue if something looks off.

Drawing a trendline, rectangle and Fibonacci retracement on a candlestick chart
Drawing tools — trendline, rectangle, Fibonacci, measurement ruler

Toggling Bollinger Bands, MACD, SMA and Stochastic indicators
Built-in indicators — Bollinger, EMA/SMA, RSI, MACD, Stochastic — toggled live

Shift-drag measurement ruler showing percentage move, points and bar and time delta
Measurement ruler — Shift-drag for % move, points, bars · time

▶ Open the live demo — drawing, indicators, measurement and replay in one chart


Overview

candlekit/charts wraps lightweight-charts with the pieces a real trading UI needs but the base library leaves to you: a stable chart controller, a runtime-agnostic drawing engine, an extensible indicator framework, a Shift-drag measurement ruler, multi-chart sync, broker integration and a deterministic historical replay engine. The core is framework-agnostic (no React, no DOM framework); the optional /react entry adds components and hooks.

It is plugin-first: drawing, indicators, and measurement are all ChartPlugins you can swap, extend, or omit. Drawing tools and indicators are original code built on lightweight-charts canvas primitives — no third-party drawing or indicator runtime — and the side-effect-free modules let tree-shaking drop whatever you don't import.

Features

  • Core charting — candlestick, OHLC bars, line, area, volume; multiple
timeframes via a session-aware resampler; responsive auto-resize; light/dark themes with full color override.
  • Drawing tools — trend line, ray, extended line, horizontal/vertical line,
arrow, rectangle, circle, Fibonacci retracement, with selection, drag-to-move, handle reshaping, locking, and persistence. Original engine rendered on lightweight-charts canvas primitives — no third-party drawing runtime.
  • Indicators — extensible registry + a built-in catalog (SMA, EMA, WMA,
VWAP, Bollinger Bands, RSI, MACD, ATR, Stochastic), all original implementations. Register your own with one call.
  • Measurement — price, percentage, bar-distance, time-delta, and
risk/reward, painted as a canvas ruler.
  • Replay — deterministic playback over historical bars: play/pause, step
±1, speed control, seek/jump, per-bar event hooks, per-day LRU cache with pre-fetch.
  • Lab (experimental) — pattern-similarity analytics over your own bars.
Echoes ("market déjà vu") finds historical windows that look like the recent price action, bands them, and projects the median of what happened next; Sketch Search matches a freehand shape you draw against history. Pure, dependency-free math + optional plugins and a React panel.
  • Architecture — TypeScript, fully typed public API, tree-shakeable ESM +
CJS, event system, plugin system, and extensible data-source / indicator / drawing frameworks.

Replay

Deterministic historical replay stepping and seeking over candlestick bars
Deterministic replay — play/pause, step ±1, speed control, seek/jump

Lab — Sketch Search & Echoes

Echoes highlights historical windows that look like the recent price action and projects the median of what happened next; Sketch Search matches a freehand shape against history
Echoes — similar past windows + median projection · Sketch Search — draw a shape, find look-alikes

Two experimental pattern-similarity tools, computed on z-normalized closes (shape, not price level), so look-alikes are found across regimes:

  • Echoes — takes the last N closes as a query, finds the most similar
non-overlapping windows in history, bands them on the chart, and projects the median of what happened next forward from the last bar.
  • Sketch Search — draw a freehand shape across the chart; it is resampled
and matched against history the same way.

The math (zNormalize, findSimilar, buildEchoScan, resampleStroke) is pure and dependency-free; the chart plugins (SketchSearchController, EchoesController) and the React <EchoesPanel> / <SketchSearchButton> are optional. See Lab Examples below, the full Lab guide, and examples/lab for a runnable demo.

Try it live in examples/lab (cd examples/lab && npm i && npm run dev).
The GIF above is regenerated by SCENE=lab node scripts/capture-demo.mjs.

Installation

npm install @getcandlekit/charts lightweight-charts

React bindings (optional):

npm install react react-dom

That's it. lightweight-charts is the only runtime dependency (a peer, so you control its version); react/react-dom are needed only for @getcandlekit/charts/react. Drawing tools and indicators are built in — no extra packages, no git installs.

Quick Start

Vanilla JS / TypeScript

import { ChartController, toBars } from "@getcandlekit/charts";

const el = document.getElementById("chart")!; const chart = new ChartController(el, { theme: "dark", seriesType: "candlestick" });

chart.setData(toBars(myRows)); // myRows: { ts, open, high, low, close, volume }[]

React

import { ChartView } from "@getcandlekit/charts/react";
import "@getcandlekit/charts/styles.css";

export function App({ bars }) { return ( <div style={{ height: 480 }}> <ChartView data={bars} seriesType="candlestick" theme="dark" /> </div> ); }

Basic Examples

Switch series type and timeframe:

chart.setSeriesType("area");       // candlestick | ohlc | line | area
chart.setData(resample(rows, 5));  // 5-minute candles from 1-minute rows
chart.setTheme("light");

Live updates:

ws.onBar((bar) => chart.updateBar(bar)); // appends or replaces the last bar

Advanced Examples

Session-aware resampling (align buckets to a 09:30 market open instead of UTC midnight):

import { resample } from "@getcandlekit/charts";
const candles = resample(rows, 15, { sessionOpenMinutes: 9 * 60 + 30 });

Fixed-offset exchange time (render an always-UTC+5:30 market in wall-clock):

import { applyFixedOffset } from "@getcandlekit/charts";
const shifted = rows.map((r) => ({ ...r, ts: applyFixedOffset(r.ts, 330) }));

Replay Examples

import { createReplayController } from "@getcandlekit/charts";

const replay = createReplayController(); replay.onBar((e) => chart.updateBar(e.bar)); await replay.load({ id: "demo", series: [{ symbol: "AAPL", interval: "1m" }], start: Date.parse("2024-01-02T14:30:00Z"), end: Date.parse("2024-01-03T21:00:00Z"), source: myReplayDataSource, // implements ReplayDataSource }); replay.setSpeed(8); replay.play();

React transport bar:

import { ReplayControls } from "@getcandlekit/charts/react";
<ReplayControls controller={replay} />

Drawing Tool Examples

import { ChartView, DrawingToolbar } from "@getcandlekit/charts/react";

// drawing accepts true, an options object, or a DrawingController instance. <ChartView data={bars} drawing={{ storageKey: "drawings:AAPL" }}> <DrawingToolbar /> </ChartView>;

Imperative (vanilla):

import { ChartController, DrawingController } from "@getcandlekit/charts";

const chart = new ChartController(el); const drawing = new DrawingController({ storageKey: "drawings:AAPL" }); chart.use(drawing); drawing.engine.startTool("TrendLine");

Indicator Examples

import { ChartView, IndicatorPicker, IndicatorController, createBuiltinRegistry } from "@getcandlekit/charts/react";

const indicators = new IndicatorController(createBuiltinRegistry()); indicators.add("RSI", { length: 14 }); indicators.add("EMA", { length: 21 });

<ChartView data={bars} indicators={indicators}> <IndicatorPicker /> </ChartView>;

Register a custom indicator (the extension point):

import { IndicatorRegistry } from "@getcandlekit/charts";

const registry = new IndicatorRegistry().register({ name: "PriceMid", title: "HL/2", shortTitle: "MID", category: "overlay", defaultInputs: {}, inputConfig: [], plotConfig: [{ id: "mid", color: "#f59e0b" }], hlineConfig: [], calculate: (bars) => ({ plots: { mid: bars.map((b) => ({ time: b.time, value: (b.high + b.low) / 2 })) }, }), });

Lab Examples

React (<ChartView> hosts the plugins; the components drive them):

import { ChartView, SketchSearchButton, EchoesPanel } from "@getcandlekit/charts/react";
import "@getcandlekit/charts/styles.css";

<ChartView data={bars} sketch echoes={{ windowLen: 30, horizon: 30, k: 8 }}> <SketchSearchButton /> {/ toggle, then drag a shape on the chart /} <EchoesPanel /> {/ Scan → bands + median projection + stats /} </ChartView>;

Imperative (vanilla — same plugins, your own UI):

import { ChartController, EchoesController, SketchSearchController } from "@getcandlekit/charts";

const chart = new ChartController(el); chart.setData(bars);

const echoes = new EchoesController({ windowLen: 30, horizon: 30, k: 8 }); chart.use(echoes); echoes.subscribe((scan) => scan && console.log(scan.stats)); // { count, upCount, medianEndPct, ... } echoes.run();

const sketch = new SketchSearchController({ onResult: (r) => console.log(r?.matches) }); chart.use(sketch); sketch.setActive(true); // arm; drag a freehand shape, release to search

Pure math, no chart (search any series of closes):

import { findSimilar, buildEchoScan } from "@getcandlekit/charts";

const matches = findSimilar(closes, closes.slice(-30), { k: 5 }); // [{ startIndex, endIndex, distance }] const scan = buildEchoScan(bars, 30, 30, 8); // window/horizon/k → null if too little history

Plugin Examples

import type { ChartPlugin } from "@getcandlekit/charts";

const lastPriceLabel: ChartPlugin = { id: "last-price-label", init(ctx) { ctx.bus.on("data", ({ bars }) => { const last = bars[bars.length - 1]; if (last) console.log("last close", last.close); }); }, destroy() {}, };

chart.use(lastPriceLabel);

API Overview

| Export | Kind | Purpose | | --- | --- | --- | | ChartController | class | Imperative chart wrapper (data, series type, theme, plugins, events). | | toBars, resample, floorToBucket | fn | Pure data normalization + session-aware resampling. | | resolveTheme, lightTheme, darkTheme | fn/const | Theme presets + resolution. | | EventBus | class | Typed sync event bus. | | DrawingController, DrawingEngine | class | Built-in drawing plugin + its model/state. | | IndicatorRegistry, IndicatorController, createBuiltinRegistry | class/fn | Extensible indicator framework + built-in catalog. | | MeasurementController, RulerPrimitive | class | Shift-drag measurement. | | createReplayController | fn | Deterministic replay. | | createSyncEngine | fn | Multi-chart sync. | | EchoesController, SketchSearchController | class | Lab plugins — Echoes (déjà vu) + Sketch Search. | | findSimilar, buildEchoScan, zNormalize, resampleStroke | fn | Pure pattern-similarity math (no chart). | | ChartView (/react) | component | Declarative chart + plugin host. | | EchoesPanel, SketchSearchButton (/react) | component | Lab results panel + sketch toggle. |

Full reference: docs/api-reference.md.

Performance Notes

  • Single offset conversion at the data boundary; drawings/replay stay in one
coordinate domain (no per-render timezone math).
  • setData autoscale fits once on the first non-empty paint; later updates
preserve user pan/zoom.
  • Replay uses a per-day LRU cache with backward/forward pre-fetch; the cursor
drives everything (no wall-clock coupling).
  • Tree-shakeable ESM — a vanilla bundle never pulls React. Drawing and
indicators are self-contained (no extra runtime deps to load).

Browser Support

Evergreen browsers (Chrome, Edge, Firefox, Safari) with Canvas + ResizeObserver. ESM and CJS builds are shipped; target: es2020.

Roadmap

  • [ ] Text + freehand/brush drawing tools
  • [ ] Indicator settings UI (param editing) in the React picker
  • [ ] Crosshair tooltip component
  • [ ] More indicators (Ichimoku, SuperTrend, Keltner)
  • [ ] Vue / Svelte bindings
  • [ ] Screenshot/export helper

Star History

If candlekit saves you from stitching repos together, a ⭐ helps others find it.

Star History Chart

Contributing

See CONTRIBUTING.md and AGENTS.md. In short: npm install, npm run typecheck && npm run lint && npm run test && npm run build.

License

MIT — see LICENSE. Third-party attributions in NOTICE. "Lightweight Charts™" is a trademark of TradingView, Inc.; this project is not affiliated with TradingView.

🔗 More in this category

© 2026 GitRepoTrend · rohanbeingsocial/candlekit-charts · Updated daily from GitHub