Trading surfaces
Choose the smallest surface that completes the user's workflow. A chart can provide on-chart trading, Account Manager can stand alone, and the terminal can compose the full workspace. They are different presentations over the same controller contracts, not separate broker integrations.
Do not mount a terminal when the product only needs an account table or one trading chart. Add another surface only after the first one has correct state, symbol routing, error handling, and teardown.
Choose what to mount
| Start with | Use it for | Mount |
|---|---|---|
| Chart trading | On-chart orders, positions, executions, and price-axis actions | sdk.chart.mount(...) |
| Account Manager | Account summary, pages, tables, filters, export, and row actions | sdk.accountPanel.mount(...) |
| Trading terminal | A linked chart, Dockview panels, symbol selection, hotkeys, and widget panel arrangement | sdk.tradingTerminal.mount(...) |
Order tickets are entry surfaces rather than workspace compositions. Start in Order entry when the workflow is only stock, crypto, option, or prediction-market submission.
Keep one authority per concern
| Concern | Canonical authority | Rule |
|---|---|---|
| Broker state and mutations | TradingControllerApi | Reuse one connected controller across every surface in the same broker session. |
| Bars, quotes, depth, and tape | MarketDataControllerApi | Use the same market-data controller when surfaces must observe the same feed and cache. |
| Active instrument | SymbolLinkControllerApi | Carry the complete provider-owned SdkSymbolInfo; do not synchronize ticker strings by hand. |
| Complete terminal composition | TradeScriptAdapterApi | Inject one host-owned adapter, or let the terminal create one from datafeed plus broker or trading. |
The owner that creates an authority also owns its final disconnect or destroy. Unmount every borrowing surface before destroying a shared controller.
Compose standalone surfaces
The same controller obtained from a chart can drive a separate Account Manager. Both containers need a real height.
import type {
MarketDataFeed,
SdkSymbolInfo,
TradeScriptSdkProducts,
TradingBrokerAdapter,
} from '@tradescript/pro/sdk';
declare const sdk: TradeScriptSdkProducts;
declare const datafeed: MarketDataFeed;
declare const broker: TradingBrokerAdapter;
declare const symbol: SdkSymbolInfo;
const chartMount = sdk.chart.mount({
mount: '#chart',
datafeed,
broker,
symbol,
interval: '1D',
features: { trading: true },
});
const widget = await chartMount.ready();
const trading = widget.trading();
await trading.connect();
await trading.getState();
const accountMount = sdk.accountPanel.mount({
mount: '#account-manager',
trading,
defaultPageId: 'positions',
});
async function destroyTradingSurfaces() {
accountMount.destroy();
try {
await trading.disconnect();
} finally {
chartMount.destroy();
}
}
Use the complete terminal instead when the host needs linked chart and trading panels, optional depth and tape panels, shared hotkeys, and panel persistence. Do not mount the standalone copies beside it unless the product intentionally needs a second view of the same authority. Persist its outer topology through Widget layout storage, independently from the chart workspaces inside it.
Verify every surface
- A broker update appears once in every mounted view that consumes it.
- A symbol change carries the exact selected instrument to every unpinned view.
- Disabled panels make no unsupported broker or market-data calls.
- Empty, loading, error, and disconnected states remain usable.
- Teardown removes every subscription and disconnects each owned authority once.
Next steps
- Chart trading — add on-chart state and auxiliary entry surfaces.
- Account Manager — declare pages, tables, actions, and account switching.
- Trading terminal — compose a complete linked workspace.
- Test a broker integration — prove state, mutation, reconnect, and teardown contracts.