# API mapping

> Concept by concept, from Lightweight Charts, Highcharts Stock, Advanced Charts or ChartIQ.

Section: Commercial. Source: https://ortexcharts.com/docs/migration

## How to Read This Page

If you have not decided yet, start with [moving from TradingView or
Highcharts](https://ortexcharts.com/docs/moving-in): it is organised by how products actually embed a chart, and it
says what the move costs from each shape. This page is the concept-by-concept mapping you want
open while you do it.

Four libraries, four honest comparisons. Each section maps the concepts that line up, then
states plainly what that library does which ORTEX Charts does not. The second half is the
part that matters when you are deciding, so it is not buried.

Competitor APIs change between major versions. The mappings below are written against
Lightweight Charts 5, Highcharts Stock 13, TradingView Advanced Charts 20-era and ChartIQ 8;
check the exact names against the version you are on.

One thing is common to all four migrations: **timestamps in ORTEX Charts are milliseconds
since the Unix epoch, in UTC, everywhere.** Not seconds, not business-day objects, not local
dates. That single conversion is most of the work in a mechanical port.

## The Translators Do the Mechanical Half

For the two libraries most people arrive from, you do not have to do the mapping by hand.
`@ortex-charts/migrate` takes what you already have — a TradingView datafeed and widget
options, or a Highcharts options object — and returns a working chart plus a list of what
did not carry over, so the port is a checklist rather than a guess.

```bash
npm install @ortex-charts/migrate
```

```ts
import { tradingViewWidget, tradingViewDatafeed, fromHighcharts } from "@ortex-charts/migrate";

// Drop-in for `new TradingView.widget({...})`
const shell = tradingViewWidget({ container_id: "chart", datafeed, symbol: "NASDAQ:AAPL", interval: "D", theme: "Dark" });

// Or keep your own shell and wrap only the datafeed
createChartShell(el, { datafeed: tradingViewDatafeed(myDatafeed), symbol: "NASDAQ:AAPL", resolution: "1D" });

// Highcharts and Highcharts Stock, options object and all
const { chart, series, indicators, markers, unsupported } = fromHighcharts(el, highchartsOptions);
if (unsupported.length) console.info("Look at:", unsupported);
```

The inputs are typed to accept the vendors' own objects as they are: a
`ChartingLibraryWidgetOptions` with its `IBasicDataFeed`, or a `Highcharts.Options`, without
a cast. Two pages port one real chart each, end to end: [moving from
Highcharts](https://ortexcharts.com/docs/from-highcharts) and [moving from TradingView](https://ortexcharts.com/docs/from-tradingview).

The TradingView wrapper turns the callback interface into the promise one: `onReady` is
awaited once, `resolveSymbol` is resolved once per symbol and cached, `getBars` is converted
from seconds to milliseconds, `subscribeBars` returns an unsubscribe function, and
resolutions map both ways (`D` ↔ `1D`). `pricescale` and `minmov` become `priceFormat`, and
the first entry of `logo_urls` becomes the legend logo. `supportedResolutions()` on the
wrapped feed answers with what the symbol, else `onReady`, declared, and
`tradingViewWidgetAsync` waits for it so the toolbar offers only those.

The Highcharts translator reads the series types (`line`, `spline`, `area`, `areaspline`,
`column`, `bar`, `candlestick`, `ohlc`, `scatter`), every point shape Highcharts accepts,
y-axes placed with `top` and `height` as panes, the column on the second axis under a
candlestick as the volume, `sma`, `ema`, `wma`, `rsi`, `atr`, `bb`, `macd` and `stochastic`
series as indicators with their periods, `flags` as markers, `plotLines` as price lines
(once per axis), a left axis, and `dashStyle`, `lineWidth`, `fillOpacity` and `visible`.
`fromHighchartsCategory` and `fromHighchartsPie` do the same for column, bar and pie charts.

Anything without a counterpart is reported rather than silently dropped, and nothing is
emitted for it: the Highcharts translator lists series types, `yAxis.min`/`max`, percent
stacking and the modules the shell replaces (`navigator`, `rangeSelector`, `scrollbar`,
`exporting`, `annotations`, `stockTools`) in `unsupported`; the TradingView translator lists
every widget key, `disabled_features` or `enabled_features` flag and `overrides` path it did
not read in `ignored`, on the shell it returns. `translateHighcharts`,
`translateHighchartsCategory`, `translateHighchartsPie` and `fromTVWidgetOptions` return the
translation without creating anything, which is what you want in a test or a gradual move.

The rest of this page is the conceptual mapping, which you still want to read: the
translators get a chart on the screen, not a finished port.

## From TradingView Lightweight Charts

This is the easiest migration of the four. The mental models are close: one chart, series
you add to it, data you set and update, a time scale you drive.

### API Mapping

| Lightweight Charts | ORTEX Charts |
|---|---|
| `createChart(el, options)` | `createChart(el, options)`, or `createFinancialChart(el, options)` for a chart with a volume pane |
| `chart.addSeries(CandlestickSeries, o)` | `chart.addSeries("candlestick", o)` |
| `chart.addSeries(LineSeries, o)` | `chart.addSeries("line", o)` |
| `chart.addSeries(AreaSeries, o)` | `chart.addSeries("area", o)` |
| `chart.addSeries(BaselineSeries, o)` | `chart.addSeries("baseline", o)` |
| `chart.addSeries(HistogramSeries, o)` | `chart.addSeries("histogram", o)` |
| `chart.addSeries(BarSeries, o)` | `chart.addSeries("bar", o)` |
| `series.setData(data)` | `series.setData(data)` |
| `series.update(bar)` | `series.update(bar)` |
| `series.applyOptions(o)` | `series.applyOptions(o)` |
| `chart.removeSeries(series)` | `chart.removeSeries(series.id)` |
| `chart.applyOptions(o)` | `chart.applyOptions(o)` |
| `chart.timeScale().fitContent()` | `chart.timeScale.fitContent()` |
| `chart.timeScale().setVisibleLogicalRange({from, to})` | `chart.timeScale.setVisibleRange(from, to)` |
| `chart.timeScale().scrollToRealTime()` | `chart.timeScale.scrollToRealtime()` |
| `chart.subscribeCrosshairMove(cb)` | `chart.subscribeCrosshairMove(cb)` |
| `chart.subscribeClick(cb)` | `chart.subscribeClick(cb)` |
| `chart.addPane()` | `chart.addPane({ heightRatio })` |
| `createSeriesMarkers(series, markers)` | `addSeriesMarkers(chart, series, markers)`, or `fc.setMarkers(markers)` |
| `series.createPriceLine(o)` | `chart.addPriceLine(series.id, o)` |
| `chart.remove()` | `chart.remove()` |
| Custom series plugin | `registerSeriesType(name, def)` |
| Pane primitive plugin | `chart.addPrimitive(primitive, paneId)` |

### The Differences That Bite

- **`timeScale` is a property, not a method.** `chart.timeScale.fitContent()`.
- **Times are milliseconds.** Lightweight Charts takes Unix **seconds** or a business-day
  object. Multiply by 1,000; convert `{ year, month, day }` to a UTC midnight timestamp.
- **Series are removed by id**, not by reference: `chart.removeSeries(series.id)`.
- **Series types are strings**, not imported constructors.
- **Colors default from the theme.** Where you set `upColor` and `downColor` on every series,
  you can set them once in the theme instead.
- **A series declares how it aligns** to the main timeline. Lightweight Charts requires every
  series to share a time axis; here a daily series on an intraday chart is
  `align: "forwardFill"` rather than a data-preparation problem.

### What Lightweight Charts Has That ORTEX Charts Does Not

- **It is open source, Apache 2.0.** No license key, no mark, no contract, no cost. If that
  is the deciding factor, it decides.
- It is about 5 KB smaller for the subset it covers.
- It has a longer public track record and a larger body of community examples.

### What You Gain

A toolbar, symbol search, 32 drawing tools, 51 indicators, event markers, order flow, bar replay,
alerts, host-managed layouts, an adapter layer, and a faster first paint at large data
sizes — for about 5 KB more.

## From Highcharts Stock

The mental model is further away. Highcharts is declarative: you describe a whole chart as
one options object and call `update` to change it. ORTEX Charts is imperative: you create
objects and call methods on them.

### API Mapping

| Highcharts Stock | ORTEX Charts |
|---|---|
| `Highcharts.stockChart(el, options)` | `createFinancialChart(el, options)` |
| `series: [{ type: "candlestick", data }]` | `chart.addSeries("candlestick").setData(data)` |
| `data: [[x, o, h, l, c]]` | `[{ time, open, high, low, close, volume }]` |
| `series: [{ type: "line", data: [[x, y]] }]` | `chart.addSeries("line").setData([[time, value]])` |
| `yAxis: [{ …}, { … }]` with `height` and `top` | `chart.addPane({ heightRatio })` plus `priceScaleId` |
| `yAxis.type: "logarithmic"` | `chart.priceScale("right").applyOptions({ mode: "logarithmic" })` |
| `series[i].addPoint(point, redraw, shift)` | `series.update(point)` |
| `series[i].setData(data)` | `series.setData(data)` |
| `chart.update(options)` | `chart.applyOptions(options)` |
| `series[i].update({ color })` | `series.applyOptions({ color })` |
| `series: [{ type: "sma", linkedTo: "main", params: { period } }]` | `chart.addIndicator("sma", { length })` |
| `series: [{ type: "flags", data }]` | `chart.setEvents(events)` or `chart.setMarkers(markers)` |
| `chart.setSize(w, h)` | `chart.resize(w, h)`, or leave `autoSize` on |
| `Highcharts.setOptions({ colors })` | `chart.setTheme({ ...darkTheme, palette })` |
| `chart.destroy()` | `chart.remove()` |
| `exporting` module | `chart.takeScreenshot()`, `shell.exportCsv()`, `downloadPNG`, `downloadCSV` |

### The Differences That Bite

- **There is no global options object.** Nothing is configured for the page; every chart
  carries its own options and its own theme.
- **Panes are not y-axes with pixel offsets.** A pane is a real container with a relative
  height weight, and a scale lives inside it.
- **Indicators are not linked series.** They are a separate concept with their own
  registration, inputs and outputs.
- **Rendering is Canvas, not SVG.** There is no DOM node per point to style with CSS or
  select with a query, and no SVG export. Styling is options and theme tokens.
- **Redrawing is automatic.** There is no `redraw` flag on mutators; the chart schedules a
  frame.
- **Times are milliseconds** here as well, which Highcharts also uses, so this is the one
  migration where timestamps need no conversion.

### What Highcharts Stock Has That ORTEX Charts Does Not

- **A navigator strip and range-selector buttons** (1m, 3m, YTD, 1y, All) as built-in
  components. Range presets are the shell's period buttons, or a few lines on
  `setVisibleTimeRange`; a navigator mini-chart is not built in. The "All" button is not
  `timeScale.fitContent()` on a long history: Highcharts groups daily bars into weekly points
  to fit ten years in one view, while `fitContent` stops at `minBarSpacing`, half a pixel per
  bar by default, so 2,500 daily bars do not fit in 1,100 pixels and the view opens on the
  most recent bars that do. Lower `timeScale.minBarSpacing`, or open on a year.
- **An accessibility module**: screen-reader descriptions of the data, a focusable data
  table, and keyboard navigation of points. See [The toolbar](https://ortexcharts.com/docs/toolbar) for what is and
  is not implemented here.
- **A server-side export server** producing PNG, PDF and SVG from a running service.
- **SVG rendering**, if per-point DOM matters to you for styling or testing.
- **A boost module** for very large point counts.

### What You Gain

About a fifth of the payload, a financial toolbar and drawing tools that Highcharts Stock
does not include, an index-based time axis that removes closed periods without configuration,
order flow, bar replay, and per-product rather than per-developer licensing.

## From TradingView Advanced Charts

This is the migration with the largest gap in both directions, because Advanced Charts is a
complete application delivered as a widget rather than a library you compose.

### API Mapping

| Advanced Charts | ORTEX Charts |
|---|---|
| `new TradingView.widget({ … })` | `createChartShell(el, { … })` |
| `datafeed` with `onReady`, `resolveSymbol`, `getBars`, `subscribeBars`, `searchSymbols` | `Datafeed` with `resolveSymbol`, `getBars`, `subscribeBars`, `searchSymbols`; no `onReady` |
| `LibrarySymbolInfo` | `SymbolInfo` |
| `resolution` as `"1"`, `"60"`, `"1D"` | The same notation |
| `widget.setSymbol(symbol, interval, cb)` | `shell.setSymbol(s)` and `shell.setResolution(r)` |
| `widget.activeChart().createStudy(name, …)` | `shell.addIndicator(id, inputs)` |
| `widget.activeChart().createShape(point, o)` | `tools.add({ kind, points, style })` |
| `widget.activeChart().createMultipointShape(points, o)` | The same |
| `widget.activeChart().setChartType(n)` | `shell.setSeriesType("candlestick")` |
| `widget.activeChart().setVisibleRange({from, to})` | `chart.timeScale.setVisibleTimeRange(from, to)` |
| `widget.save(cb)` and `widget.load(state)` | `shell.getLayout()` and `shell.setLayout(layout)` |
| `disabled_features` and `enabled_features` | `toolbar`, `drawings`, `indicators`, `drawingTools` switches |
| `overrides` | Theme tokens and series options |
| `widget.onChartReady(cb)` | The shell is ready when `createChartShell` returns |
| Timescale marks | `chart.setEvents(events)` with `style: "lane"` |
| Compare study | The built-in `price` overlay for another symbol |

Datafeed shapes are deliberately close, so a port is usually mechanical: drop `onReady`,
return `{ bars, noMoreData }` instead of calling `onHistoryCallback`, and return bars with
millisecond `time` rather than second `time`.

### The Differences That Bite

- **Callbacks become promises.** `getBars` returns a promise instead of calling
  `onHistoryCallback` and `onErrorCallback`.
- **Times are milliseconds**, not seconds.
- **There is no iframe.** The chart is in your DOM, so your CSS, your fonts and your
  developer tools all apply — and so do your layout bugs.
- **State is yours.** There is no `save`/`load` server contract and no chart storage service;
  `getLayout` gives you JSON and you decide where it lives.
- **Feature flags become option switches.** The `disabled_features` string list is replaced
  by typed options on the shell.

### What Advanced Charts Has That ORTEX Charts Does Not

- **Around 110 built-in studies** against 51. The long tail there is mostly variations
  on what is here.
- **The TradingView platform behind it**: the interface users already recognize, and the
  Pine Script ecosystem that comes with the platform rather than with the library. Custom
  studies in Advanced Charts itself are JavaScript, as they are here.
- **Around 90 drawing tools** against 32.
- **Multi-chart layouts** (two-by-two and the rest) as a built-in container, with symbol and
  interval synchronization. `linkCharts` synchronizes time and crosshair here, but the grid
  container is your CSS.
- **Around 30 interface languages.** The chrome here is English only.
- **A broker and order-management integration** — order tickets, positions, depth of market,
  an account panel — in the Trading Platform edition.
- **The brand recognition.** Users know the interface.

### What You Gain

89.9 KB in one file instead of 4.8 MB across 154. A chart you can style, extend and debug.
No attribution requirement on a licensed build, and no restriction to services offered
free of charge: the free Advanced Charts agreement requires the TradingView mark **and** a
service the public can use without paying, which rules out a subscription product and an
internal desk tool outright.

## From ChartIQ

ChartIQ is the closest competitor on feature depth and the furthest away on API style. It is
also the most expensive of the four, sold as an annual enterprise contract.

### API Mapping

| ChartIQ | ORTEX Charts |
|---|---|
| `new CIQ.ChartEngine({ container })` | `createFinancialChart(el, options)` |
| `stxx.loadChart(symbol, { periodicity, masterData })` | `chart.bind(datafeed, { symbol, resolution })` |
| `quotefeed` with `fetchInitialData`, `fetchPaginationData`, `fetchUpdateData` | `Datafeed` with `getBars` and `subscribeBars` |
| `stxx.setPeriodicity({ period, interval })` | `binding.setResolution("15")` |
| `stxx.setChartType("candle")` | `fc.setSeriesType("candlestick")` |
| `stxx.setChartScale("log")` | `chart.priceScale("right").applyOptions({ mode: "logarithmic" })` |
| `CIQ.Studies.addStudy(stxx, "rsi", inputs, outputs)` | `fc.addIndicator("rsi", inputs, options)` |
| `stxx.addSeries(symbol, params)` | `chart.addSeries(type, options).setData(data)` |
| `stxx.createDrawing(kind, params)` | `tools.add({ kind, points, style })` |
| `stxx.exportDrawings()` and `importDrawings()` | `tools.getDrawings()` and `setDrawings()` |
| `stxx.append`/`updateChartData` | `series.update(bar)` |
| Themes as CSS | Theme tokens on the chart |
| `stxx.destroy()` | `chart.remove()` |

### The Differences That Bite

- **Styling is options, not CSS.** ChartIQ is styled with stylesheets over its own class
  names; here every color is a theme token or a series option.
- **There is no periodicity object.** A resolution is a string.
- **There is no `masterData` concept**; series own their own data and alignment.

### What ChartIQ Has That ORTEX Charts Does Not

- **A much deeper indicator and study library**, with study editing, comparison studies and
  a study browser.
- **Term structure, options chains, cross-section and time-span event charts** as first-class
  chart types.
- **A trading and order-management integration**, and a market-depth component.
- **Multi-chart layouts and workspace management** as products in their own right.
- **A managed data service and a signature integration ecosystem.**
- **An accessibility story**, including screen-reader support.

### What You Gain

The demo transfers 4.4 MB and reaches DOMContentLoaded at 3.4 seconds. The full ORTEX chart
is 89.9 KB in one file. Order flow — footprint bars, exact volume and market profiles, real
delta from aggressor data — is included rather than a platform tier. And the price is public.

## A Migration Checklist

Whichever library you are coming from:

1. **Convert timestamps to milliseconds, UTC.** Multiply seconds by 1,000, convert
   business-day objects to a UTC midnight, and drop local-date parsing.
2. **Set `timeZone` to the exchange zone**, not to the browser zone, or daily bars will land
   on the wrong day for a third of your users.
3. **Set `session`** if you draw intraday bars, so hourly candles start at the open. See
   [Time, sessions and resolutions](https://ortexcharts.com/docs/time).
4. **Move colors into a theme** rather than onto every series, so the theme switch works.
5. **Replace per-series time alignment work with `align`.** Data that does not share the
   price timeline is a series option here, not a pre-processing step.
6. **Replace `setData`-per-tick with `update`.** This is the single biggest performance
   difference between a good port and a bad one.
7. **Decide where layouts and drawings live**, because the library will not decide for you.
   See [The shell and layouts](https://ortexcharts.com/docs/shell).
8. **Audit your indicator list against the 51 built-ins** and budget for the ones you have
   to write. This is the most common source of unplanned work in a migration.

## The Honest Summary

| If you need | Choose |
|---|---|
| Open source with no license at all | Lightweight Charts |
| 110 studies, 90 drawing tools, 30 interface languages | TradingView Advanced Charts |
| A navigator, an accessibility module, a server-side export service, SVG | Highcharts Stock |
| The deepest study library, term structure, order management, an enterprise contract | ChartIQ |
| Millions of points on screen at 60 Hz | SciChart |
| A small, fast, extensible financial chart with a toolbar, drawings, order flow and replay, that you can white-label, priced per product | ORTEX Charts |
