From 42b40d708f9d0c1244b48341868a232f126f88ad Mon Sep 17 00:00:00 2001 From: gitbugr Date: Tue, 16 Oct 2018 00:54:40 +0100 Subject: [PATCH] + Promise support. [exampleAsync(...) functions added] ~ updated readme. ~ updated version number --- README.md | 71 +++++++++++++++++++++++++++++------ dist/hst_reader.d.ts | 21 ++++++++++- dist/hst_reader.js | 89 ++++++++++++++++++++++++++++++++++++-------- package-lock.json | 2 +- package.json | 2 +- src/hst_reader.ts | 82 ++++++++++++++++++++++++++++++++-------- 6 files changed, 220 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index c9ca91e..2417b8d 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ Parser for the MetaTrader History (.hst) File Format in Node.js ### Table of Contents - * [Summary](#) - * [Table of Contents](#) - * [Installation](#) - * [Usage](#) - * [Author](#) - * [Thank You](#) - * [Licence](#) + * [Summary](#summary) + * [Table of Contents](#table-of-contents) + * [Installation](#installation) + * [Usage](#usage) + * [Author](#author) + * [Thank You](#thank-you) + * [Licence](#licence) ### Installation @@ -29,14 +29,14 @@ bower install hst-parser --save ### Usage ```javascript -const HSTReader = require('hst-parser').HSTReader; +const HSTParser = require('hst-parser'); -const tradeHistory = new HSTReader('./data/USDGBP.hst'); // your .hst file +const tradeHistory = new HSTParser('./data/USDGBP.hst'); // your .hst file ``` #### Variables -the HSTReader class exposes some variables for you to use +the HSTParser class exposes some variables for you to use ```javascript console.log(tradeHistory.version); // file version from headers // example output: 400 @@ -77,7 +77,7 @@ Example: #### isValidFormat() -Checks if file can be parsed by HSTReader. (currently supports versions 400 and 401 of .hst files) +Checks if file can be parsed by HSTParser. (currently supports versions 400 and 401 of .hst files) ```javascript if(tradeHistory.isValidFormat()) { // do stuff @@ -94,6 +94,18 @@ console.log(tradeHistory.getCandleNumber(200)); // output: {Candle} ``` +#### getCandleNumberAsync(candleNumber) + +Returns promise that resolves to candle data at specified position +```javascript +tradeHistory.getCandleNumber(200).then(candle => { + console.log(candle); +}).catch(err => { + console.log(err); +}) +// output: {Candle} +``` + #### getNextCandle() Returns next set of candle data @@ -102,6 +114,18 @@ console.log(tradeHistory.getNextCandle()); // output: {Candle} ``` +#### getNextCandleAsync() + +Returns promise that resolves to next set of candle data +```javascript +tradeHistory.getNextCandleAsync().then(candle => { + console.log(candle); +}).catch(err => { + console.log(err); +}) +// output: {Candle} +``` + #### getPrevCandle() Returns previous set of candle data @@ -110,6 +134,18 @@ console.log(tradeHistory.getPrevCandle()); // output: {Candle} ``` +#### getPrevCandleAsync() + +Returns promise that resolves to previous set of candle data +```javascript +tradeHistory.getPrevCandleAsync().then(candle => { + console.log(candle); +}).catch(err => { + console.log(err); +}) +// output: {Candle} +``` + #### getCandleAt(date, ...[startDate, i]) Returns set of candle data at specified date and time @@ -119,6 +155,19 @@ console.log(tradeHistory.getCandleAt(myBirthday)); // output: {Candle} ``` +#### getCandleAtAsync(date) + +Returns promise that resolves to set of candle data at specified date and time +```javascript +const myBirthday = new Date(1996, 0, 26); +tradeHistory.getCandleAt(myBirthday).then(candle => { + console.log(candle); +}).catch(err => { + console.log(err); +}) +// output: {Candle} +``` + ### Author Kyron Taylor (gitbugr) diff --git a/dist/hst_reader.d.ts b/dist/hst_reader.d.ts index b25a26f..f29ca1b 100644 --- a/dist/hst_reader.d.ts +++ b/dist/hst_reader.d.ts @@ -1,11 +1,10 @@ import Candle from "./interfaces/candle"; -export default class HSTReader { +export default class HSTParser { version: number; symbol: string; period: number; start: Date; candleNumber: number; - endOfFile: boolean; private fd; private byteOffset; private candleByteSize; @@ -22,15 +21,28 @@ export default class HSTReader { * @return {Candle} returns the next candle in the file */ getNextCandle(): Candle; + /** + * @return {Promise} returns promise that resolves to the next candle in the file + */ + getNextCandleAsync(): Promise; /** * @return {Candle} returns the previous candle in the file */ getPrevCandle(): Candle; + /** + * @return {Promise} returns promise that resolves to the previous candle in the file + */ + getPrevCandleAsync(): Promise; /** * @param {number} candleNumber finds candle from number * @return {Candle} returns specified candle */ getCandleNumber(candleNumber: number): Candle; + /** + * @param {number} candleNumber finds candle from number + * @return {Promise} returns promise that resolves to specified candle + */ + getCandleNumberAsync(candleNumber: number): Promise; /** * @param {Date} date finds candle at specified date and time * @param {Date=} startDate optional: due to missing candles, we try to find based on most likely position @@ -38,6 +50,11 @@ export default class HSTReader { * @return {Candle} returns the candle if found */ getCandleAt(date: Date, startDate?: Date, i?: number): Candle; + /** + * @param {Date} date finds candle at specified date and time + * @return {Promise} returns promise, resolves to Candle object + */ + getCandleAtAsync(date: Date): Promise; /** * @return {Candle} returns candle at byte position */ diff --git a/dist/hst_reader.js b/dist/hst_reader.js index 96ab624..b7a7078 100644 --- a/dist/hst_reader.js +++ b/dist/hst_reader.js @@ -14,21 +14,21 @@ Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); // parser dataa const parser_data_1 = __importDefault(require("./parser_data")); -class HSTReader { +class HSTParser { /** * @param {string} filename Reads headers of specified file and stores into class variables. */ constructor(filename) { // check if file exists if (!fs.existsSync(filename)) { - throw new Error(`Can't find this file: ${filename}`); + throw new Error("Could not find file"); } // open file and store file descriptor as variable - this.fd = fs.openSync(filename, 'r'); + this.fd = fs.openSync(filename, "r+"); // verify filesize is larger than header size this.filesize = fs.statSync(filename).size; if (this.filesize < 148) { - throw new Error(`Damn, that's a small file. Too small.`); + throw new Error("File too small"); } // set up buffers const version = Buffer.alloc(4); @@ -50,7 +50,6 @@ class HSTReader { this.symbol = symbol.toString("utf8"); this.period = period.readInt32LE(0); this.start = new Date(start.readInt32LE(0) * 1000); - this.endOfFile = false; // set byte offset to end of header-block this.candleByteSize = this.version === 400 ? 44 : 60; this.byteOffset = 148 - this.candleByteSize; @@ -69,13 +68,25 @@ class HSTReader { if (this.byteOffset + this.candleByteSize <= this.filesize) { this.byteOffset += this.candleByteSize; this.candleNumber += 1; - this.endOfFile = false; } else { - this.endOfFile = true; + throw new Error("Already at end of file"); } return this.readCandle(); } + /** + * @return {Promise} returns promise that resolves to the next candle in the file + */ + getNextCandleAsync() { + return new Promise((resolve, reject) => { + try { + resolve(this.getNextCandle()); + } + catch (err) { + reject(err); + } + }); + } /** * @return {Candle} returns the previous candle in the file */ @@ -83,18 +94,52 @@ class HSTReader { if (this.byteOffset - this.candleByteSize >= 148) { this.byteOffset -= this.candleByteSize; this.candleNumber -= 1; - this.endOfFile = false; + } + else { + throw new Error("Already at start of file"); } return this.readCandle(); } + /** + * @return {Promise} returns promise that resolves to the previous candle in the file + */ + getPrevCandleAsync() { + return new Promise((resolve, reject) => { + try { + resolve(this.getPrevCandle()); + } + catch (err) { + reject(err); + } + }); + } /** * @param {number} candleNumber finds candle from number * @return {Candle} returns specified candle */ getCandleNumber(candleNumber) { this.candleNumber = candleNumber; - this.byteOffset = 148 + (candleNumber * this.candleByteSize); - return this.readCandle(); + const newByteOffset = 148 + (candleNumber * this.candleByteSize); + if (newByteOffset < this.filesize) { + return this.readCandle(); + } + else { + throw new Error("File too small"); + } + } + /** + * @param {number} candleNumber finds candle from number + * @return {Promise} returns promise that resolves to specified candle + */ + getCandleNumberAsync(candleNumber) { + return new Promise((resolve, reject) => { + try { + resolve(this.getCandleNumber(candleNumber)); + } + catch (err) { + reject(err); + } + }); } /** * @param {Date} date finds candle at specified date and time @@ -116,9 +161,23 @@ class HSTReader { return this.getCandleAt(date, candle.timestamp, i + 1); } else { - throw new Error("Could not find candle"); + throw new Error("Candle not found"); } } + /** + * @param {Date} date finds candle at specified date and time + * @return {Promise} returns promise, resolves to Candle object + */ + getCandleAtAsync(date) { + return new Promise((resolve, reject) => { + try { + resolve(this.getCandleAt(date)); + } + catch (err) { + reject(err); + } + }); + } /** * @return {Candle} returns candle at byte position */ @@ -129,7 +188,7 @@ class HSTReader { const parserFunctions = { date: (buffer) => { let timestamp = buffer.readInt32LE(0); - timestamp = timestamp < 9999999999 ? timestamp * 1000 : timestamp; + timestamp = this.version === 400 ? timestamp * 1000 : timestamp; return new Date(timestamp); }, double: (buffer) => buffer.readDoubleLE(0), @@ -150,7 +209,5 @@ class HSTReader { return candleData; } } -exports.default = HSTReader; -module.exports = { - HSTReader, -}; +exports.default = HSTParser; +module.exports = HSTParser; diff --git a/package-lock.json b/package-lock.json index 50447f9..8420097 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "hst-parser", - "version": "0.7.0", + "version": "0.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9f04a1b..7073d72 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hst-parser", "description": "Parser for the MetaTrader History (.hst) File Format", "author": "gitbugr ", - "version": "0.1.2", + "version": "0.2.0", "license": "MIT", "main": "dist/hst_reader.js", "repository": { diff --git a/src/hst_reader.ts b/src/hst_reader.ts index 5f4faa3..c09c395 100644 --- a/src/hst_reader.ts +++ b/src/hst_reader.ts @@ -7,7 +7,7 @@ import Candle from "./interfaces/candle"; // parser dataa import parserData from "./parser_data"; -export default class HSTReader { +export default class HSTParser { // File Headers public version: number; public symbol: string; @@ -15,7 +15,6 @@ export default class HSTReader { public start: Date; // Variables public candleNumber: number; - public endOfFile: boolean; private fd: number; private byteOffset: number; private candleByteSize: number; @@ -27,14 +26,14 @@ export default class HSTReader { constructor(filename: string) { // check if file exists if (!fs.existsSync(filename)) { - throw new Error(`Can't find this file: ${filename}`); + throw new Error("Could not find file"); } // open file and store file descriptor as variable - this.fd = fs.openSync(filename, 'r'); + this.fd = fs.openSync(filename, "r+"); // verify filesize is larger than header size this.filesize = fs.statSync(filename).size; if (this.filesize < 148) { - throw new Error(`Damn, that's a small file. Too small.`); + throw new Error("File too small"); } // set up buffers const version: Buffer = Buffer.alloc(4); @@ -57,7 +56,6 @@ export default class HSTReader { this.symbol = symbol.toString("utf8"); this.period = period.readInt32LE(0); this.start = new Date(start.readInt32LE(0) * 1000); - this.endOfFile = false; // set byte offset to end of header-block this.candleByteSize = this.version === 400 ? 44 : 60; this.byteOffset = 148 - this.candleByteSize; @@ -76,12 +74,23 @@ export default class HSTReader { if (this.byteOffset + this.candleByteSize <= this.filesize) { this.byteOffset += this.candleByteSize; this.candleNumber += 1; - this.endOfFile = false; } else { - this.endOfFile = true; + throw new Error("Already at end of file"); } return this.readCandle(); } + /** + * @return {Promise} returns promise that resolves to the next candle in the file + */ + public getNextCandleAsync(): Promise { + return new Promise((resolve, reject) => { + try { + resolve(this.getNextCandle()); + } catch (err) { + reject(err); + } + }); + } /** * @return {Candle} returns the previous candle in the file */ @@ -89,18 +98,48 @@ export default class HSTReader { if (this.byteOffset - this.candleByteSize >= 148) { this.byteOffset -= this.candleByteSize; this.candleNumber -= 1; - this.endOfFile = false; + } else { + throw new Error("Already at start of file"); } return this.readCandle(); } + /** + * @return {Promise} returns promise that resolves to the previous candle in the file + */ + public getPrevCandleAsync(): Promise { + return new Promise((resolve, reject) => { + try { + resolve(this.getPrevCandle()); + } catch (err) { + reject(err); + } + }); + } /** * @param {number} candleNumber finds candle from number * @return {Candle} returns specified candle */ public getCandleNumber(candleNumber: number): Candle { this.candleNumber = candleNumber; - this.byteOffset = 148 + (candleNumber * this.candleByteSize); - return this.readCandle(); + const newByteOffset = 148 + (candleNumber * this.candleByteSize); + if (newByteOffset < this.filesize) { + return this.readCandle(); + } else { + throw new Error("File too small"); + } + } + /** + * @param {number} candleNumber finds candle from number + * @return {Promise} returns promise that resolves to specified candle + */ + public getCandleNumberAsync(candleNumber: number): Promise { + return new Promise((resolve, reject) => { + try { + resolve(this.getCandleNumber(candleNumber)); + } catch (err) { + reject(err); + } + }); } /** * @param {Date} date finds candle at specified date and time @@ -119,9 +158,22 @@ export default class HSTReader { candle = this.getCandleNumber(Math.floor(this.candleNumber / 2)); return this.getCandleAt(date, candle.timestamp, i + 1); } else { - throw new Error("Could not find candle"); + throw new Error("Candle not found"); } } + /** + * @param {Date} date finds candle at specified date and time + * @return {Promise} returns promise, resolves to Candle object + */ + public getCandleAtAsync(date: Date): Promise { + return new Promise((resolve, reject) => { + try { + resolve(this.getCandleAt(date)); + } catch (err) { + reject(err); + } + }); + } /** * @return {Candle} returns candle at byte position */ @@ -133,7 +185,7 @@ export default class HSTReader { const parserFunctions: any = { date: (buffer: Buffer) => { let timestamp: number = buffer.readInt32LE(0); - timestamp = timestamp < 9999999999 ? timestamp * 1000 : timestamp; + timestamp = this.version === 400 ? timestamp * 1000 : timestamp; return new Date(timestamp); }, double: (buffer: Buffer) => buffer.readDoubleLE(0), @@ -157,6 +209,4 @@ export default class HSTReader { } } -module.exports = { - HSTReader, -}; +module.exports = HSTParser;