Interactive JavaScript Financial Charting Library – FCS Chart

Category: Chart & Graph , Javascript | October 27, 2026
Authorfcsapi
Last UpdateOctober 27, 2026
LicenseMIT
Tags
Views0 views
Interactive JavaScript Financial Charting Library – FCS Chart

stioFCS Chart is a vanilla JavaScript financial charting library for interactive Forex, cryptocurrency, and stock market charts.

It includes nine chart types, technical indicators, drawing tools, and historical replay for web-based market analysis.

It loads historical candles through FCS API and can stream live price updates through WebSocket. Historical data limits and WebSocket access depend on FCS API credentials.

Features

  • Candlestick, OHLC, line, area, Heikin-Ashi, Renko, and other financial chart views.
  • Over 60 technical indicators, including RSI, MACD, moving averages, and Bollinger Bands.
  • Trendlines, Fibonacci tools, patterns, shapes, and text annotations.
  • Up to four charts in a shared layout, with separate symbols and timeframes.
  • Historical replay and screenshot export.
  • Dark and light themes, chart-only display, and configurable toolbars.
  • Symbol search filters for markets, exchanges, and individual assets.
  • Programmatic price lines, trade markers, and configurable broker ask/bid quotes.
  • Chart settings, templates, and drawing undo/redo controls.

How To Use It

Installation

Load the stylesheet and core JavaScript from a CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.css">
<script src="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.js"></script>

Basic Usage

Create two nested elements and set a height on the outer container. This example uses the free chart with no API key, which limits history to 300 candles and displays provider branding.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bitcoin Price Chart</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.css">
  <style>
    #fcs_chartparent { width: 100%; height: 520px; }
  </style>
</head>
<body>
  <div id="fcs_chartparent">
    <div id="fcs_chart"></div>
  </div>
  <script src="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.js"></script>
  <script>
    const chart = new FCSAPIChart({
      container: document.getElementById('fcs_chart'),
      parentid: 'fcs_chartparent',
      symbol: 'BINANCE:BTCUSDT',
      period: '1H',
      theme: 'dark',
      enableCache: false
    });
  </script>
</body>
</html>

Authenticate Market Data Requests

The free chart needs no credentials. For a deployed application, use an FCS API credential that matches your account and domain policy.

A domain-restricted publicKey is suitable for browser use when you configure Allowed Domains in the FCS API dashboard.

Use this initializer in place of the one in Basic Usage. Keep the HTML containers, stylesheet and script from that example.

const chart = new FCSAPIChart({
  container: document.getElementById('fcs_chart'),
  parentid: 'fcs_chartparent',
  publicKey: 'YOUR_PUBLIC_KEY',
  symbol: 'BINANCE:BTCUSDT',
  period: '1H',
  enableCache: false
});

The core constructor accepts four authentication configurations: an accessKey alone, a domain-restricted publicKey alone, both keys together, or a jwt_token alone. Supplying both keys hides the access key from network requests, not from page source. A server-issued JWT keeps the access key on your server and expires after a configured interval.

For JWT authentication, implement /api/chart-jwt on your own server. Its server-side request to https://api-v4.fcsapi.com/forex/jwt_token must include your private access_key and an expiry in seconds; the optional domain parameter can restrict the token to your site. Return the FCS response with status, response.jwt_token and response.expires_in to the browser. Never expose that upstream URL with your private access key in client-side code.

The following replaces the Basic Usage initializer. It obtains the first token before creating the chart and renews it for subsequent data requests. Call the returned dispose() when removing the chart.

async function mountSecureChart() {
  async function getToken() {
    const response = await fetch('/api/chart-jwt', {
      credentials: 'same-origin'
    });
    if (!response.ok) throw new Error('Token endpoint failed');
    const result = await response.json();
    const token = result.response?.jwt_token;
    const expiresIn = Number(result.response?.expires_in);
    if (!result.status || !token || !(expiresIn > 0)) {
      throw new Error(result.msg || 'Invalid token response');
    }
    return { token, expiresIn };
  }
  const first = await getToken();
  const chart = new FCSAPIChart({
    container: document.getElementById('fcs_chart'),
    parentid: 'fcs_chartparent',
    jwt_token: first.token,
    symbol: 'BINANCE:BTCUSDT',
    enableCache: false
  });
  let timerId;
  let disposed = false;
  function schedule(seconds) {
    timerId = setTimeout(renew, Math.max(10, seconds - 30) * 1000);
  }
  async function renew() {
    try {
      const next = await getToken();
      if (disposed) return;
      chart.updateJWTtoken(next.token);
      schedule(next.expiresIn);
    } catch (error) {
      console.error('Chart token refresh failed:', error);
      if (!disposed) timerId = setTimeout(renew, 10000);
    }
  }
  schedule(first.expiresIn);
  return {
    chart,
    dispose() {
      disposed = true;
      clearTimeout(timerId);
      chart.destroy();
    }
  };
}
mountSecureChart().catch(console.error);

