Hi team,
during the course of the Tantalus project we had quite some thoughts on what it means to build a decentralised market, and market concepts ("trading" if you will) in general.
In this post I want to share thoughts on different kinds of orders and what they mean for doing swaps - i.e. decentral settlement of orders.
I want to share domain knowledge, learn more myself and align our brain model.
It would be cool if we can share these thoughts / model with people that have more domain knowledge (e.g. Toby) to find flaws early and not get stuck in a "wrong" model.
I generally think that we still have a lack of domain knowledge and would like to reach out to more experienced people for learning sessions. Happy for advice on that matter. (My current strategy is to trade more myself so I learn more while doing.)
I am planning to create another Basecamp post that can serve as another "glossary" entry after some discussion / alignment here.
I see this as information that does not change once agreed upon, but helps us keep the model together.
---
Introduction to Limit Order and Market Order:
Limit Order and Market Order are general financial terms outside the crypto world.
Forex Order Model Recap: https://3.basecamp.com/4403044/buckets/15109376/messages/2878398232
This model describes a Limit Order.
The Limit Order:
A Limit Order is an order where we specify a price limit.
The order will only be matched once the price reaches the specified limit.
Limit orders are publicly available (i.e. visible) in the market directly after creation.
A limit order does not necessarily settle at exactly the price specified. It settles at at least the specified price (i.e. it can settle at a better price).
The Market Order:
The market order (or "best" order, or "best price" order) is an order that does not specify a price.
It only specifies a quantity that we want to buy/sell.
The best market price is selected automatically for you when publishing such an order.
Effectively this means:
When publishing a sell market order the best price is determined as the highest buy price currently on the market.
When publishing a buy market order the best price is determined as lowest sell price currently on the market.
Note that some market places implement more elaborate orders like stop orders (also called stop-limit orders), that take into account when a limit order becomes publicly visible [1].
Some more thoughts on orders:
As far as my understand goes, market orders are important for bringing trading volume into a market, i.e. how much quantity of a currency is traded during a time interval.
If there is only limit orders in a market, and both sides don't move the market is "stale", i.e. no orders get executed.
Excursus:
Bid: The current best buy price. I think that eventually we will have to weight this by volume, because the price is bound to a certain quantity at that price.
Ask: The current best sell price. I think that eventually we will have to weight this by volume, because the price is bound to a certain quantity at that price.
---
This section goes more into detail of orders and swaps in the COMIT market.
We currently emit order matches in cnd that are followed by sending a swap request to the matching peer. If we both sent and received a matching swap request we start swapping (i.e. the swap becomes available on cnd's /swaps endpoint with Alice having the fund action).
Settling a Limit Order in one swap with matching quantities but different price:
Rule (1) - An order matches if both parties get at least the price they asked for.
Example:
Alice publishes a sell limit order:
BtcDaiOrder: {
position: sell,
price: 12000,
quantity: 1
}
She wants to get at least 12000 DAI for her 1 BTC.
Bob publishes a buy limit order:
BtcDaiOrder: {
position: buy,
price: 12001,
quantity: 1
}
He is willing to give 12001 DAI for getting 1 BTC.
The two orders should match!( Keep in mind that there is not only two persons in the market. So, if I really want a trade to happen I offer a better price. That is what Bob is doing.)
When it comes to the domain of swaps we initially found the "settle at a better price than the order" behaviour tricky, because we have to agree on the quantity for the swap.
I think we can establish rule (1) and settle at the price of the newer order, if the price is favourable for the older order's side.
For the above scenario both should:
1. Have a match
2. Send a Swap with price 12001
3. If either party sends the swap, but never receives a swap from the other party, the reputation should be decreased.
Settling a Limit Order in multiple swaps (i.e. partial filling):
In addition to rule (1):Rule (3) - When cancelling an order, the open part will be cancelled, part of the order in any other state cannot be cancelled. Order.state = 'open' | 'settling' | 'closed' | 'failed' | ' cancelled'. Currently each state is represented as % of the order quantity, rounded to 2 positions after the point.
Rule (2) - When an order matches on price, but the quantities don't match, the order with smaller amount is settled as swap. The remaining part of the order that was not completely filled stays in the market until a match is found.
Settling a Market Order:
When sending a buy Market Order to our cnd:
1. Take all the current sell orders we know, excluding our own.
2. Take the sell order with the lowest sell price.
3. Emit market order match and send swap request.
When processing an incoming buy Market Order from another peer:
1. Take all the sell orders, including our own.
2. If the sell order with the highest price is ours: Emit market order match and send swap request.
For sending/receiving a market sell order the behaviour is flipped accordingly.
Note that in combination with partial filling this can result in settling an order in multiple swaps at multiple prices :)
---
[1] https://www.investopedia.com/ask/answers/04/022704.asp
Cheers,
Daniel
Limit Order and Market Order are general financial terms outside the crypto world.
Forex Order Model Recap: https://3.basecamp.com/4403044/buckets/15109376/messages/2878398232
This model describes a Limit Order.
The Limit Order:
A Limit Order is an order where we specify a price limit.
The order will only be matched once the price reaches the specified limit.
Limit orders are publicly available (i.e. visible) in the market directly after creation.
A limit order does not necessarily settle at exactly the price specified. It settles at at least the specified price (i.e. it can settle at a better price).So at the moment, we kind of have limit orders but they are more restricted:- We only match exact price, not exact price or better- We only match exact quantity. Limit order could be partially settled, matching with several smaller order
This makes me think that we should review and aim to make our order actual limit orders.
The Market Order:
The market order (or "best" order, or "best price" order) is an order that does not specify a price.
It only specifies a quantity that we want to buy/sell.
The best market price is selected automatically for you when publishing such an order.
Effectively this means:
When publishing a sell market order the best price is determined as the highest buy price currently on the market.
When publishing a buy market order the best price is determined as lowest sell price currently on the market.
This kind of matches our "best" button order.In our case, we kind of place a limit order (see above) with the best price. The difference with a proper market order is that if someone else takes the best price before us thenno execution happens. Whereas on a central exchange, it will continue to execute the order (and tell you the price afterwards).I think this feature is hard to implement on a DexOB. However, being able to place proper limit order at a best price could be a nice replacement in the short/medium term.
If we want to do a proper market order then I would expect the following flow (taking in account our current design).1. User choose quantity to sell/buy and click "market order". Let's say buy 5BTC
2. Ambrosia looks at current order book, see a 2 BTC limit order at $10,000 and a 4BTC limit order at $11,000.3. Ambrosia broadcast a 2BTC limit order at $10,000 and a 3BTC limit order at $11,0004. The other party sees the 2BTC limit order, it then gets fully executed5. The other(other) party see the 3BTC limit order, it gets fully executed. The other party's order (4BTC) is only partially executed.6. Ambrosia report back to the user and says that the market price for those 5BTC where (2 * 10,000 + 3 * 11,000)/5= $10,600.
Note that some market places implement more elaborate orders like stop orders (also called stop-limit orders), that take into account when a limit order becomes publicly visible [1].
Some more thoughts on orders:
As far as my understand goes, market orders are important for bringing trading volume into a market, i.e. how much quantity of a currency is traded during a time interval.It's more that makers create limit orders and "market orders" are the easiest order to use. You don't try to predict a price, or plan in advance. You just want to sell/buy now at the current price. It's the "simplest" way to trade.But again, being able to place a proper limit order at the current best rate is a good way to have pseudo-market orders on the DexOB.
If there is only limit orders in a market, and both sides don't move the market is "stale", i.e. no orders get executed.
True, until someone replace a limit order with another one that is executable.
Excursus:
Bid: The current best buy price. I think that eventually we will have to weight this by volume, because the price is bound to a certain quantity at that price.
This is not a feature available on the exchanges I am familiar with. Can you define "current best buy" using trading terms? Are you talking about limit order at best price? If so, then yes of course if the quantity of your order is bigger thanthe quantity of the best price limit order on the trading book, then your limit order will not execute completely. That is something that is expected on a CEX so I don't think we should get out our way and make something better.
When it comes to the domain of swaps we initially found the "settle at a better price than the order" behaviour tricky, because we have to agree on the quantity for the swap.I think it's easy to have a consensus rule here: the smallest quantity is the one to be used.
I think we can establish rule (1) and settle at the price of the newer order, if the price is favourable for the older order's side.
For the above scenario both should:
1. Have a match
2. Send a Swap with price 12001
3. If either party sends the swap, but never receives a swap from the other party, the reputation should be decreased.
Let's not go so fast regarding reputation. Maybe Alice already executed the swap with someone else! Or she wanted to "withdraw" her order. (ok I see you already mentioned that later)
Settling a Limit Order in multiple swaps (i.e. partial filling):
In addition to rule (1):Rule (3) - When cancelling an order, the open part will be cancelled, part of the order in any other state cannot be cancelled. Order.state = 'open' | 'settling' | 'closed' | 'failed' | ' cancelled'. Currently each state is represented as % of the order quantity, rounded to 2 positions after the point.
Rule (2) - When an order matches on price, but the quantities don't match, the order with smaller amount is settled as swap. The remaining part of the order that was not completely filled stays in the market until a match is found.
At the moment it is not possible to cancel an order.Maybe instead, Ambrosia for the party that only partially had their order fulfilled should send a new order for the same price and remaining quantity.
[snip]
In a way reputation is something that can be added later. But we should keep it in mind.When it comes to the domain of swaps we initially found the "settle at a better price than the order" behaviour tricky, because we have to agree on the quantity for the swap.I think it's easy to have a consensus rule here: the smallest quantity is the one to be used.
I think we can establish rule (1) and settle at the price of the newer order, if the price is favourable for the older order's side.
For the above scenario both should:
1. Have a match
2. Send a Swap with price 12001
3. If either party sends the swap, but never receives a swap from the other party, the reputation should be decreased.
Let's not go so fast regarding reputation. Maybe Alice already executed the swap with someone else! Or she wanted to "withdraw" her order. (ok I see you already mentioned that later)
I think we should give some reputation a try early, for an isolated use case. Early feedback on the reputation will give us good learnings I think. I think the above example is fairly straight forward. We don't have to immediately decrease the reputation score, but if we don't get a response from the same user X times then we should. To prevent spamming.
It actually is possible! Cancelling the open part of an order is implemented in cnd :)Settling a Limit Order in multiple swaps (i.e. partial filling):
In addition to rule (1):Rule (3) - When cancelling an order, the open part will be cancelled, part of the order in any other state cannot be cancelled. Order.state = 'open' | 'settling' | 'closed' | 'failed' | ' cancelled'. Currently each state is represented as % of the order quantity, rounded to 2 positions after the point.
Rule (2) - When an order matches on price, but the quantities don't match, the order with smaller amount is settled as swap. The remaining part of the order that was not completely filled stays in the market until a match is found.
At the moment it is not possible to cancel an order.Maybe instead, Ambrosia for the party that only partially had their order fulfilled should send a new order for the same price and remaining quantity.
[snip]
When sending a buy Market Order to our cnd:
1. Take all the current sell orders we know, excluding our own.
2. Take the sell order with the lowest sell price.
3. Emit market order match and send swap request.
When processing an incoming buy Market Order from another peer:
1. Take all the sell orders, including our own.
2. If the sell order with the highest price is ours: Emit market order match and send swap request.
[snip]
In a way reputation is something that can be added later. But we should keep it in mind.When it comes to the domain of swaps we initially found the "settle at a better price than the order" behaviour tricky, because we have to agree on the quantity for the swap.I think it's easy to have a consensus rule here: the smallest quantity is the one to be used.
I think we can establish rule (1) and settle at the price of the newer order, if the price is favourable for the older order's side.
For the above scenario both should:
1. Have a match
2. Send a Swap with price 12001
3. If either party sends the swap, but never receives a swap from the other party, the reputation should be decreased.
Let's not go so fast regarding reputation. Maybe Alice already executed the swap with someone else! Or she wanted to "withdraw" her order. (ok I see you already mentioned that later)
I think we should give some reputation a try early, for an isolated use case. Early feedback on the reputation will give us good learnings I think. I think the above example is fairly straight forward. We don't have to immediately decrease the reputation score, but if we don't get a response from the same user X times then we should. To prevent spamming.
It actually is possible! Cancelling the open part of an order is implemented in cnd :)Settling a Limit Order in multiple swaps (i.e. partial filling):
In addition to rule (1):Rule (3) - When cancelling an order, the open part will be cancelled, part of the order in any other state cannot be cancelled. Order.state = 'open' | 'settling' | 'closed' | 'failed' | ' cancelled'. Currently each state is represented as % of the order quantity, rounded to 2 positions after the point.
Rule (2) - When an order matches on price, but the quantities don't match, the order with smaller amount is settled as swap. The remaining part of the order that was not completely filled stays in the market until a match is found.
At the moment it is not possible to cancel an order.Maybe instead, Ambrosia for the party that only partially had their order fulfilled should send a new order for the same price and remaining quantity.
Can someone describe how it works?
Initially the complete quantity is in open.
When an order has a matching swap the complete quantity moves from open to settling.
Once the swap is finished it moves from settling to closed.
If the swap fails it moves from settling to failed.
If the user cancels the order it moves to cancelled. At the moment the user can only cancel the complete order, as long as everything is in the open state (i.e. the order has not been matched).
We initially created an order with quantity 1 BTC.
0.1 BTC already got settled and are closed.
0.2 BTC are currently being settled in another swap.
Since we expect the price to change we don't want to wait for the rest to settle, and cancel the rest.
This would result in (simplified in Bitcoin, the amounts are actually in Sats and represented as string):
BtcDaiOrder {
position: ...,
price: ...,
quantity: 1,
state: {
open: 0,
closed: 0.1,
settling: 0.2,
failed: 0,
cancelled: 0.7,
}
}
Upon cancellation, if the open amount is 0 we additionally remove the order from the orderbook.
[snip]
On Tue, 8 Sep 2020 at 21:32, Daniel Karzel <dan...@coblox.tech> wrote: [snip]I don't see the need of a central authority for that. Cnd's matching engine can collect all orders and match the what is considered best for you, as described in the original email: Settling a Market Order: When sending a buy Market Order to our cnd: 1. Take all the current sell orders we know, excluding our own. 2. Take the sell order with the lowest sell price. 3. Emit market order match and send swap request.I think this explanation is too abbreviated. What do you mean by "Emit market order match"? Emit from the orderbook to cnd? When do you send an order on the network? Is the order you send to the network the same than the other orders?When processing an incoming buy Market Order from another peer:What is the difference between a "market order" and a current order in the orderbook?
1. Take all the sell orders, including our own. 2. If the sell order with the highest price is ours: Emit market order match and send swap request.So you are saying that a "market order" is priceless. So when you receive it, you look at your pool of order. If the best order is your order then you proceed with the match.
Settling market orders at a "good" price requires a certain amount of orders in the market (i.e. trading volume). I don't fully understand you concerns. You state that a DexOB cannot fairly complete a market order. What is "unfair" in your eyes?I stand corrected, I did not fully understand the proposed flow until now.I don't have a problem with focussing on Limit orders, but I think Market orders are possible in a DexOB.I think they are possible in cnd/nectar/ambrosia. I don't think we need market orders in the DexOB to give a market order UX. See my argumentation above.
[snip]It actually is possible! Cancelling the open part of an order is implemented in cnd :)Can someone describe how it works? Orders have a quantity. Orders have five different states, that the quantity can be spread over: open, closed, settling, failed, cancelled. Assuming that we don't have partial order filling yet: Initially the complete quantity is in open. When an order has a matching swap the complete quantity moves from open to settling.(A)Once the swap is finished it moves from settling to closed.(B)If the swap fails it moves from settling to failed.(C)If the user cancels the order it moves to cancelled. At the moment the user can only cancel the complete order, as long as everything is in the open state (i.e. the order has not been matched).(D)Assuming partial filling (Not implemented yet): We initially created an order with quantity 1 BTC. 0.1 BTC already got settled and are closed. 0.2 BTC are currently being settled in another swap.In (A), (B), (C), (D), Do you mean a new order is broadcast, exactly the same than before, but with a different status?
Since we expect the price to change we don't want to wait for the rest to settle, and cancel the rest.Do you mean a new order is broadcast with a cancel status?
This would result in (simplified in Bitcoin, the amounts are actually in Sats and represented as string): BtcDaiOrder { position: ..., price: ..., quantity: 1, state: { open: 0, closed: 0.1, settling: 0.2, failed: 0, cancelled: 0.7, } } Upon cancellation, if the open amount is 0 we additionally remove the order from the orderbook. Note that previously we used percentage of the quantity to represent the state. This is cumbersome for the UI (and cnd for that matter...). This is the PR that changes it to quantities: https://github.com/comit-network/comit-rs/pull/3140[snip]