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
| Type | Description | Example |
|---|---|---|
INTEGER_RANGE | Integer with min/max | { type: 'INTEGER_RANGE', defaultValue: 14, min: 1, max: 500 } |
DOUBLE_RANGE | Floating point with min/max | { type: 'DOUBLE_RANGE', defaultValue: 2.0, min: 0.1, max: 10, precision: 2 } |
BOOLEAN | True/false toggle | { type: 'BOOLEAN', defaultValue: true } |
STRING | Text input | { type: 'STRING', defaultValue: 'CLOSE' } |
Line types
| Type | Description |
|---|---|
LINEAR | Continuous line |
POINTS | Point markers |
HISTOGRAM | Vertical bars from zero |
TREND_HISTOGRAM | Histogram colored by trend |
DIFFERENCE | Area between two lines |
LINEAR_TREND | Line colored by trend |
TREND_POINTS | Points colored by trend |
ABOVE_CANDLE_TEXT | Text above candles |
BELOW_CANDLE_TEXT | Text below candles |
COLOR_CANDLE | Colors 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
-
Not initializing state arrays
// Bad
main: function(ctx) { state.prices[index] = value; }
// Good
main: function(ctx) {
if (!ctx.state.prices) {
ctx.state.prices = [];
}
} -
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'); -
Not checking for N/A
// Bad
return [value1 + value2];
// Good
if (utils.na(value1) || utils.na(value2)) {
return [NaN];
}
return [value1 + value2];