decred / dcrdex

The Decred Decentralized Exchange (DEX), powered by atomic-swaps.
Other
185 stars 92 forks source link

Discussion: New "CancelReplace" order type #1972

Closed martonp closed 11 months ago

martonp commented 1 year ago

A new order type that cancels an existing order and simultaneously places another order onto the order book would be very useful for market making. Instead of having to wait an epoch for a cancel order to match and another epoch to place a limit order, it could happen in one shot. This would be especially helpful when running multiple bot strategies on the same market. Any thoughts?

martonp commented 1 year ago

A BatchCancel/Replace would also be useful.. it would cancel a batch of orders, and if all the orders in the batch were cancelled, then the replacement order would get booked.

A BatchCancel without any replacement would also be useful, as market makers will probably submit multiple cancels simultaneously, and this would reduce the communication needed between server and client.

chappjc commented 1 year ago

BatchCancel has some interesting consequences with respect to the epoch shuffle.

If there's a user with 10 orders booked and they submit 10 individual cancel orders, those cancels get shuffled in the epoch along with other users' orders that might want to match with the booked orders. Some cancels might match, and some trades might match first.

If that user with 10 booked orders submits a BatchCancel, what happens if some of the orders in the batch were completely filled by other trades (and thus unbooked) by other orders higher in the queue? Can some of the cancels match but not all?

If that BatchCancel ends up as the last order in the shuffled queue, the user rolled the dice and got unlucky. If there were 10 individual cancels instead, they'd more likely be distributed with any other user's orders. (a) what's a better approach for that user? (b) does this in any way undermine the fair matching scheme we have with the epoch shuffle, making it potentially easier to spoof orders?

martonp commented 1 year ago

I was thinking to have BatchCancel be equivalent to having a group of independent cancels at the same point of the epoch shuffle. Any cancels for orders in the batch that are no longer on the books would just be disregarded, and the rest would be cancelled.

BatchCancelReplace would work the same as BatchCancel, but it would place the replacement order/orders only if all of the orders that are being cancelled are no longer in the order book.

The main use case I see for this is for the market maker bot. If the user is running multiple bots on the same market, or even just one but the market moved and the orders need to be placed at a different rate, we have to ensure that the user will not self-match. A BatchCancelReplace would be the most efficient way to ensure this. I don't see this being used by someone who is just making trades on the UI. They would still use the regular Cancel order.

Maybe I'm missing something, but I don't think that this would undermine the fair matching scheme. It will still be impossible to know where in the epoch shuffle the batch would be.

martonp commented 1 year ago

There really only needs to be one new order type called BatchOrder which contains a list of orders. The cancels (if any) would be processed first, then the limit/market orders (if any). Just like any other order, it could appear anywhere in the shuffle.

chappjc commented 1 year ago

we have to ensure that the user will not self-match

That's a good justification, and it avoids the need to wait to place orders in the next epoch.

I'm not sure it will be overly helpful though if the user/bot cannot fund the new orders with the still-locked coins from the ones they want to cancel. They may yet be filled so I don't think they can do this, so they are stuck having separate funds for the replacement orders.

If the user is running multiple bots on the same market

This notion surprises me. Would that be normal? What's the use case, where a single bot/program would not suffice?

Maybe I'm missing something, but I don't think that this would undermine the fair matching scheme. It will still be impossible to know where in the epoch shuffle the batch would be.

I'm not seeing an issue either. I just wanted to raise it as a consideration.

martonp commented 1 year ago

This notion surprises me. Would that be normal? What's the use case, where a single bot/program would not suffice?

For example if they are running both a bot that stacks orders on both sides of the current price, and also an arbitrage bot.

I'm not sure it will be overly helpful though if the user/bot cannot fund the new orders with the still-locked coins from the ones they want to cancel.

That's true. Potentially there could be a parameterized order that only books the new limit/market orders if all of the cancels actually match. And these orders could use locked funds from previous orders for new ones. But this is not an issue in the case of a user running both a regular market making bot and an arbitrage bot. The two bots would have funds seprately allocated to each of them.

chappjc commented 1 year ago

For example if they are running both a bot that stacks orders on both sides of the current price, and also an arbitrage bot.

I've been unable to digest the above. I would think this would be a hybrid program, but a single bot. Mainly for sake of unified inventory management, but also I would expect that if the mm bot stacking limit orders got a bunch of DEX fills and it was profitable to arb that to a CEX, it would do that (possibly even before waiting for DEX settlement as long as they were matched and settling).

chappjc commented 1 year ago

Regarding BatchOrder, let me try to summarize:

Question:

What if one of the cancel orders in a BatchOrder fails to match? Do the remaining orders in the batch get ignored and the batch terminates? If so, that could be exploited to spoof orders by including a cancel that is unlikely to match or even cannot match if you have a limit ahead that would fill the targeted order. I think all orders would have to go through matching. That would still prevent self-matching, and make the cancel-replace cycle more efficient, even if you have to commit to the new trades regardless of how the cancels turn out.... at least you know the orders targeted by the cancels are no longer booked.

chappjc commented 1 year ago

I think next steps for BatchOrder are to propose specification changes:

martonp commented 1 year ago

Yes I agree, cancels cannot target orders in the batch. Cancels should be processed first, then limit/market orders. I think the batch should be all or nothing though, this way locked funds from the cancelled orders can be reused for the new limit orders.

edit: Actually this is a bit more complicated. I'll think this through a bit more.

chappjc commented 1 year ago

I think the batch should be all or nothing though, this way locked funds from the cancelled orders can be reused for the new limit orders

Makes sense, but that poses challenges for both client and server, but mainly client. Client will have coins simultaneously assigned to two orders, and it becomes tricky to ensure it either unlocks (or does not!) these coins depending on the outcome of matching. Server may be OK, but unlocking of coins from the canceled order will have to be super prompt and potentially in a part of the code where we don't wanna be doing that. If there's partial fills on the fly and there's change replacing things, yikes.

All-or-nothing is also a good way to spoof orders. I'm sure users can craft BatchOrders that are darn near impossible to process fully, yet it doesn't become clear until matching.

Could work. Just needs to be fleshed out in spec changes first. We'll have to add conduct and penalization to the list of possible spec changes.