Enable Live Market Updates

WebSocket updates require streaming access in addition to historical market data access. Supply your socketApiKey and keep enableSocket: true. This initializer uses a domain-restricted public key for the historical API; configure the keys for your FCS API account before using it.

const chart = new FCSAPIChart({
  container: document.getElementById('fcs_chart'),
  parentid: 'fcs_chartparent',
  publicKey: 'YOUR_PUBLIC_KEY',
  socketApiKey: 'YOUR_SOCKET_KEY',
  enableSocket: true,
  symbol: 'BINANCE:BTCUSDT',
  period: '1m',
  enableCache: false
});

Display a Compact Chart

displayMode: 'chartonly' hides the chart controls for article embeds and small market widgets.

const compactChart = new FCSAPIChart({
  container: document.getElementById('fcs_chart'),
  parentid: 'fcs_chartparent',
  symbol: 'NASDAQ:AAPL',
  period: '1D',
  displayMode: 'chartonly',
  enableCache: false
});

Limit Symbol Search

Restrict the symbol picker to the exchanges and assets available in your application.

const chart = new FCSAPIChart({
  container: document.getElementById('fcs_chart'),
  parentid: 'fcs_chartparent',
  symbol: 'BINANCE:BTCUSDT',
  enableCache: false,
  searchModalTabs: { fav: 'Favorites', crypto: 'Crypto' },
  searchAllowSymbols: ['BINANCE:BTCUSDT', 'BINANCE:ETHUSDT'],
  searchExcludeSymbols: ['BINANCE:DOGEUSDT'],
  searchAllowExchanges: { crypto: ['BINANCE'] },
  hideExchangeInOHLC: true
});

Display Indicators and Trade Markers

Use the chart instance from Basic Usage after its initial data has loaded. Place the button before the closing </body> tag, and add the event listener after chart initialization. addIndicator() returns a Promise resolving to an indicator ID or null for an unknown type.

<button id="add-rsi" type="button">Add RSI</button>
document.getElementById('add-rsi').addEventListener('click', async () => {
  const indicatorId = await chart.addIndicator({
    type: 'Rsi',
    length: 14
  });
  console.log('Indicator ID:', indicatorId);
});

Trade markers use a timestamp in Unix seconds (or a candle index) and a price from the loaded series. Substitute the correct candle timestamp and price for your data.

chart.addMarker({
  timestamp: 1791388800,
  price: 85200,
  type: 'buy',
  text: 'Entry',
  id: 'trade-entry-1'
});

Set Broker Price Lines and Spreads

Horizontal lines can mark take-profit, stop-loss, and entry levels. addHorizontalLine() returns a Promise resolving to the line ID. Use prices within the range of the symbol you are displaying.

async function addTradeLevels() {
  const takeProfitId = await chart.addHorizontalLine({
    price: 46000,
    label: 'Take Profit',
    color: '#16a34a',
    style: 'dashed'
  });
  chart.updateHorizontalLine(takeProfitId, { price: 47000 });
  return takeProfitId;
}

A broker spread changes the displayed ask and bid lines, not the underlying candles. For spreadPips, the value applies to each side of the quote. A value of 10 produces a total gap of 20 pips around a close-price base.

chart.setAskBid({
  base: 'close',
  spreadPips: 10,
  perSymbol: {
    'BINANCE:BTCUSDT': { spreadPips: 15 }
  }
});
// Restore the raw market quote.
chart.setAskBid(null);

Configuration Options

Containers, Data, and Authentication

