Moving Averages (SMA, EMA, WMA) in a JavaScript or React Financial Chart
Moving averages smooth price into a line, so the trend is easier to see. SciTrader.js has three: the SMA (simple), the EMA (exponential) and the WMA (weighted). This page explains what each is, how each is calculated and how traders use them, and shows how to add moving averages to a JavaScript or React financial chart with SciTrader.js, with live examples you can edit in CodePen.
The SMA, EMA and WMA are three 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 a Moving Average?
A moving average is the average close over the last length candles, recalculated at every candle, so it "moves" along the chart. It follows price with a lag: the longer the length, the smoother the line and the later it turns.
The three differ in how they weight the candles in the window:
| Moving average | Class | Weights | Reacts to new prices |
|---|---|---|---|
| SMA: Simple Moving Average | SMAStudy | Every candle equally | Slowest |
| WMA: Weighted Moving Average | WMAStudy | Linearly: the newest most, the oldest least | Faster |
| EMA: Exponential Moving Average | EMAStudy | Exponentially, with older candles never quite dropping out | Faster than the SMA, smooth |
Moving averages are prices, so a chart draws them on the price pane, over the candles.
How Are Moving Averages Calculated?
Each uses the last closes, where is length, 14 by default; is the newest.
SMA: Simple Moving Average. The plain average:
WMA: Weighted Moving Average. Weights , from the oldest close to the newest, divided by the sum of the weights:
EMA: Exponential Moving Average. Each value moves part of the way from the previous EMA towards the latest close. The first value is the SMA of the first closes:
With , is about 0.095: each new close moves the EMA about 9.5% of the way towards it.
Each line starts after length candles. SciTrader loads that many extra candles to the left of the visible period, so the lines start at the left edge.
How to Use Moving Averages
These are the common uses. They are conventions traders use, not signals that hold every time:
- Trend direction. Price above a rising moving average suggests an uptrend; below a falling one, a downtrend.
- Crossovers. A faster average crossing above a slower one is read as bullish, and below as bearish. With the 50- and 200-candle SMAs on a daily chart, these are known as the golden cross and death cross.
- Support and resistance. In a trend, pullbacks often stall near a well-watched average, such as the 20 EMA or the 50 SMA.
- Choosing one. The EMA and WMA turn sooner, but give more false signals in choppy markets; the SMA is steadier, but later.
How to Add Moving Averages to a JavaScript Financial Chart
Add SMAStudy, EMAStudy and WMAStudy to the chart's studies, one for each line. The example below is a daily BTC-USD chart from Coinbase over a year, with a 50-day SMA in amber, a 20-day EMA in teal and a 10-day WMA in purple.
The code for this example is found below.
- TS
import "scichart-scitrader/scitrader.css";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
EMAStudy,
idbPriceStore,
OHLCStudy,
SciFinanceChartPanel,
SMAStudy,
VolumeStudy,
WMAStudy,
} 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: "BTC-USD",
interval: CandleInterval.ONE_DAY,
period: "1Y",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// Moving averages are overlays: they draw on the price pane, against the price axis.
// length: the number of candles averaged (default 14). Give each its own colour
new SMAStudy({ length: 50, renderOptions: { stroke: "#ff9f1c", strokeThickness: 2 } }), // simple: equal weights
new EMAStudy({ length: 20, renderOptions: { stroke: "#2ec4b6", strokeThickness: 2 } }), // exponential
new WMAStudy({ length: 10, renderOptions: { stroke: "#e056fd", strokeThickness: 2 } }), // weighted: linear
],
});
// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}
createChart();
How to Add Moving Averages 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,
EMAStudy,
idbPriceStore,
ISciFinanceChartPanelConfig,
OHLCStudy,
SMAStudy,
VolumeStudy,
WMAStudy,
} from "scichart-scitrader";
import { SciFinanceChartView } from "scichart-scitrader-react";
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
export function MovingAveragesChart() {
// 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: "BTC-USD",
interval: CandleInterval.ONE_DAY,
period: "1Y",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// Moving averages are overlays: they draw on the price pane, against the price axis.
// length: the number of candles averaged (default 14). Give each its own colour
new SMAStudy({ length: 50, renderOptions: { stroke: "#ff9f1c", strokeThickness: 2 } }), // simple: equal weights
new EMAStudy({ length: 20, renderOptions: { stroke: "#2ec4b6", strokeThickness: 2 } }), // exponential
new WMAStudy({ length: 10, renderOptions: { stroke: "#e056fd", strokeThickness: 2 } }), // weighted: linear
],
}),
[]
);
// SciFinanceChartView fills its parent, so give the parent a height
return <SciFinanceChartView config={config} />;
}
Adding and Removing Moving Averages at Runtime
SMAStudy, EMAStudy and WMAStudy are studies like any other, so you can add them to a chart that is already showing, and remove them again:
import { EMAStudy, EStudyType, SMAStudy, studyProvider } from "scichart-scitrader";
const chart = financeChartPanel.financeApi;
// Add a 200-day SMA, e.g. for a golden cross with the 50-day SMA
const sma200 = new SMAStudy({ length: 200, renderOptions: { stroke: "#ef5350" } });
await chart.attachStudy(sma200);
// Add an EMA by type, with the default settings, e.g. from an indicator picker
await chart.attachStudy(studyProvider.getStudy(EStudyType.EMA));
// Remove the 200-day SMA
chart.detachStudy(sma200);
See Add Technical Indicators to a Financial Chart for more, including a ready-made indicator picker.
SMAStudy, EMAStudy and WMAStudy Options and Settings
The three take the same options:
| Option | Default | What it does |
|---|---|---|
length | 14 | The number of candles averaged |
render | The theme's colours | The line: stroke, stroke, stroke |
pane | The price 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, length is named period:
| Study | Inputs | Styles |
|---|---|---|
SMAStudy | period | stroke, stroke, stroke |
EMAStudy | period | stroke, stroke, stroke |
WMAStudy | period | stroke, stroke, stroke |
The SMAStudy, EMAStudy and WMAStudy classes, with their TSDoc
class SMAStudy extends StudyBase<number> {
length: number;
readonly renderOptions: IFastLineRenderableSeriesOptions;
getRequiredWarmup(): number;
constructor(options?: ISMAOptions);
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): ISMAOptions;
/** Opts in to the in-place apply pipeline — see {@link onDescriptorApplied}. */
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
createRenderableSeries(): FastLineRenderableSeries[];
}
/**
* Exponential Moving Average overlay. Shares the price pane's y-axis (like
* SMA) and follows the canonical Close-only line-study pattern.
*/
class EMAStudy extends StudyBase<number> {
length: number;
readonly renderOptions: IFastLineRenderableSeriesOptions;
getRequiredWarmup(): number;
constructor(options?: IEMAOptions);
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): IEMAOptions;
/** Opts in to the in-place apply pipeline — see {@link onDescriptorApplied}. */
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
createRenderableSeries(): FastLineRenderableSeries[];
}
/**
* Weighted Moving Average overlay. Shares the price pane's y-axis and follows
* the canonical Close-only line-study pattern (identical to {@link EMAStudy}
* but using the `WMA` calculator and a distinct default stroke).
*/
class WMAStudy extends StudyBase<number> {
length: number;
readonly renderOptions: IFastLineRenderableSeriesOptions;
getRequiredWarmup(): number;
constructor(options?: IWMAOptions);
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): IWMAOptions;
/** Opts in to the in-place apply pipeline — see {@link onDescriptorApplied}. */
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
createRenderableSeries(): FastLineRenderableSeries[];
}
The ISMAOptions, IEMAOptions and IWMAOptions interfaces, with their TSDoc
interface ISMAOptions extends IStudyOptions {
inputId?: DataSourceId;
length?: number;
renderOptions?: IFastLineRenderableSeriesOptions;
}
interface IEMAOptions extends IStudyOptions {
inputId?: DataSourceId;
length?: number;
renderOptions?: IFastLineRenderableSeriesOptions;
}
interface IWMAOptions extends IStudyOptions {
inputId?: DataSourceId;
length?: number;
renderOptions?: IFastLineRenderableSeriesOptions;
}
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.