wiki/examples/ts/fetch-first-ohlcv-timestamp.md
// eslint-disable-next-line no-unused-vars
import ccxt from '../../js/ccxt.js';
// AUTO-TRANSPILE //
// ###### Description ######
//
// This function tries to fetch the "listing time" of a symbol by fetching the earliest available bar in daily resolution.
// Top-tier exchanges also support fetching smaller timeframes (eg. 1 minute) even several years back, so for those exchanges you can also use `useMinuteTimeframe = true` argument to get the timestamp rounded to the earliest minute bar (instead of daily bar timestamp).
// See usage in the end of this file
async function fetchFirstBarTimestamp (exchange:any, symbol: string, useMinuteTimeframe = false) {
// set some constants
const millisecondsPerDay = 86400000;
const minutesPerDay = 1440;
const minimumTimestamp = 1230768000000; // 2009-01-01 (bitcoin created year)
// get market features
const market = exchange.market (symbol);
const marketType = exchange.safeString (market, 'type');
let features = exchange.safeDict (exchange.features, marketType, {});
if (market['subType'] !== undefined) {
features = exchange.safeDict (features, market['subType'], {});
}
const ohlcv = exchange.safeDict (features, 'fetchOHLCV');
if (ohlcv === undefined) {
return undefined;
}
const limit = exchange.safeInteger (ohlcv, 'limit');
const fetchParams = { 'maxRetriesOnFailure': 3 };
// start loop
let currentSince = exchange.milliseconds () - millisecondsPerDay * (limit - 1);
let foundStartTime = 0;
// eslint-disable-next-line
while (true) {
currentSince = Math.max (currentSince, minimumTimestamp);
const dailyBars = await exchange.fetchOHLCV (symbol, '1d', currentSince, limit, fetchParams);
if (dailyBars.length <= 0) {
break; // if no days returned, then probably start date was passed
}
const firstTs = dailyBars[0][0];
if (firstTs === foundStartTime) {
// if the first timestamp is equal to the last-fetched timestamp, then break here, because some exchanges still return initial bar even if since is much ahead to listing time
break;
}
foundStartTime = firstTs;
currentSince = foundStartTime - millisecondsPerDay * (limit - 1); // shift 'since' one step back
if (dailyBars.length === 1) {
// in some cases, some exchanges might still return first bar of chart when endtime overlaps previous day
break;
}
}
// if minute resolution needed
if (useMinuteTimeframe) {
const maxIteration = Math.ceil (minutesPerDay / limit) * 2;
const allPromises: any[] = [];
for (let i = 0; i < maxIteration; i++) {
currentSince = foundStartTime - millisecondsPerDay + i * limit * 60 * 1000; // shift one-duration back for more accuracy for different kind of exchanges, like OKX, where first daily bar is offset by one day, but minute bars present
allPromises.push (exchange.fetchOHLCV (symbol, '1m', currentSince, limit, fetchParams));
}
const allResponses = await Promise.all (allPromises);
// find earliest bar
for (let i = 0; i < allResponses.length; i++) {
const response = allResponses[i];
if (response.length > 0) {
foundStartTime = response[0][0];
break;
}
}
}
return foundStartTime;
}
// ###### Usage ######
const runExample = false; // set to true to run example
if (runExample) {
const myEx = new ccxt.binance ();
await myEx.loadMarkets ();
const symbol = 'TRUMP/USDT';
const earliest_timestamp = await fetchFirstBarTimestamp (myEx, symbol, true);
console.log ('- Earliest bar timestamp:', earliest_timestamp, ', readable: ', myEx.iso8601 (earliest_timestamp));
console.log ('- market.created value:', myEx.market (symbol)['created']);
}
export default fetchFirstBarTimestamp;