Skip to main content

Production Guides

These guides begin where Quickstart ends: the chart mounts, and the work now is connecting it to systems that carry real money and real users. Each one opens the smallest possible boundary, then adds verification and failure handling. Every card below names what you get, what you need first, how long it takes, and which side of the boundary owns the code.

GoalGuideDifficultyTime
Load history and stream live barsREST and WebSocket chartBeginner45–90 min
Add orders, positions, and executionsBroker integrationIntermediate45–90 min
Save chart state server-sideStorage quickstartIntermediate45–90 min
Ship a trusted host indicatorAdd custom indicatorsBeginner20–40 min
Change product chrome and appearanceCustomize the terminalBeginner20–45 min
Coordinate several chartsBuild a multi-chart workspaceIntermediate30–60 min
Prove the mounted integrationRuntime integration testingIntermediate20–40 min

Guide cards

Build a chart with REST and WebSocket data

  • Outcome: a chart that bootstraps history over REST, ticks live over WebSocket, and survives reconnects.
  • You need: a REST bars endpoint, a WebSocket bar stream, and one canonical symbol/interval mapping for both.
  • You own: authentication, vendor normalization, retries, and connections. The SDK owns range requests, rendering, and bar merging.

Integrate a broker

  • Outcome: a trading-enabled chart showing the active account and submitting server-validated orders.
  • You need: a chart that reaches ready(), an authenticated order API, and a server-owned account context.
  • You own: risk checks, broker rules, account authority, and final acceptance. The SDK owns the order UI and typed state display.

Connect chart storage

  • Outcome: save and reload of chart layouts, drawings, templates, user settings, and replay progress against your REST backend.
  • You need: an authenticated user and tenant context plus either the REST chart storage adapter or a custom chart storage adapter.
  • You own: tenant identity, authorization, versioning, and conflict handling. The SDK owns serialization and when saves fire.

Add custom indicators

  • Outcome: a host-shipped indicator registered at startup, plotted on the chart, and configurable through typed inputs.
  • You need: a working chart and a trusted TypeScript module in the host build.
  • You own: source review, build, versioning, and registration. The SDK owns computation scheduling, plotting, and the settings dialog.

Customize the terminal

  • Outcome: feature policy, theme, and runtime presentation (legend, watermark, colors, overrides) under your control.
  • You need: a working widget and datafeed plus approved theme values.
  • You own: feature policy, defaults, and user preference ownership. The SDK owns applying layers in precedence order.

Build a multi-chart workspace

  • Outcome: a synchronized grid of charts with stable identities and per-chart symbol state.
  • You need: a datafeed that can serve every configured symbol and stable host-owned chart ids.
  • You own: chart identity, shared-state policy, external panels, and cleanup. The SDK owns the grid, sync, and workspace serialization.

Runtime integration testing

  • Outcome: a deterministic smoke suite covering mount, readiness, data, interaction, cleanup, and failure.
  • You need: a browser-capable test runner and a real chart mount element.
  • You own: deterministic fixtures, public assertions, and release evidence. The SDK owns the public interfaces and mounted runtime those fixtures exercise.

Each guide adds exactly one boundary. Ship and verify a boundary before opening the next one — a chart that renders bars is already a complete integration, and every row below is optional on top of it.

  1. Complete Quickstart and prove one chart reaches ready().
  2. Add one production boundary at a time, starting with REST and WebSocket data.
  3. Keep the first version intentionally small and verify its visible result.
  4. Add optional capabilities only after the minimum path remains green.

One production configuration, annotated

A completed integration converges on this shape: every boundary wired into a single mount, each line commented with the guide that owns it. No line is required, and none has to arrive at the same time as the others.

chart-bootstrap.ts
import { createTradeScriptSdk, type MarketDataFeed } from '@tradescript/pro/sdk/core';
import {
createCachingDatafeed,
createRestChartStorageAdapter,
} from '@tradescript/pro/sdk';
import type { TradingBrokerAdapter } from '@tradescript/pro/sdk';

declare const rawFeed: MarketDataFeed; // guides/rest-websocket-chart
declare const broker: TradingBrokerAdapter; // trading/broker-integration
declare const deploymentLease: string; // getting-started/authorization
declare const currentUser: { id: string };
declare function getAccessToken(): Promise<string>;

// Market data — the cache wrapper owns dedup, range merging, and aggregation,
// so your feed only has to fetch. See datafeeds/resolutions.
const datafeed = createCachingDatafeed(rawFeed, {
policy: 'memory',
resolutionRebuildPolicy: 'aggregate',
});

// Chart storage — chart layouts, drawings, templates, user settings, and replay state
// over your REST API. See storage/.
const storage = createRestChartStorageAdapter({
baseUrl: 'https://api.example.com/chart-storage',
apiVersion: 'v1',
clientId: 'pro-terminal',
userId: currentUser.id,
headers: async () => ({ Authorization: `Bearer ${await getAccessToken()}` }),
});

// Authorization — one SDK per application, created from the backend-cached
// lease. See getting-started/authorization.
const sdk = await createTradeScriptSdk({ lease: deploymentLease });

const mounted = sdk.chart.mount({
mount: '#terminal',
symbol: { ticker: 'AAPL', exchange: 'NASDAQ', type: 'stock' },
interval: '15m',
datafeed,
broker,
storage,

// Appearance — see guides/customize-terminal and styling/themes.
theme: 'dark',
timezone: 'America/New_York',

// Product policy — every capability is explicit. See styling/features.
features: {
symbolSearch: true,
drawings: true,
builtInIndicators: true,
trading: true,
layoutStorage: { enabled: true, toolbar: true },
userSettings: { enabled: true, persistence: true },
},

// Operations — structured failures and debounced save signals.
// See errors/ and storage/chart-layouts.
autoSave: true,
onError: (error) => reportChartError(error.code, error.message),
});

const widget = await mounted.ready();
const chart = widget.chart();
await chart.dataReady();

export { mounted, widget, chart };

declare function reportChartError(code: string, message: string): void;

Every guide has a visible line in that file. Delete the lines for boundaries you have not opened yet and the chart still runs.

Next steps