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.
package/dist/index.js CHANGED
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  return to;
19
19
  };
20
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
@@ -45,6 +49,7 @@ __export(src_exports, {
45
49
  getCurrentRates: () => getCurrentRates,
46
50
  getHistoricRates: () => getHistoricRates,
47
51
  getHistoricalRates: () => getHistoricalRates,
52
+ getHistoricalRatesToStream: () => getHistoricalRatesToStream,
48
53
  normaliseDates: () => normaliseDates,
49
54
  processData: () => processData,
50
55
  schema: () => schema,
@@ -280,6 +285,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
280
285
  Instrument2["bbwiususd"] = "bbwiususd";
281
286
  Instrument2["bbyususd"] = "bbyususd";
282
287
  Instrument2["bciteur"] = "bciteur";
288
+ Instrument2["bchchf"] = "bchchf";
289
+ Instrument2["bcheur"] = "bcheur";
290
+ Instrument2["bchgbp"] = "bchgbp";
283
291
  Instrument2["bchusd"] = "bchusd";
284
292
  Instrument2["bdevgbgbx"] = "bdevgbgbx";
285
293
  Instrument2["bdxususd"] = "bdxususd";
@@ -320,6 +328,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
320
328
  Instrument2["brxususd"] = "brxususd";
321
329
  Instrument2["bsxususd"] = "bsxususd";
322
330
  Instrument2["btgbgbx"] = "btgbgbx";
331
+ Instrument2["btcchf"] = "btcchf";
332
+ Instrument2["btceur"] = "btceur";
333
+ Instrument2["btcgbp"] = "btcgbp";
323
334
  Instrument2["btcusd"] = "btcusd";
324
335
  Instrument2["bundtreur"] = "bundtreur";
325
336
  Instrument2["burlususd"] = "burlususd";
@@ -510,6 +521,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
510
521
  Instrument2["esususd"] = "esususd";
511
522
  Instrument2["essususd"] = "essususd";
512
523
  Instrument2["estcususd"] = "estcususd";
524
+ Instrument2["ethchf"] = "ethchf";
525
+ Instrument2["etheur"] = "etheur";
526
+ Instrument2["ethgbp"] = "ethgbp";
513
527
  Instrument2["ethusd"] = "ethusd";
514
528
  Instrument2["etnususd"] = "etnususd";
515
529
  Instrument2["etsyususd"] = "etsyususd";
@@ -778,6 +792,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
778
792
  Instrument2["lsegbgbx"] = "lsegbgbx";
779
793
  Instrument2["lsiususd"] = "lsiususd";
780
794
  Instrument2["lstrususd"] = "lstrususd";
795
+ Instrument2["ltcchf"] = "ltcchf";
796
+ Instrument2["ltceur"] = "ltceur";
797
+ Instrument2["ltcgbp"] = "ltcgbp";
781
798
  Instrument2["ltcusd"] = "ltcusd";
782
799
  Instrument2["luluususd"] = "luluususd";
783
800
  Instrument2["luvususd"] = "luvususd";
@@ -1281,6 +1298,9 @@ var Instrument = /* @__PURE__ */ ((Instrument2) => {
1281
1298
  Instrument2["xlfususd"] = "xlfususd";
1282
1299
  Instrument2["xliususd"] = "xliususd";
1283
1300
  Instrument2["xlkususd"] = "xlkususd";
1301
+ Instrument2["xlmchf"] = "xlmchf";
1302
+ Instrument2["xlmeur"] = "xlmeur";
1303
+ Instrument2["xlmgbp"] = "xlmgbp";
1284
1304
  Instrument2["xlmusd"] = "xlmusd";
1285
1305
  Instrument2["xlnxususd"] = "xlnxususd";
1286
1306
  Instrument2["xlpususd"] = "xlpususd";
@@ -1342,8 +1362,17 @@ var Format = /* @__PURE__ */ ((Format2) => {
1342
1362
 
1343
1363
  // src/config/volume-unit.ts
1344
1364
  var VolumeUnit = {
1365
+ /**
1366
+ * A single unit of a currency, commodity, or security.
1367
+ */
1345
1368
  units: "units",
1369
+ /**
1370
+ * A thousand units of a currency, commodity, or security.
1371
+ */
1346
1372
  thousands: "thousands",
1373
+ /**
1374
+ * A million units of a currency, commodity, or security.
1375
+ */
1347
1376
  millions: "millions"
1348
1377
  };
1349
1378
 
@@ -3393,7 +3422,7 @@ var instrument_meta_data_default = {
3393
3422
  batusd: {
3394
3423
  name: "BAT/USD",
3395
3424
  description: "Basic Attention Token vs US Dollar",
3396
- decimalFactor: 1e5,
3425
+ decimalFactor: 1e3,
3397
3426
  startHourForTicks: "2019-08-05T00:00:02.214Z",
3398
3427
  startDayForMinuteCandles: "2019-08-05T00:00:00.000Z",
3399
3428
  startMonthForHourlyCandles: "2019-08-05T00:00:00.000Z",
@@ -3471,6 +3500,33 @@ var instrument_meta_data_default = {
3471
3500
  startMonthForHourlyCandles: "2020-11-02T12:00:00.000Z",
3472
3501
  startYearForDailyCandles: "2020-11-02T00:00:00.000Z"
3473
3502
  },
3503
+ bchchf: {
3504
+ name: "BCH/CHF",
3505
+ description: "Bitcoin Cash vs Swiss Franc",
3506
+ decimalFactor: 10,
3507
+ startHourForTicks: "2023-03-14T14:52:58.644Z",
3508
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
3509
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3510
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3511
+ },
3512
+ bcheur: {
3513
+ name: "BCH/EUR",
3514
+ description: "Bitcoin Cash vs Euro",
3515
+ decimalFactor: 10,
3516
+ startHourForTicks: "2023-03-14T14:53:02.753Z",
3517
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3518
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3519
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3520
+ },
3521
+ bchgbp: {
3522
+ name: "BCH/GBP",
3523
+ description: "Bitcoin Cash vs Pound Sterling",
3524
+ decimalFactor: 10,
3525
+ startHourForTicks: "2023-03-14T14:53:02.089Z",
3526
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3527
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3528
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3529
+ },
3474
3530
  bchusd: {
3475
3531
  name: "BCH/USD",
3476
3532
  description: "Bitcoin Cash vs US dollar",
@@ -3831,6 +3887,33 @@ var instrument_meta_data_default = {
3831
3887
  startMonthForHourlyCandles: "2011-01-04T08:00:00.000Z",
3832
3888
  startYearForDailyCandles: "2011-01-04T00:00:00.000Z"
3833
3889
  },
3890
+ btcchf: {
3891
+ name: "BTC/CHF",
3892
+ description: "Bitcoin vs Swiss Frank",
3893
+ decimalFactor: 10,
3894
+ startHourForTicks: "2023-03-14T14:53:06.990Z",
3895
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
3896
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
3897
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3898
+ },
3899
+ btceur: {
3900
+ name: "BTC/EUR",
3901
+ description: "Bitcoin vs Euro",
3902
+ decimalFactor: 10,
3903
+ startHourForTicks: "2018-05-15T10:25:32.340Z",
3904
+ startDayForMinuteCandles: "2018-05-15T10:24:00.000Z",
3905
+ startMonthForHourlyCandles: "2018-05-15T10:00:00.000Z",
3906
+ startYearForDailyCandles: "2018-05-15T00:00:00.000Z"
3907
+ },
3908
+ btcgbp: {
3909
+ name: "BTC/GBP",
3910
+ description: "Bitcoin vs Pound Sterling",
3911
+ decimalFactor: 10,
3912
+ startHourForTicks: "2023-03-14T15:03:45.307Z",
3913
+ startDayForMinuteCandles: "2023-03-14T15:03:00.000Z",
3914
+ startMonthForHourlyCandles: "2023-03-14T15:00:00.000Z",
3915
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
3916
+ },
3834
3917
  btcusd: {
3835
3918
  name: "BTC/USD",
3836
3919
  description: "Bitcoin vs US Dollar",
@@ -5541,6 +5624,33 @@ var instrument_meta_data_default = {
5541
5624
  startMonthForHourlyCandles: "2022-05-12T13:00:00.000Z",
5542
5625
  startYearForDailyCandles: "2022-05-12T00:00:00.000Z"
5543
5626
  },
5627
+ ethchf: {
5628
+ name: "ETH/CHF",
5629
+ description: "Ether vs Swiss Franc",
5630
+ decimalFactor: 10,
5631
+ startHourForTicks: "2023-03-14T14:53:03.726Z",
5632
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5633
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5634
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5635
+ },
5636
+ etheur: {
5637
+ name: "ETH/EUR",
5638
+ description: "Ether vs Euro",
5639
+ decimalFactor: 10,
5640
+ startHourForTicks: "2023-03-14T14:53:03.677Z",
5641
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5642
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5643
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5644
+ },
5645
+ ethgbp: {
5646
+ name: "ETH/GBP",
5647
+ description: "Ether vs Pound Sterling",
5648
+ decimalFactor: 10,
5649
+ startHourForTicks: "2023-03-14T14:53:03.676Z",
5650
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
5651
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
5652
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
5653
+ },
5544
5654
  ethusd: {
5545
5655
  name: "ETH/USD",
5546
5656
  description: "Ether vs US Dollar",
@@ -7953,6 +8063,33 @@ var instrument_meta_data_default = {
7953
8063
  startMonthForHourlyCandles: "2022-05-13T13:00:00.000Z",
7954
8064
  startYearForDailyCandles: "2022-05-13T00:00:00.000Z"
7955
8065
  },
8066
+ ltcchf: {
8067
+ name: "LTC/CHF",
8068
+ description: "Litecoin vs Swiss Franc",
8069
+ decimalFactor: 10,
8070
+ startHourForTicks: "2023-03-14T14:52:50.061Z",
8071
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
8072
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8073
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8074
+ },
8075
+ ltceur: {
8076
+ name: "LTC/EUR",
8077
+ description: "Litecoin vs Euro",
8078
+ decimalFactor: 10,
8079
+ startHourForTicks: "2023-03-14T14:55:12.375Z",
8080
+ startDayForMinuteCandles: "2023-03-14T14:55:00.000Z",
8081
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8082
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8083
+ },
8084
+ ltcgbp: {
8085
+ name: "LTC/GBP",
8086
+ description: "Pound Sterling",
8087
+ decimalFactor: 10,
8088
+ startHourForTicks: "2023-03-14T14:52:50.074Z",
8089
+ startDayForMinuteCandles: "2023-03-14T14:52:00.000Z",
8090
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
8091
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
8092
+ },
7956
8093
  ltcusd: {
7957
8094
  name: "LTC/USD",
7958
8095
  description: "Litecoin vs US Dollar",
@@ -12480,6 +12617,33 @@ var instrument_meta_data_default = {
12480
12617
  startMonthForHourlyCandles: "2017-11-15T16:00:00.000Z",
12481
12618
  startYearForDailyCandles: "2017-11-15T00:00:00.000Z"
12482
12619
  },
12620
+ xlmchf: {
12621
+ name: "XLM/CHF",
12622
+ description: "Stellar vs Swiss Franc",
12623
+ decimalFactor: 1e5,
12624
+ startHourForTicks: "2023-03-14T14:53:03.870Z",
12625
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12626
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12627
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12628
+ },
12629
+ xlmeur: {
12630
+ name: "XLM/EUR",
12631
+ description: "Stellar vs Euro",
12632
+ decimalFactor: 1e5,
12633
+ startHourForTicks: "2023-03-14T14:53:03.820Z",
12634
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12635
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12636
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12637
+ },
12638
+ xlmgbp: {
12639
+ name: "XLM/GBP",
12640
+ description: "Stellar vs Pound Sterling",
12641
+ decimalFactor: 1e5,
12642
+ startHourForTicks: "2023-03-14T14:53:03.821Z",
12643
+ startDayForMinuteCandles: "2023-03-14T14:53:00.000Z",
12644
+ startMonthForHourlyCandles: "2023-03-14T14:00:00.000Z",
12645
+ startYearForDailyCandles: "2023-03-14T00:00:00.000Z"
12646
+ },
12483
12647
  xlmusd: {
12484
12648
  name: "XLM/USD",
12485
12649
  description: "Stellar vs US Dollar",
@@ -12753,7 +12917,7 @@ function normaliseDates({
12753
12917
  minFromIsoDate = startYearForDailyCandles;
12754
12918
  }
12755
12919
  let minFromDate = new Date(minFromIsoDate);
12756
- let maxToDate = new Date();
12920
+ let maxToDate = /* @__PURE__ */ new Date();
12757
12921
  if (utcOffset) {
12758
12922
  startDate.setUTCMinutes(startDate.getUTCMinutes() + utcOffset);
12759
12923
  endDate.setUTCMinutes(endDate.getUTCMinutes() + utcOffset);
@@ -12775,7 +12939,7 @@ function getYMDH(date) {
12775
12939
  }
12776
12940
  function getStartOfUtc(date, period, offset = 0) {
12777
12941
  const [year, month, day, hours] = getYMDH(date);
12778
- let startOfUtc = new Date();
12942
+ let startOfUtc = /* @__PURE__ */ new Date();
12779
12943
  if (period === "hour") {
12780
12944
  startOfUtc = new Date(Date.UTC(year, month, day, hours + offset));
12781
12945
  } else if (period === "day") {
@@ -12789,7 +12953,7 @@ function getStartOfUtc(date, period, offset = 0) {
12789
12953
  }
12790
12954
  function getIsCurrentObj(date) {
12791
12955
  const [year, month, day, hours] = getYMDH(date);
12792
- const [currentYear, currentMonth, currentDay, currentHours] = getYMDH(new Date());
12956
+ const [currentYear, currentMonth, currentDay, currentHours] = getYMDH(/* @__PURE__ */ new Date());
12793
12957
  const isCurrentYear = year === currentYear;
12794
12958
  const isCurrentMonth = isCurrentYear && month === currentMonth;
12795
12959
  const isCurrentDay = isCurrentMonth && day === currentDay;
@@ -12914,7 +13078,7 @@ function getConstructor(instrument, priceType, endDate) {
12914
13078
  };
12915
13079
  }
12916
13080
  function getDateLimit(startDate, endDate, timeframe) {
12917
- const nowDate = new Date();
13081
+ const nowDate = /* @__PURE__ */ new Date();
12918
13082
  const adjustedEndDate = endDate < nowDate ? endDate : nowDate;
12919
13083
  let dateLimit = adjustedEndDate;
12920
13084
  if (timeframe === "tick" /* tick */ || timeframe === "s1" /* s1 */ || timeframe === "m1" /* m1 */ || timeframe === "m5" /* m5 */ || timeframe === "m15" /* m15 */ || timeframe === "m30" /* m30 */) {
@@ -12949,6 +13113,16 @@ function generateUrls({
12949
13113
  // src/buffer-fetcher/index.ts
12950
13114
  var import_node_fetch = __toESM(require("node-fetch"));
12951
13115
  var BufferFetcher = class {
13116
+ batchSize;
13117
+ pauseBetweenBatchesMs;
13118
+ onItemFetch;
13119
+ onBatchFetch;
13120
+ fetcherFn;
13121
+ retryCount;
13122
+ retryOnEmpty;
13123
+ pauseBetweenRetriesMs;
13124
+ failAfterRetryCount;
13125
+ cacheManager;
12952
13126
  constructor({
12953
13127
  batchSize = 10,
12954
13128
  pauseBetweenBatchesMs = 1e3,
@@ -12993,6 +13167,9 @@ var BufferFetcher = class {
12993
13167
  })
12994
13168
  );
12995
13169
  }
13170
+ /**
13171
+ * @experimental
13172
+ */
12996
13173
  async fetch_optimized(urls) {
12997
13174
  const batches = splitArrayInChunks(urls, this.batchSize);
12998
13175
  for (let i = 0, n = batches.length; i < n; i++) {
@@ -13050,7 +13227,6 @@ var BufferFetcher = class {
13050
13227
  return bufferObjects;
13051
13228
  }
13052
13229
  async fetchBuffer(url) {
13053
- var _a;
13054
13230
  if (this.fetcherFn) {
13055
13231
  return this.fetcherFn(url);
13056
13232
  }
@@ -13070,7 +13246,7 @@ var BufferFetcher = class {
13070
13246
  errorMsg = e instanceof Error ? e.message : JSON.stringify(e);
13071
13247
  }
13072
13248
  const isStatusOk = response.status === 200;
13073
- const contentLength = Number(((_a = response == null ? void 0 : response.headers) == null ? void 0 : _a.get("content-length")) || 0);
13249
+ const contentLength = Number(response?.headers?.get("content-length") || 0);
13074
13250
  const isResponseWithData = contentLength > 0;
13075
13251
  isTrySuccess = isCallSuccess && isStatusOk;
13076
13252
  if (this.retryOnEmpty) {
@@ -13165,7 +13341,7 @@ function getOHLC({
13165
13341
  volumes
13166
13342
  }) {
13167
13343
  if (filterFlats) {
13168
- input = input.filter((data) => (data == null ? void 0 : data[5]) !== 0);
13344
+ input = input.filter((data) => data?.[5] !== 0);
13169
13345
  }
13170
13346
  if (input.length === 0) {
13171
13347
  return [];
@@ -13496,7 +13672,7 @@ function processData({
13496
13672
  }
13497
13673
 
13498
13674
  // src/output-formatter/index.ts
13499
- var headers = ["timestamp", "open", "high", "low", "close", "volume"];
13675
+ var candleHeaders = ["timestamp", "open", "high", "low", "close", "volume"];
13500
13676
  var tickHeaders = ["timestamp", "askPrice", "bidPrice", "askVolume", "bidVolume"];
13501
13677
  function formatOutput({
13502
13678
  processedData,
@@ -13506,7 +13682,7 @@ function formatOutput({
13506
13682
  if (processedData.length === 0) {
13507
13683
  return [];
13508
13684
  }
13509
- const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : headers;
13685
+ const bodyHeaders = timeframe === "tick" /* tick */ ? tickHeaders : candleHeaders;
13510
13686
  if (format === "json" /* json */) {
13511
13687
  const data = processedData.map((arr) => {
13512
13688
  return arr.reduce((all, item, i) => {
@@ -13530,6 +13706,9 @@ var import_path = require("path");
13530
13706
  var import_fs_extra = require("fs-extra");
13531
13707
  var DEFAULT_CACHE_FOLDER = ".dukascopy-cache";
13532
13708
  var CacheManager = class {
13709
+ cacheManifest;
13710
+ cacheFolderPath;
13711
+ cacheKeyFormatter;
13533
13712
  constructor({
13534
13713
  cacheFolderPath,
13535
13714
  cacheKeyFormatter
@@ -13588,7 +13767,7 @@ function formatBytes(bytes, decimals = 2) {
13588
13767
  }
13589
13768
 
13590
13769
  // package.json
13591
- var version = "1.0.1";
13770
+ var version = "1.1.0";
13592
13771
 
13593
13772
  // src/getHistoricalRates.ts
13594
13773
  var import_debug = __toESM(require("debug"));
@@ -13710,7 +13889,7 @@ async function getCurrentRates({
13710
13889
  const instrumentName = instrumentMetaData[instrument].name;
13711
13890
  const offerSide = priceType === "bid" ? "B" : "A";
13712
13891
  const timeDirection = "N";
13713
- const now = new Date();
13892
+ const now = /* @__PURE__ */ new Date();
13714
13893
  let fromDate = now;
13715
13894
  let toDate = now;
13716
13895
  if (dates) {
@@ -13805,6 +13984,146 @@ function getTimeframeLimit(timeframe, now, limit) {
13805
13984
  };
13806
13985
  return new Date(nowTimestamp - limit * bufferMultiplier * timeframeLimits[timeframe]);
13807
13986
  }
13987
+
13988
+ // src/getHistoricalRatesToStream.ts
13989
+ var import_debug2 = __toESM(require("debug"));
13990
+ var import_stream = require("stream");
13991
+ var import_promises = require("stream/promises");
13992
+ var DEBUG_NAMESPACE2 = "dukascopy-node";
13993
+ async function getHistoricalRatesToStream(config) {
13994
+ const stream = new import_stream.Readable({
13995
+ objectMode: true,
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
14059
+ });
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
+ }
14103
+ }
14104
+ });
14105
+ callback();
14106
+ } catch (err) {
14107
+ callback(err);
14108
+ }
14109
+ }
14110
+ })
14111
+ ).then(() => {
14112
+ if (++urlsProcessed === urlsforFetchingData.length) {
14113
+ this.push(null);
14114
+ }
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
+ });
14125
+ return stream;
14126
+ }
13808
14127
  // Annotate the CommonJS export names for ESM import in node:
13809
14128
  0 && (module.exports = {
13810
14129
  BufferFetcher,
@@ -13826,6 +14145,7 @@ function getTimeframeLimit(timeframe, now, limit) {
13826
14145
  getCurrentRates,
13827
14146
  getHistoricRates,
13828
14147
  getHistoricalRates,
14148
+ getHistoricalRatesToStream,
13829
14149
  normaliseDates,
13830
14150
  processData,
13831
14151
  schema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dukascopy-node-plus",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
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 --format esm,cjs --dts --legacy-output",
16
+ "build": "rm -rf dist && tsup-node src/index.ts src/cli/index.ts src/index.example.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",
@@ -25,8 +25,7 @@
25
25
  "release:beta": "pnpm build && npm publish --tag beta"
26
26
  },
27
27
  "author": {
28
- "name": "Leonid Pyrlia",
29
- "url": "https://www.linkedin.com/in/leonid-pyrlia/"
28
+ "name": "Dr. Mohammed REZGUI"
30
29
  },
31
30
  "license": "MIT",
32
31
  "repository": {
@@ -49,38 +48,35 @@
49
48
  "btcusd"
50
49
  ],
51
50
  "dependencies": {
52
- "chalk": "3.0.0",
53
- "cli-progress": "3.10.0",
54
- "commander": "5.0.0",
51
+ "chalk": "5.3.0",
52
+ "cli-progress": "3.12.0",
53
+ "commander": "12.0.0",
55
54
  "dayjs": "1.11.10",
56
55
  "debug": "4.3.4",
57
- "fastest-validator": "1.10.0",
58
- "fs-extra": "10.1.0",
56
+ "fastest-validator": "1.17.0",
57
+ "fs-extra": "11.2.0",
59
58
  "lzma-purejs-requirejs": "1.0.0",
60
- "node-fetch": "2.6.7",
59
+ "node-fetch": "2.7.0",
61
60
  "python-struct": "1.1.3"
62
61
  },
63
62
  "devDependencies": {
64
- "@types/cli-progress": "3.9.2",
65
- "@types/debug": "4.1.7",
66
- "@types/fs-extra": "9.0.13",
67
- "@types/node": "17.0.25",
68
- "@types/node-fetch": "2.6.1",
69
- "@typescript-eslint/eslint-plugin": "5.20.0",
70
- "@typescript-eslint/parser": "5.20.0",
71
- "eslint": "8.13.0",
72
- "eslint-config-prettier": "8.5.0",
73
- "eslint-plugin-prettier": "4.0.0",
74
- "msw": "1.0.1",
75
- "prettier": "2.6.2",
76
- "standard-version": "9.3.2",
77
- "tsup": "5.12.5",
78
- "tsx": "3.12.2",
79
- "typescript": "4.6.3",
80
- "vite": "4.1.4",
81
- "vitest": "0.28.5"
63
+ "@types/cli-progress": "3.11.5",
64
+ "@types/debug": "4.1.12",
65
+ "@types/fs-extra": "11.0.4",
66
+ "@types/node": "^18.19.30",
67
+ "@types/node-fetch": "2.6.11",
68
+ "@typescript-eslint/eslint-plugin": "7.5.0",
69
+ "@typescript-eslint/parser": "7.5.0",
70
+ "msw": "2.2.13",
71
+ "prettier": "3.2.5",
72
+ "standard-version": "9.5.0",
73
+ "tsup": "8.0.2",
74
+ "tsx": "4.7.2",
75
+ "typescript": "5.4.4",
76
+ "vite": "5.2.8",
77
+ "vitest": "1.4.0"
82
78
  },
83
79
  "engines": {
84
- "node": ">=12"
80
+ "node": ">=18"
85
81
  }
86
82
  }