Skip to content

Commit 590893e

Browse files
authored
Bulk order cleanup per price level (#17785)
1 parent f60b782 commit 590893e

File tree

15 files changed

+479
-236
lines changed

15 files changed

+479
-236
lines changed

aptos-move/framework/aptos-experimental/doc/bulk_order_book.md

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ sophisticated order matching, cancellation, and reinsertion capabilities.
106106
- [Function `cancel_bulk_order`](#0x7_bulk_order_book_cancel_bulk_order)
107107
- [Arguments:](#@Arguments:_19)
108108
- [Aborts:](#@Aborts:_20)
109+
- [Function `get_bulk_order`](#0x7_bulk_order_book_get_bulk_order)
109110
- [Function `get_remaining_size`](#0x7_bulk_order_book_get_remaining_size)
110111
- [Function `get_prices`](#0x7_bulk_order_book_get_prices)
111112
- [Function `get_sizes`](#0x7_bulk_order_book_get_sizes)
@@ -663,7 +664,7 @@ with the same order ID in the future.
663664
- If no order exists for the specified account
664665

665666

666-
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book.md#0x7_bulk_order_book_cancel_bulk_order">cancel_bulk_order</a>&lt;M: <b>copy</b>, drop, store&gt;(self: &<b>mut</b> <a href="bulk_order_book.md#0x7_bulk_order_book_BulkOrderBook">bulk_order_book::BulkOrderBook</a>&lt;M&gt;, price_time_idx: &<b>mut</b> <a href="price_time_index.md#0x7_price_time_index_PriceTimeIndex">price_time_index::PriceTimeIndex</a>, <a href="../../aptos-framework/doc/account.md#0x1_account">account</a>: <b>address</b>): (<a href="order_book_types.md#0x7_order_book_types_OrderIdType">order_book_types::OrderIdType</a>, u64, u64)
667+
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book.md#0x7_bulk_order_book_cancel_bulk_order">cancel_bulk_order</a>&lt;M: <b>copy</b>, drop, store&gt;(self: &<b>mut</b> <a href="bulk_order_book.md#0x7_bulk_order_book_BulkOrderBook">bulk_order_book::BulkOrderBook</a>&lt;M&gt;, price_time_idx: &<b>mut</b> <a href="price_time_index.md#0x7_price_time_index_PriceTimeIndex">price_time_index::PriceTimeIndex</a>, <a href="../../aptos-framework/doc/account.md#0x1_account">account</a>: <b>address</b>): <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrder">bulk_order_book_types::BulkOrder</a>&lt;M&gt;
667668
</code></pre>
668669

669670

@@ -676,20 +677,49 @@ with the same order ID in the future.
676677
self: &<b>mut</b> <a href="bulk_order_book.md#0x7_bulk_order_book_BulkOrderBook">BulkOrderBook</a>&lt;M&gt;,
677678
price_time_idx: &<b>mut</b> aptos_experimental::price_time_index::PriceTimeIndex,
678679
<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>: <b>address</b>
679-
): (OrderIdType, u64, u64) {
680+
): BulkOrder&lt;M&gt; {
680681
<b>if</b> (!self.orders.contains(&<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>)) {
681682
<b>abort</b> <a href="bulk_order_book.md#0x7_bulk_order_book_EORDER_NOT_FOUND">EORDER_NOT_FOUND</a>;
682683
};
683684
// For cancellation, instead of removing the order, we will just cancel the active orders and set the sizes <b>to</b> 0.
684685
// This allows us <b>to</b> reuse the order id for the same <a href="../../aptos-framework/doc/account.md#0x1_account">account</a> in the future without creating a new order.
685686
<b>let</b> order = self.orders.remove(&<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>);
686-
<b>let</b> order_id = order.get_order_id();
687-
<b>let</b> remaining_bid_size = order.get_total_remaining_size(<b>true</b>);
688-
<b>let</b> remaining_ask_size = order.get_total_remaining_size(<b>false</b>);
687+
<b>let</b> order_copy = order;
689688
<a href="bulk_order_book.md#0x7_bulk_order_book_cancel_active_orders">cancel_active_orders</a>(price_time_idx, &order);
690689
order.set_empty();
691690
self.orders.add(<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>, order);
692-
(order_id, remaining_bid_size, remaining_ask_size)
691+
order_copy
692+
}
693+
</code></pre>
694+
695+
696+
697+
</details>
698+
699+
<a id="0x7_bulk_order_book_get_bulk_order"></a>
700+
701+
## Function `get_bulk_order`
702+
703+
704+
705+
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book.md#0x7_bulk_order_book_get_bulk_order">get_bulk_order</a>&lt;M: <b>copy</b>, drop, store&gt;(self: &<a href="bulk_order_book.md#0x7_bulk_order_book_BulkOrderBook">bulk_order_book::BulkOrderBook</a>&lt;M&gt;, <a href="../../aptos-framework/doc/account.md#0x1_account">account</a>: <b>address</b>): <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrder">bulk_order_book_types::BulkOrder</a>&lt;M&gt;
706+
</code></pre>
707+
708+
709+
710+
<details>
711+
<summary>Implementation</summary>
712+
713+
714+
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book.md#0x7_bulk_order_book_get_bulk_order">get_bulk_order</a>&lt;M: store + <b>copy</b> + drop&gt;(
715+
self: &<a href="bulk_order_book.md#0x7_bulk_order_book_BulkOrderBook">BulkOrderBook</a>&lt;M&gt;,
716+
<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>: <b>address</b>
717+
): BulkOrder&lt;M&gt; {
718+
<b>if</b> (!self.orders.contains(&<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>)) {
719+
<b>abort</b> <a href="bulk_order_book.md#0x7_bulk_order_book_EORDER_NOT_FOUND">EORDER_NOT_FOUND</a>;
720+
};
721+
722+
self.orders.get(&<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>).destroy_some()
693723
}
694724
</code></pre>
695725

aptos-move/framework/aptos-experimental/doc/bulk_order_book_types.md

Lines changed: 14 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -310,30 +310,6 @@ both original and remaining sizes for tracking purposes.
310310
</dt>
311311
<dd>
312312

313-
</dd>
314-
<dt>
315-
<code>orig_bid_size: u64</code>
316-
</dt>
317-
<dd>
318-
319-
</dd>
320-
<dt>
321-
<code>orig_ask_size: u64</code>
322-
</dt>
323-
<dd>
324-
325-
</dd>
326-
<dt>
327-
<code>total_remaining_bid_size: u64</code>
328-
</dt>
329-
<dd>
330-
331-
</dd>
332-
<dt>
333-
<code>total_remaining_ask_size: u64</code>
334-
</dt>
335-
<dd>
336-
337313
</dd>
338314
<dt>
339315
<code>bid_prices: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;</code>
@@ -481,18 +457,11 @@ A new <code><a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrde
481457
} <b>else</b> {
482458
(ask_prices, ask_sizes)
483459
};
484-
// Original bid and ask sizes are the sum of the sizes at each price level
485-
<b>let</b> orig_bid_size = bid_sizes.fold(0, |acc, size| acc + size);
486-
<b>let</b> orig_ask_size = ask_sizes.fold(0, |acc, size| acc + size);
487460
BulkOrder::V1 {
488461
order_id,
489462
<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>,
490463
unique_priority_idx,
491464
order_sequence_number,
492-
orig_bid_size,
493-
orig_ask_size,
494-
total_remaining_bid_size: orig_bid_size, // Initially, the remaining size is the original size
495-
total_remaining_ask_size: orig_ask_size, // Initially, the remaining size is the original size
496465
bid_prices: post_only_bid_prices,
497466
bid_sizes: post_only_bid_sizes,
498467
ask_prices: post_only_ask_prices,
@@ -936,10 +905,10 @@ A <code>SingleBulkOrderMatch</code> containing the match details.
936905
is_bid: bool,
937906
matched_size: u64
938907
): OrderMatch&lt;M&gt; {
939-
<b>let</b> price = <b>if</b> (is_bid) {
940-
order.bid_prices[0]
908+
<b>let</b> (price, remaining_size) = <b>if</b> (is_bid) {
909+
(order.bid_prices[0], order.bid_sizes[0] - matched_size)
941910
} <b>else</b> {
942-
order.ask_prices[0]
911+
(order.ask_prices[0], order.ask_sizes[0] - matched_size)
943912
};
944913
new_order_match&lt;M&gt;(
945914
new_order_match_details&lt;M&gt;(
@@ -948,8 +917,8 @@ A <code>SingleBulkOrderMatch</code> containing the match details.
948917
<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(),
949918
order.<a href="bulk_order_book_types.md#0x7_bulk_order_book_types_get_unique_priority_idx">get_unique_priority_idx</a>(),
950919
price,
951-
order.orig_bid_size + order.orig_ask_size,
952-
order.total_remaining_bid_size + order.total_remaining_ask_size - matched_size,
920+
0, // Original size is not applicable for bulk orders
921+
remaining_size,
953922
is_bid,
954923
good_till_cancelled(),
955924
order.metadata,
@@ -984,9 +953,9 @@ A <code>SingleBulkOrderMatch</code> containing the match details.
984953
is_bid: bool,
985954
): u64 {
986955
<b>if</b> (is_bid) {
987-
self.total_remaining_bid_size
956+
self.bid_sizes.fold(0, |acc, size| acc + size)
988957
} <b>else</b> {
989-
self.total_remaining_ask_size
958+
self.ask_sizes.fold(0, |acc, size| acc + size)
990959
}
991960
}
992961
</code></pre>
@@ -1315,21 +1284,19 @@ the size; otherwise, it inserts the new price level at the front.
13151284
other: &OrderMatchDetails&lt;M&gt;,
13161285
) {
13171286
// Reinsert the order into the bulk order
1318-
<b>let</b> (prices, sizes, total_remaining) = <b>if</b> (other.is_bid_from_match_details()) {
1319-
(&<b>mut</b> self.bid_prices, &<b>mut</b> self.bid_sizes, &<b>mut</b> self.total_remaining_bid_size)
1287+
<b>let</b> (prices, sizes) = <b>if</b> (other.is_bid_from_match_details()) {
1288+
(&<b>mut</b> self.bid_prices, &<b>mut</b> self.bid_sizes)
13201289
} <b>else</b> {
1321-
(&<b>mut</b> self.ask_prices, &<b>mut</b> self.ask_sizes, &<b>mut</b> self.total_remaining_ask_size)
1290+
(&<b>mut</b> self.ask_prices, &<b>mut</b> self.ask_sizes)
13221291
};
13231292
// Reinsert the price and size at the front of the respective vectors - <b>if</b> the price already <b>exists</b>, we ensure that
13241293
// it is same <b>as</b> the reinsertion price and we just increase the size
13251294
// If the price does not exist, we insert it at the front.
13261295
<b>if</b> (prices.length() &gt; 0 && prices[0] == other.get_price_from_match_details()) {
13271296
sizes[0] += other.get_remaining_size_from_match_details(); // Increase the size at the first price level
1328-
*total_remaining += other.get_remaining_size_from_match_details(); // Increase the total remaining size
13291297
} <b>else</b> {
13301298
prices.insert(0, other.get_price_from_match_details()); // Insert the new price at the front
13311299
sizes.insert(0, other.get_remaining_size_from_match_details()); // Insert the new size at the front
1332-
*total_remaining += other.get_remaining_size_from_match_details(); // Set the total remaining size <b>to</b> the new size
13331300
}
13341301
}
13351302
</code></pre>
@@ -1385,14 +1352,13 @@ A tuple containing the next active price and size as options.
13851352
is_bid: bool,
13861353
matched_size: u64,
13871354
): (Option&lt;u64&gt;, Option&lt;u64&gt;) {
1388-
<b>let</b> (prices, sizes, total_remaining) = <b>if</b> (is_bid) {
1389-
(&<b>mut</b> self.bid_prices, &<b>mut</b> self.bid_sizes, &<b>mut</b> self.total_remaining_bid_size)
1355+
<b>let</b> (prices, sizes) = <b>if</b> (is_bid) {
1356+
(&<b>mut</b> self.bid_prices, &<b>mut</b> self.bid_sizes)
13901357
} <b>else</b> {
1391-
(&<b>mut</b> self.ask_prices, &<b>mut</b> self.ask_sizes, &<b>mut</b> self.total_remaining_ask_size)
1358+
(&<b>mut</b> self.ask_prices, &<b>mut</b> self.ask_sizes)
13921359
};
13931360
<b>assert</b>!(matched_size &lt;= sizes[0], <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_EUNEXPECTED_MATCH_SIZE">EUNEXPECTED_MATCH_SIZE</a>); // Ensure the remaining size is not more than the size at the first price level
13941361
sizes[0] -= matched_size; // Decrease the size at the first price level by the matched size
1395-
*total_remaining -= matched_size; // Decrease the total remaining size
13961362
<b>if</b> (sizes[0] == 0) {
13971363
// If the size at the first price level is now 0, remove this price level
13981364
prices.remove(0);
@@ -1436,8 +1402,6 @@ Sets the bulk order to empty state by clearing all sizes.
14361402
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_set_empty">set_empty</a>&lt;M: store + <b>copy</b> + drop&gt;(
14371403
self: &<b>mut</b> <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrder">BulkOrder</a>&lt;M&gt;
14381404
) {
1439-
self.total_remaining_bid_size = 0;
1440-
self.total_remaining_ask_size = 0;
14411405
self.bid_sizes = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_empty">vector::empty</a>();
14421406
self.ask_sizes = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_empty">vector::empty</a>();
14431407
self.bid_prices = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_empty">vector::empty</a>();
@@ -1455,7 +1419,7 @@ Sets the bulk order to empty state by clearing all sizes.
14551419

14561420

14571421

1458-
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_destroy_bulk_order">destroy_bulk_order</a>&lt;M: <b>copy</b>, drop, store&gt;(self: <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrder">bulk_order_book_types::BulkOrder</a>&lt;M&gt;): (<a href="order_book_types.md#0x7_order_book_types_OrderIdType">order_book_types::OrderIdType</a>, <b>address</b>, <a href="order_book_types.md#0x7_order_book_types_UniqueIdxType">order_book_types::UniqueIdxType</a>, u64, u64, u64, u64, u64, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, M)
1422+
<pre><code><b>public</b> <b>fun</b> <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_destroy_bulk_order">destroy_bulk_order</a>&lt;M: <b>copy</b>, drop, store&gt;(self: <a href="bulk_order_book_types.md#0x7_bulk_order_book_types_BulkOrder">bulk_order_book_types::BulkOrder</a>&lt;M&gt;): (<a href="order_book_types.md#0x7_order_book_types_OrderIdType">order_book_types::OrderIdType</a>, <b>address</b>, <a href="order_book_types.md#0x7_order_book_types_UniqueIdxType">order_book_types::UniqueIdxType</a>, u64, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;, M)
14591423
</code></pre>
14601424

14611425

@@ -1471,10 +1435,6 @@ Sets the bulk order to empty state by clearing all sizes.
14711435
<b>address</b>,
14721436
UniqueIdxType,
14731437
u64,
1474-
u64,
1475-
u64,
1476-
u64,
1477-
u64,
14781438
<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;,
14791439
<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;,
14801440
<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;,
@@ -1486,10 +1446,6 @@ Sets the bulk order to empty state by clearing all sizes.
14861446
<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>,
14871447
unique_priority_idx,
14881448
order_sequence_number,
1489-
orig_bid_size,
1490-
orig_ask_size,
1491-
total_remaining_bid_size,
1492-
total_remaining_ask_size,
14931449
bid_prices,
14941450
bid_sizes,
14951451
ask_prices,
@@ -1501,10 +1457,6 @@ Sets the bulk order to empty state by clearing all sizes.
15011457
<a href="../../aptos-framework/doc/account.md#0x1_account">account</a>,
15021458
unique_priority_idx,
15031459
order_sequence_number,
1504-
orig_bid_size,
1505-
orig_ask_size,
1506-
total_remaining_bid_size,
1507-
total_remaining_ask_size,
15081460
bid_prices,
15091461
bid_sizes,
15101462
ask_prices,

aptos-move/framework/aptos-experimental/doc/market_bulk_order.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Returns:
8585
ask_sizes,
8686
metadata,
8787
));
88-
<b>let</b> (order_id, _, _, _, _, _, _, _, bid_sizes, bid_prices, ask_sizes, ask_prices, _ ) = bulk_order.destroy_bulk_order(); // We don't need <b>to</b> keep the bulk order <b>struct</b> after placement
88+
<b>let</b> (order_id, _, _, _, bid_sizes, bid_prices, ask_sizes, ask_prices, _ ) = bulk_order.destroy_bulk_order(); // We don't need <b>to</b> keep the bulk order <b>struct</b> after placement
8989
// Emit an <a href="../../aptos-framework/doc/event.md#0x1_event">event</a> for the placed bulk order
9090
market.emit_event_for_bulk_order_placed(order_id, <a href="../../aptos-framework/doc/account.md#0x1_account">account</a>, bid_sizes, bid_prices, ask_sizes, ask_prices);
9191
<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(order_id)
@@ -153,9 +153,17 @@ Parameters:
153153
user: <b>address</b>,
154154
callbacks: &MarketClearinghouseCallbacks&lt;M, R&gt;
155155
) {
156-
<b>let</b> (order_id, remaining_bid_size, remaining_ask_size) = market.get_order_book_mut().<a href="market_bulk_order.md#0x7_market_bulk_order_cancel_bulk_order">cancel_bulk_order</a>(user);
157-
<b>if</b> (remaining_bid_size &gt; 0 || remaining_ask_size &gt; 0) {
158-
callbacks.cleanup_bulk_orders(user, order_id);
156+
<b>let</b> cancelled_bulk_order = market.get_order_book_mut().<a href="market_bulk_order.md#0x7_market_bulk_order_cancel_bulk_order">cancel_bulk_order</a>(user);
157+
<b>let</b> (order_id, _, _, _, bid_sizes, bid_prices, ask_sizes, ask_prices, _ ) = cancelled_bulk_order.destroy_bulk_order();
158+
<b>let</b> i = 0;
159+
<b>while</b> (i &lt; bid_sizes.length()) {
160+
callbacks.cleanup_bulk_order_at_price(user, order_id, <b>true</b>, bid_prices[i], bid_sizes[i]);
161+
i += 1;
162+
};
163+
<b>let</b> j = 0;
164+
<b>while</b> (j &lt; ask_sizes.length()) {
165+
callbacks.cleanup_bulk_order_at_price(user, order_id, <b>false</b>, ask_prices[j], ask_sizes[j]);
166+
j += 1;
159167
};
160168
market.emit_event_for_bulk_order_cancelled(order_id, user);
161169
}

0 commit comments

Comments
 (0)