10101 icon indicating copy to clipboard operation
10101 copied to clipboard

feat: Rewrite order matching strategy

Open holzeis opened this issue 9 months ago • 0 comments

I opted to finish this PR up to a point where it can be merged and left a couple of todos that need to get addressed when we start implementing limit orders.


Refactors the current trading component into a clearly separated orderbook component and a trade execution component. The linking part is the ExecutableMatch which can be derived from the matches stored into the database.

At the moment we assume optimistically that the trade execution will succeed. However, we should consider that a pending match may never get filled or it fails at execution in such a scenario we would need to rollback the matched orders.

An overview of the changes:

  • Adds the order id to the trade entry so we can link which order created the trade.
  • Allows for orders to get partially matched and update the matches table accordingly
  • Matched limit orders are created as Filled from the get go since we do not execute them with our own maker.
  • (Partially) Matched limit orders are not deleted anymore, but the quantity is updated to how much has already been mapped. (e.g. if an open limit order of $1000 gets deleted with $300 matched it will be updated to Taken with a quantity of $300)

Example of a matches table after opening and closing a position of $3576. Note the maker generates $1000 orders.

orderbook=# select execution_price, quantity, order_id, match_order_id from matches where trader_id='032752136072951607b66dd85f236363efab91b315b1c4fc8d9530ee873875108a' and match_state='Filled' order by created_at;
 execution_price | quantity |               order_id               |            match_order_id            
-----------------+----------+--------------------------------------+--------------------------------------
           60001 |     1000 | 42dd8a30-a20d-4640-bddd-f5467a638d28 | 9acc7260-0f24-405e-ad84-550a797b4464
           60001 |     1000 | 42dd8a30-a20d-4640-bddd-f5467a638d28 | c486a21c-312e-4ae0-ab35-38a8e93d07d5
           60001 |     1000 | 42dd8a30-a20d-4640-bddd-f5467a638d28 | e30ff0dc-4f8a-4888-a3ea-cddf63c94179
           60001 |      576 | 42dd8a30-a20d-4640-bddd-f5467a638d28 | adae6065-d78a-4ed6-bab3-9852f395ef67
           59999 |     1000 | a6be5b42-8817-40f7-8f86-0615df33c57a | 19811f8f-7fe7-4dd1-9b3a-72f24a0fcee5
           59999 |     1000 | a6be5b42-8817-40f7-8f86-0615df33c57a | 6cf3b7bd-2652-4590-afed-f15ece0a1ded
           59999 |     1000 | a6be5b42-8817-40f7-8f86-0615df33c57a | 0c8b6575-2ba2-4e37-8aa2-9c0e8beb055d
           59999 |      576 | a6be5b42-8817-40f7-8f86-0615df33c57a | 17fcb395-4434-4ca8-9cb2-4ca75ec73063
(8 rows)

Example of updated limit orders when deleted.

orderbook=# select order_id, price, direction, quantity, order_type from orders where order_id in ('19811f8f-7fe7-4dd1-9b3a-72f24a0fcee5', '6cf3b7bd-2652-4590-afed-f15ece0a1ded', '0c8b6575-2ba2-4e37-8aa2
               order_id               | price | direction | quantity | order_type 
--------------------------------------+-------+-----------+----------+------------
 19811f8f-7fe7-4dd1-9b3a-72f24a0fcee5 | 59999 | long      |     1000 | limit
 6cf3b7bd-2652-4590-afed-f15ece0a1ded | 59999 | long      |     1000 | limit
 0c8b6575-2ba2-4e37-8aa2-9c0e8beb055d | 59999 | long      |     1000 | limit
 17fcb395-4434-4ca8-9cb2-4ca75ec73063 | 59999 | long      |      576 | limit
(4 rows)

holzeis avatar May 15 '24 14:05 holzeis