export async function jBars (from, to, res) { console.log('[jBars]: Method call', res, from, to); var toDate = new Date(to*1000); var fromDate = new Date(from*1000); if (res=="1W") { // for 1W, day must be Sunday const day = fromDate.getUTCDay(); // 0<=day<7 fromDate.setDate(fromDate.getDate() + (7-day)%7 ); } // Set fromDate to be compatible with Tim's datafiles. // This potentially increases number of samples returned. if (res.endsWith("W") || res.endsWith("D")) { // Days/Weeks -- set to midnight fromDate.setUTCHours(0, 0, 0); } else { let minutesRes = parseInt(res); if (minutesRes >= 60) { // Hours let hoursRes = Math.floor(minutesRes/60); let fromHours = fromDate.getUTCHours(); fromDate.setUTCHours(fromHours - fromHours % hoursRes, 0, 0, 0); } else { // Minutes let fromMinutes = fromDate.getUTCMinutes(); fromDate.setUTCMinutes(fromMinutes - fromMinutes % minutesRes, 0, 0); } } console.log("fromDate:", fromDate.toUTCString()); console.log("toDate: ", toDate.toUTCString()); const contract = "0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"; // const contract = "0xC6962004f452bE9203591991D15f6b388e09E8D0"; const file_res = ['1m', '3m', '5m', '10m', '15m', '30m', '1H', '2H', '4H', '8H', '12H', '1D', '2D', '3D', '1W',]; const supported_res = ['1', '3', '5', '10', '15', '30', '60', '120', '240', '480', '720', '1D', '2D', '3D', '1W',]; const daily_res = ['1', '3', '5', '10', '15', '30']; const single_res = ['1W']; if (!supported_res.includes(res)) throw Error(`resolution ${res} not supported.`); const is_daily_res = daily_res.includes(res); const is_single_res = single_res.includes(res); const is_monthly_res = !is_single_res && !is_daily_res; let bars = []; for ( // Once around for each sample in from-to range let iDate = fromDate, // loop state iFile = undefined, iohlc = 0, ohlc; iDate < toDate; ) { let bar = undefined; // Fetch one sample file as needed if (iFile == undefined ? true : is_monthly_res ? iFile.getUTCMonth() != iDate.getUTCMonth() : is_daily_res ? iFile.getUTCDate() != iDate.getUTCDate() : false // is_single_res ) { const fres = file_res[supported_res.indexOf(res)] const yr = iDate.getUTCFullYear(); const yrdir = is_single_res ? "" : `/${yr}`; const mo = String(iDate.getUTCMonth()+1).padStart(2, '0'); // January is month 0 in Date object const date = is_daily_res ? String(iDate.getUTCDate()).padStart(2, '0') : ""; const yrmo = !is_single_res ? `-${yr}${mo}` : ""; const server = "https://alpha.dexorder.trade" let url = `${server}/ohlc/42161/${contract}/${fres}${yrdir}/${contract}-${fres}${yrmo}${date}.json`; let response = await fetch(url); if (response.ok) { ohlc = await response.json(); console.log(`Fetch: ${ohlc.length} resolution ${res} samples from ${url}`) console.log(`first: ${new Date(ohlc[0][0]*1000).toUTCString()}`) console.log(`last: ${new Date(ohlc[ohlc.length-1][0]*1000).toUTCString()}`) } else { console.log(`Fetch: file not found: ${url}`) ohlc = []; // no file, then empty data } iFile = new Date(iDate); iohlc = 0; } // Skip samples not for our time for(; iohlc < ohlc.length; iohlc++ ) { // if ( new Date(ohlc[iohlc][0]+'Z').getTime() >= iDate.getTime() ) break; if ( ohlc[iohlc][0]*1000 >= iDate.getTime() ) break; } // console.log(`iohlc: ${iohlc}`); // let ohlcDate = iohlc >= ohlc.length ? undefined : new Date(ohlc[iohlc][0]+'Z'); let ohlcDate = iohlc >= ohlc.length ? undefined : new Date(ohlc[iohlc][0]*1000); // no ohlc sample file, or sample file exists and asking for sample beyond last sample, insert missing sample const insert_missing_samples = false; const visible_missing_samples = false; if (ohlcDate == undefined) { bar = { time: iDate.getTime(), } if (visible_missing_samples) bar = Object.assign(bar, { // Comment these to make invisible open: 50, high: 50, low: 0, close: 0, }); if (!insert_missing_samples) bar = undefined; } // file exists, but ohlc sample not for this time, insert missing sample else if ( iDate.getTime() != ohlcDate.getTime() ) { bar = { time: iDate.getTime(), } if (visible_missing_samples) bar = Object.assign(bar, { open: 100, high: 100, low: 0, close: 0, }); if (!insert_missing_samples) bar = undefined; } // Copy ohlc sample else { bar = { time: iDate.getTime(), open: ohlc[iohlc][1] ?? ohlc[iohlc][4], // open high: ohlc[iohlc][2] ?? ohlc[iohlc][4], // high low: ohlc[iohlc][3] ?? ohlc[iohlc][4], // low close: ohlc[iohlc][4], // close } iohlc++; } if (bar != undefined) bars.push(bar); // Increment loop variable if (supported_res.indexOf(res)1day iDate.setUTCDate(iDate.getUTCDate()+1); } } // noData should be set only if no bars are in the requested period and earlier. // In our case, we are guaranteed to have contiguous samples. // So we only return no bars (bars.length==0) if: // 1. period is entirely before first data available. // 2. period is entirely after last data available. // Returning noData based on bars.length works perfectly assuming that TV never asks for case 2. // This is probably not a safe assumption. The alternative would be to search // backward to find beginning of history. How far to search? let noData = bars.length == 0; if (noData) console.log("noData == true!"); return [bars, {noData}]; }