Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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, polars or pyarrow directly.
  • ClickHouse, DuckDB, PostgreSQL, Polars — put the UI directly over the tick store with a virtual server.
  • Research notebooks — the same widget in Jupyter.

Examples