nodejs-order-book 8.0.0 → 8.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/README.md CHANGED
@@ -13,6 +13,34 @@ Ultra-fast Node.js Order Book written in TypeScript for high-frequency trading (
13
13
 
14
14
  :star: Star me on GitHub — it motivates me a lot!
15
15
 
16
+ ## Table of Contents
17
+
18
+ - [Features](#features)
19
+ - [Installation](#installation)
20
+ - [Usage](#usage)
21
+ - [Experimental Conditional Orders](#conditional-orders-)
22
+ - [About Primary Functions](#about-primary-functions)
23
+ - [Create order `createOrder()`](#create-order)
24
+ - [Create Limit order `limit()`](#create-limit-order)
25
+ - [Create Market order `market()`](#create-market-order)
26
+ - [Create Stop Limit order `stopLimit()`](#create-stop-limit-order)
27
+ - [Create Stop Market order `stopMarket()`](#create-stop-market-order)
28
+ - [Create OCO (One-Cancels-the-Other) order `oco()`](#create-oco-one-cancels-the-other-order)
29
+ - [Modify an existing order `modifiy()`](#modify-an-existing-order)
30
+ - [Cancel order `cancel()`](#cancel-order)
31
+ - [Order Book Options](#order-book-options)
32
+ - [Snapshot](#snapshot)
33
+ - [Journal Logs](#journal-logs)
34
+ - [Enable Journaling](#enable-journaling)
35
+ - [Development](#development)
36
+ - [Build](#build)
37
+ - [Testing](#testing)
38
+ - [Coverage](#coverage)
39
+ - [Benchmarking](#benchmarking)
40
+ - [Contributing](#contributing)
41
+ - [Donation](#donation)
42
+ - [License](#license)
43
+
16
44
  ## Features
17
45
 
18
46
  - Standard price-time priority
@@ -348,7 +376,7 @@ bids: 90 -> 5 90 -> 5
348
376
  80 -> 1 80 -> 1
349
377
  ```
350
378
 
351
- ## Options
379
+ ## Order Book Options
352
380
 
353
381
  The orderbook can be initialized with the following options by passing them to the constructor:
354
382
 
@@ -47,7 +47,16 @@ var OrderBook = /** @class */ (function () {
47
47
  /* node:coverage ignore next 4 - We don't need test for this */
48
48
  if (!_this.experimentalConditionalOrders)
49
49
  throw new Error("In order to use conditional orders you need to instantiate the order book with the `experimentalConditionalOrders` option set to true");
50
- return _this._stopMarket(options);
50
+ var response = _this._stopMarket(options);
51
+ if (_this.enableJournaling && response.err === null) {
52
+ response.log = {
53
+ opId: ++_this._lastOp,
54
+ ts: Date.now(),
55
+ op: "sm",
56
+ o: options,
57
+ };
58
+ }
59
+ return response;
51
60
  };
52
61
  /**
53
62
  * Create a stop limit order. See {@link StopLimitOrderOptions} for details.
@@ -65,7 +74,16 @@ var OrderBook = /** @class */ (function () {
65
74
  /* node:coverage ignore next 4 - We don't need test for this */
66
75
  if (!_this.experimentalConditionalOrders)
67
76
  throw new Error("In order to use conditional orders you need to instantiate the order book with the `experimentalConditionalOrders` option set to true");
68
- return _this._stopLimit(options);
77
+ var response = _this._stopLimit(options);
78
+ if (_this.enableJournaling && response.err === null) {
79
+ response.log = {
80
+ opId: ++_this._lastOp,
81
+ ts: Date.now(),
82
+ op: "sl",
83
+ o: options,
84
+ };
85
+ }
86
+ return response;
69
87
  };
70
88
  /**
71
89
  * Create an OCO (One-Cancels-the-Other) order.
@@ -94,7 +112,16 @@ var OrderBook = /** @class */ (function () {
94
112
  /* node:coverage ignore next 4 - We don't need test for this */
95
113
  if (!_this.experimentalConditionalOrders)
96
114
  throw new Error("In order to use conditional orders you need to instantiate the order book with the `experimentalConditionalOrders` option set to true");
97
- return _this._oco(options);
115
+ var response = _this._oco(options);
116
+ if (_this.enableJournaling && response.err === null) {
117
+ response.log = {
118
+ opId: ++_this._lastOp,
119
+ ts: Date.now(),
120
+ op: "oco",
121
+ o: options,
122
+ };
123
+ }
124
+ return response;
98
125
  };
99
126
  /**
100
127
  * Modify an existing order with given ID. When an order is modified by price or quantity,
@@ -228,7 +255,7 @@ var OrderBook = /** @class */ (function () {
228
255
  };
229
256
  this._market = function (options, incomingResponse) {
230
257
  var response = incomingResponse !== null && incomingResponse !== void 0 ? incomingResponse : _this.validateMarketOrder(options);
231
- if (response.err != null)
258
+ if (response.err !== null)
232
259
  return response;
233
260
  var quantityToTrade = options.size;
234
261
  var iter;
@@ -253,41 +280,19 @@ var OrderBook = /** @class */ (function () {
253
280
  }
254
281
  response.quantityLeft = quantityToTrade;
255
282
  _this.executeConditionalOrder(options.side, priceBefore, response);
256
- if (_this.enableJournaling) {
257
- response.log = {
258
- opId: ++_this._lastOp,
259
- ts: Date.now(),
260
- op: "m",
261
- o: { side: options.side, size: options.size },
262
- };
263
- }
264
283
  return response;
265
284
  };
266
285
  this._limit = function (options, incomingResponse) {
267
286
  var _a, _b;
268
287
  var response = incomingResponse !== null && incomingResponse !== void 0 ? incomingResponse : _this.validateLimitOrder(options);
269
- if (response.err != null)
288
+ if (response.err !== null)
270
289
  return response;
271
- var order = _this.createLimitOrder(response, options.side, options.id, options.size, options.price, (_a = options.postOnly) !== null && _a !== void 0 ? _a : false, (_b = options.timeInForce) !== null && _b !== void 0 ? _b : types_1.TimeInForce.GTC, options.ocoStopPrice);
272
- if (_this.enableJournaling && order != null) {
273
- response.log = {
274
- opId: ++_this._lastOp,
275
- ts: Date.now(),
276
- op: "l",
277
- o: {
278
- side: order.side,
279
- id: order.id,
280
- size: order.size,
281
- price: order.price,
282
- timeInForce: order.timeInForce,
283
- },
284
- };
285
- }
290
+ _this.createLimitOrder(response, options.side, options.id, options.size, options.price, (_a = options.postOnly) !== null && _a !== void 0 ? _a : false, (_b = options.timeInForce) !== null && _b !== void 0 ? _b : types_1.TimeInForce.GTC, options.ocoStopPrice);
286
291
  return response;
287
292
  };
288
293
  this._stopMarket = function (options) {
289
294
  var response = _this.validateMarketOrder(options);
290
- if (response.err != null)
295
+ if (response.err !== null)
291
296
  return response;
292
297
  var stopMarket = order_1.OrderFactory.createOrder(__assign(__assign({}, options), { type: types_1.OrderType.STOP_MARKET }));
293
298
  return _this._stopOrder(stopMarket, response);
@@ -295,7 +300,7 @@ var OrderBook = /** @class */ (function () {
295
300
  this._stopLimit = function (options) {
296
301
  var _a;
297
302
  var response = _this.validateLimitOrder(options);
298
- if (response.err != null)
303
+ if (response.err !== null)
299
304
  return response;
300
305
  var stopLimit = order_1.OrderFactory.createOrder(__assign(__assign({}, options), { type: types_1.OrderType.STOP_LIMIT, timeInForce: (_a = options.timeInForce) !== null && _a !== void 0 ? _a : types_1.TimeInForce.GTC }));
301
306
  return _this._stopOrder(stopLimit, response);
@@ -304,7 +309,7 @@ var OrderBook = /** @class */ (function () {
304
309
  var _a;
305
310
  var response = _this.validateLimitOrder(options);
306
311
  /* node:coverage ignore next - Already validated with limit test */
307
- if (response.err != null)
312
+ if (response.err !== null)
308
313
  return response;
309
314
  if (_this.validateOCOOrder(options)) {
310
315
  // We use the same ID for Stop Limit and Limit Order, since
@@ -318,7 +323,7 @@ var OrderBook = /** @class */ (function () {
318
323
  ocoStopPrice: options.stopPrice,
319
324
  }, response);
320
325
  /* node:coverage ignore next - Already validated with limit test */
321
- if (response.err != null)
326
+ if (response.err !== null)
322
327
  return response;
323
328
  var stopLimit = order_1.OrderFactory.createOrder({
324
329
  type: types_1.OrderType.STOP_LIMIT,
@@ -546,21 +551,48 @@ var OrderBook = /** @class */ (function () {
546
551
  if (side == null || size == null) {
547
552
  throw (0, errors_1.CustomError)(errors_1.ERROR.INVALID_JOURNAL_LOG);
548
553
  }
549
- _this.market({ side: side, size: size });
554
+ _this.market(log.o);
550
555
  break;
551
556
  }
552
557
  case "l": {
553
- var _b = log.o, side = _b.side, id = _b.id, size = _b.size, price = _b.price, timeInForce = _b.timeInForce;
558
+ var _b = log.o, side = _b.side, id = _b.id, size = _b.size, price = _b.price;
554
559
  if (side == null || id == null || size == null || price == null) {
555
560
  throw (0, errors_1.CustomError)(errors_1.ERROR.INVALID_JOURNAL_LOG);
556
561
  }
557
- _this.limit({
558
- side: side,
559
- id: id,
560
- size: size,
561
- price: price,
562
- timeInForce: timeInForce,
563
- });
562
+ _this.limit(log.o);
563
+ break;
564
+ }
565
+ case "sm": {
566
+ var _c = log.o, side = _c.side, size = _c.size, stopPrice = _c.stopPrice;
567
+ if (side == null || size == null || stopPrice == null) {
568
+ throw (0, errors_1.CustomError)(errors_1.ERROR.INVALID_JOURNAL_LOG);
569
+ }
570
+ _this.stopMarket(log.o);
571
+ break;
572
+ }
573
+ case "sl": {
574
+ var _d = log.o, side = _d.side, id = _d.id, size = _d.size, price = _d.price, stopPrice = _d.stopPrice;
575
+ if (side == null ||
576
+ id == null ||
577
+ size == null ||
578
+ price == null ||
579
+ stopPrice == null) {
580
+ throw (0, errors_1.CustomError)(errors_1.ERROR.INVALID_JOURNAL_LOG);
581
+ }
582
+ _this.stopLimit(log.o);
583
+ break;
584
+ }
585
+ case "oco": {
586
+ var _e = log.o, side = _e.side, id = _e.id, size = _e.size, price = _e.price, stopPrice = _e.stopPrice, stopLimitPrice = _e.stopLimitPrice;
587
+ if (side == null ||
588
+ id == null ||
589
+ size == null ||
590
+ price == null ||
591
+ stopPrice == null ||
592
+ stopLimitPrice == null) {
593
+ throw (0, errors_1.CustomError)(errors_1.ERROR.INVALID_JOURNAL_LOG);
594
+ }
595
+ _this.oco(log.o);
564
596
  break;
565
597
  }
566
598
  case "d":
@@ -751,40 +783,23 @@ var OrderBook = /** @class */ (function () {
751
783
  enumerable: false,
752
784
  configurable: true
753
785
  });
754
- OrderBook.prototype.createOrder = function (typeOrOptions, side, size, price, orderID, timeInForce, stopPrice, stopLimitPrice, stopLimitTimeInForce, postOnly) {
755
- if (timeInForce === void 0) { timeInForce = types_1.TimeInForce.GTC; }
756
- if (stopLimitTimeInForce === void 0) { stopLimitTimeInForce = types_1.TimeInForce.GTC; }
757
- var options;
758
- // We don't want to test the deprecated signature.
759
- /* node:coverage disable */
760
- if (typeof typeOrOptions === "string" &&
761
- side !== undefined &&
762
- size !== undefined) {
763
- options = {
764
- type: typeOrOptions,
765
- side: side,
766
- size: size,
767
- // @ts-expect-error
768
- price: price,
769
- id: orderID,
770
- timeInForce: timeInForce,
771
- // @ts-expect-error
772
- stopPrice: stopPrice,
773
- // @ts-expect-error
774
- stopLimitPrice: stopLimitPrice,
775
- stopLimitTimeInForce: stopLimitTimeInForce,
776
- postOnly: postOnly,
777
- };
778
- /* node:coverage enable */
779
- }
780
- else if (typeof typeOrOptions === "object") {
781
- options = typeOrOptions;
782
- /* node:coverage disable */
783
- }
784
- else {
785
- throw new Error("Invalid arguments.");
786
- }
787
- /* node:coverage enable */
786
+ /**
787
+ * Create new order. See {@link CreateOrderOptions} for details.
788
+ *
789
+ * @param options
790
+ * @param options.type - `limit` | `market` | 'stop_limit' | 'stop_market' | 'oco'
791
+ * @param options.side - `sell` or `buy`
792
+ * @param options.size - How much of currency you want to trade in units of base currency
793
+ * @param options.price - The price at which the order is to be fullfilled, in units of the quote currency. Param only for limit order
794
+ * @param options.orderID - Unique order ID. Param only for limit order
795
+ * @param options.postOnly - Can be used with 'limit' order and when it's `true` the order will be rejected if immediately matches and trades as a taker. Default is `false`
796
+ * @param options.stopPrice - The price at which the order will be triggered. Used with `stop_limit` and `stop_market` order.
797
+ * @param options.stopLimitPrice - The price at which the order will be triggered. Used with `stop_limit` and `stop_market` order.
798
+ * @param options.timeInForce - Time-in-force supported are: `GTC` (default), `FOK`, `IOC`. Param only for limit order
799
+ * @param options.stopLimitTimeInForce - Time-in-force supported are: `GTC` (default), `FOK`, `IOC`. Param only for limit order
800
+ * @returns An object with the result of the processed order or an error. See {@link IProcessOrder} for the returned data structure
801
+ */
802
+ OrderBook.prototype.createOrder = function (options) {
788
803
  switch (options.type) {
789
804
  case types_1.OrderType.MARKET:
790
805
  return this.market(options);
@@ -807,43 +822,49 @@ var OrderBook = /** @class */ (function () {
807
822
  };
808
823
  }
809
824
  };
810
- OrderBook.prototype.market = function (sideOrOptions, size) {
811
- // We don't want to test the deprecated signature.
812
- /* node:coverage disable */
813
- if (typeof sideOrOptions === "string" && size !== undefined) {
814
- return this._market({ side: sideOrOptions, size: size });
815
- /* node:coverage enable */
816
- }
817
- if (typeof sideOrOptions === "object") {
818
- return this._market(sideOrOptions);
819
- /* node:coverage disable */
825
+ /**
826
+ * Create a market order. See {@link MarketOrderOptions} for details.
827
+ *
828
+ * @param options
829
+ * @param options.side - `sell` or `buy`
830
+ * @param options.size - How much of currency you want to trade in units of base currency
831
+ * @returns An object with the result of the processed order or an error. See {@link IProcessOrder} for the returned data structure
832
+ */
833
+ OrderBook.prototype.market = function (options) {
834
+ var response = this._market(options);
835
+ if (this.enableJournaling && response.err === null) {
836
+ response.log = {
837
+ opId: ++this._lastOp,
838
+ ts: Date.now(),
839
+ op: "m",
840
+ o: options,
841
+ };
820
842
  }
821
- throw new Error("Invalid arguments.");
822
- /* node:coverage enable */
843
+ return response;
823
844
  };
824
- OrderBook.prototype.limit = function (sideOrOptions, orderID, size, price, timeInForce) {
825
- if (timeInForce === void 0) { timeInForce = types_1.TimeInForce.GTC; }
826
- // We don't want to test the deprecated signature.
827
- /* node:coverage disable */
828
- if (typeof sideOrOptions === "string" &&
829
- orderID !== undefined &&
830
- size !== undefined &&
831
- price !== undefined) {
832
- return this._limit({
833
- id: orderID,
834
- side: sideOrOptions,
835
- size: size,
836
- price: price,
837
- timeInForce: timeInForce,
838
- });
839
- /* node:coverage enable */
840
- }
841
- if (typeof sideOrOptions === "object") {
842
- return this._limit(sideOrOptions);
843
- /* node:coverage disable */
845
+ /**
846
+ * Create a limit order. See {@link LimitOrderOptions} for details.
847
+ *
848
+ * @param options
849
+ * @param options.side - `sell` or `buy`
850
+ * @param options.id - Unique order ID
851
+ * @param options.size - How much of currency you want to trade in units of base currency
852
+ * @param options.price - The price at which the order is to be fullfilled, in units of the quote currency
853
+ * @param options.postOnly - When `true` the order will be rejected if immediately matches and trades as a taker. Default is `false`
854
+ * @param options.timeInForce - Time-in-force type supported are: GTC, FOK, IOC. Default is GTC
855
+ * @returns An object with the result of the processed order or an error. See {@link IProcessOrder} for the returned data structure
856
+ */
857
+ OrderBook.prototype.limit = function (options) {
858
+ var response = this._limit(options);
859
+ if (this.enableJournaling && response.err === null) {
860
+ response.log = {
861
+ opId: ++this._lastOp,
862
+ ts: Date.now(),
863
+ op: "l",
864
+ o: options,
865
+ };
844
866
  }
845
- throw new Error("Invalid arguments.");
846
- /* node:coverage enable */
867
+ return response;
847
868
  };
848
869
  return OrderBook;
849
870
  }());