Skip to main content

Use secondary market data

Load secondary bars in your application and pass them when you add or update the indicator. Inside the indicator, call security(...) to read the aligned series. This keeps data access in one place: your existing datafeed.

note

Secondary indicator data is not a chart comparison. It does not add a comparison series, open the Compare Symbols dialog, or change chart state; the supplied bars are available only inside that indicator's calculation.

Dataflow

The indicator declares the symbol input. Your application decides how that symbol maps to a venue and loads the matching bars.

Minimal working pair

Indicator — declare the symbol and read the supplied series:

import { indicator, input, plot, close, security } from '@tradescript/pro/sdk/indicators'

export default indicator('Secondary close', () => {
const other = input.symbol('Other', 'ETHUSDT', { id: 'other' })
plot.line(close, { key: 'main', title: 'Main' })
plot.line(security(other, 'close', { map: 'continuous' }), {
key: 'other',
title: 'Other',
})
}, { pane: 'price' })

Application — register, load, attach:

import { registerCustomIndicator, loadSecuritiesForIndicator } from '@tradescript/pro/sdk'
import secondaryClose from './indicators/secondaryClose'

const name = registerCustomIndicator(secondaryClose)
const securities = await loadSecuritiesForIndicator(secondaryClose, mainBars, { other: 'ETHUSDT' }, loadBars)

chart.addIndicator({
name,
paneId: 'candle_pane',
inputs: { other: 'ETHUSDT' },
securities,
})

Result: the main close and secondary close render on the same pane. With map: 'continuous', the most recent secondary value is used between secondary bars.

The four things that matter

Symbol ownership

  • Your application resolves every input.symbol value and loads the bars. Indicators only read the supplied series.

Interval alignment

  • Secondary bars are matched to main-series bars by timestamp. The map option on security(...) decides what happens when timestamps disagree:
ModeBehavior
precise (default)Exact timestamp match only; missing bars → NaN
continuousLatest secondary bar at or before main time; if none, next later bar

Missing data

  • With precise, every unmatched main bar yields NaN in the secondary series — plots show gaps. With continuous, values carry forward, so a slow-updating secondary interval renders as steps. Warm-up positions of derived ta.* series are NaN either way.

Refreshing data

  • Reload and pass secondary bars again when the chart symbol, interval, or the secondary-symbol input changes. Remove the indicator normally when it is no longer needed.

Application helpers

Exported from @tradescript/pro/sdk:

HelperRole
symbolInputsOf(indicator)input.symbol specs
resolveSymbolMap(indicator, overrides)Resolved ticker strings
loadSecuritiesForIndicator(indicator, mainBars, overrides, loadBars, options?)Build Record<string, SecuritySeries>
attachSecuritiesToIndicatorInstance(instance, securities)Write the typed instance.securities field
runIndicatorWithSecurities(...)Load + indicator.run convenience
runtimeWithSecurities(securities, base?)Context object for direct indicator calls

Full load example

import {
registerCustomIndicator,
loadSecuritiesForIndicator,
} from '@tradescript/pro/sdk';
import secondaryCloseIndicator from './indicators/secondaryCloseIndicator';

const ci = secondaryCloseIndicator;
const name = registerCustomIndicator(ci);

const mainBars = chartDataAsAuthoringBars(chart.getDataList());
const overrides = { other: 'SPOT:BINANCE:ETHUSDT' };

const securities = await loadSecuritiesForIndicator(
ci,
mainBars,
overrides,
async (request) => {
// request.symbol, request.key, request.mainBars, request.from, request.to
const history = await datafeed.loadBars(
{ ticker: request.symbol },
'15m',
{ startTime: request.from!, endTime: request.to!, barCount: mainBars.length },
);
return history.bars.map((b, index) => ({
time: b.time,
open: b.open,
high: b.high,
low: b.low,
close: b.close,
volume: b.volume ?? 0,
index,
}));
},
);

// Chart path: pass the resolved secondary series through IndicatorDefinition.securities
chart.addIndicator({
name,
paneId: 'candle_pane',
inputs: overrides,
securities,
});

Time-scale extension

Set canExtendTimeScale: true on the indicator when you plot values at future timestamps. The chart reserves room to the right of the latest bar for those values without adding artificial bars. Ordinary plots and markers remain aligned with the chart bars.