- [Fetch First Ohlcv Timestamp](./examples/ts/) ```javascript // 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; ```