dukascopy-node-plus 1.0.0 → 1.1.0

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.
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
3
3
  }) : x)(function(x) {
4
4
  if (typeof require !== "undefined")
5
5
  return require.apply(this, arguments);
6
- throw new Error('Dynamic require of "' + x + '" is not supported');
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
7
  });
8
8
 
9
9
  // src/utils/instrument-meta-data/generated/instrument-enum.ts
@@ -230,6 +230,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
230
230
  Instrument2["bbwiususd"] = "bbwiususd";
231
231
  Instrument2["bbyususd"] = "bbyususd";
232
232
  Instrument2["bciteur"] = "bciteur";
233
+ Instrument2["bchchf"] = "bchchf";
234
+ Instrument2["bcheur"] = "bcheur";
235
+ Instrument2["bchgbp"] = "bchgbp";
233
236
  Instrument2["bchusd"] = "bchusd";
234
237
  Instrument2["bdevgbgbx"] = "bdevgbgbx";
235
238
  Instrument2["bdxususd"] = "bdxususd";
@@ -270,6 +273,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
270
273
  Instrument2["brxususd"] = "brxususd";
271
274
  Instrument2["bsxususd"] = "bsxususd";
272
275
  Instrument2["btgbgbx"] = "btgbgbx";
276
+ Instrument2["btcchf"] = "btcchf";
277
+ Instrument2["btceur"] = "btceur";
278
+ Instrument2["btcgbp"] = "btcgbp";
273
279
  Instrument2["btcusd"] = "btcusd";
274
280
  Instrument2["bundtreur"] = "bundtreur";
275
281
  Instrument2["burlususd"] = "burlususd";
@@ -460,6 +466,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
460
466
  Instrument2["esususd"] = "esususd";
461
467
  Instrument2["essususd"] = "essususd";
462
468
  Instrument2["estcususd"] = "estcususd";
469
+ Instrument2["ethchf"] = "ethchf";
470
+ Instrument2["etheur"] = "etheur";
471
+ Instrument2["ethgbp"] = "ethgbp";
463
472
  Instrument2["ethusd"] = "ethusd";
464
473
  Instrument2["etnususd"] = "etnususd";
465
474
  Instrument2["etsyususd"] = "etsyususd";
@@ -728,6 +737,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
728
737
  Instrument2["lsegbgbx"] = "lsegbgbx";
729
738
  Instrument2["lsiususd"] = "lsiususd";
730
739
  Instrument2["lstrususd"] = "lstrususd";
740
+ Instrument2["ltcchf"] = "ltcchf";
741
+ Instrument2["ltceur"] = "ltceur";
742
+ Instrument2["ltcgbp"] = "ltcgbp";
731
743
  Instrument2["ltcusd"] = "ltcusd";
732
744
  Instrument2["luluususd"] = "luluususd";
733
745
  Instrument2["luvususd"] = "luvususd";
@@ -1231,6 +1243,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
1231
1243
  Instrument2["xlfususd"] = "xlfususd";
1232
1244
  Instrument2["xliususd"] = "xliususd";
1233
1245
  Instrument2["xlkususd"] = "xlkususd";
1246
+ Instrument2["xlmchf"] = "xlmchf";
1247
+ Instrument2["xlmeur"] = "xlmeur";
1248
+ Instrument2["xlmgbp"] = "xlmgbp";
1234
1249
  Instrument2["xlmusd"] = "xlmusd";
1235
1250
  Instrument2["xlnxususd"] = "xlnxususd";
1236
1251
  Instrument2["xlpususd"] = "xlpususd";
