dukascopy-node-plus 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -13706,158 +13706,178 @@ var import_debug = __toESM(require("debug"));
13706
13706
  var import_stream = require("stream");
13707
13707
  var import_promises = require("stream/promises");
13708
13708
  var DEBUG_NAMESPACE = "dukascopy-node";
13709
- async function getHistoricalRatesToStream(config) {
13709
+ function getHistoricalRatesToStream(config) {
13710
13710
  const stream = new import_stream.Readable({
13711
13711
  objectMode: true,
13712
13712
  async read(_size) {
13713
- try {
13714
- const { input, isValid, validationErrors } = validateConfigNode(config);
13715
- (0, import_debug.default)(`${DEBUG_NAMESPACE}:config`)("%O", {
13716
- input,
13717
- isValid,
13718
- validationErrors
13719
- });
13720
- if (!isValid) {
13721
- this.emit("error", { validationErrors });
13722
- this.push(null);
13723
- return;
13724
- }
13725
- const {
13726
- instrument,
13727
- dates: { from, to },
13728
- timeframe,
13729
- priceType,
13730
- volumes,
13731
- volumeUnits,
13732
- utcOffset,
13733
- ignoreFlats,
13734
- format,
13735
- batchSize,
13736
- pauseBetweenBatchesMs,
13737
- useCache,
13738
- cacheFolderPath,
13739
- retryCount,
13740
- pauseBetweenRetriesMs,
13741
- retryOnEmpty
13742
- } = input;
13743
- const [startDate, endDate] = normaliseDates({
13744
- instrument,
13745
- startDate: from,
13746
- endDate: to,
13747
- timeframe,
13748
- utcOffset
13749
- });
13750
- const [startDateMs, endDateMs] = [+startDate, +endDate];
13751
- const onItemFetch = process.env.DEBUG ? (url, buffer, isCacheHit) => {
13752
- (0, import_debug.default)(`${DEBUG_NAMESPACE}:fetcher`)(
13753
- url,
13754
- `| ${formatBytes(buffer.length)} |`,
13755
- `${isCacheHit ? "cache" : "network"}`
13756
- );
13757
- } : void 0;
13758
- const bufferFetcher = new BufferFetcher({
13759
- batchSize,
13760
- pauseBetweenBatchesMs,
13761
- cacheManager: useCache ? new CacheManager({ cacheFolderPath }) : void 0,
13762
- retryCount,
13763
- pauseBetweenRetriesMs,
13764
- onItemFetch,
13765
- retryOnEmpty
13766
- });
13767
- let firstLine = true;
13768
- let urlsProcessed = 0;
13769
- const urlsforFetchingData = generateUrls({
13770
- instrument: input.instrument,
13771
- timeframe: input.timeframe,
13772
- priceType: input.priceType,
13773
- startDate,
13774
- endDate
13713
+ }
13714
+ });
13715
+ try {
13716
+ const { input, isValid, validationErrors } = validateConfigNode(config);
13717
+ (0, import_debug.default)(`${DEBUG_NAMESPACE}:config`)("%O", {
13718
+ input,
13719
+ isValid,
13720
+ validationErrors
13721
+ });
13722
+ if (!isValid) {
13723
+ stream.emit("error", { validationErrors });
13724
+ stream.push(null);
13725
+ return stream;
13726
+ }
13727
+ const {
13728
+ instrument,
13729
+ dates: { from, to },
13730
+ timeframe,
13731
+ priceType,
13732
+ volumes,
13733
+ volumeUnits,
13734
+ utcOffset,
13735
+ ignoreFlats,
13736
+ format,
13737
+ batchSize,
13738
+ pauseBetweenBatchesMs,
13739
+ useCache,
13740
+ cacheFolderPath,
13741
+ retryCount,
13742
+ pauseBetweenRetriesMs,
13743
+ retryOnEmpty
13744
+ } = input;
13745
+ const [startDate, endDate] = normaliseDates({
13746
+ instrument,
13747
+ startDate: from,
13748
+ endDate: to,
13749
+ timeframe,
13750
+ utcOffset
13751
+ });
13752
+ const [startDateMs, endDateMs] = [+startDate, +endDate];
13753
+ const onItemFetch = process.env.DEBUG ? (url, buffer, isCacheHit) => {
13754
+ (0, import_debug.default)(`${DEBUG_NAMESPACE}:fetcher`)(
13755
+ url,
13756
+ `| ${formatBytes(buffer.length)} |`,
13757
+ `${isCacheHit ? "cache" : "network"}`
13758
+ );
13759
+ } : void 0;
13760
+ const bufferFetcher = new BufferFetcher({
13761
+ batchSize,
13762
+ pauseBetweenBatchesMs,
13763
+ cacheManager: useCache ? new CacheManager({ cacheFolderPath }) : void 0,
13764
+ retryCount,
13765
+ pauseBetweenRetriesMs,
13766
+ onItemFetch,
13767
+ retryOnEmpty
13768
+ });
13769
+ const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
13770
+ let firstLine = true;
13771
+ let urlsProcessed = 0;
13772
+ const urlsforFetchingData = generateUrls({
13773
+ instrument: input.instrument,
13774
+ timeframe: input.timeframe,
13775
+ priceType: input.priceType,
13776
+ startDate,
13777
+ endDate
13778
+ });
13779
+ const promiseProcessedData = urlsforFetchingData.map((url) => {
13780
+ return new Promise((resolve2, reject) => {
13781
+ bufferFetcher.fetch([url]).then((bufferObjects) => {
13782
+ try {
13783
+ const processedData = processData({
13784
+ instrument: input.instrument,
13785
+ requestedTimeframe: input.timeframe,
13786
+ bufferObjects,
13787
+ priceType: input.priceType,
13788
+ volumes: input.volumes,
13789
+ volumeUnits: input.volumeUnits,
13790
+ ignoreFlats: input.ignoreFlats
13791
+ });
13792
+ resolve2(processedData);
13793
+ } catch (err) {
13794
+ reject(err);
13795
+ }
13796
+ }).catch((err) => {
13797
+ reject(err);
13775
13798
  });
13776
- await (0, import_promises.pipeline)(
13777
- import_stream.Readable.from(urlsforFetchingData),
13778
- new import_stream.Transform({
13779
- objectMode: true,
13780
- transform: async (url, _, callback) => {
13781
- const bufferObject = {
13782
- url,
13783
- buffer: await bufferFetcher.fetchBuffer(url),
13784
- isCacheHit: useCache
13785
- };
13786
- try {
13787
- const processedData = processData({
13788
- instrument: input.instrument,
13789
- requestedTimeframe: input.timeframe,
13790
- bufferObjects: [bufferObject],
13791
- priceType: input.priceType,
13792
- volumes: input.volumes,
13793
- volumeUnits: input.volumeUnits,
13794
- ignoreFlats: input.ignoreFlats
13795
- });
13796
- processedData.forEach((item) => {
13797
- const [timestamp] = item;
13798
- if (timestamp && timestamp >= startDateMs && timestamp < endDateMs) {
13799
- if (input.format === "array" /* array */) {
13800
- this.push(item);
13801
- } else {
13802
- const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
13803
- if (format === "json" /* json */) {
13804
- const data = item.reduce((all, item2, i) => {
13805
- const name = bodyHeaders[i];
13806
- all[name] = item2;
13807
- return all;
13808
- }, {});
13809
- this.push(data);
13810
- } else if (format === "csv" /* csv */) {
13811
- if (firstLine) {
13812
- const csvHeaders = bodyHeaders.join(",");
13813
- this.push(csvHeaders);
13814
- firstLine = false;
13815
- }
13816
- this.push(item.join(","));
13817
- }
13818
- }
13799
+ });
13800
+ });
13801
+ (0, import_promises.pipeline)(
13802
+ import_stream.Readable.from(promiseProcessedData),
13803
+ new import_stream.Transform({
13804
+ objectMode: true,
13805
+ transform: async (processedDataPr, _, callback) => {
13806
+ const processedData = await processedDataPr;
13807
+ try {
13808
+ processedData.forEach((item) => {
13809
+ const [timestamp] = item;
13810
+ if (timestamp && timestamp >= startDateMs && timestamp < endDateMs) {
13811
+ if (input.format === "array" /* array */) {
13812
+ stream.push(item);
13813
+ } else if (format === "json" /* json */) {
13814
+ const data = item.reduce((all, item2, i) => {
13815
+ const name = bodyHeaders[i];
13816
+ all[name] = item2;
13817
+ return all;
13818
+ }, {});
13819
+ stream.push(data);
13820
+ } else if (format === "csv" /* csv */) {
13821
+ if (firstLine) {
13822
+ const csvHeaders = bodyHeaders.join(",");
13823
+ stream.push(csvHeaders);
13824
+ firstLine = false;
13819
13825
  }
13820
- });
13821
- callback();
13822
- } catch (err) {
13823
- callback(err);
13826
+ stream.push(`
13827
+ ${item.join(",")}`);
13828
+ }
13824
13829
  }
13830
+ });
13831
+ if (++urlsProcessed === urlsforFetchingData.length) {
13832
+ stream.push(null);
13825
13833
  }
13826
- })
13827
- ).then(() => {
13828
- if (++urlsProcessed === urlsforFetchingData.length) {
13829
- this.push(null);
13834
+ callback();
13835
+ } catch (err) {
13836
+ callback(err);
13830
13837
  }
13831
- }).catch((err) => {
13832
- this.emit("error", err);
13833
- this.push(null);
13834
- });
13835
- } catch (err) {
13836
- this.emit("error", err);
13837
- this.push(null);
13838
- }
13839
- }
13840
- });
13838
+ }
13839
+ })
13840
+ ).catch((err) => {
13841
+ stream.emit("error", err);
13842
+ stream.push(null);
13843
+ });
13844
+ } catch (err) {
13845
+ stream.emit("error", err);
13846
+ stream.push(null);
13847
+ }
13841
13848
  return stream;
13842
13849
  }
13843
13850
 
13844
- // src/index.example.ts
13851
+ // src/index.example.stream.ts
13852
+ var printMemory = () => {
13853
+ const formatMemoryUsage = (data) => `${Math.round(data / 1024 / 1024 * 100) / 100} MB`;
13854
+ const memoryData = process.memoryUsage();
13855
+ const memoryUsage = {
13856
+ rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated for the process execution`,
13857
+ heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`,
13858
+ heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`,
13859
+ external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory`
13860
+ };
13861
+ console.log(memoryUsage);
13862
+ };
13845
13863
  (async () => {
13846
13864
  try {
13865
+ printMemory();
13847
13866
  const data = await getHistoricalRatesToStream({
13848
13867
  instrument: "eurusd",
13849
13868
  dates: {
13850
13869
  from: /* @__PURE__ */ new Date("2021-02-01"),
13851
- to: /* @__PURE__ */ new Date("2021-03-01")
13870
+ to: /* @__PURE__ */ new Date("2021-06-03")
13852
13871
  },
13853
- timeframe: "d1",
13872
+ timeframe: "m1",
13854
13873
  format: "csv"
13855
13874
  });
13856
13875
  data.on("data", (chunk) => {
13857
- console.log(chunk);
13876
+ process.stdout.write(chunk);
13858
13877
  });
13859
13878
  data.on("end", () => {
13860
- console.log("end");
13879
+ console.log();
13880
+ printMemory();
13861
13881
  });
13862
13882
  } catch (error) {
13863
13883
  console.log("error", error);
package/dist/index.js CHANGED
@@ -13767,7 +13767,7 @@ function formatBytes(bytes, decimals = 2) {
13767
13767
  }
13768
13768
 
13769
13769
  // package.json
13770
- var version = "1.1.0";
13770
+ var version = "1.1.2";
13771
13771
 
13772
13772
  // src/getHistoricalRates.ts
13773
13773
  var import_debug = __toESM(require("debug"));
@@ -13990,138 +13990,145 @@ var import_debug2 = __toESM(require("debug"));
13990
13990
  var import_stream = require("stream");
13991
13991
  var import_promises = require("stream/promises");
13992
13992
  var DEBUG_NAMESPACE2 = "dukascopy-node";
13993
- async function getHistoricalRatesToStream(config) {
13993
+ function getHistoricalRatesToStream(config) {
13994
13994
  const stream = new import_stream.Readable({
13995
13995
  objectMode: true,
13996
13996
  async read(_size) {
13997
- try {
13998
- const { input, isValid, validationErrors } = validateConfigNode(config);
13999
- (0, import_debug2.default)(`${DEBUG_NAMESPACE2}:config`)("%O", {
14000
- input,
14001
- isValid,
14002
- validationErrors
14003
- });
14004
- if (!isValid) {
14005
- this.emit("error", { validationErrors });
14006
- this.push(null);
14007
- return;
14008
- }
14009
- const {
14010
- instrument,
14011
- dates: { from, to },
14012
- timeframe,
14013
- priceType,
14014
- volumes,
14015
- volumeUnits,
14016
- utcOffset,
14017
- ignoreFlats,
14018
- format,
14019
- batchSize,
14020
- pauseBetweenBatchesMs,
14021
- useCache,
14022
- cacheFolderPath,
14023
- retryCount,
14024
- pauseBetweenRetriesMs,
14025
- retryOnEmpty
14026
- } = input;
14027
- const [startDate, endDate] = normaliseDates({
14028
- instrument,
14029
- startDate: from,
14030
- endDate: to,
14031
- timeframe,
14032
- utcOffset
14033
- });
14034
- const [startDateMs, endDateMs] = [+startDate, +endDate];
14035
- const onItemFetch = process.env.DEBUG ? (url, buffer, isCacheHit) => {
14036
- (0, import_debug2.default)(`${DEBUG_NAMESPACE2}:fetcher`)(
14037
- url,
14038
- `| ${formatBytes(buffer.length)} |`,
14039
- `${isCacheHit ? "cache" : "network"}`
14040
- );
14041
- } : void 0;
14042
- const bufferFetcher = new BufferFetcher({
14043
- batchSize,
14044
- pauseBetweenBatchesMs,
14045
- cacheManager: useCache ? new CacheManager({ cacheFolderPath }) : void 0,
14046
- retryCount,
14047
- pauseBetweenRetriesMs,
14048
- onItemFetch,
14049
- retryOnEmpty
14050
- });
14051
- let firstLine = true;
14052
- let urlsProcessed = 0;
14053
- const urlsforFetchingData = generateUrls({
14054
- instrument: input.instrument,
14055
- timeframe: input.timeframe,
14056
- priceType: input.priceType,
14057
- startDate,
14058
- endDate
13997
+ }
13998
+ });
13999
+ try {
14000
+ const { input, isValid, validationErrors } = validateConfigNode(config);
14001
+ (0, import_debug2.default)(`${DEBUG_NAMESPACE2}:config`)("%O", {
14002
+ input,
14003
+ isValid,
14004
+ validationErrors
14005
+ });
14006
+ if (!isValid) {
14007
+ stream.emit("error", { validationErrors });
14008
+ stream.push(null);
14009
+ return stream;
14010
+ }
14011
+ const {
14012
+ instrument,
14013
+ dates: { from, to },
14014
+ timeframe,
14015
+ priceType,
14016
+ volumes,
14017
+ volumeUnits,
14018
+ utcOffset,
14019
+ ignoreFlats,
14020
+ format,
14021
+ batchSize,
14022
+ pauseBetweenBatchesMs,
14023
+ useCache,
14024
+ cacheFolderPath,
14025
+ retryCount,
14026
+ pauseBetweenRetriesMs,
14027
+ retryOnEmpty
14028
+ } = input;
14029
+ const [startDate, endDate] = normaliseDates({
14030
+ instrument,
14031
+ startDate: from,
14032
+ endDate: to,
14033
+ timeframe,
14034
+ utcOffset
14035
+ });
14036
+ const [startDateMs, endDateMs] = [+startDate, +endDate];
14037
+ const onItemFetch = process.env.DEBUG ? (url, buffer, isCacheHit) => {
14038
+ (0, import_debug2.default)(`${DEBUG_NAMESPACE2}:fetcher`)(
14039
+ url,
14040
+ `| ${formatBytes(buffer.length)} |`,
14041
+ `${isCacheHit ? "cache" : "network"}`
14042
+ );
14043
+ } : void 0;
14044
+ const bufferFetcher = new BufferFetcher({
14045
+ batchSize,
14046
+ pauseBetweenBatchesMs,
14047
+ cacheManager: useCache ? new CacheManager({ cacheFolderPath }) : void 0,
14048
+ retryCount,
14049
+ pauseBetweenRetriesMs,
14050
+ onItemFetch,
14051
+ retryOnEmpty
14052
+ });
14053
+ const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
14054
+ let firstLine = true;
14055
+ let urlsProcessed = 0;
14056
+ const urlsforFetchingData = generateUrls({
14057
+ instrument: input.instrument,
14058
+ timeframe: input.timeframe,
14059
+ priceType: input.priceType,
14060
+ startDate,
14061
+ endDate
14062
+ });
14063
+ const promiseProcessedData = urlsforFetchingData.map((url) => {
14064
+ return new Promise((resolve2, reject) => {
14065
+ bufferFetcher.fetch([url]).then((bufferObjects) => {
14066
+ try {
14067
+ const processedData = processData({
14068
+ instrument: input.instrument,
14069
+ requestedTimeframe: input.timeframe,
14070
+ bufferObjects,
14071
+ priceType: input.priceType,
14072
+ volumes: input.volumes,
14073
+ volumeUnits: input.volumeUnits,
14074
+ ignoreFlats: input.ignoreFlats
14075
+ });
14076
+ resolve2(processedData);
14077
+ } catch (err) {
14078
+ reject(err);
14079
+ }
14080
+ }).catch((err) => {
14081
+ reject(err);
14059
14082
  });
14060
- await (0, import_promises.pipeline)(
14061
- import_stream.Readable.from(urlsforFetchingData),
14062
- new import_stream.Transform({
14063
- objectMode: true,
14064
- transform: async (url, _, callback) => {
14065
- const bufferObject = {
14066
- url,
14067
- buffer: await bufferFetcher.fetchBuffer(url),
14068
- isCacheHit: useCache
14069
- };
14070
- try {
14071
- const processedData = processData({
14072
- instrument: input.instrument,
14073
- requestedTimeframe: input.timeframe,
14074
- bufferObjects: [bufferObject],
14075
- priceType: input.priceType,
14076
- volumes: input.volumes,
14077
- volumeUnits: input.volumeUnits,
14078
- ignoreFlats: input.ignoreFlats
14079
- });
14080
- processedData.forEach((item) => {
14081
- const [timestamp] = item;
14082
- if (timestamp && timestamp >= startDateMs && timestamp < endDateMs) {
14083
- if (input.format === "array" /* array */) {
14084
- this.push(item);
14085
- } else {
14086
- const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
14087
- if (format === "json" /* json */) {
14088
- const data = item.reduce((all, item2, i) => {
14089
- const name = bodyHeaders[i];
14090
- all[name] = item2;
14091
- return all;
14092
- }, {});
14093
- this.push(data);
14094
- } else if (format === "csv" /* csv */) {
14095
- if (firstLine) {
14096
- const csvHeaders = bodyHeaders.join(",");
14097
- this.push(csvHeaders);
14098
- firstLine = false;
14099
- }
14100
- this.push(item.join(","));
14101
- }
14102
- }
14083
+ });
14084
+ });
14085
+ (0, import_promises.pipeline)(
14086
+ import_stream.Readable.from(promiseProcessedData),
14087
+ new import_stream.Transform({
14088
+ objectMode: true,
14089
+ transform: async (processedDataPr, _, callback) => {
14090
+ const processedData = await processedDataPr;
14091
+ try {
14092
+ processedData.forEach((item) => {
14093
+ const [timestamp] = item;
14094
+ if (timestamp && timestamp >= startDateMs && timestamp < endDateMs) {
14095
+ if (input.format === "array" /* array */) {
14096
+ stream.push(item);
14097
+ } else if (format === "json" /* json */) {
14098
+ const data = item.reduce((all, item2, i) => {
14099
+ const name = bodyHeaders[i];
14100
+ all[name] = item2;
14101
+ return all;
14102
+ }, {});
14103
+ stream.push(data);
14104
+ } else if (format === "csv" /* csv */) {
14105
+ if (firstLine) {
14106
+ const csvHeaders = bodyHeaders.join(",");
14107
+ stream.push(csvHeaders);
14108
+ firstLine = false;
14103
14109
  }
14104
- });
14105
- callback();
14106
- } catch (err) {
14107
- callback(err);
14110
+ stream.push(`
14111
+ ${item.join(",")}`);
14112
+ }
14108
14113
  }
14114
+ });
14115
+ if (++urlsProcessed === urlsforFetchingData.length) {
14116
+ stream.push(null);
14109
14117
  }
14110
- })
14111
- ).then(() => {
14112
- if (++urlsProcessed === urlsforFetchingData.length) {
14113
- this.push(null);
14118
+ callback();
14119
+ } catch (err) {
14120
+ callback(err);
14114
14121
  }
14115
- }).catch((err) => {
14116
- this.emit("error", err);
14117
- this.push(null);
14118
- });
14119
- } catch (err) {
14120
- this.emit("error", err);
14121
- this.push(null);
14122
- }
14123
- }
14124
- });
14122
+ }
14123
+ })
14124
+ ).catch((err) => {
14125
+ stream.emit("error", err);
14126
+ stream.push(null);
14127
+ });
14128
+ } catch (err) {
14129
+ stream.emit("error", err);
14130
+ stream.push(null);
14131
+ }
14125
14132
  return stream;
14126
14133
  }
14127
14134
  // Annotate the CommonJS export names for ESM import in node:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dukascopy-node-plus",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Node.js library for downloading historical market tick data for for Crypto, Stocks, ETFs, CFDs, Forex",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -13,7 +13,7 @@
13
13
  "dukascopy-node": "./dist/cli/index.js"
14
14
  },
15
15
  "scripts": {
16
- "build": "rm -rf dist && tsup-node src/index.ts src/cli/index.ts src/index.example.ts --format esm,cjs --dts --legacy-output",
16
+ "build": "rm -rf dist && tsup-node src/index.ts src/cli/index.ts src/index.example.stream.ts src/index.example.nostream.ts --format esm,cjs --dts --legacy-output",
17
17
  "test": "vitest run",
18
18
  "coverage": "vitest run --coverage",
19
19
  "format": "prettier --config .prettierrc 'src/**/*.ts' --write",