nodejs-order-book 10.0.1 → 10.1.1
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 +198 -0
- package/dist/cjs/errors.js +47 -45
- package/dist/cjs/index.js +4 -3
- package/dist/cjs/order.js +229 -272
- package/dist/cjs/orderbook.js +848 -784
- package/dist/cjs/orderqueue.js +68 -66
- package/dist/cjs/orderside.js +139 -147
- package/dist/cjs/stopbook.js +69 -69
- package/dist/cjs/stopqueue.js +47 -51
- package/dist/cjs/stopside.js +68 -68
- package/dist/cjs/types.js +8 -1
- package/dist/cjs/utils.js +2 -2
- package/dist/esm/errors.js +47 -46
- package/dist/esm/index.js +2 -2
- package/dist/esm/order.js +227 -273
- package/dist/esm/orderbook.js +844 -781
- package/dist/esm/orderqueue.js +67 -66
- package/dist/esm/orderside.js +134 -143
- package/dist/esm/stopbook.js +67 -68
- package/dist/esm/stopqueue.js +46 -51
- package/dist/esm/stopside.js +64 -65
- package/dist/esm/types.js +7 -0
- package/dist/esm/utils.js +2 -2
- package/dist/types/errors.d.ts +2 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/order.d.ts +5 -1
- package/dist/types/types.d.ts +24 -0
- package/package.json +13 -12
package/dist/esm/stopside.js
CHANGED
|
@@ -3,71 +3,70 @@ import createRBTree from "functional-red-black-tree";
|
|
|
3
3
|
import { CustomError, ERROR } from "./errors";
|
|
4
4
|
import { StopQueue } from "./stopqueue";
|
|
5
5
|
import { Side } from "./types";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (_this._prices[strPrice] === undefined) {
|
|
15
|
-
var priceQueue = new StopQueue(price);
|
|
16
|
-
_this._prices[strPrice] = priceQueue;
|
|
17
|
-
_this._priceTree = _this._priceTree.insert(price, priceQueue);
|
|
18
|
-
}
|
|
19
|
-
return _this._prices[strPrice].append(order);
|
|
20
|
-
};
|
|
21
|
-
// removes order from definite price level
|
|
22
|
-
this.remove = function (id, stopPrice) {
|
|
23
|
-
var strPrice = stopPrice.toString();
|
|
24
|
-
if (_this._prices[strPrice] === undefined) {
|
|
25
|
-
throw CustomError(ERROR.INVALID_PRICE_LEVEL);
|
|
26
|
-
}
|
|
27
|
-
var deletedOrder = _this._prices[strPrice].remove(id);
|
|
28
|
-
if (_this._prices[strPrice].len() === 0) {
|
|
29
|
-
delete _this._prices[strPrice];
|
|
30
|
-
_this._priceTree = _this._priceTree.remove(stopPrice);
|
|
31
|
-
}
|
|
32
|
-
return deletedOrder;
|
|
33
|
-
};
|
|
34
|
-
this.removePriceLevel = function (priceLevel) {
|
|
35
|
-
delete _this._prices[priceLevel.toString()];
|
|
36
|
-
_this._priceTree = _this._priceTree.remove(priceLevel);
|
|
37
|
-
};
|
|
38
|
-
// Get orders queue between two price levels
|
|
39
|
-
this.between = function (priceBefore, marketPrice) {
|
|
40
|
-
var queues = [];
|
|
41
|
-
var lowerBound = priceBefore;
|
|
42
|
-
var upperBound = marketPrice;
|
|
43
|
-
var highest = Math.max(priceBefore, marketPrice);
|
|
44
|
-
var lowest = Math.min(priceBefore, marketPrice);
|
|
45
|
-
if (_this._side === Side.BUY) {
|
|
46
|
-
lowerBound = highest;
|
|
47
|
-
upperBound = lowest - 1;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
lowerBound = lowest;
|
|
51
|
-
upperBound = highest + 1;
|
|
52
|
-
}
|
|
53
|
-
_this._priceTree.forEach(function (price, queue) {
|
|
54
|
-
if ((_this._side === Side.BUY && price >= lowest) ||
|
|
55
|
-
(_this._side === Side.SELL && price <= highest)) {
|
|
56
|
-
queues.push(queue);
|
|
57
|
-
}
|
|
58
|
-
}, lowerBound, // Inclusive
|
|
59
|
-
upperBound);
|
|
60
|
-
return queues;
|
|
61
|
-
};
|
|
62
|
-
this.priceTree = function () {
|
|
63
|
-
return _this._priceTree;
|
|
64
|
-
};
|
|
65
|
-
var compare = side === Side.SELL
|
|
66
|
-
? function (a, b) { return a - b; }
|
|
67
|
-
: function (a, b) { return b - a; };
|
|
6
|
+
export class StopSide {
|
|
7
|
+
_priceTree;
|
|
8
|
+
_prices = {};
|
|
9
|
+
_side;
|
|
10
|
+
constructor(side) {
|
|
11
|
+
const compare = side === Side.SELL
|
|
12
|
+
? (a, b) => a - b
|
|
13
|
+
: (a, b) => b - a;
|
|
68
14
|
this._priceTree = createRBTree(compare);
|
|
69
15
|
this._side = side;
|
|
70
16
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
17
|
+
// appends order to definite price level
|
|
18
|
+
append = (order) => {
|
|
19
|
+
const price = order.stopPrice;
|
|
20
|
+
const strPrice = price.toString();
|
|
21
|
+
if (this._prices[strPrice] === undefined) {
|
|
22
|
+
const priceQueue = new StopQueue(price);
|
|
23
|
+
this._prices[strPrice] = priceQueue;
|
|
24
|
+
this._priceTree = this._priceTree.insert(price, priceQueue);
|
|
25
|
+
}
|
|
26
|
+
return this._prices[strPrice].append(order);
|
|
27
|
+
};
|
|
28
|
+
// removes order from definite price level
|
|
29
|
+
remove = (id, stopPrice) => {
|
|
30
|
+
const strPrice = stopPrice.toString();
|
|
31
|
+
if (this._prices[strPrice] === undefined) {
|
|
32
|
+
throw CustomError(ERROR.INVALID_PRICE_LEVEL);
|
|
33
|
+
}
|
|
34
|
+
const deletedOrder = this._prices[strPrice].remove(id);
|
|
35
|
+
if (this._prices[strPrice].len() === 0) {
|
|
36
|
+
delete this._prices[strPrice];
|
|
37
|
+
this._priceTree = this._priceTree.remove(stopPrice);
|
|
38
|
+
}
|
|
39
|
+
return deletedOrder;
|
|
40
|
+
};
|
|
41
|
+
removePriceLevel = (priceLevel) => {
|
|
42
|
+
delete this._prices[priceLevel.toString()];
|
|
43
|
+
this._priceTree = this._priceTree.remove(priceLevel);
|
|
44
|
+
};
|
|
45
|
+
// Get orders queue between two price levels
|
|
46
|
+
between = (priceBefore, marketPrice) => {
|
|
47
|
+
const queues = [];
|
|
48
|
+
let lowerBound = priceBefore;
|
|
49
|
+
let upperBound = marketPrice;
|
|
50
|
+
const highest = Math.max(priceBefore, marketPrice);
|
|
51
|
+
const lowest = Math.min(priceBefore, marketPrice);
|
|
52
|
+
if (this._side === Side.BUY) {
|
|
53
|
+
lowerBound = highest;
|
|
54
|
+
upperBound = lowest - 1;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
lowerBound = lowest;
|
|
58
|
+
upperBound = highest + 1;
|
|
59
|
+
}
|
|
60
|
+
this._priceTree.forEach((price, queue) => {
|
|
61
|
+
if ((this._side === Side.BUY && price >= lowest) ||
|
|
62
|
+
(this._side === Side.SELL && price <= highest)) {
|
|
63
|
+
queues.push(queue);
|
|
64
|
+
}
|
|
65
|
+
}, lowerBound, // Inclusive
|
|
66
|
+
upperBound);
|
|
67
|
+
return queues;
|
|
68
|
+
};
|
|
69
|
+
priceTree = () => {
|
|
70
|
+
return this._priceTree;
|
|
71
|
+
};
|
|
72
|
+
}
|
package/dist/esm/types.js
CHANGED
|
@@ -3,6 +3,13 @@ export var Side;
|
|
|
3
3
|
Side["BUY"] = "buy";
|
|
4
4
|
Side["SELL"] = "sell";
|
|
5
5
|
})(Side || (Side = {}));
|
|
6
|
+
export var SelfTradePreventionMode;
|
|
7
|
+
(function (SelfTradePreventionMode) {
|
|
8
|
+
SelfTradePreventionMode["NONE"] = "NONE";
|
|
9
|
+
SelfTradePreventionMode["EXPIRE_TAKER"] = "EXPIRE_TAKER";
|
|
10
|
+
SelfTradePreventionMode["EXPIRE_MAKER"] = "EXPIRE_MAKER";
|
|
11
|
+
SelfTradePreventionMode["EXPIRE_BOTH"] = "EXPIRE_BOTH";
|
|
12
|
+
})(SelfTradePreventionMode || (SelfTradePreventionMode = {}));
|
|
6
13
|
export var OrderType;
|
|
7
14
|
(function (OrderType) {
|
|
8
15
|
OrderType["LIMIT"] = "limit";
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* node:coverage ignore next - Don't know why this line is uncovered */
|
|
2
|
-
export
|
|
2
|
+
export const safeStringify = (value) => {
|
|
3
3
|
try {
|
|
4
4
|
return JSON.stringify(value);
|
|
5
5
|
}
|
|
@@ -8,7 +8,7 @@ export var safeStringify = function (value) {
|
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
10
|
/* node:coverage ignore next - Don't know why this line is uncovered */
|
|
11
|
-
export
|
|
11
|
+
export const safeParse = (value) => {
|
|
12
12
|
try {
|
|
13
13
|
return JSON.parse(value);
|
|
14
14
|
}
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -14,7 +14,8 @@ export declare enum ERROR {
|
|
|
14
14
|
LIMIT_ORDER_FOK_NOT_FILLABLE = "LIMIT_ORDER_FOK_NOT_FILLABLE",
|
|
15
15
|
LIMIT_ORDER_POST_ONLY = "LIMIT_ORDER_POST_ONLY",
|
|
16
16
|
ORDER_ALREDY_EXISTS = "ORDER_ALREDY_EXISTS",
|
|
17
|
-
ORDER_NOT_FOUND = "ORDER_NOT_FOUND"
|
|
17
|
+
ORDER_NOT_FOUND = "ORDER_NOT_FOUND",
|
|
18
|
+
STP_TRIGGERED = "STP_TRIGGERED"
|
|
18
19
|
}
|
|
19
20
|
export declare const ErrorCodes: Record<ERROR, number>;
|
|
20
21
|
export declare const ErrorMessages: Record<ERROR, string>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { OrderBook } from "./orderbook";
|
|
2
2
|
import type { CreateOrderOptions, ICancelOrder, IOrder, IProcessOrder, LimitOrderOptions, MarketOrderOptions, OCOOrderOptions, OrderBookOptions, OrderUpdatePrice, OrderUpdateSize, StopLimitOrderOptions, StopMarketOrderOptions } from "./types";
|
|
3
|
-
import { OrderType, Side } from "./types";
|
|
4
|
-
export { type CreateOrderOptions, type ICancelOrder, type IOrder, type IProcessOrder, type LimitOrderOptions, type MarketOrderOptions, type OCOOrderOptions, OrderBook, type OrderBookOptions, OrderType, type OrderUpdatePrice, type OrderUpdateSize, Side, type StopLimitOrderOptions, type StopMarketOrderOptions, };
|
|
3
|
+
import { OrderType, SelfTradePreventionMode, Side } from "./types";
|
|
4
|
+
export { type CreateOrderOptions, type ICancelOrder, type IOrder, type IProcessOrder, type LimitOrderOptions, type MarketOrderOptions, type OCOOrderOptions, OrderBook, type OrderBookOptions, OrderType, type OrderUpdatePrice, type OrderUpdateSize, SelfTradePreventionMode, Side, type StopLimitOrderOptions, type StopMarketOrderOptions, };
|
package/dist/types/order.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type ILimitOrder, type InternalLimitOrderOptions, type InternalStopLimitOrderOptions, type InternalStopMarketOrderOptions, type IStopLimitOrder, type IStopMarketOrder, type OrderOptions, OrderType, type Side, type TimeInForce } from "./types";
|
|
1
|
+
import { type ILimitOrder, type InternalLimitOrderOptions, type InternalStopLimitOrderOptions, type InternalStopMarketOrderOptions, type IStopLimitOrder, type IStopMarketOrder, type OrderOptions, OrderType, SelfTradePreventionMode, type Side, type TimeInForce } from "./types";
|
|
2
2
|
declare abstract class BaseOrder {
|
|
3
3
|
readonly _id: string;
|
|
4
4
|
readonly _side: Side;
|
|
5
5
|
_size: number;
|
|
6
6
|
_time: number;
|
|
7
|
+
readonly _accountId: string;
|
|
8
|
+
readonly _stpMode: SelfTradePreventionMode;
|
|
7
9
|
constructor(options: OrderOptions);
|
|
8
10
|
get id(): string;
|
|
9
11
|
get side(): Side;
|
|
@@ -11,6 +13,8 @@ declare abstract class BaseOrder {
|
|
|
11
13
|
set size(size: number);
|
|
12
14
|
get time(): number;
|
|
13
15
|
set time(time: number);
|
|
16
|
+
get accountId(): string;
|
|
17
|
+
get stpMode(): SelfTradePreventionMode;
|
|
14
18
|
abstract toString(): void;
|
|
15
19
|
abstract toJSON(): void;
|
|
16
20
|
abstract toObject(): void;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export declare enum Side {
|
|
|
4
4
|
BUY = "buy",
|
|
5
5
|
SELL = "sell"
|
|
6
6
|
}
|
|
7
|
+
export declare enum SelfTradePreventionMode {
|
|
8
|
+
NONE = "NONE",
|
|
9
|
+
EXPIRE_TAKER = "EXPIRE_TAKER",
|
|
10
|
+
EXPIRE_MAKER = "EXPIRE_MAKER",
|
|
11
|
+
EXPIRE_BOTH = "EXPIRE_BOTH"
|
|
12
|
+
}
|
|
7
13
|
export declare enum OrderType {
|
|
8
14
|
LIMIT = "limit",
|
|
9
15
|
MARKET = "market",
|
|
@@ -26,10 +32,14 @@ interface BaseOrderOptions {
|
|
|
26
32
|
id?: string;
|
|
27
33
|
side: Side;
|
|
28
34
|
size: number;
|
|
35
|
+
accountId?: string;
|
|
36
|
+
stpMode?: SelfTradePreventionMode;
|
|
29
37
|
}
|
|
30
38
|
interface InternalBaseOrderOptions extends BaseOrderOptions {
|
|
31
39
|
type: OrderType;
|
|
32
40
|
time?: number;
|
|
41
|
+
accountId?: string;
|
|
42
|
+
stpMode?: SelfTradePreventionMode;
|
|
33
43
|
}
|
|
34
44
|
/**
|
|
35
45
|
* Specific options for a market order.
|
|
@@ -62,6 +72,8 @@ export interface InternalLimitOrderOptions extends ILimitOrderOptions {
|
|
|
62
72
|
takerQty: number;
|
|
63
73
|
postOnly?: boolean;
|
|
64
74
|
ocoStopPrice?: number;
|
|
75
|
+
accountId?: string;
|
|
76
|
+
stpMode?: SelfTradePreventionMode;
|
|
65
77
|
}
|
|
66
78
|
/**
|
|
67
79
|
* Specific options for a stop market order.
|
|
@@ -72,6 +84,8 @@ export interface StopMarketOrderOptions extends MarketOrderOptions {
|
|
|
72
84
|
export interface InternalStopMarketOrderOptions extends IMarketOrderOptions {
|
|
73
85
|
type: OrderType.STOP_MARKET;
|
|
74
86
|
stopPrice: number;
|
|
87
|
+
accountId?: string;
|
|
88
|
+
stpMode?: SelfTradePreventionMode;
|
|
75
89
|
}
|
|
76
90
|
/**
|
|
77
91
|
* Specific options for a stop limit order.
|
|
@@ -83,6 +97,8 @@ export interface InternalStopLimitOrderOptions extends ILimitOrderOptions {
|
|
|
83
97
|
type: OrderType.STOP_LIMIT;
|
|
84
98
|
stopPrice: number;
|
|
85
99
|
isOCO?: boolean;
|
|
100
|
+
accountId?: string;
|
|
101
|
+
stpMode?: SelfTradePreventionMode;
|
|
86
102
|
}
|
|
87
103
|
/**
|
|
88
104
|
* Specific options for oco order.
|
|
@@ -116,6 +132,8 @@ export interface ILimitOrder {
|
|
|
116
132
|
timeInForce: TimeInForce;
|
|
117
133
|
takerQty: number;
|
|
118
134
|
makerQty: number;
|
|
135
|
+
accountId?: string;
|
|
136
|
+
stpMode?: SelfTradePreventionMode;
|
|
119
137
|
}
|
|
120
138
|
/**
|
|
121
139
|
* Object object representation of a stop market order returned by the toObject() method.
|
|
@@ -127,6 +145,8 @@ export interface IStopMarketOrder {
|
|
|
127
145
|
size: number;
|
|
128
146
|
stopPrice: number;
|
|
129
147
|
time: number;
|
|
148
|
+
accountId?: string;
|
|
149
|
+
stpMode?: SelfTradePreventionMode;
|
|
130
150
|
}
|
|
131
151
|
/**
|
|
132
152
|
* Object object representation of a stop limit order returned by the toObject() method.
|
|
@@ -141,6 +161,8 @@ export interface IStopLimitOrder {
|
|
|
141
161
|
timeInForce: TimeInForce;
|
|
142
162
|
time: number;
|
|
143
163
|
isOCO: boolean;
|
|
164
|
+
accountId?: string;
|
|
165
|
+
stpMode?: SelfTradePreventionMode;
|
|
144
166
|
}
|
|
145
167
|
/**
|
|
146
168
|
* Represents an order in the order book.
|
|
@@ -167,6 +189,8 @@ export interface IProcessOrder {
|
|
|
167
189
|
err: OrderBookError | null;
|
|
168
190
|
/** Optional journal log entry related to the order processing. */
|
|
169
191
|
log?: JournalLog;
|
|
192
|
+
/** Orders expired due to Self-Trade Prevention (STP). */
|
|
193
|
+
stpExpired?: IOrder[];
|
|
170
194
|
}
|
|
171
195
|
export interface ConditionOrderOptions {
|
|
172
196
|
stopPrice: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodejs-order-book",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.1",
|
|
4
4
|
"description": "Node.js Lmit Order Book for high-frequency trading (HFT).",
|
|
5
5
|
"author": "Andrea Fassina <fasenderos@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,20 +44,21 @@
|
|
|
44
44
|
"functional-red-black-tree": "1.0.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@biomejs/biome": "^2.1
|
|
48
|
-
"@commitlint/cli": "^
|
|
49
|
-
"@commitlint/config-conventional": "^
|
|
50
|
-
"@release-it/conventional-changelog": "^
|
|
47
|
+
"@biomejs/biome": "^2.5.1",
|
|
48
|
+
"@commitlint/cli": "^21.1.0",
|
|
49
|
+
"@commitlint/config-conventional": "^21.1.0",
|
|
50
|
+
"@release-it/conventional-changelog": "^11.0.1",
|
|
51
51
|
"@types/functional-red-black-tree": "^1.0.6",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
52
|
+
"@types/node": "^26.0.1",
|
|
53
|
+
"c8": "^11.0.0",
|
|
54
|
+
"gaussian": "^1.3.0",
|
|
55
|
+
"husky": "^9.1.7",
|
|
55
56
|
"nanobench": "^3.0.0",
|
|
56
57
|
"pinst": "^3.0.0",
|
|
57
|
-
"release-it": "^
|
|
58
|
-
"ts-node": "^10.
|
|
59
|
-
"tsx": "^4.
|
|
60
|
-
"typescript": "^
|
|
58
|
+
"release-it": "^20.2.1",
|
|
59
|
+
"ts-node": "^10.9.2",
|
|
60
|
+
"tsx": "^4.22.4",
|
|
61
|
+
"typescript": "^6.0.3"
|
|
61
62
|
},
|
|
62
63
|
"publishConfig": {
|
|
63
64
|
"access": "public"
|