OptionDescription
containerRequired. Inner chart DOM element.
parentidRequired. ID of the outer chart container.
accessKeyPrivate REST API key; browser code exposes it in the page source.
publicKeyPublic key restricted through Allowed Domains; it can be used alone or alongside accessKey.
jwt_tokenShort-lived FCS API JWT used alone, refreshed with updateJWTtoken() before expiry.
socketApiKeySeparate WebSocket API key for live market updates.
socketUrlCustom WebSocket endpoint URL.
url_paramsExtra key-value query parameters sent with API requests; cannot replace authentication or reserved chart parameters.
symbolInitial EXCHANGE:SYMBOL; default BINANCE:BTCUSDT.
periodInitial timeframe; default 1D.
lengthRequested number of candles; default 600, subject to plan limits (free chart: 300).
enableCacheSaves recent chart preferences in localStorage; default true.
changeURLUpdates the page URL with the chart’s symbol/period; default false.
enableSocketEnables live price updates when a Socket Key is available; default true.

Appearance and Layout

OptionDescription
displayModenormal (default) for full controls, or chartonly for an embed.
themelight (default) or dark.
defaultChartTypeInitial chart type; default candlestick. See chart types below.
timezonelocal (default), UTC, or an offset such as +05:00.
enableSidebarDrawing-tool sidebar; default true.
enableToolbarTop toolbar; default true.
enableRangeSelectorBottom range selector; default true.
enableSearchSymbol search control; default true.
enableIndicatorsIndicator selection control; default true.
enableMultiChartMulti-chart layout selector; default true.
enableReplayHistorical replay control; default true.
enableCaptureScreenshot/export control; default true.
enableUndoRedoDrawing undo and redo buttons; default true.
enableTemplatesChart template save/load controls; default true.
enableSettingsChart settings control; default true.
enableSymbolInfoSymbol information panel; default true.
enableChartTypeSelectorChart type selector; default true.
enableTimeframeSelectorTimeframe selector; default true.

Search and Market Labels

OptionDescription
searchModalTabsObject mapping visible tab keys to labels; default null (all categories).
searchAllowSymbolsArray of allowed symbol IDs; default null (unrestricted).
searchExcludeSymbolsArray of blocked symbol IDs; default null.
searchAllowExchangesExchange restrictions by market tab; default null.
hideExchangeAllPlacesHides exchange names throughout search and chart information; default false.
hideExchangeInOHLCHides exchange names only from the OHLC legend; default false.

Search tab keys: fav, all, forex, crypto, commodity, stock, dr, fund, futures, indices, dex. For searchAllowExchanges, exchange-based tabs such as crypto, forex, and dex accept arrays. Country-based tabs such as stock, fund, dr, and indices accept objects like { US: ['NASDAQ'], PK: '*' }.

Chart Controls and Drawing

OptionDescription
enableContextMenuChart right-click menu; default true.
enableDrawingToolsDrawing and annotation tools; default true.
enableGridBackground grid; default true.
enableCrosshairHover crosshair; default true.
enableCrosshairLabelsPrice/time labels on crosshair axes; default true.
enablePriceLineLatest-price line and label; default true.
enableCountdownCountdown under the latest-price label; default true.
enableAskBidLinesAsk/bid lines; default false. A live feed requires WebSocket access.
enableAskPriceLabelsAsk labels on the price axis; default true.
enableBidPriceLabelsBid labels on the price axis; default true.
enableHighLowLabelsHigh/low labels for the visible data; default true.
enableIndicatorLabelsIndicator names on chart panels; default true.
enableOHLCBarOHLC legend; default true.
indicatorPanelBgColorIndicator-panel background; default null (theme color).
autoScaleFits the vertical price scale to visible data; default true.
logScaleLogarithmic price scale; default false.
defaultMagnetModeSnaps drawing points to candle OHLC values; default false.
askBidSpread and markup configuration; default null (raw quote).
askLabelColorCustom ask-price label color (hex value).
bidLabelColorCustom bid-price label color (hex value).
lastPriceLabelColorLatest-price label color; null uses the candle color.

`askBid` Fields

The option accepts a spread/markup object. It only changes the quote lines and labels. Direct price-unit fields take precedence over pips, which take precedence over percent when several units are supplied for one adjustment.

