As I was typing out the question I found the solution, it was a shared sandbox by 'cerchio-pixel' that I implemented and it worked in my project.
Link to the codesandbox
Here is the React component for implementing the Financial Chart below for quick reference:
import React from "react";
import { format } from "d3-format";
import { timeFormat } from "d3-time-format";
import {
elderRay,
ema,
discontinuousTimeScaleProviderBuilder,
Chart,
ChartCanvas,
CurrentCoordinate,
BarSeries,
CandlestickSeries,
ElderRaySeries,
LineSeries,
MovingAverageTooltip,
OHLCTooltip,
SingleValueTooltip,
lastVisibleItemBasedZoomAnchor,
XAxis,
YAxis,
CrossHairCursor,
EdgeIndicator,
MouseCoordinateX,
MouseCoordinateY,
ZoomButtons,
withDeviceRatio,
withSize,
} from "react-financial-charts";
import { initialData } from "./data/data";
const Stonk = () => {
const ScaleProvider =
discontinuousTimeScaleProviderBuilder().inputDateAccessor(
(d) => new Date(d.date)
);
const height = 700;
const width = 900;
const margin = { left: 0, right: 48, top: 0, bottom: 24 };
const ema12 = ema()
.id(1)
.options({ windowSize: 12 })
.merge((d, c) => {
d.ema12 = c;
})
.accessor((d) => d.ema12);
const ema26 = ema()
.id(2)
.options({ windowSize: 26 })
.merge((d, c) => {
d.ema26 = c;
})
.accessor((d) => d.ema26);
const elder = elderRay();
const calculatedData = elder(ema26(ema12(initialData)));
const { data, xScale, xAccessor, displayXAccessor } =
ScaleProvider(initialData);
const pricesDisplayFormat = format(".2f");
const max = xAccessor(data[data.length - 1]);
const min = xAccessor(data[Math.max(0, data.length - 100)]);
const xExtents = [min, max + 5];
const gridHeight = height - margin.top - margin.bottom;
const elderRayHeight = 100;
const elderRayOrigin = (_, h) => [0, h - elderRayHeight];
const barChartHeight = gridHeight / 4;
const barChartOrigin = (_, h) => [0, h - barChartHeight - elderRayHeight];
const chartHeight = gridHeight - elderRayHeight;
const yExtents = (data) => {
return [data.high, data.low];
};
const dateTimeFormat = "%d %b";
const timeDisplayFormat = timeFormat(dateTimeFormat);
const barChartExtents = (data) => {
return data.volume;
};
const candleChartExtents = (data) => {
return [data.high, data.low];
};
const yEdgeIndicator = (data) => {
return data.close;
};
const volumeColor = (data) => {
return data.close > data.open
? "rgba(38, 166, 154, 0.3)"
: "rgba(239, 83, 80, 0.3)";
};
const volumeSeries = (data) => {
return data.volume;
};
const openCloseColor = (data) => {
return data.close > data.open ? "#26a69a" : "#ef5350";
};
return (
<ChartCanvas
height={height}
ratio={3}
width={width}
margin={margin}
data={data}
displayXAccessor={displayXAccessor}
seriesName="Data"
xScale={xScale}
xAccessor={xAccessor}
xExtents={xExtents}
zoomAnchor={lastVisibleItemBasedZoomAnchor}
>
<Chart
id={2}
height={barChartHeight}
origin={barChartOrigin}
yExtents={barChartExtents}
>
<BarSeries fillStyle={volumeColor} yAccessor={volumeSeries} />
</Chart>
<Chart id={3} height={chartHeight} yExtents={candleChartExtents}>
<XAxis showGridLines showTickLabel={false} />
<YAxis showGridLines tickFormat={pricesDisplayFormat} />
<CandlestickSeries />
<LineSeries yAccessor={ema26.accessor()} strokeStyle={ema26.stroke()} />
<CurrentCoordinate
yAccessor={ema26.accessor()}
fillStyle={ema26.stroke()}
/>
<LineSeries yAccessor={ema12.accessor()} strokeStyle={ema12.stroke()} />
<CurrentCoordinate
yAccessor={ema12.accessor()}
fillStyle={ema12.stroke()}
/>
<MouseCoordinateY
rectWidth={margin.right}
displayFormat={pricesDisplayFormat}
/>
<EdgeIndicator
itemType="last"
rectWidth={margin.right}
fill={openCloseColor}
lineStroke={openCloseColor}
displayFormat={pricesDisplayFormat}
yAccessor={yEdgeIndicator}
/>
<MovingAverageTooltip
origin={[8, 24]}
options={[
{
yAccessor: ema26.accessor(),
type: "EMA",
stroke: ema26.stroke(),
windowSize: ema26.options().windowSize,
},
{
yAccessor: ema12.accessor(),
type: "EMA",
stroke: ema12.stroke(),
windowSize: ema12.options().windowSize,
},
]}
/>
<ZoomButtons />
<OHLCTooltip origin={[8, 16]} />
</Chart>
<Chart
id={4}
height={elderRayHeight}
yExtents={[0, elder.accessor()]}
origin={elderRayOrigin}
padding={{ top: 8, bottom: 8 }}
>
<XAxis showGridLines gridLinesStrokeStyle="#e0e3eb" />
<YAxis ticks={4} tickFormat={pricesDisplayFormat} />
<MouseCoordinateX displayFormat={timeDisplayFormat} />
<MouseCoordinateY
rectWidth={margin.right}
displayFormat={pricesDisplayFormat}
/>
<ElderRaySeries yAccessor={elder.accessor()} />
<SingleValueTooltip
yAccessor={elder.accessor()}
yLabel="Elder Ray"
yDisplayFormat={(d) =>
`${pricesDisplayFormat(d.bullPower)}, ${pricesDisplayFormat(
d.bearPower
)}`
}
origin={[8, 16]}
/>
</Chart>
<CrossHairCursor />
</ChartCanvas>
);
};
export default Stonk;
where the data.js file is as follows:
export let initialData = [
{
date: "2021-02-02 16:00:00",
open: 134.9307,
low: 134.9105,
high: 135.4215,
close: 135.0087,
volume: 73591581
},
{
date: "2021-02-02 15:45:00",
open: 134.9707,
low: 134.9307,
high: 134.9707,
close: 134.9307,
volume: 67639193
},
{
date: "2021-02-02 15:30:00",
open: 134.6608,
low: 134.6608,
high: 134.975,
close: 134.975,
volume: 64815258
},
{
date: "2021-02-02 15:15:00",
open: 134.8585,
low: 134.6237,
high: 134.9716,
close: 134.6608,
volume: 62892896
},
{
date: "2021-02-02 15:00:00",
open: 134.985,
low: 134.78,
high: 135.0,
close: 134.8585,
volume: 60880828
},
]
I added the files above and imported the component elsewhere in my project and it worked just as expected. I may have been missing something very obvious and/or didn't have enough documentation to read on how to implement the library but hopefully this helps someone else who could not find enough resources on how to implement it and was searching the Q&A, now they'll have a StackOverflow search result. Happy Hacking!