25.8 KB·no dependencies·MIT

The charting library an AI agent can read

Lighter, faster, smarter

A canvas charting engine with no dependencies. Put it on your site and your users can ask about a chart — the agent reads what is on screen and draws the answer back onto it.

Documentation View source
chart.js
import { createChart, AreaSeries } from '@arincen/charts';

const chart = createChart(el, { autoSize: true });

chart.addSeries(AreaSeries).setData(data);
chart.toText();   // and a model can read it
25.8KB
gzipped, light build
0
dependencies
701
tests, every one of them run on this build
3
calls to read, picture and annotate a chart

The part nobody else has

Your users' eye and hand on the chart

Every charting library draws for eyes. Everything else — a model, a screen reader, an alerting job — has to dig through series internals and write the same summary again, badly, in every project. This one says what it is showing, in words, and takes an answer back as markers, levels and shaded regions.

Runs here, on this page. No key, no request, nothing leaves your browser.

chart.toText()

chart.annotate()

// 1. the chart says what it is showing
const description = chart.toText();

// 2. your model reads it
const answer = await ask(`${description}

  Name the periods worth a second look. Reply as JSON:
  [{ "from": <unix>, "to": <unix>, "text": "<six words>" }]`);

// 3. the answer goes back on the chart
chart.annotate(JSON.parse(answer));

Your application already has the data. This is not about the data.

You have the rows, and you have a model of your own — ask it what happened last March and it will tell you. What neither of them has is the chart: where the reader is pointing, which readings are on screen right now, and a way to put the answer back where they are looking. That is the part somebody has to write per chart, per project, and it is the part this does.

"Why did it spike here?"
Your database cannot say where "here" is. Pixel coordinates become a timestamp and a price through a scale that changes on every zoom. chart.pointer()
"Zoom into the March crash."
That is not a sentence to answer, it is an action to take. The agent moves the view the reader is looking at. chart.timeScale().setVisibleRange()
"Draw the trend line between these two lows."
A model can work out the levels. Somebody still has to put a line on a canvas at the right coordinates — and take that one line off again when the next sentence asks. chart.annotate()

It usually costs less, too: a description of what is on screen is a few dozen tokens, and the ten thousand readings behind it are not. The model decides what it actually needs and asks for those rows. Not a universal claim — arithmetic over thousands of readings needs the readings — but the nine thousand candles nobody asked about need never be sent.

Every one of those, running on this page

Four charts, four calls. Point at one, move the view of another, draw on a third and take a single line back off it, and let the fourth find every chart on this page the way an agent would.

chart.pointer()point at the chart
chart.timeScale().setVisibleRange()press a button
chart.annotate()press a button
window.arincenChartspress a button

It states, it does not interpret

No "bullish", no "resistance", no trend call. A conclusion about somebody else's money is theirs to draw — and a test fails our build if any of those words appear in the output.

It describes what is on screen

And says so. A model told the high is 150 about a chart holding five years will say something wrong about the other four, so the window is stated outright.

The same call serves a screen reader

It is the plainest text description of a chart there is, which is the other reason to have it. Full keyboard navigation and a live region ship in the same build.

Twenty-one charts, all running

Everything it draws, drawing right now

Not screenshots. Every square below is a live chart from the same file this page loaded, and every one of them is the smallest honest demonstration of one thing.

Candlesticks

Rounded bodies, wicks drawn separately, and our green and red rather than anybody else's.

Area, with the fill carried into the axes

The gutters take the same gradient, so the chart reads as one object instead of a coloured middle between two grey strips.

Lines, as many as you like

A price and its ten-period average. Hover one and the others fade back.

Baseline

Green above the level you set, red below it, filled both ways.

OHLC bars

The oldest notation on a price chart, and still the densest.

Volume

A histogram coloured per bar, formatted in thousands and millions without asking.

Two panes, one time axis

Price above, volume below, sharing a crosshair. Drag the divider — it has a grip.

Price on the right, volume on the left

Two series on two scales, each measured on its own numbers.

Two instruments, one scale

Percentage mode, so a 40 dollar stock and a 4000 dollar one can be read against each other.

A period switcher

Press one. The data is replaced and the view refits — no rebuild, no flicker, no second chart.

Buy, sell and a target

Entries, exits and the level you are watching. Markers are outlined in the page colour so they stay legible over a candle.

Your name on it

A watermark of your own text, behind the series and in front of nothing.

A chart type we do not ship

A rolling high-low band, drawn by a renderer of your own. Custom series replace the drawing entirely.

A tooltip, without writing one

Hover it. Nobody else gives you this — every project hand-rolls the same floating box.

The hours the market was shut

Three intraday days. The shading comes from opening hours you supply and the platform's own timezone database.

Annotations, from wherever

A region and a point, drawn from the shape a model returns — or from your own analysis.

A light chart on a dark page

One word: theme. Nine values across five branches of the options tree, including the one everybody misses.

Nothing to draw, and it says so

Rather than labelling an axis 0.00 to 1.00 over an empty grid, which is a chart stating prices it does not have.

Three sparklines in a table

One call each. Green if it ended higher than it started, red if it did not, no axes, nothing to drag.

live

A live feed

A reading a second through update(), with the last price pulsing — unless the reader has asked for less movement.

The numbers behind it

toCSV() gives you the readings, toImage() gives you the picture. The first two rows are printed on the chart.