FieldDescription
basefeed (default) uses market ask/bid; close uses the candle close; raw disables adjustment.
spreadPipsAdds/subtracts pips per side; default 0.
spreadPercentFraction of the price per side; default 0 (0.01 means 1%).
spreadAbsolute price adjustment per side; default 0.
markupPipsShifts both sides by the given pips; default 0.
markupPercentPrice-fraction markup applied to both sides; default 0.
markupAbsolute-price markup applied to both sides; default 0.
perSymbolOverrides top-level rules for individual EXCHANGE:SYMBOL IDs; default {}.

Symbol Formats

MarketExample
ForexFX:EURUSD
CryptocurrencyBINANCE:BTCUSDT
StocksNASDAQ:AAPL

Supported Chart Types

ValueDisplay
candlestickStandard candlestick bodies and wicks.
barsOpen-high-low-close bars.
lineClose-price line.
areaFilled area beneath a line.
hollowHollow candles.
heikin-ashiAveraged Heikin-Ashi candles.
high-lowHigh/low price ranges.
volume-candlesCandles with volume-based widths.
renkoPrice-movement bricks.

Supported Timeframes

CategoryValues
Minutes1m, 2m, 3m, 5m, 10m, 15m, 30m
Hours1H, 2H, 4H, 6H, 8H, 12H
Daily / longer1D, 1W, 1M

API Methods

// Markets, timeframe, and appearance.
chart.setSymbol('NASDAQ:AAPL');          // Display another symbol.
chart.setPeriod('4H');                   // Switch to a four-hour period.
chart.setTheme('light');                 // Change dark/light theme.
chart.setChartType('line');              // Change chart representation.
// Quotes, indicators, and markers.
chart.setAskBid({ base: 'close', spreadPips: 10 }); // Change ask/bid rule; null resets it.
const indicatorId = await chart.addIndicator({ type: 'Sma', len: 20 }); // Promise: indicator ID or null.
chart.removeIndicator(indicatorId);      // Remove an indicator by ID.
chart.addMarker({ timestamp: 1791388800, price: 85200, type: 'buy', id: 'buy-1' }); // Mark a candle.
chart.removeMarker('buy-1');             // Remove marker by ID or list position.
chart.clearMarkers();                    // Remove all trade markers.
// Programmatic horizontal lines.
const lineId = await chart.addHorizontalLine({ price: 45000, label: 'TP' }); // Promise: line ID.
chart.updateHorizontalLine(lineId, { price: 46000 }); // Change one line's properties.
chart.removeHorizontalLine(lineId);      // Remove one line by ID.
const lines = chart.getHorizontalLines(); // Array of programmatic lines.
const removedCount = chart.clearHorizontalLines(); // Number of removed lines.
// Export, authentication, and lifecycle.
const pngDataUrl = chart.exportImage();  // Base64 PNG data URL for image/download.
chart.updateJWTtoken('FRESH_JWT');       // Replace an expiring JWT.
chart.resize();                          // Recalculate dimensions after a size change.
chart.destroy();                         // Release DOM, listeners, socket, and other resources.

Indicator Input Examples

addIndicator({ type, ...inputs }) accepts a type and that study’s parameter names.

IndicatorInput properties
Smalen, outColor
Emalength1, length2, length3
Rsilength
Bblength, mult
Macdfast_length, slow_length, signal_length

Marker Fields

addMarker() accepts an object describing a marker on a candle.

FieldDescription
timestampCandle Unix timestamp in seconds, or a candle index.
pricePrice at which to place the marker.
typeMarker style, such as buy, sell, long, short, entry, exit, tp, sl, arrow-up, arrow-down, star, or flag.
colorMarker color.
textMarker label.
idIdentifier for later removal.

Horizontal Line Options

addHorizontalLine(options) returns a Promise for the ID. updateHorizontalLine(id, options) changes existing line properties.

OptionDescription
priceRequired numeric line price.
colorHex color; default #ff6d00.
labelText next to the line; default empty string.
stylesolid (default) or dashed.
lineWidthLine width in pixels; default 2.
textPositionabove-left, above-center (default), above-right, below-left, below-center, or below-right.
textColorLabel color; default #ffffff.
textSizeLabel font size; default 12.
idOptional custom identifier; generated automatically when omitted.

Alternatives

You Might Be Interested In:


Leave a Reply