npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@luxalgo/vela-pinets

v0.2.15

Published

PineTS scripting engine for the Vela charting library — Pine Script indicators executed in-process or in a Web Worker, plugged into Vela's public ScriptingEngine port.

Downloads

6,246

Readme

npm version Downloads License

Vela PineTS is the Pine Script addon for Vela. It runs indicator() and strategy() scripts through Vela's public ScriptingEngine port — in-process (PineEngine) or off the main thread (PineWorkerEngine). A strategy() script also emits its broker-emulator order fills as IndicatorModel.trades, which Vela paints as on-chart trade markers.

Vela itself ships no scripting engine and stays Apache-2.0. This package is AGPL-3.0 because the PineTS runtime it executes is.

What's in the box

  • PineEngine: the in-process engine. The simplest setup — transpile and execute on the chart's thread.
  • PineWorkerEngine: the same Pine semantics in a Web Worker. The worker source is inlined at build time and spawned from a Blob URL, so heavy scripts never block the chart.
  • Declaration props: both engines publish the mutable indicator() / strategy() arguments (initial_capital, precision, …) as a props schema. Vela shows them on the settings dialog's Properties tab; hosts override them via addIndicator({ props }) / handle.setProps().
  • Browser builds: vela-pinets.global.js / .global.min.js expose window.VelaPinets for script-tag usage. Load vela.global.js first.

Installing

npm install @luxalgo/vela-pinets @luxalgo/vela pinets

@luxalgo/vela and pinets are peers of the whole package: the published entry imports both unconditionally, so each must resolve whichever engine you pick. Vela is a peer rather than a dependency for the same reason the browser build maps it onto window.Vela — a second copy would duplicate the SDK registries, not just the bytes. The worker avoids a second pinets by inlining its own at build time.

Quick start

Register the engine, then add a script. The language is pine, so calls that omit language still resolve:

import { Vela } from '@luxalgo/vela';
import { PineEngine } from '@luxalgo/vela-pinets';

const chart = new Vela('#chart', { symbol: 'BTCUSDT', timeframe: '60', live: true });
chart.registerEngine('pine', new PineEngine());
chart.addIndicator(`//@version=5
indicator("EMA 20", overlay=true)
plot(ta.ema(close, 20), color=color.orange, linewidth=2)`);

Prefer the chart to stay responsive under heavy scripts? Same port, off the main thread:

import { PineWorkerEngine } from '@luxalgo/vela-pinets';

chart.registerEngine('pine', new PineWorkerEngine());

The workspace takes an engine factory and an indicator manifest — inline JSON, a URL returning it, or an async loader:

import { VelaWorkspace } from '@luxalgo/vela/workspace';
import { PineWorkerEngine } from '@luxalgo/vela-pinets';

new VelaWorkspace('#chart', {
    symbol: 'BTCUSDT',
    timeframe: '60',
    live: true,
    engines: { pine: () => new PineWorkerEngine() },
    indicators: '/indicators.json', // or an inline [{ name, script | url, language?, enabled? }]
});

Host tooling can execute-and-inject safely with chart.runIndicator(source) (structured errors, no dead legend rows) and read a running script's state, including its return value, via handle.context() (read-only snapshots, worker-safe). See Vela's scripting engines guide.

Browser bundle

The package also ships self-contained browser builds for script-tag usage: dist/vela-pinets.global.js (readable, development) and dist/vela-pinets.global.min.js (minified, production). Either file attaches the engines to window.VelaPinets. Load Vela's vela.global.js first so @luxalgo/vela resolves to the page's window.Vela.

Strategies

A strategy() script runs through the same engine as an indicator. PineTS's broker emulator already computes the full ledger; this package emits one marker per order fill as IndicatorModel.trades, at the fill bar and price. Ledger slices of the same fill merge: a reversal paints a single entry carrying the summed quantity, and an exit that closes several lots FIFO paints once. Order ids label the markers; a comment= replaces the id. Vela paints them on the price pane.

Declaration props

Both engines expose the mutable indicator() / strategy() declaration arguments through Vela's props channel. prepare publishes a schema whose defaults are the effective values (source-declared ← engine default ← Pine spec), and prop overrides — add-time, live, or edited on the Properties tab — replay the script.

const engine = new PineEngine({
    defaultProps: { initial_capital: 50_000 },
    props: 'strategy', // 'all' | 'strategy' | 'none' | a whitelist of prop keys
});

chart.addIndicator({
    script: `//@version=5
strategy("Demo", overlay=true, initial_capital=10000)
if ta.crossover(close, ta.sma(close, 20))
    strategy.entry("Long", strategy.long)`,
    props: { commission_value: 0.05 },
});

defaultProps sets host-level defaults for scripts that don't declare the prop themselves. props gates which scripts publish the schema — 'strategy' gives strategies a Properties tab while plain indicators keep an inputs-only dialog.

Volume footprints (request.footprint())

Vela owns bars, not order flow, so Pine's request.footprint() needs a host-supplied source of per-bar volume footprints. Pass one to either engine and it becomes the optional getFootprintData surface of the PineTS market-data provider (worker-backed engines round-trip each call to the main thread, like request.security fetches). Without it every request.footprint() call answers na. The source is asked for the chart's series and, when request.footprint() runs inside request.security(), for that context's own symbol and timeframe.

import type { FootprintSource } from '@luxalgo/vela-pinets';

const footprints: FootprintSource = async (symbol, timeframe, range) => {
    // range: { from?, to?, limit? } — the loaded history first, then the forming bar's tail
    const bars = await myOrderFlow.footprints(symbol, timeframe, range);
    return bars.map((b) => ({
        openTime: b.time, // the matching bar's open time
        levels: b.levels.map((l) => ({ price: l.price, buyVolume: l.buy, sellVolume: l.sell })),
    }));
};

const engine = new PineWorkerEngine({ footprints });

Levels are raw volume-at-price at whatever grid the source has (a level's price is the low edge of its bucket); PineTS re-bins them into ticks_per_row × syminfo.mintick rows and derives POC, value area and imbalances itself. Bars the source omits read as na. Requires a pinets build that ships request.footprint().

Development

npm install
npm run playground   # vite playground on http://localhost:5192
npm test             # vitest
npm run build        # tsup → dist/

The playground is the Vela widget plus this package's PineWorkerEngine (HMR, engine sources from src/). An EMA is on from the first paint; the Code topbar entry runs arbitrary Pine through chart.runIndicator.

Vela is consumed as file:../Vela (built dist): clone this repo next to Vela and build Vela first.

License

Vela PineTS is licensed under the GNU Affero General Public License v3.0 (see LICENSE) because it depends on pinets, which is AGPL-3.0. The Vela charting library itself is Apache-2.0 and carries no Pine code.