Each of these is a handful of lines. The documentation carries the code for all of them, and a page you can edit them on.

Feature by feature

Some of what you only get here

Every row is something the charting libraries we checked have no API for — including the one most teams are migrating from, whose published type declarations we read rather than trusted our memory of. Anywhere else, each of these is yours to build.

FeatureArincen Charts

A chart a model can read and draw on

toText(), toImage() and annotate(). No provider, no key, no bundled client.

Export the picture and the numbers

A PNG of what is on screen, and a CSV of the readings behind it, in one call each.

A tooltip that follows the crosshair

They have no tooltip API at all, so every project hand-rolls the same one.

Keyboard and screen-reader support

Arrows, page keys, Home and End, with every move announced. On by default, because a chart nobody can reach without a mouse has its prices locked behind one.

Dark mode in one word

By hand it is nine values across five branches of the options tree, and the one everybody misses turns the price under the pointer into dark text on a dark tag.

A chart that says it has no data

Instead of labelling an axis 0.00 to 1.00 over an empty grid, which is a chart stating prices it does not have.

It tells you what is wrong with your data

Out of order, duplicated, a NaN, a price quoted as a string — counted and named, rather than drawn short in silence.

Plugin failures are reported, not swallowed

A primitive that throws loses its own drawing and says which hook failed, instead of vanishing with an empty console.

The hours the market was shut

Shaded from hours you supply and the platform's own timezone database, so summer time needs nothing from anyone.

A sparkline in one call

Six chart options and three series options have to be turned off before a chart becomes a shape in a table cell. Or one function.

It respects reduced motion

The pulsing last price and the glide after a flick stand down when the reader has asked for less movement.

Right-to-left text, without mirroring the chart

Labels follow the locale; time still runs left to right, because a reversed axis puts the newest bar where every reader looks for the oldest.

And this is only some of them. The rest — a tooltip that writes its own contents, primitives, custom series, right-to-left labels, conflation for a hundred thousand bars — is in the documentation.

Two builds, one codebase

The features you do not use are not there

Most of what a charting library carries is structural, and most pages never use it. A bundler cannot remove it — the core references it, and nothing can prove your page has one pane. So it is removed earlier, when the library is built.

Switch the build and watch what the chart can still do.

  • Line, area, baseline, candlestick, bar and histogram series
  • Crosshair, markers, price lines and primitives
  • Pan, zoom, pinch and axis drag
  • Panes
  • Logarithmic, percentage and indexed-to-100 price scales
  • Left and overlay price scales
  • Custom series
  • Watermarks, touch tracking and kinetic scroll

Not disabled. Absent — the method is undefined and the code is not in the file.

The case for it

Why this one

Arincen Charts
25.8 KB
lightweight-charts
60 KB

Something other than eyes can read it

One call hands a model exactly what is on screen, in words. Another draws its answer back as regions, points and levels. No key, no bundled client, no provider to be tied to — and the same call is the plainest description a screen reader has ever been given of a chart.

Small enough to stop thinking about

Charts are usually the heaviest thing on a financial page. This one is smaller than most icon sets.

Nothing to audit

No dependencies at all. Nothing to update, nothing to have a vulnerability filed against, nothing pulling in a transitive tree.

Already carrying real traffic

Every chart on Arincen is drawn by it, on both domains — instrument pages, portfolios, articles, the mobile app and the embeddable widgets.

Extend it without forking

Primitives draw over a chart that already works. Custom series replace the drawing entirely. Both take plain objects, so the thing you need next is yours to write rather than ours to approve.

Get going

Start here

One command, or a script tag and no build step at all.

Works with

ReactVueSvelteAngularSolidAstroA script tagiOS and Android WebViews
import { createChart, AreaSeries } from '@arincen/charts';

const chart = createChart(document.getElementById('chart'), {
    autoSize: true,
});

const series = chart.addSeries(AreaSeries, {
    lineColor: '#db2777',
});

series.setData(data);
chart.timeScale().fitContent();

Risk Disclosure: Trading in financial instruments involves high risks including the risk of losing some, or all, of your investment amount, and may not be suitable for all investors. Prices of cryptocurrencies are extremely volatile and may be affected by external factors such as financial, regulatory or political events. Trading on margin increases the financial risks. Never invest money you cannot afford to lose, and carefully assess the suitability of complex products such as CFDs and derivatives in light of your financial situation. Before deciding to trade in financial instrument or cryptocurrencies you should be fully informed of the risks and costs associated with trading the financial markets, carefully consider your investment objectives, level of experience, and risk appetite, and seek professional advice where needed. Arincen would like to remind you that the data contained in this website is not necessarily real-time nor accurate. The data and prices on the website are not necessarily accurate and may differ from the actual price at any given market, meaning prices are indicative and not appropriate for trading purposes.

Arincen and any provider of the data contained in this website will not accept liability for any loss or damage as a result of your trading, or your reliance on the information contained within this website. It is prohibited to use, store, reproduce, display, modify, transmit or distribute the data contained in this website without the explicit prior written permission of Arincen and/or the data provider. All intellectual property rights are reserved by the providers and/or the exchange providing the data contained in this website. Arincen may be compensated by the advertisers that appear on the website, based on your interaction with the advertisements or advertisers.

© 2026 - Arincen L.L.C-FZ - License No. 2420098.01. All Rights Reserved.