Финансовый чарт на WebGL2, который целиком живёт в коде

Есть момент, знакомый каждому, кто собирал торговый интерфейс. Втыкаешь готовый виджет с графиком, всё красиво, свечи бегают. А потом приходит задача: нужен свой тип баров или кастомный индикатор поверх данных. И тут выясняется, что большая часть библиотеки это чёрный ящик, а расширяться она умеет ровно так, как задумал автор.
Vela от LuxAlgo выглядит как попытка сделать наоборот. Это открытый пакет для отрисовки финансовых графиков на вебе, написанный на TypeScript под лицензией Apache-2.0. Идея простая: сам чарт headless, то есть без готового интерфейса, и управляется из кода, а всё остальное подключается через публичные точки расширения.
На GitHub у проекта 655 звёзд и 143 форка. Звёзд немного, но проект живой: последний коммит датируется октябрём 2026-го.
Из чего состоит пакет

Установка стандартная:
npm install @luxalgo/vela
Дальше выбор из двух уровней. Первый это @luxalgo/vela, голое ядро: модель данных, движки, рисование, провайдеры и собственный рендерер. Второй это @luxalgo/vela/workspace, готовое приложение в один вызов.
import { VelaWorkspace } from '@luxalgo/vela/workspace';
import { BinanceProvider } from '@luxalgo/vela/providers/binance';
const chart = new VelaWorkspace('#chart', {
layout: false,
symbol: 'BTCUSDT',
timeframe: '60',
live: true,
theme: 'dark',
providers: { binance: () => new BinanceProvider() },
persist: true,
});
layout: false даёт одну панель, а строкой вида '2h', '4' или '8' можно собрать сетку из нескольких графиков под общим тулбаром. Флаг persist: true сохраняет рынок, стиль, часовой пояс, рисунки и индикаторы в localStorage, так что после перезагрузки пользователь возвращается к тому же виду.
Если хочется полного контроля, берёте ядро напрямую:
import { Vela } from '@luxalgo/vela';
import { BinanceProvider } from '@luxalgo/vela/providers/binance';
const chart = new Vela('#chart', { symbol: 'binance:BTCUSDT', timeframe: '60', live: true });
chart.data.registerProvider('binance', new BinanceProvider());
await chart.ready();
Не хочется ходить в сеть? Передайте свои бары через опцию data и работайте полностью офлайн.
Рендерер и индикаторы
Рисует Vela своим кодом на WebGL2, с откатом на canvas2d для старых окружений. Обёртки над чужой библиотекой тут нет. Отдельно идут провайдеры для Binance, Coinbase и Hyperliquid, а также self-contained сборки dist/vela.global.js и dist/vela.global.min.js для подключения через тег script, публичное API оказывается в window.Vela.
Встроенных исследований заявлено больше 70: скользящие средние, полосы и каналы, осцилляторы моментума, трендовые и волатильные метрики, объёмные исследования, плюс привязанные к цене наложения вроде VWAP, SuperTrend и Pivot Points. Считаются они прямо по барам чарта, без scripting engine. У каждого есть строка легенды, диалог настроек и сохранение между перезагрузками. Рядом живут объём и профиль объёма по видимой области.
Любопытная деталь: движок для кастомных скриптов Vela сама не поставляет. Ставите аддон под нужный язык или пишете свой против публичного интерфейса ScriptingEngine. Pine Script вынесен в отдельный пакет @luxalgo/vela-pinets, и он уже AGPL-3.0, потому что внутри исполняется PineTS. Сама Vela остаётся Apache-2.0 и кода Pine в себе не несёт.
import { PineEngine } from '@luxalgo/vela-pinets';
chart.registerEngine('pine', new PineEngine());
chart.addIndicator(`//@version=6
indicator("EMA 20", overlay=true)
plot(ta.ema(close, 20), color=color.orange, linewidth=2)`);
Для хост-инструментов есть chart.runIndicator(source) со структурированными ошибками вместо мёртвых строк в легенде, а состояние запущенного скрипта, включая возвращаемое значение, можно прочитать через handle.context().
Plugin SDK и расширение
Вот на что стоит смотреть в первую очередь, если вы уже обжигались на закрытых чартах. Через публичный SDK регистрируются свои типы графиков и canvas-слои, без форка:
import { registerChartType, registerRendererLayer } from '@luxalgo/vela/plugin';
registerChartType({
id: 'renko-like',
label: 'Renko-like',
barTransform: { full: (bars) => transformAll(bars), next: (bar) => transformOne(bar) },
});
registerRendererLayer({
id: 'renko-like',
placement: 'above-data',
create: () => ({ mount(canvas) {/* keep it */}, render({ bars, data, coords, scale, bounds }) {/* paint */} }),
});
Зарегистрированный тип сам появляется в выпадающем списке стилей рабочей области, а dataEngine типа графика пишет в канал своего слоя без дополнительной обвязки. Есть и манифест индикаторов: инлайн JSON, URL или асинхронный загрузчик.
Рабочая область тоже не пустая. Один график или сетка под общим тулбаром, строка статуса, водяной знак символа, нижняя панель с диапазонами, часами и часовым поясом, дерево объектов. Управление заточено под клавиатуру: буква или 0 открывают поиск символа, цифра от 1 до 9 задаёт таймфрейм, ? вызывает панель шорткатов.
Что стоит учесть до старта
Лицензия Apache-2.0, но с нюансом. В файле NOTICE есть требование об атрибуции, и по умолчанию каждый чарт рисует маленький водяной знак Vela с логотипом, ссылающимся на страницу проекта. Его можно переставить или перестилизовать под свой дизайн. Отключать (chart.renderer.set('attribution', false)) разрешено только если такое же видимое упоминание имени со ссылкой стоит где-то ещё на той же странице. Скрывать атрибуцию просто так нельзя. Модель знакомая по другим чартовым библиотекам, но лучше прочитать NOTICE до интеграции, а не после.
Ещё авторы честно разделяют лицензии. Нужен Pine на борту, тащите AGPL-аддон и живите с его условиями. Нужно чистое ядро под Apache-2.0, не подключайте аддон.
Кому это подойдёт
Если вы пишете торговый терминал, аналитическую панель или внутренний инструмент с биржевыми данными и хотите управлять поведением чарта из кода, Vela стоит посмотреть. Особенно когда по прошлым проектам знакомо ощущение «виджет умеет всё, кроме того, что мне надо».
Нужен готовый внешний вид без возни с рендерером, берите workspace и не трогайте ядро. Планируете свой тип баров или нестандартный слой поверх данных, SDK здесь открыт и документирован. А для простых задач вроде одного sparkline на дашборде весь этот аппарат будет избыточным, там хватит чего-то полегче.
Начать логично с playground:
npm install
npm run playground # vite playground на http://localhost:5190
npm test # vitest
npm run build
Полная документация лежит в каталоге docs: quickstart, руководство по workspace, опции, API reference и описание архитектуры. Отдельно расписан plugin SDK, если сразу идёте в расширения.
