Back to Ccxt

Fetch First Ohlcv Timestamp

wiki/examples/ts/fetch-first-ohlcv-timestamp.md

4.5.524.0 KB
Original Source
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;