import axios from 'axios'; import moment from 'moment-timezone'; /** * Create a new instance of Epex */ class Epex { _dateFormat: string = 'YYYY-MM-DD'; _baseUrl: string = 'https://www.epexspot.com/en/market-data?underlying_year=&modality=Auction&sub_modality=DayAhead&product=60&data_mode=table&period='; constructor() { } /** * @type {string} */ set dateFormat(dateFormat: string) { this._dateFormat = dateFormat; } /** * @type {string} */ set baseUrl(baseUrl: string) { this._baseUrl = baseUrl; } /** * Parse the dayahead auctions from epexspot * @param {String} date The date of the auctions in the given dateFormat * @param {String} country The country short * @return {Promise} Resolves the auctions as array * @fulfil {Array} - The auctions as an array * @reject {Error} - An error */ public parse(date: string, countryShort: string): Promise<{ timestamp: number, price: number, energy: number, country: string }[]> { return new Promise((resolve, reject) => { if (!date || !countryShort) reject(new Error('One or both of the parameter "date" and "countryShort" are missing')); this.parseInformations(this.createUrl(this._baseUrl, date, countryShort, this._dateFormat), date, this._dateFormat, countryShort).then(resolve).catch(reject); }); } /** * Create the URL from epexspot.com by given parameters. * @private * @param {String} baseUrl The base url from epexspot.com * @param {String} date The date of the data to read * @param {String} country The short of the datas country (FR, CH, AT, DE-LU, BE, NL, GB) * @param {String} dateFormat The format from the given date * @return {String} The URL pointing to the data */ private createUrl(baseUrl: string, date: string, countryShort: string, dateFormat: string): string { const yesterday = moment(date, dateFormat).subtract(1, 'day').format('YYYY-MM-DD'); date = moment(date, dateFormat).format('YYYY-MM-DD'); return `${baseUrl}&market_area=${countryShort.toUpperCase()}&trading_date=${yesterday}&delivery_date=${date}`; } /** * Get a string between two strings * @private * @param {String} text String to search in * @param {String} startString Beginning of the substring (included) * @param {String} endString End of the substring (excluded) * @return {String} The string between first and second string */ private stringBetween(text: string, start: string, end?: string): string { let startIndex = text.indexOf(start); let endIndex = end ? text.indexOf(end) : text.length; return text.substring(startIndex, endIndex); } /** * Get all strings between two strings * @private * @param {String} text String for search in * @param {RegExp} reg Search beginning * @param {String} sub2 Search end * @return {Array} One index for every match */ private stringBetweenArray(text: string, start: RegExp, endString: string): string[] { let result: string[] = []; let startMatch = text.match(start); if (startMatch) { let endIndex = text.indexOf(endString); while (startMatch && endIndex >= 0) { let startString = startMatch[0]; let startIndex = text.indexOf(startString); endIndex = startIndex + startString.length + text.substring(startIndex + startString.length).indexOf(endString); let subString = text.substring(startIndex + startString.length, endIndex); result.push(subString.trim()); text = text.substring(endIndex + endString.length); startMatch = text.match(start); endIndex = text.indexOf(endString); } } return result; } /** * Parse the information from the website * @private * @param {String} url The URL pointing to the data * @param {String} datum The date of the data to read * @param {String} dateFormat The format from the given date * @param {String} country The short of the datas country (FR, CH, AT, DE-LU, BE, NL, GB) * @return {Promise} The data as JSON objekts */ private parseInformations(url: string, date: string, dateFormat: string, countryShort: string): Promise<{ timestamp: number, price: number, energy: number, country: string }[]> { return new Promise(async (resolve, reject) => { try { const requestDate = moment(date, dateFormat); let infos: { timestamp: number, price: number, energy: number, country: string, buyenergy: number, sellenergy: number }[] = []; let response = await axios.get(url); let html = response.data; let searchString = html.match(new RegExp('
| /g, ' | '); let timestamp = new Date(requestDate.valueOf() + i * 3600000); infos.push({ timestamp: timestamp.getTime(), price: parseFloat(row[3].replace(',', '')), energy: parseFloat(row[2].replace(',', '')), buyenergy: parseFloat(row[0].replace(',', '')), sellenergy: parseFloat(row[1].replace(',', '')), country: countryShort.toLowerCase() }); } resolve(infos); } catch (err) { reject(err); } }); } } export const epex = new Epex();