Quick Start
First off
If you haven't installed Depth yet, Install Depth
After installing
The installation already sets up a chart, this will go through setting up your own data adapter
Create a new file
Create a file, you could call it myDataAdapter.ts or whatever you like
Creating the class
Start by importing the types you'll need
myDataAdapter.ts
import type { IDataAdapter, SymbolInfo, OhlcvBar } from '@christtrade/depth';Then create a class implementing IDataAdapter
myDataAdapter.ts
export class MyAdapter implements IDataAdapter {
}You'll get errors complaining that some functions aren't implemented, which will be fixed in the next step
Finalizing the class
First, add an array containing all your symbols.
If you need to get symbols from some api (or anything else that needs to be prepared), add connect() and do that there -
its an optional function, for this guide, we won't need it - but if you want to use it you can
Example:
myDataAdapter.ts
private symbols: SymbolInfo[] = []
async connect():Promise<void> {
this.symbols = await fetch('/api/symbols')
//all other preparing you need to do...
}For this tutorial, we'll keep it simple with a static array.
myDataAdapter.ts
private readonly symbols: SymbolInfo[] = [
{
symbol: '/NQ1',
description: 'Nasdaq 100 E-mini Futures (Front Cont.)',
exchange: 'CME',
dataLevel: 'ohlcv',
type: 'future',
supportedResolutions: [
1_000_000_000n, // 1 second in ns
60n * 1_000_000_000n, // 1 minute
60n * 60n * 1_000_000_000n, // 1 hour
24n * 60n * 60n * 1_000_000_000n, // 1 day
],
priceFormat: {
precision: 2,
minTick: 0.25,
},
contract: {
multiplier: 20,
currency: 'USD',
continuous: true,
},
session: {
hours: '1800-1700',
timezone: 'America/New_York',
days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu'],
holidays: [],
corrections: [],
}
}
];If you're thinking this might be a lot, you should read SymbolInfo for help setting up the correct config for your symbol!
Then we'll start implementing the IDataAdapter required functions:
Starting off with resolveSymbol():
myDataAdapter.ts
resolveSymbol(symbol: string): SymbolInfo | Promise<SymbolInfo> {
return this.symbols.find((s) => s.symbol.toLowerCase() === symbol.toLowerCase());
}Then searchSymbols(), which fills the symbol picker:
myDataAdapter.ts
async searchSymbols(): Promise<SymbolInfo[]> {
return this.symbols;
}Hand back the list and the chart will match, rank, and page it for you.
You can also add a list of keywords to a symbol's SymbolInfo (for example: keywords: ['gold', 'bullion'])
and it becomes findable by those words too.
Matching is word-anchored and fuzzy. A query matches the start of the ticker, the start of any
word in the name or keywords, or as a run of characters anchored to one of those starts
(ehusdt finds ethusdt, crdano, finds Cardano etc). You can read more about how it works
in the source code. Just know that it will find the symbol you're searching for.
If the amount of symbols you got is too big to ship to the browser, or you just want to take control,
take the request argument and search it yourself. Make sure to say so in getCapabilities():
myDataAdapter.ts
async searchSymbols(request: SymbolSearchRequest): Promise<SymbolSearchResponse> {
const res = await fetch(
`/api/symbols?q=${encodeURIComponent(request.query)}&limit=${request.limit ?? 50}`,
{ signal: request.signal },
);
const { symbols, nextCursor } = await res.json();
return { symbols, hasMore: !!nextCursor, cursor: nextCursor };
}
getCapabilities(): AdapterCapabilities {
return { symbolSearch: 'server' };
}The chart then debounces keystrokes, aborts superseded requests, and drops any answer that arrives after a newer one.
The debounce defaults to 200ms for 'server' and 0 for 'none'. If you
declare 'server' only to do your own matching over a list you already hold
in memory, turn the wait off.. it buys nothing and the picker feels slow
with it:
getCapabilities(): AdapterCapabilities {
return { symbolSearch: 'server', symbolSearchDebounceMs: 0 };
}Lastly fetchBars():
myDataAdapter.ts
async fetchBars(request: FetchRequest): Promise<BarResponse[]> {
const { symbolInfo, range, timeframe } = request;
const res = await fetch(
`/api/bars?symbol=${symbolInfo.symbol}&barNs=${timeframe.barNs}&from=${range.fromNs}&to=${range.toNs}`,
);
return {
ohlcvBars: res.json();
}
}This will vary a lot depending on your setup - you could fetch from an api route (like in the example above) or possibly get your data from the public/ folder, this one is up to you. If you want free data, I'd recommend Dukascopy, they got lots of symbols, many go down to second-level
Note
If you need real time data, implement subscribeRealtime() - currenly we only implemented getting historical data. If that's all you need, you don't need to add this
subscribeRealtime() (Optional):
myDataAdapter.ts
subscribeRealtime(onBar: (bar: BarResponse) => void): () => void {
//TBD
}So now the full myDataAdapter.ts file should look like this:
import type { IDataAdapter, SymbolInfo, OhlcvBar } from '@christtrade/depth';
export class MyAdapter implements IDataAdapter {
private readonly symbols: SymbolInfo[] = [
{
symbol: '/NQ1',
description: 'Nasdaq 100 E-mini Futures (Front Cont.)',
exchange: 'CME',
dataLevel: 'ohlcv',
type: 'future',
supportedResolutions: [
1_000_000_000n, // 1 second in ns
60n * 1_000_000_000n, // 1 minute
60n * 60n * 1_000_000_000n, // 1 hour
24n * 60n * 60n * 1_000_000_000n, // 1 day
],
priceFormat: {
precision: 2,
minTick: 0.25,
},
contract: {
multiplier: 20,
currency: 'USD',
continuous: true,
},
session: {
hours: '1800-1700',
timezone: 'America/New_York',
days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu'],
holidays: [],
corrections: [],
}
}
];
async connect():Promise<void> {
// Nothing needed here for this guide
// Add stuff here if you need - this runs first and only once
// set up workers, load symbols, etc...
}
resolveSymbol(symbol: string): SymbolInfo | Promise<SymbolInfo> {
return this.symbols.find((s) => s.symbol.toLowerCase() === symbol.toLowerCase());
}
async searchSymbols(): Promise<SymbolInfo[]> {
return this.symbols
}
async fetchBars(request: FetchRequest): Promise<BarResponse[]> {
const { symbolInfo, range, timeframe } = request
const res = await fetch(
`/api/bars?symbol=${symbolInfo.symbol}&barNs=${timeframe.barNs}&from=${range.fromNs}&to=${range.toNs}`,
);
return {
ohlcvBars: res.json();
}
}
subscribeRealtime(onBar: (bar: BarResponse) => void): () => void {
//TBD
}
}Connecting the datafeed to the chart
First import the datafeed
chart.tsx
import { MyAdapter } from './myDataAdapter.ts'Then just replace the mock adapter with this one:
chart.tsx
import { useChristTradeChart } from '@christtrade/depth';
import { MyAdapter } from './myDataAdapter.ts' //add this
export default function MyChart() {
// replace the mock adapter with the new one
const adapter = useMemo(() => new MyAdapter(), []);
const { chart, element } = useChristTradeChart({
dataAdapter: adapter,
symbol: '/NQ1', // Make sure to remember to update the symbol!
horizon: Date.now(),
initialLoad: {
start: Date.now() - 1000 * 60 * 60 * 24,
end: Date.now(),
},
});
return <div style={{ width: '100%', height: '600px' }}>{element}</div>;
}Done
And now we're done. Simple right?
Just keep in mind to make sure the fetchBars function should return BarResponse[]!
Now you should have a fully functional chart with your own data. You should now go to Configuration to tailor the chart to your site. If you're a pro, you could try getting trading to work with your own Execution Adapter!