sbx-react-stock-chart
v3.5.56
Published
React stock chart component with candlestick/line/area/bars rendering, indicators, drawing tools, alerts, and a runtime API.
Readme
sbx-react-stock-chart
React stock chart component with candlestick/line/area/bars rendering, indicators, drawing tools, alerts, and a runtime API.
Installation
npm i sbx-react-stock-chartAlternative:
yarn add sbx-react-stock-chart
pnpm add sbx-react-stock-chartRequirements
react16.xreact-dom16.x- Browser environment (
window,document,requestAnimationFrame)
Quick Start
import React, { useRef, useState } from 'react';
import Chart from 'sbx-react-stock-chart';
const Feed = {
onFeeder(symbol, cb) {
// subscribe and call cb({ symbol, bid, ask, time, volume? })
},
offFeeder(symbol, cb) {
// unsubscribe
},
};
async function getHistory({ symbol, frame, count }) {
return {
data: [
// [open, high, low, close, volume, timeSec]
[1.081, 1.084, 1.079, 1.082, 1200, 1710000000],
[1.082, 1.085, 1.080, 1.084, 950, 1710014400],
],
};
}
export default function App() {
const chartRef = useRef(null);
const [assets, setAssets] = useState([
{
key: 'eurusd-main',
symbol: 'EURUSD',
digits: 5,
timeFrame: 4 * 60 * 60,
type: 'candle',
indicators: {},
drawing_tools: {},
orders: [],
alerts: [],
priceLabels: [],
},
]);
return (
<div style={{ height: 560 }}>
<Chart
ref={chartRef}
assets={assets}
feed={Feed}
getHistory={getHistory}
settings={{
hideTooltips: true,
showVolume: true,
showStats: false,
showPriceAlerts: true,
autoScale: false,
display: { contextMenu: true },
controls: { enable: true },
}}
onChange={(ctx) => {
if (ctx.event === 'change:timeFrame') {
setAssets((prev) =>
prev.map((a) => (a.key === ctx._id ? { ...a, timeFrame: ctx.data } : a))
);
}
}}
/>
</div>
);
}Component Props (Wrapper Export)
The package default export is the multi-asset wrapper component (src/Chart/chart-wrapper.jsx).
| Prop | Type | Required | Description |
|---|---|---|---|
| assets | Asset[] | yes | List of charts to render. Each asset is one chart tab/pane. |
| feed | { onFeeder, offFeeder } | yes | Real-time quote subscribe/unsubscribe adapter. |
| getHistory | (params) => Promise<{data: Candle[]}> | yes | Historical candles loader. |
| settings | ChartSettings | yes (practically) | Main configuration object (UI + rendering + style). |
| onChange | (ctx) => void | no | Main event callback. |
| tokens | Record<string, string> | no | UI localization overrides. |
| templates | { indicators?: any[] } | no | Indicator templates source for dropdown UI. |
| favorites | any[] | no | Favorite indicators list (used in UI). |
| containers | Array<{name, position, component, collapse?}> | no | Custom overlay widgets mounted on each chart box. |
| delta_width | number | no | Right-side future space (in chart coordinates). |
| timeFrame | number | no | Fallback timeframe in seconds (when not set in asset). |
| type | ChartType | no | Initial chart type override. |
| style | Record<string, string> | no | Custom named colors injected into chart color registry. |
| serverUTCTimeOffset | number | no | Seconds offset for grid/time labels. |
| mainPaneMask | {enable?: boolean, color?: string, opacity?: number} | no | Runtime main pane mask override. |
| license | string | no | License key used by built-in license check. |
| onMove | (ctx) => void | no | Passed through but currently not used by core logic. |
Data Contracts
Candle
type Candle = [open, high, low, close, volume, timeSec];Asset
type Asset = {
key: string;
symbol: string;
digits?: number;
timeFrame?: number; // seconds, e.g. 60 / 300 / 14400
type?: ChartType;
indicators?: Record<string, any>;
drawing_tools?: Record<string, any>;
orders?: Array<any>;
alerts?: Array<any>;
priceLabels?: Array<{ price: number; color: string }>;
};Feed
type Feed = {
onFeeder: (symbol: string, cb: (tick: Tick) => void) => void;
offFeeder: (symbol: string, cb: (tick: Tick) => void) => void;
};
type Tick = {
symbol: string;
bid: number;
ask?: number;
time: number; // unix sec
volume?: number;
};getHistory
type GetHistory = (params: {
symbol: string;
frame: number; // seconds
count: number;
}) => Promise<{ data: Candle[] }>;Full settings Reference
settings combines:
- wrapper/UI settings (controls panel, footer, visibility, menu)
- render engine settings (candles, grid, cursor, orders, etc.)
1) Wrapper/UI settings
| Key | Type | Description |
|---|---|---|
| hideTooltips | boolean | Hides tooltips in left controls. |
| display.contextMenu | boolean | Enables right-click chart context menu. |
| controls.enable | boolean | Enables/disables left controls bar. |
| controls.visible | string[] | Controls order/visibility allowlist. |
| controls.hidden | string[] | Controls denylist (removed from visible result). |
| indicators.visible | string[] | Indicator systemName allowlist in indicator picker. |
| indicators.hidden | string[] | Indicator denylist in indicator picker. |
| indicators.templates | boolean | Enables indicator templates save/load UI block. |
| drawingTools.visible | string[] | Drawing tool systemName allowlist. |
| drawingTools.hidden | string[] | Drawing tool denylist. |
| footer.enable | boolean | Enables bottom footer with preset periods. |
| footer.components | ReactComponent[] | Extra footer right-side components. |
| layout | React.CSSProperties | Applied to outer .chart-main container. |
controls.visible supported ids:
CHART_TYPETIME_FRAMEINDICATORSDT_LINESDT_FIBODT_POLYDT_GEOMETRYDT_TEXT_TOOLSHRZOOM_INZOOM_OUTZOOM_CENTERSCREEN_SHOT
2) Render engine settings (all supported keys)
type ChartSettings = {
// UI-level
hideTooltips?: boolean;
display?: {
contextMenu?: boolean;
};
controls?: {
enable?: boolean;
visible?: string[];
hidden?: string[];
};
indicators?: {
visible?: string[];
hidden?: string[];
templates?: boolean;
};
drawingTools?: {
visible?: string[];
hidden?: string[];
};
footer?: {
enable?: boolean;
components?: Array<any>;
};
layout?: Record<string, any>;
// Core render flags
showVolume?: boolean;
showStats?: boolean;
showPriceAlerts?: boolean;
autoScale?: boolean;
animation?: boolean;
showDeveloperLogo?: boolean;
orderOffset?: number;
currentPrice?: {
visible?: {
bid?: boolean;
middle?: boolean;
ask?: boolean;
};
};
volume?: {
enable?: boolean;
colors?: { up?: string; down?: string };
};
candles?: {
body?: { enable?: boolean; colors?: { up?: string; down?: string } };
border?: { enable?: boolean; colors?: { up?: string; down?: string } };
wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
};
columns?: {
body?: { enable?: boolean; colors?: { up?: string; down?: string } };
border?: { enable?: boolean; colors?: { up?: string; down?: string } };
wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
};
heiken?: {
body?: { enable?: boolean; colors?: { up?: string; down?: string } };
border?: { enable?: boolean; colors?: { up?: string; down?: string } };
wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
};
line?: {
stroke?: { enable?: boolean; color?: string; width?: number };
area?: { enable?: boolean; color?: string; opacity?: number };
};
baseline?: {
stroke?: {
enable?: boolean;
width?: number;
colors?: { up?: string; down?: string };
};
base?: {
color?: string;
width?: number;
opacity?: number;
};
area?: {
enable?: boolean;
opacity?: number;
colors?: { up?: string; down?: string };
};
};
bars?: {
width?: number;
openEnable?: boolean;
colors?: { up?: string; down?: string };
};
steps_line?: {
width?: number;
color?: string;
openEnable?: boolean; // supported in settings editor
};
high_low?: {
body?: { enable?: boolean; color?: string };
border?: { enable?: boolean; color?: string };
};
grid?: {
line?: {
enable?: boolean;
color?: string;
width?: number;
opacity?: number;
};
text?: {
enable?: boolean;
color?: string;
};
};
mainPaneMask?: {
enable?: boolean;
color?: string;
opacity?: number; // 0..1
};
orders?: {
line?: {
enable?: boolean;
color?: string;
width?: number;
opacity?: number;
};
text?: {
enable?: boolean;
color?: string;
};
badge?: {
borderColor?: string;
backgroundColor?: string;
};
};
cursor?: {
line?: {
color?: string;
width?: number;
opacity?: number;
dashed?: boolean;
dashInterval?: number;
};
badge?: {
borderColor?: string;
backgroundColor?: string;
};
};
offset?: {
top?: number;
bottom?: number;
};
assetLabel?: {
fill?: string;
};
};Default Engine Settings (from source)
This is the default core settings object from src/Chart/core/Main.js before merging your props.settings:
{
showVolume: false,
showStats: false,
showPriceAlerts: false,
autoScale: false,
animation: true,
orderOffset: 0,
currentPrice: { visible: { bid: true, middle: false, ask: false } },
volume: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
candles: {
body: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
border: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
wick: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
},
columns: {
body: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
border: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
wick: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
},
heiken: {
body: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
border: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
wick: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
},
line: {
stroke: { enable: true, color: '#2f3342', width: 2 },
area: { enable: true, color: '#57a1d0', opacity: 0.1 },
},
baseline: {
stroke: { enable: true, width: 2, colors: { up: '#26b276', down: '#f73e4a' } },
base: { color: '#1f222c', width: 1, opacity: 0.5 },
area: { enable: true, opacity: 0.12, colors: { up: '#26b276', down: '#f73e4a' } },
},
bars: { width: 4, openEnable: true, colors: { up: '#26b276', down: '#f73e4a' } },
steps_line: { width: 4, color: '#2862ff' },
high_low: {
body: { enable: true, color: '#2862ff' },
border: { enable: true, color: '#2862ff' },
},
grid: {
line: { enable: true, color: '#1f222c', width: 1, opacity: 0.2 },
text: { enable: true, color: '#2f3342' },
},
mainPaneMask: { enable: true, color: '#ffffff', opacity: 1 },
orders: {
line: { enable: true, color: '#1f222c', width: 1, opacity: 0.2 },
text: { enable: true, color: '#2f3342' },
badge: { borderColor: '#c9c9c9', backgroundColor: '#c9c9c9' },
},
cursor: {
line: { color: '#1f222c', width: 1, opacity: 0.8, dashed: true, dashInterval: 8 },
badge: { borderColor: '#c9c9c9', backgroundColor: '#c9c9c9' },
},
offset: { top: 10, bottom: 10 },
assetLabel: { fill: 'rgba(0, 0, 0, 0.3)' },
}Runtime API (chart.api)
const wrapper = chartRef.current;
const key = wrapper.state.activeChart;
const api = wrapper[`chart-${key}`].api;Methods
setSettings(obj, event?)getSettings(path)setColors(obj)setNewCandle({ frame, candle })_setNewCandle({ frame, bid, volume?, time })setNewQuote(q?)changeType(value)changeVerticalZoom(value)panVerticalByPixels(deltaPx)getIndicators()getIndicatorByKey(key)addIndicator(name, data)removeIndicator(name)removeIndicatorsAll()hideIndicator(name)initDrawingTools(data)getDrawingTools()addDrawingTools(data)addText(data?)updateText(key, patch)removeText(key)removeDrawingTools(data)removeDrawingToolsAll()setCount(count)setTimeline(time, count?)stopEvent()startEvent()addStopLoss()addTakeProfit()reloadChart(asset, digits, options?)zoomChart(val)goToTime({ time })setCenter()changeSymbol(asset)addOpenPositions(positions)switchChart(type='candle')setTime(time)drawArrow(type)toggleCrossTarget()panByCandles(delta)panToHistory(step=1)panToLatest(step=1)
Main onChange Events
chart:initialchart:activeChangechart:contextMenuchart:openOrderchart:priceAlerts:openchart:priceAlerts:removechange:timeFramechange:countchange:typechange:settingschange:indicatorsfavorites:addfavorites:delete
Chart Type Values
candlelineareabarsheiken_ashihigh_lowcolumnsline_stepbaseline
Local Development
npm run dev
npm run build
npm run build_packageAuthors
- Viktor Semenov
- Vladislav Fisher
Copyright (c) 2017-2026 ScaleTrade & AlfaLabs Group LLC
