Trading blotters, order books and market data
Perspective was originally developed at J.P. Morgan and open sourced through FINOS, the Fintech Open Source Foundation, before joining the OpenJS Foundation. Financial market data is the workload it was designed around: wide tables, high update rates, keyed replacement of rows, and users who need to re-slice the data themselves while it is moving.
The building blocks
A blotter is an indexed table in a data grid. With
index set to the order or trade id, each
update() replaces that row in place; partial updates (only the changed
fields) are supported, and remove() deletes by key.
const table = await worker.table(
{ id: "string", symbol: "string", side: "string", price: "float", qty: "integer", status: "string", time: "datetime" },
{ index: "id" },
);
table.update([{ id: "o-1841", status: "filled" }]);
An order book is a pivot of that same table: group_by price,
split_by side, sum of quantity, filtered to open orders.
await viewer.restore({
plugin: "X Bar",
group_by: ["price"],
split_by: ["side"],
columns: ["qty"],
filter: [["status", "==", "open"]],
});
Candlesticks are a pivot too: group_by a time bucket expression, with
first, last, high and low aggregates over aliases of the price column,
drawn by the Candlestick or OHLC plugin.
await viewer.restore({
plugin: "Candlestick",
group_by: ["bucket(\"time\", 'm')"],
columns: ["open", "close", "high", "low"],
expressions: {
"bucket(\"time\", 'm')": "bucket(\"time\", 'm')",
open: '"price"',
close: '"price"',
high: '"price"',
low: '"price"',
},
aggregates: { open: "first", close: "last", high: "high", low: "low" },
});
Because every one of these is a View over one streaming Table, they stay
mutually consistent tick by tick, and users can change any of them — regroup
by sector, filter to a book, switch the blotter to a heatmap — without code.
Conditional formatting
The data grid supports per-column number formatting, positive/negative foreground and background colors, gradients and in-cell bars, all set from the column settings panel and captured in the saved configuration.
Deployment shapes
- Desktop containers and internal web apps —
<perspective-viewer>is a standard Web Component with no framework dependency, and ships React bindings. - Python services — host tables from
Tornado, FastAPI/Starlette or aiohttp;
ingest
pandas,polarsorpyarrowdirectly. - ClickHouse, DuckDB, PostgreSQL, Polars — put the UI directly over the tick store with a virtual server.
- Research notebooks — the same widget in Jupyter.
Examples
- Market — blotter, order book chart and candlesticks over one simulated feed.
- Market — Orders