@@ -292,6 +292,7 @@ class TradingPair {
292
292
let remainingOrder : OwnOrder | undefined = { ...takerOrder } ;
293
293
294
294
const queue = takerOrder . isBuy ? this . queues ! . sell : this . queues ! . buy ;
295
+ const queueRemovedOrdersWithHold : OwnOrder [ ] = [ ] ;
295
296
const getMatchingQuantity = ( remainingOrder : OwnOrder , oppositeOrder : Order ) => takerOrder . isBuy
296
297
? TradingPair . getMatchingQuantity ( remainingOrder , oppositeOrder )
297
298
: TradingPair . getMatchingQuantity ( oppositeOrder , remainingOrder ) ;
@@ -300,13 +301,18 @@ class TradingPair {
300
301
while ( remainingOrder && ! queue . isEmpty ( ) ) {
301
302
// get the best available maker order from the top of the queue
302
303
const makerOrder = queue . peek ( ) ! ;
303
- const matchingQuantity = getMatchingQuantity ( remainingOrder , makerOrder ) ;
304
+ const makerAvailableQuantityOrder = isOwnOrder ( makerOrder )
305
+ ? { ...makerOrder , quantity : makerOrder . quantity - makerOrder . hold , hold : 0 }
306
+ : makerOrder ;
307
+
308
+ const matchingQuantity = getMatchingQuantity ( remainingOrder , makerAvailableQuantityOrder ) ;
304
309
if ( matchingQuantity <= 0 ) {
305
310
// there's no match with the best available maker order, so end the matching routine
306
311
break ;
307
312
} else {
308
313
/** Whether the maker order is fully matched and should be removed from the queue. */
309
314
const makerFullyMatched = makerOrder . quantity === matchingQuantity ;
315
+ const makerAvailableQuantityFullyMatched = makerAvailableQuantityOrder . quantity === matchingQuantity ;
310
316
const remainingFullyMatched = remainingOrder . quantity === matchingQuantity ;
311
317
312
318
if ( makerFullyMatched && remainingFullyMatched ) {
@@ -317,27 +323,38 @@ class TradingPair {
317
323
const matchedMakerOrder = TradingPair . splitOrderByQuantity ( makerOrder , matchingQuantity ) ;
318
324
this . logger . debug ( `reduced order ${ makerOrder . id } by ${ matchingQuantity } quantity while matching order ${ takerOrder . id } ` ) ;
319
325
matches . push ( { maker : matchedMakerOrder , taker : remainingOrder } ) ;
320
- } else if ( makerFullyMatched ) {
326
+ } else if ( makerAvailableQuantityFullyMatched ) {
321
327
// maker order quantity is not sufficient. taker order will split
322
328
const matchedTakerOrder = TradingPair . splitOrderByQuantity ( remainingOrder , matchingQuantity ) ;
323
- matches . push ( { maker : makerOrder , taker : matchedTakerOrder } ) ;
329
+ matches . push ( { maker : makerAvailableQuantityOrder , taker : matchedTakerOrder } ) ;
324
330
} else {
325
- assert ( false , 'matchingQuantity should not be lower than both orders quantity values' ) ;
331
+ assert ( false , 'matchingQuantity should not be lower than both orders available quantity values' ) ;
326
332
}
327
333
328
334
if ( remainingFullyMatched ) {
329
335
remainingOrder = undefined ;
330
336
}
337
+
331
338
if ( makerFullyMatched ) {
332
339
// maker order is fully matched, so remove it from the queue and map
333
340
assert ( queue . poll ( ) === makerOrder ) ;
334
341
const map = this . getOrderMap ( makerOrder ) ! ;
335
342
map . delete ( makerOrder . id ) ;
336
343
this . logger . debug ( `removed order ${ makerOrder . id } while matching order ${ takerOrder . id } ` ) ;
344
+ } else if ( makerAvailableQuantityFullyMatched ) {
345
+ // only an own order can be fully matched for available quantity, but not fully matched in the overall
346
+ assert ( isOwnOrder ( makerOrder ) ) ;
347
+
348
+ assert ( queue . poll ( ) === makerOrder ) ;
349
+ queueRemovedOrdersWithHold . push ( makerOrder as OwnOrder ) ;
337
350
}
338
351
}
339
352
}
340
353
354
+ // return the removed orders with hold to the queue.
355
+ // their hold quantity might be released later
356
+ queueRemovedOrdersWithHold . forEach ( order => queue . add ( order ) ) ;
357
+
341
358
return { matches, remainingOrder } ;
342
359
}
343
360
}
0 commit comments