Skip to main content

Quick reference

A quick reference guide for creating custom studies in DXcharts.

Basic template

__CHART_REACT_API.addCustomStudy({
name: 'My Indicator',
metainfo: {
id: 'MY_INDICATOR',
title: 'My Indicator',
overlaying: true, // true = overlay, false = separate pane
parameters: [
{ id: 'length', title: 'Length', type: 'INTEGER_RANGE', defaultValue: 14, min: 1, max: 500 }
],
lines: [
{ id: 'output', title: 'Output', type: 'LINEAR', color: '#2962FF', thickness: 2 }
]
},
constructor: {
main: function(ctx) {
const input = ctx.input;
const state = ctx.state;
const index = ctx.index;

if (!state.data) {
state.data = [];
}

const value = input.close(0);
state.data[index] = value;
// Your calculation here
return [value];
}
}
});

Parameter types

TypeDescriptionExample
INTEGER_RANGEInteger with min/max{ type: 'INTEGER_RANGE', defaultValue: 14, min: 1, max: 500 }
DOUBLE_RANGEFloating point with min/max{ type: 'DOUBLE_RANGE', defaultValue: 2.0, min: 0.1, max: 10, precision: 2 }
BOOLEANTrue/false toggle{ type: 'BOOLEAN', defaultValue: true }
STRINGText input{ type: 'STRING', defaultValue: 'CLOSE' }

Line types

TypeDescription
LINEARContinuous line
POINTSPoint markers
HISTOGRAMVertical bars from zero
TREND_HISTOGRAMHistogram colored by trend
DIFFERENCEArea between two lines
LINEAR_TRENDLine colored by trend
TREND_POINTSPoints colored by trend
ABOVE_CANDLE_TEXTText above candles
BELOW_CANDLE_TEXTText below candles
COLOR_CANDLEColors candles

Context API

export interface CustomStudyContext {
index: number;
input: {
open: (offset?: number) => number;
high: (offset?: number) => number;
low: (offset?: number) => number;
close: (offset?: number) => number;
volume: (offset?: number) => number;
};
parameters: Record<string, unknown>;
state: Record<string, unknown>;
utils: CustomStudyUtils;
}

Price data

// Basic OHLCV (offset = 0 means current, 1 means previous, etc.)
const close = input.close(0); // Current close
const open = input.open(1); // Previous open
const high = input.high(0); // Current high
const low = input.low(0); // Current low
const volume = input.volume(0); // Current volume

// Timestamp
const time = input.time(0); // Candle timestamp (milliseconds)

// Advanced market data (may be undefined)
const vwap = input.vwap(0); // Volume Weighted Average Price
const openInterest = input.openInterest(0);// Open Interest
const impVol = input.impVolatility(0); // Implied Volatility

// Price helpers
const median = input.median(0); // (high + low) / 2
const typical = input.typical(0); // (high + low + close) / 3
const ohlcAvg = input.ohlcAverage(0); // (open + high + low + close) / 4

// Generic price accessor (works with PRICE_FIELD parameters)
const price = input.getPrice('CLOSE', 0);
const price = input.getPrice('TYPICAL', 0);
// Types: 'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOLUME', 'MEDIAN', 'TYPICAL', 'OHLC_AVERAGE'

Common utilities

tip

For complete documentation of all utility functions, see Utility Functions Reference.

Note: Most utility functions accept data as either an array or an accessor function:

// Using array directly
utils.sma(state.prices, 20, index)

// Using accessor function
utils.sma(function(i) { return state.prices[i]; }, 20, index)

Moving Averages

// Simple MA
utils.sma(data, period, index)
utils.sma((i) => data[i], period, index)

// Exponential MA
utils.ema(data, period, index, 'key')
utils.ema((i) => data[i], period, index, 'key')

// Weighted MA
utils.wma(data, period, index)

// Running MA
utils.rma(data, period, index, 'key')

Statistics

// Standard deviation
utils.stdev(data, period, index)

// Variance
utils.variance(data, period, index)

// Correlation
utils.correlation(data1, data2, period, index)

Price Analysis

// Max in period
utils.highest(data, period, index)

// Min in period
utils.lowest(data, period, index)

utils.tr(index) // True Range
utils.atr(period, index, 'key') // Average TR

Utilities

utils.na(value)                   // Check if N/A
utils.nz(value, replacement) // Replace N/A

// Value change
utils.change(data, index, period)

// Sum over period
utils.sum(data, period, index)

utils.abs(value) // Absolute value
utils.max(...values) // Maximum
utils.min(...values) // Minimum

State Management

main: function(ctx) {
const input = ctx.input;
const utils = ctx.utils;
const state = ctx.state;
const index = ctx.index;

// Initialize arrays on first use
if (!state.prices) {
state.prices = [];
state.emaValues = [];
state.output = [];
}

// Store at current index
state.prices[index] = input.close(0);

// Use unique keys for utils
state.emaValues[index] = utils.ema(function(i) {
return state.prices[i];
}, 9, index, 'ema_unique');
}

Common patterns

Simple Moving Average

constructor: {
main: function(ctx) {
const input = ctx.input;
const utils = ctx.utils;
const parameters = ctx.parameters;
const state = ctx.state;
const index = ctx.index;

if (!state.prices) {
state.prices = [];
}

state.prices[index] = input.close(0);
const sma = utils.sma(function(i) {
return state.prices[i];
}, parameters.length, index);
return [sma];
}
}

Exponential Moving Average

constructor: {
main: function(ctx) {
const input = ctx.input;
const utils = ctx.utils;
const parameters = ctx.parameters;
const state = ctx.state;
const index = ctx.index;

if (!state.prices) {
state.prices = [];
}

state.prices[index] = input.close(0);
const ema = utils.ema(function(i) {
return state.prices[i];
}, parameters.length, index, 'ema');
return [ema];
}
}

Bollinger Bands

constructor: {
main: function(ctx) {
const input = ctx.input;
const utils = ctx.utils;
const parameters = ctx.parameters;
const state = ctx.state;
const index = ctx.index;

if (!state.prices) {
state.prices = [];
}

state.prices[index] = input.close(0);
const basis = utils.sma(function(i) {
return state.prices[i];
}, parameters.length, index);
const dev = utils.stdev(function(i) {
return state.prices[i];
}, parameters.length, index);
if (utils.na(basis) || utils.na(dev)) {
return [NaN, NaN, NaN];
}
const upper = basis + parameters.mult * dev;
const lower = basis - parameters.mult * dev;
return [upper, basis, lower];
}
}

Removing studies

__CHART_REACT_API.removeCustomStudy('MY_INDICATOR');

Common errors

  1. Not initializing state arrays

    // Bad
    main: function(ctx) { state.prices[index] = value; }

    // Good
    main: function(ctx) {
    if (!ctx.state.prices) {
    ctx.state.prices = [];
    }
    }
  2. Reusing state keys

    // Bad - same key
    utils.ema(function(i) {
    return data1[i];
    }, 9, index, 'ema');
    utils.ema(function(i) {
    return data2[i];
    }, 9, index, 'ema');

    // Good - unique keys
    utils.ema(function(i) {
    return data1[i];
    }, 9, index, 'ema1');
    utils.ema(function(i) {
    return data2[i];
    }, 9, index, 'ema2');
  3. Not checking for N/A

    // Bad
    return [value1 + value2];

    // Good
    if (utils.na(value1) || utils.na(value2)) {
    return [NaN];
    }
    return [value1 + value2];