Skip to content

Commit 1c484b1

Browse files
authored
Merge pull request #382 from f3rno/fix-ob-raw-checksum
Fix: OB Checksums (raw price level sorting & number representation)
2 parents b490706 + 3103619 commit 1c484b1

File tree

2 files changed

+169
-92
lines changed

2 files changed

+169
-92
lines changed

lib/models/order_book.js

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,27 @@ class OrderBook extends EventEmitter {
5050
const ask = this.asks[i]
5151

5252
if (bid) {
53+
const price = raw ? bid[0] : Number(preparePrice(bid[0]))
54+
5355
data.push(
54-
raw ? bid[0] : Number(preparePrice(bid[0])), // order ID or price
56+
raw
57+
? price
58+
: /e/.test(price + '')
59+
? price.toFixed(Math.abs((price + '').split('e')[1]) + 1) // i.e. 1.7e-7 to fixed
60+
: price,
5561
bid[2] // amount
5662
)
5763
}
5864

5965
if (ask) {
66+
const price = raw ? ask[0] : Number(preparePrice(ask[0]))
67+
6068
data.push(
61-
raw ? ask[0] : Number(preparePrice(ask[0])), //
69+
raw
70+
? price
71+
: /e/.test(price + '')
72+
? price.toFixed(Math.abs((price + '').split('e')[1]) + 1) // i.e. 1.7e-7 to fixed
73+
: price,
6274
ask[2] //
6375
)
6476
}
@@ -101,16 +113,28 @@ class OrderBook extends EventEmitter {
101113
: arr[topAskI + i]
102114

103115
if (bid) {
116+
const price = raw ? bid[0] : Number(preparePrice(bid[0]))
117+
104118
data.push(
105-
raw ? bid[0] : Number(preparePrice(bid[0])), // order ID or price
119+
raw
120+
? bid[0]
121+
: /e/.test(price + '')
122+
? price.toFixed(Math.abs((price + '').split('e')[1]) + 1) // i.e. 1.7e-7 to fixed
123+
: price, // order ID or price
106124
bid[2] // amount
107125
)
108126
}
109127

110128
if (ask) {
129+
const price = raw ? ask[0] : Number(preparePrice(ask[0]))
130+
111131
data.push(
112-
raw ? ask[0] : Number(preparePrice(ask[0])), //
113-
ask[2] //
132+
raw
133+
? ask[0]
134+
: /e/.test(price + '')
135+
? price.toFixed(Math.abs((price + '').split('e')[1]) + 1) // i.e. 1.7e-7 to fixed
136+
: price,
137+
ask[2]
114138
)
115139
}
116140
}
@@ -151,9 +175,11 @@ class OrderBook extends EventEmitter {
151175
const price = entry[priceI]
152176
const oID = entry[0] // only for raw books
153177
const amount = entry[2]
178+
const dir = amount < 0 ? -1 : 1
154179
const side = amount < 0 ? this.asks : this.bids
155180

156181
let insertIndex = -1
182+
let pl
157183

158184
// apply insert directly if empty
159185
if (side.length === 0 && (raw || count > 0)) {
@@ -162,24 +188,17 @@ class OrderBook extends EventEmitter {
162188
return true
163189
}
164190

191+
// Match by price level, or order ID for raw books
165192
for (let i = 0; i < side.length; i++) {
166-
if (insertIndex === -1 && (
167-
(amount > 0 && price > side[i][priceI]) ||
168-
(amount < 0 && price < side[i][priceI])
169-
)) {
170-
insertIndex = i // insert index to maintain sort
171-
}
172-
173-
// Match by price level, or order ID for raw books
174193
if ((!raw && side[i][priceI] === price) || (raw && side[i][0] === oID)) {
175194
if ((!raw && count === 0) || (raw && price === 0)) {
176195
side.splice(i, 1) // remove
196+
this.emit('update', entry)
197+
return true
177198
} else if (!raw || (raw && price > 0)) {
178-
side[i] = entry // update
199+
side.splice(i, 1) // remove, add update as new entry below
200+
break
179201
}
180-
181-
this.emit('update', entry)
182-
return true
183202
}
184203
}
185204

@@ -188,6 +207,21 @@ class OrderBook extends EventEmitter {
188207
return false
189208
}
190209

210+
for (let i = 0; i < side.length; i++) {
211+
pl = side[i]
212+
213+
if (insertIndex === -1 && (
214+
(dir === -1 && pl[2] < 0 && price < pl[priceI]) || // by price
215+
(dir === -1 && pl[2] < 0 && price === pl[priceI] && (raw && entry[0] < pl[0])) || // by order ID
216+
(dir === 1 && pl[2] > 0 && price > pl[priceI]) ||
217+
(dir === 1 && pl[2] > 0 && price === pl[priceI] && (raw && entry[0] < pl[0])) ||
218+
(dir === 1 && pl[2] < 0)
219+
)) {
220+
insertIndex = i // insert index to maintain sort
221+
break
222+
}
223+
}
224+
191225
// add
192226
if (insertIndex === -1) {
193227
side.push(entry)
@@ -308,8 +342,7 @@ class OrderBook extends EventEmitter {
308342
}
309343

310344
/**
311-
* Modifies an array-format OB in place with an update entry. Sort is not
312-
* gauranteed!
345+
* Modifies an array-format OB in place with an update entry. Maintains sort
313346
*
314347
* @param {number[][]} ob
315348
* @param {number[]} entry
@@ -319,22 +352,26 @@ class OrderBook extends EventEmitter {
319352
static updateArrayOBWith (ob, entry, raw = false) {
320353
const priceI = raw ? 1 : 0
321354
const price = entry[priceI]
355+
const amount = entry[2]
356+
const dir = amount < 0 ? -1 : 1
322357
const count = raw ? -1 : entry[1]
323358
let insertIndex = -1
359+
let pl // price level
324360

325361
for (let i = 0; i < ob.length; i++) {
326-
if (price > ob[i][priceI] && insertIndex === -1) {
327-
insertIndex = i
328-
}
362+
pl = ob[i]
329363

330-
if ((!raw && ob[i][priceI] === price) || (raw && ob[i][0] === entry[0])) {
364+
if (
365+
(!raw && pl[priceI] === price) ||
366+
(raw && pl[0] === entry[0])
367+
) {
331368
if ((!raw && count === 0) || (raw && price === 0)) {
332369
ob.splice(i, 1) // remove existing
370+
return true
333371
} else {
334-
ob[i] = entry // update existing
372+
ob.splice(i, 1) // update; remove & re-insert
373+
break
335374
}
336-
337-
return true
338375
}
339376
}
340377

@@ -343,6 +380,23 @@ class OrderBook extends EventEmitter {
343380
return false
344381
}
345382

383+
for (let i = 0; i < ob.length; i++) {
384+
pl = ob[i]
385+
386+
if (insertIndex === -1) {
387+
if (
388+
(dir === -1 && pl[2] < 0 && price < pl[priceI]) || // by price
389+
(dir === -1 && pl[2] < 0 && price === pl[priceI] && (raw && entry[0] < pl[0])) || // by order ID
390+
(dir === 1 && pl[2] > 0 && price > pl[priceI]) ||
391+
(dir === 1 && pl[2] > 0 && price === pl[priceI] && (raw && entry[0] < pl[0])) ||
392+
(dir === 1 && pl[2] < 0)
393+
) {
394+
insertIndex = i
395+
break
396+
}
397+
}
398+
}
399+
346400
// add
347401
if (insertIndex === -1) {
348402
ob.push(entry)

0 commit comments

Comments
 (0)