@@ -1292,8 +1307,17 @@ var Format = /* @__PURE__ */ ((Format2) => {
1292
1307
 
1293
1308
  // src/config/volume-unit.ts
1294
1309
  var VolumeUnit = {
1310
+ /**
1311
+ * A single unit of a currency, commodity, or security.
1312
+ */
1295
1313
  units: "units",
1314
+ /**
1315
+ * A thousand units of a currency, commodity, or security.
1316
+ */
1296
1317
  thousands: "thousands",
1318
+ /**
1319
+ * A million units of a currency, commodity, or security.
1320
+ */
1297
1321
  millions: "millions"
1298
1322
  };
1299
1323
 
@@ -3344,7 +3368,7 @@ var instrument_meta_data_default = {
3344
3368
  batusd: {
3345
3369
  name: "BAT/USD",
3346
3370
  description: "Basic Attention Token vs US Dollar",
3347
- decimalFactor: 1e5,
3371
+ decimalFactor: 1e3,
3348
3372
  startHourForTicks: "2019-08-05T00:00:02.214Z",
3349
3373
  startDayForMinuteCandles: "2019-08-05T00:00:00.000Z",
3350
3374
  startMonthForHourlyCandles: "2019-08-05T00:00:00.000Z",
@@ -3422,6 +3446,33 @@ var instrument_meta_data_default = {
3422
3446
  startMonthForHourlyCandles: "2020-11-02T12:00:00.000Z",
3423
3447
  startYearForDailyCandles: "2020-11-02T00:00:00.000Z"
3424
3448
  },
3449
+ bchchf: {
3450
+ name: "BCH/CHF",
3451
+ description: "Bitcoin Cash vs Swiss Franc",
3452
+ decimalFactor: 10,
3453
+ startHourForTicks: "2023-03-14T14:52:58.644Z",
3454
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
3455
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3456
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3457
+ },
3458
+ bcheur: {
3459
+ name: "BCH/EUR",
3460
+ description: "Bitcoin Cash vs Euro",
3461
+ decimalFactor: 10,
3462
+ startHourForTicks: "2023-03-14T14:53:02.753Z",
3463
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3464
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3465
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3466
+ },
3467
+ bchgbp: {
3468
+ name: "BCH/GBP",
3469
+ description: "Bitcoin Cash vs Pound Sterling",
3470
+ decimalFactor: 10,
3471
+ startHourForTicks: "2023-03-14T14:53:02.089Z",
3472
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3473
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3474
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3475
+ },
3425
3476
  bchusd: {
3426
3477
  name: "BCH/USD",
3427
3478
  description: "Bitcoin Cash vs US dollar",
@@ -3782,6 +3833,33 @@ var instrument_meta_data_default = {
3782
3833
  startMonthForHourlyCandles: "2011-01-04T08:00:00.000Z",
3783
3834
  startYearForDailyCandles: "2011-01-04T00:00:00.000Z"
3784
3835
  },
3836
+ btcchf: {
3837
+ name: "BTC/CHF",
3838
+ description: "Bitcoin vs Swiss Frank",
3839
+ decimalFactor: 10,
3840
+ startHourForTicks: "2023-03-14T14:53:06.990Z",
3841
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3842
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3843
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3844
+ },
3845
+ btceur: {
3846
+ name: "BTC/EUR",
3847
+ description: "Bitcoin vs Euro",
3848
+ decimalFactor: 10,
3849
+ startHourForTicks: "2018-05-15T10:25:32.340Z",
3850
+ startDayForMinuteCandles: "2018-05-15T10:24:00.000Z",
3851
+ startMonthForHourlyCandles: "2018-05-15T10:00:00.000Z",
3852
+ startYearForDailyCandles: "2018-05-15T00:00:00.000Z"
3853
+ },
3854
+ btcgbp: {
3855
+ name: "BTC/GBP",
3856
+ description: "Bitcoin vs Pound Sterling",
3857
+ decimalFactor: 10,
3858
+ startHourForTicks: "2023-03-14T15:03:45.307Z",
3859
+ startDayForMinuteCandles: "2023-03-14T15:03:00.000Z",
3860
+ startMonthForHourlyCandles: "2023-03-14T15:00:00.000Z",
3861
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3862
+ },
3785
3863
  btcusd: {
3786
3864
  name: "BTC/USD",
3787
3865
  description: "Bitcoin vs US Dollar",
@@ -5492,6 +5570,33 @@ var instrument_meta_data_default = {
5492
5570
  startMonthForHourlyCandles: "2022-05-12T13:00:00.000Z",
5493
5571
  startYearForDailyCandles: "2022-05-12T00:00:00.000Z"
5494
5572
  },
5573
+ ethchf: {
5574
+ name: "ETH/CHF",
5575
+ description: "Ether vs Swiss Franc",
5576
+ decimalFactor: 10,
5577
+ startHourForTicks: "2023-03-14T14:53:03.726Z",
5578
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5579
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5580
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5581
+ },
5582
+ etheur: {
5583
+ name: "ETH/EUR",
5584
+ description: "Ether vs Euro",
5585
+ decimalFactor: 10,
5586
+ startHourForTicks: "2023-03-14T14:53:03.677Z",
5587
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5588
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5589
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5590
+ },
5591
+ ethgbp: {
5592
+ name: "ETH/GBP",
5593
+ description: "Ether vs Pound Sterling",
5594
+ decimalFactor: 10,
5595
+ startHourForTicks: "2023-03-14T14:53:03.676Z",
5596
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5597
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5598
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5599
+ },
5495
5600
  ethusd: {
5496
5601
  name: "ETH/USD",
5497
5602
  description: "Ether vs US Dollar",
@@ -7904,6 +8009,33 @@ var instrument_meta_data_default = {
7904
8009
  startMonthForHourlyCandles: "2022-05-13T13:00:00.000Z",
7905
8010
  startYearForDailyCandles: "2022-05-13T00:00:00.000Z"
7906
8011
  },
8012
+ ltcchf: {
8013
+ name: "LTC/CHF",
8014
+ description: "Litecoin vs Swiss Franc",
8015
+ decimalFactor: 10,
8016
+ startHourForTicks: "2023-03-14T14:52:50.061Z",
8017
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
8018
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8019
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8020
+ },
8021
+ ltceur: {
8022
+ name: "LTC/EUR",
8023
+ description: "Litecoin vs Euro",
8024
+ decimalFactor: 10,
8025
+ startHourForTicks: "2023-03-14T14:55:12.375Z",
8026
+ startDayForMinuteCandles: "2023-03-14T14:55:00.000Z",
8027
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8028
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8029
+ },
8030
+ ltcgbp: {
8031
+ name: "LTC/GBP",
8032
+ description: "Pound Sterling",
8033
+ decimalFactor: 10,
8034
+ startHourForTicks: "2023-03-14T14:52:50.074Z",
8035
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
8036
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8037
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8038
+ },
7907
8039
  ltcusd: {
7908
8040
  name: "LTC/USD",
7909
8041
  description: "Litecoin vs US Dollar",
@@ -12431,6 +12563,33 @@ var instrument_meta_data_default = {
12431
12563
  startMonthForHourlyCandles: "2017-11-15T16:00:00.000Z",
12432
12564
  startYearForDailyCandles: "2017-11-15T00:00:00.000Z"
12433
12565
  },
12566
+ xlmchf: {
12567
+ name: "XLM/CHF",
12568
+ description: "Stellar vs Swiss Franc",
12569
+ decimalFactor: 1e5,
12570
+ startHourForTicks: "2023-03-14T14:53:03.870Z",
12571
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12572
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12573
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12574
+ },
12575
+ xlmeur: {
12576
+ name: "XLM/EUR",
12577
+ description: "Stellar vs Euro",
12578
+ decimalFactor: 1e5,
12579
+ startHourForTicks: "2023-03-14T14:53:03.820Z",
12580
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12581
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12582
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12583
+ },
12584
+ xlmgbp: {
12585
+ name: "XLM/GBP",
12586
+ description: "Stellar vs Pound Sterling",
12587
+ decimalFactor: 1e5,
12588
+ startHourForTicks: "2023-03-14T14:53:03.821Z",
12589
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12590
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12591
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12592
+ },
12434
12593
  xlmusd: {
12435
12594
  name: "XLM/USD",
12436
12595
  description: "Stellar vs US Dollar",
@@ -12704,7 +12863,7 @@ function normaliseDates({
12704
12863
  minFromIsoDate = startYearForDailyCandles;
12705
12864
  }
12706
12865
  let minFromDate = new Date(minFromIsoDate);
12707
- let maxToDate = new Date();
12866
+ let maxToDate = /* @__PURE__ */ new Date();
12708
12867
  if (utcOffset) {
12709
12868
  startDate.setUTCMinutes(startDate.getUTCMinutes() + utcOffset);
12710
12869
  endDate.setUTCMinutes(endDate.getUTCMinutes() + utcOffset);
@@ -12726,7 +12885,7 @@ function getYMDH(date) {
12726
12885
  }
12727
12886
  function getStartOfUtc(date, period, offset = 0) {
12728
12887
  const [year, month, day, hours] = getYMDH(date);
12729
- let startOfUtc = new Date();
12888
+ let startOfUtc = /* @__PURE__ */ new Date();
12730
12889
  if (period === "hour") {
12731
12890
  startOfUtc = new Date(Date.UTC(year, month, day, hours + offset));
12732
12891
  } else if (period === "day") {
@@ -12740,7 +12899,7 @@ function getStartOfUtc(date, period, offset = 0) {
12740
12899
  }
12741
12900
  function getIsCurrentObj(date) {
12742
12901
  const [year, month, day, hours] = getYMDH(date);
12743
- const [currentYear, currentMonth, currentDay, currentHours] = getYMDH(new Date());
12902
+ const [currentYear, currentMonth, currentDay, currentHours] = getYMDH(/* @__PURE__ */ new Date());
12744
12903
  const isCurrentYear = year === currentYear;
12745
12904
  const isCurrentMonth = isCurrentYear && month === currentMonth;
12746
12905
  const isCurrentDay = isCurrentMonth && day === currentDay;
@@ -12902,7 +13061,7 @@ function getConstructor(instrument, priceType, endDate) {
12902
13061
  };
12903
13062
  }
12904
13063
  function getDateLimit(startDate, endDate, timeframe) {
12905
- const nowDate = new Date();
13064
+ const nowDate = /* @__PURE__ */ new Date();
12906
13065
  const adjustedEndDate = endDate < nowDate ? endDate : nowDate;
12907
13066
  let dateLimit = adjustedEndDate;
12908
13067
  if (timeframe === "tick" /* tick */ || timeframe === "s1" /* s1 */ || timeframe === "m1" /* m1 */ || timeframe === "m5" /* m5 */ || timeframe === "m15" /* m15 */ || timeframe === "m30" /* m30 */) {
@@ -12937,6 +13096,16 @@ function generateUrls({
12937
13096
  // src/buffer-fetcher/index.ts
12938
13097
  import fetch, { Response } from "node-fetch";
12939
13098
  var BufferFetcher = class {
13099
+ batchSize;
13100
+ pauseBetweenBatchesMs;
13101
+ onItemFetch;
13102
+ onBatchFetch;
13103
+ fetcherFn;
13104
+ retryCount;
13105
+ retryOnEmpty;
13106
+ pauseBetweenRetriesMs;
13107
+ failAfterRetryCount;
13108
+ cacheManager;
12940
13109
  constructor({
12941
13110
  batchSize = 10,
12942
13111
  pauseBetweenBatchesMs = 1e3,
@@ -12981,6 +13150,9 @@ var BufferFetcher = class {
12981
13150
  })
12982
13151
  );
12983
13152
  }
13153
+ /**
13154
+ * @experimental
13155
+ */
12984
13156
  async fetch_optimized(urls) {
12985
13157
  const batches = splitArrayInChunks(urls, this.batchSize);
12986
13158
  for (let i = 0, n = batches.length; i < n; i++) {
@@ -13038,7 +13210,6 @@ var BufferFetcher = class {
13038
13210
  return bufferObjects;
13039
13211
  }
13040
13212
  async fetchBuffer(url) {
13041
- var _a;
13042
13213
  if (this.fetcherFn) {
13043
13214
  return this.fetcherFn(url);
13044
13215
  }
@@ -13058,7 +13229,7 @@ var BufferFetcher = class {
13058
13229
  errorMsg = e instanceof Error ? e.message : JSON.stringify(e);
13059
13230
  }
13060
13231
  const isStatusOk = response.status === 200;
13061
- const contentLength = Number(((_a = response == null ? void 0 : response.headers) == null ? void 0 : _a.get("content-length")) || 0);
13232
+ const contentLength = Number(response?.headers?.get("content-length") || 0);
13062
13233
  const isResponseWithData = contentLength > 0;
13063
13234
  isTrySuccess = isCallSuccess && isStatusOk;
13064
13235
  if (this.retryOnEmpty) {
@@ -13153,7 +13324,7 @@ function getOHLC({
13153
13324
  volumes
13154
13325
  }) {
13155
13326
  if (filterFlats) {
13156
- input = input.filter((data) => (data == null ? void 0 : data[5]) !== 0);
13327
+ input = input.filter((data) => data?.[5] !== 0);
13157
13328
  }
13158
13329
  if (input.length === 0) {
13159
13330
  return [];
@@ -13488,6 +13659,9 @@ import { resolve } from "path";
13488
13659
  import { outputFile, remove, readFile, readdirSync, ensureDirSync } from "fs-extra";
13489
13660
  var DEFAULT_CACHE_FOLDER = ".dukascopy-cache";
13490
13661
  var CacheManager = class {
13662
+ cacheManifest;
13663
+ cacheFolderPath;
13664
+ cacheKeyFormatter;
13491
13665
  constructor({
13492
13666
  cacheFolderPath,
13493
13667
  cacheKeyFormatter
@@ -13542,9 +13716,6 @@ function formatBytes(bytes, decimals = 2) {
13542
13716
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
13543
13717
  }
13544
13718
 
13545
- // package.json
13546
- var version = "1.0.1";
13547
-
13548
13719
  export {
13549
13720
  __require,
13550
13721
  Instrument,
@@ -13565,6 +13736,5 @@ export {
13565
13736
  BufferFetcher,
13566
13737
  processData,
13567
13738
  CacheManager,
13568
- formatBytes,
13569
- version
13739
+ formatBytes
13570
13740
  };
@@ -0,0 +1,6 @@
1
+ // package.json
2
+ var version = "1.1.0";
3
+
4
+ export {
5
+ version
6
+ };
@@ -0,0 +1,184 @@
1
+ import {
2
+ BufferFetcher,
3
+ CacheManager,
4
+ formatBytes,
5
+ generateUrls,
6
+ normaliseDates,
7
+ processData,
8
+ validateConfigNode
9
+ } from "./chunk-D3M3SVMW.js";
10
+
11
+ // src/output-formatter/index.ts
12
+ var candleHeaders = ["timestamp", "open", "high", "low", "close", "volume"];
13
+ var tickHeaders = ["timestamp", "askPrice", "bidPrice", "askVolume", "bidVolume"];
14
+ function formatOutput({
15
+ processedData,
16
+ format,
17
+ timeframe
18
+ }) {
19
+ if (processedData.length === 0) {
20
+ return [];
21
+ }
22
+ const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
23
+ if (format === "json" /* json */) {
24
+ const data = processedData.map((arr) => {
25
+ return arr.reduce((all, item, i) => {
26
+ const name = bodyHeaders[i];
27
+ all[name] = item;
28
+ return all;
29
+ }, {});
30
+ });
31
+ return data;
32
+ }
33
+ if (format === "csv" /* csv */) {
34
+ const csvHeaders = bodyHeaders.filter((_, i) => processedData[0][i] !== void 0);
35
+ const csv = [csvHeaders, ...processedData].map((arr) => arr.join(",")).join("\n");
36
+ return csv;
37
+ }
38
+ return processedData;
39
+ }
40
+
41
+ // src/getHistoricalRatesToStream.ts
42
+ import debug from "debug";
43
+ import { Readable, Transform } from "stream";
44
+ import { pipeline } from "stream/promises";
45
+ var DEBUG_NAMESPACE = "dukascopy-node";
46
+ async function getHistoricalRatesToStream(config) {
47
+ const stream = new Readable({
48
+ objectMode: true,
49
+ async read(_size) {
50
+ try {
51
+ const { input, isValid, validationErrors } = validateConfigNode(config);
52
+ debug(`${DEBUG_NAMESPACE}:config`)("%O", {
53
+ input,
54
+ isValid,
55
+ validationErrors
56
+ });
57
+ if (!isValid) {
58
+ this.emit("error", { validationErrors });
59
+ this.push(null);
60
+ return;
61
+ }
62
+ const {
63
+ instrument,
64
+ dates: { from, to },
65
+ timeframe,
66
+ priceType,
67
+ volumes,
68
+ volumeUnits,
69
+ utcOffset,
70
+ ignoreFlats,
71
+ format,
72
+ batchSize,
73
+ pauseBetweenBatchesMs,
74
+ useCache,
75
+ cacheFolderPath,
76
+ retryCount,
77
+ pauseBetweenRetriesMs,
78
+ retryOnEmpty
79
+ } = input;
80
+ const [startDate, endDate] = normaliseDates({
81
+ instrument,
82
+ startDate: from,
83
+ endDate: to,
84
+ timeframe,
85
+ utcOffset
86
+ });
87
+ const [startDateMs, endDateMs] = [+startDate, +endDate];
88
+ const onItemFetch = process.env.DEBUG ? (url, buffer, isCacheHit) => {
89
+ debug(`${DEBUG_NAMESPACE}:fetcher`)(
90
+ url,
91
+ `| ${formatBytes(buffer.length)} |`,
92
+ `${isCacheHit ? "cache" : "network"}`
93
+ );
94
+ } : void 0;
95
+ const bufferFetcher = new BufferFetcher({
96
+ batchSize,
97
+ pauseBetweenBatchesMs,
98
+ cacheManager: useCache ? new CacheManager({ cacheFolderPath }) : void 0,
99
+ retryCount,
100
+ pauseBetweenRetriesMs,
101
+ onItemFetch,
102
+ retryOnEmpty
103
+ });
104
+ let firstLine = true;
105
+ let urlsProcessed = 0;
106
+ const urlsforFetchingData = generateUrls({
107
+ instrument: input.instrument,
108
+ timeframe: input.timeframe,
109
+ priceType: input.priceType,
110
+ startDate,
111
+ endDate
112
+ });
113
+ await pipeline(
114
+ Readable.from(urlsforFetchingData),
115
+ new Transform({
116
+ objectMode: true,
117
+ transform: async (url, _, callback) => {
118
+ const bufferObject = {
119
+ url,
120
+ buffer: await bufferFetcher.fetchBuffer(url),
121
+ isCacheHit: useCache
122
+ };
123
+ try {
124
+ const processedData = processData({
125
+ instrument: input.instrument,
126
+ requestedTimeframe: input.timeframe,
127
+ bufferObjects: [bufferObject],
128
+ priceType: input.priceType,
129
+ volumes: input.volumes,
130
+ volumeUnits: input.volumeUnits,
131
+ ignoreFlats: input.ignoreFlats
132
+ });
133
+ processedData.forEach((item) => {
134
+ const [timestamp] = item;
135
+ if (timestamp && timestamp >= startDateMs && timestamp < endDateMs) {
136
+ if (input.format === "array" /* array */) {
137
+ this.push(item);
138
+ } else {
139
+ const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
140
+ if (format === "json" /* json */) {
141
+ const data = item.reduce((all, item2, i) => {
142
+ const name = bodyHeaders[i];
143
+ all[name] = item2;
144
+ return all;
145
+ }, {});
146
+ this.push(data);
147
+ } else if (format === "csv" /* csv */) {
148
+ if (firstLine) {
149
+ const csvHeaders = bodyHeaders.join(",");
150
+ this.push(csvHeaders);
151
+ firstLine = false;
152
+ }
153
+ this.push(item.join(","));
154
+ }
155
+ }
156
+ }
157
+ });
158
+ callback();
159
+ } catch (err) {
160
+ callback(err);
161
+ }
162
+ }
163
+ })
164
+ ).then(() => {
165
+ if (++urlsProcessed === urlsforFetchingData.length) {
166
+ this.push(null);
167
+ }
168
+ }).catch((err) => {
169
+ this.emit("error", err);
170
+ this.push(null);
171
+ });
172
+ } catch (err) {
173
+ this.emit("error", err);
174
+ this.push(null);
175
+ }
176
+ }
177
+ });
178
+ return stream;
179
+ }
180
+
181
+ export {
182
+ formatOutput,
183
+ getHistoricalRatesToStream
184
+ };
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ version
4
+ } from "../chunk-DWZJECKF.js";
2
5
  import {
3
6
  BufferFetcher,
4
7
  CacheManager,
@@ -12,9 +15,8 @@ import {
12
15
  normaliseDates,
13
16
  processData,
14
17
  schema,
15
- validateConfig,
16
- version
17
- } from "../chunk-QOULS5Y3.js";
18
+ validateConfig
19
+ } from "../chunk-D3M3SVMW.js";
18
20
 
19
21
  // src/cli/cli.ts
20
22
  import { resolve, join } from "path";
@@ -62,7 +64,7 @@ var commanderSchema = program.option("-d, --debug", "Output extra debugging", fa
62
64
  function getConfigFromCliArgs(argv) {
63
65
  const options = commanderSchema.parse(argv).opts();
64
66
  if (options.dateTo === now) {
65
- options.dateTo = new Date();
67
+ options.dateTo = /* @__PURE__ */ new Date();
66
68
  }
67
69
  const cliConfig = {
68
70
  instrument: options.instrument,
@@ -167,8 +169,16 @@ import tz from "dayjs/plugin/timezone";
167
169
  // src/stream-writer/index.ts
168
170
  import fs from "fs";
169
171
  var BatchStreamWriter = class {
172
+ fileWriteStream;
173
+ timeframe;
174
+ format;
175
+ isInline;
176
+ volumes;
177
+ isFileEmpty = true;
178
+ bodyHeaders;
179
+ startDateTs;
180
+ endDateTs;
170
181
  constructor(options) {
171
- this.isFileEmpty = true;
172
182
  this.fileWriteStream = options.fileWriteStream;
173
183
  this.timeframe = options.timeframe;
174
184
  this.format = options.format;
@@ -445,7 +455,7 @@ async function run(argv) {
445
455
  } else {
446
456
  printErrors(
447
457
  "Search config invalid:",
448
- validationErrors.map((err) => (err == null ? void 0 : err.message) || "")
458
+ validationErrors.map((err) => err?.message || "")
449
459
  );
450
460
  process.exit(0);
451
461
  }
@@ -0,0 +1,27 @@
1
+ import {
2
+ getHistoricalRatesToStream
3
+ } from "./chunk-KWYYNULA.js";
4
+ import "./chunk-D3M3SVMW.js";
5
+
6
+ // src/index.example.ts
7
+ (async () => {
8
+ try {
9
+ const data = await getHistoricalRatesToStream({
10
+ instrument: "eurusd",
11
+ dates: {
12
+ from: /* @__PURE__ */ new Date("2021-02-01"),
13
+ to: /* @__PURE__ */ new Date("2021-03-01")
14
+ },
15
+ timeframe: "d1",
16
+ format: "csv"
17
+ });
18
+ data.on("data", (chunk) => {
19
+ console.log(chunk);
20
+ });
21
+ data.on("end", () => {
22
+ console.log("end");
23
+ });
24
+ } catch (error) {
25
+ console.log("error", error);
26
+ }
27
+ })();