MACD Indicator: Moving Average Convergence/Divergence in a JavaScript or React Financial Chart
The MACD (Moving Average Convergence/Divergence) indicator shows the trend and momentum of price in one pane. This page explains what MACD is, how its line, signal line and histogram are calculated and how traders read them, and shows how to add a MACD indicator to a JavaScript or React financial chart with SciTrader.js's MACDStudy, with live examples you can edit in CodePen.
MACD is one of the 32 built-in technical indicators and studies in the SciTrader SDK. For the full list, with each one's options and defaults, see Every Built-in Indicator and Study. To add and remove any of them, or build an indicator picker, see Add Technical Indicators to a Financial Chart.
What Is the MACD Indicator?
MACD, developed by Gerald Appel, tracks the gap between a fast and a slow moving average of the close. It has three parts:
- The MACD line: the fast average minus the slow average. It is above zero when the recent trend is up, and below zero when it is down.
- The signal line: a moving average of the MACD line, which smooths it.
- The histogram: the MACD line minus the signal line, drawn as columns. It shows when the two lines are converging or diverging.
Because its values are differences in price, not prices, a chart draws MACD in a pane of its own below the price chart.
How Is MACD Calculated?
MACD uses exponential moving averages (EMAs) of the close, with three lengths: fast (12 by default), slow (26) and signal (9):
An EMA weights recent candles more than older ones. Each value moves part of the way towards the latest close:
where is the EMA's length. The first EMA value is the simple average of the first length closes. See Moving Averages for more.
The MACD line starts after slow candles, and the signal line and histogram after slow + signal, about 35 candles with the defaults. SciTrader loads that many extra candles to the left of the visible period, so the lines start at the left edge.
How to Read MACD
These are the common readings. They are conventions traders use, not signals that hold every time:
- Signal line crossovers. The MACD line crossing above its signal line is commonly read as bullish, and crossing below as bearish. The histogram changes sign at the same moment.
- Zero line crossovers. The MACD line crossing zero means the fast average has crossed the slow one: a change in the trend.
- The histogram. Growing columns mean momentum is building; shrinking columns mean it is fading, often before a crossover.
- Divergence. Price making a new high while MACD makes a lower high suggests the move is losing strength.
How to Add a MACD Indicator to a JavaScript Financial Chart
Add a MACDStudy to the chart's studies. The example below is an ETH-USD chart from Coinbase with a 12, 26, 9 MACD in its own pane: the MACD line in teal, the signal line in amber, and the histogram green above zero and red below.
The code for this example is found below.
- TS
import "scichart-scitrader/scitrader.css";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
MACDStudy,
OHLCStudy,
SciFinanceChartPanel,
VolumeStudy,
} from "scichart-scitrader";
// This example expects this HTML:
// <div id="chart" style="height: 100%"></div>
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
async function createChart() {
// A financial chart is a SciFinanceChartPanel. Its indicators are studies, passed in `studies`
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "ETH-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// MACD: an oscillator, so it gets a pane of its own below the price pane.
// fast / slow: the EMA lengths whose difference is the MACD line (defaults 12 and 26).
// signal: the EMA length of the signal line (default 9).
// The histogram is MACD minus signal, coloured by which side of zero it is on
new MACDStudy({
fast: 12,
slow: 26,
signal: 9,
bandOptions: { stroke: "#2ec4b6", strokeY1: "#ff9f1c", strokeThickness: 2 }, // MACD line, signal line
histogramAboveZero: "#26a69a",
histogramBelowZero: "#ef5350",
}),
],
});
// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}
createChart();
How to Add a MACD Indicator to a React Financial Chart
In React, pass the same studies in the config of SciFinanceChartView, from scichart-scitrader-react. Create them in a useMemo, once per mounted chart: a study is a live object, bound to one chart.
The code for this example is found below.
- React
import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelConfig,
MACDStudy,
OHLCStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView } from "scichart-scitrader-react";
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
export function MacdChart() {
// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "ETH-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// MACD: an oscillator, so it gets a pane of its own below the price pane.
// fast / slow: the EMA lengths whose difference is the MACD line (defaults 12 and 26).
// signal: the EMA length of the signal line (default 9).
// The histogram is MACD minus signal, coloured by which side of zero it is on
new MACDStudy({
fast: 12,
slow: 26,
signal: 9,
bandOptions: { stroke: "#2ec4b6", strokeY1: "#ff9f1c", strokeThickness: 2 }, // MACD line, signal line
histogramAboveZero: "#26a69a",
histogramBelowZero: "#ef5350",
}),
],
}),
[]
);
// SciFinanceChartView fills its parent, so give the parent a height
return <SciFinanceChartView config={config} />;
}
Adding and Removing the MACD Indicator at Runtime
MACDStudy is a study like any other, so you can add it to a chart that is already showing, and remove it again:
import { EStudyType, MACDStudy, studyProvider } from "scichart-scitrader";
const chart = financeChartPanel.financeApi;
// Add one with your own settings...
const study = new MACDStudy();
await chart.attachStudy(study);
// ...or by type, with the default settings, e.g. from an indicator picker
await chart.attachStudy(studyProvider.getStudy(EStudyType.MACD));
// Remove it
chart.detachStudy(study);
See Add Technical Indicators to a Financial Chart for more, including a ready-made indicator picker.
MACDStudy Options and Settings
| Option | Default | What it does |
|---|---|---|
fast | 12 | Length of the fast EMA |
slow | 26 | Length of the slow EMA |
signal | 9 | Length of the signal line's EMA |
band | The theme's colours | The MACD and signal lines: stroke is the MACD line, stroke the signal line, and fill / fill shade between them |
column | (none) | The histogram's columns, e.g. data |
histogram, histogram | The theme's colours | The histogram's colours above and below zero |
pane | A new pane | The pane to draw in |
Users can change the same settings in the Settings Form, and you can change them from code with applyDescriptor. There, the MACD line colour is bandMacdColor and the signal line colour bandSignalColor:
| Study | Inputs | Styles |
|---|---|---|
MACDStudy | fast, slow, signal | histogram, histogram, band, band, fill, fill, stroke |
The MACDStudy class, with its TSDoc
class MACDStudy extends StudyBase<number> {
/** Indicator pane — small relative weight (price pane defaults to 3×). */
readonly paneSizeConfig: {
grow: number;
};
fast: number;
slow: number;
signal: number;
/**
* MACD output is a signal-EMA on top of the (slow EMA − fast EMA) line.
* The slow EMA needs `slow` inputs before it stabilises, and the signal
* EMA stacks `signal` more on top — so the first fully-valid signal
* value lands roughly at index `slow + signal - 1`. Returning
* `slow + signal` over-pads by one to keep the formula simple.
*/
getRequiredWarmup(): number;
readonly bandOptions: IBandRenderableSeriesOptions;
readonly columnOptions: IColumnRenderableSeriesOptions;
histogramAboveZero: string;
histogramBelowZero: string;
inputId: DataSourceId;
constructor(options?: IMACDOptions);
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): IMACDOptions;
/** Opts in to the in-place apply pipeline — see {@link onDescriptorApplied}. */
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
/**
* @inheritDoc
*
* The histogram flips about zero, so it takes the same `yValue >= 0` test
* {@link MacdHistogramPaletteProvider} paints the columns with.
*
* The two lines share one `XyyDataSeries`, filled as
* `appendRange(x, signalPadded, macdPadded)` — signal in Y, MACD in Y1. A band
* series paints Y with `stroke` and Y1 with `strokeY1`, so those are the strokes
* the legend reads, and the rows match the lines on screen.
*
* `stroke` paints y (MACD) and `strokeY1` paints y1 (Signal), matching what the
* two pickers are labelled. The band series used to be filled signal-first, which
* inverted both — the legend compensated by reading the opposite property, so the
* colours agreed with the pixels but neither agreed with the label.
*/
getLegendColor(outputId: DataSourceId, xIndex?: number): string | undefined;
createRenderableSeries(): IRenderableSeries[];
}
The IMACDOptions interface, with its TSDoc
interface IMACDOptions extends IStudyOptions {
inputId?: DataSourceId;
fast?: number;
slow?: number;
signal?: number;
bandOptions?: IBandRenderableSeriesOptions;
columnOptions?: IColumnRenderableSeriesOptions;
/** Histogram fill for bars above zero. Defaults to {@link DEFAULT_HISTOGRAM_ABOVE_ZERO}. */
histogramAboveZero?: string;
/** Histogram fill for bars below zero. Defaults to {@link DEFAULT_HISTOGRAM_BELOW_ZERO}. */
histogramBelowZero?: string;
}
Where to read next
- Add Technical Indicators to a Financial Chart: the other indicators, adding and removing indicators at runtime, and an indicator picker.
- Altering Study Settings: change an indicator's settings from code.
- Study Settings Form and Study List: let users edit them.