Skip to content

Commit

Permalink
add batch cancel example (#223)
Browse files Browse the repository at this point in the history
* add batch cancel example

* add batch cancel docs

* add `short_term_cancels` to documentation
  • Loading branch information
samtin0x authored Aug 22, 2024
1 parent 64a9e63 commit 56d8c2d
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 68 deletions.
60 changes: 60 additions & 0 deletions v4-client-py-v2/documentation/cancelling_orders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Cancelling Orders

This guide demonstrates how to cancel orders using the dYdX Python SDK.

## Cancelling Orders

There are two ways to cancel orders using the dYdX Python SDK:

### 1. Cancel a Specific Order

To cancel a specific order, you can use the `cancel_order` method. Here's an example:

```python
from dydx_v4_client.node.message import cancel_order

cancel_order_msg = cancel_order(
order_id,
good_til_block,
good_til_block_time
)

response = await node_client.cancel_order(
wallet,
order_id,
good_til_block=good_til_block,
good_til_block_time=good_til_block_time
)
```

### 2. Batch Cancel Orders
For cancelling multiple orders at once, you can use the batch_cancel_orders method. Here's an example:
pythonCopyfrom dydx_v4_client.node.message import batch_cancel
from v4_proto.dydxprotocol.clob.order_pb2 import OrderBatch

```python
PERPETUAL_PAIR_BTC_USD = 0

client_ids = [tx_client_id1, tx_client_id2]
short_term_cancels = [OrderBatch(clob_pair_id=PERPETUAL_PAIR_BTC_USD, client_ids=client_ids)]

batch_cancel_msg = batch_cancel(
subaccount_id,
short_term_cancels,
good_til_block
)

response = await node_client.batch_cancel_orders(
wallet,
subaccount_id,
short_term_cancels,
good_til_block
)
```

### Examples
For more detailed examples of how to cancel orders:
- **Cancelling a specific order**: See `examples/long_term_order_cancel_example.py`
- **Batch cancelling orders**: See `examples/batch_cancel_example.py`


2 changes: 1 addition & 1 deletion v4-client-py-v2/documentation/placing_orders.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ Alternatively, you can use the market-based calculator, which provides more conv
- Long term order + cancel: Example in `examples/long_term_order_cancel_example.py`

## Next Steps
Continue reading to learn how to [manage your positions](./account_order_information.md) using the dYdX Python SDK.
Continue reading to learn how to [cancel orders](./cancelling_orders.md) using the dYdX Python SDK.
8 changes: 0 additions & 8 deletions v4-client-py-v2/dydx_v4_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
from enum import IntEnum

from v4_proto.dydxprotocol.clob.order_pb2 import Order

from dydx_v4_client.faucet_client import FaucetClient
from dydx_v4_client.indexer.rest.indexer_client import IndexerClient
from dydx_v4_client.indexer.socket.websocket import IndexerSocket
from dydx_v4_client.node.client import NodeClient, QueryNodeClient
from dydx_v4_client.wallet import Wallet


class OrderFlags(IntEnum):
SHORT_TERM = 0
Expand Down
1 change: 0 additions & 1 deletion v4-client-py-v2/dydx_v4_client/indexer/rest/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from dydx_v4_client.indexer.rest.indexer_client import IndexerClient
2 changes: 0 additions & 2 deletions v4-client-py-v2/dydx_v4_client/indexer/socket/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
from dydx_v4_client.indexer.socket.websocket import IndexerSocket
from dydx_v4_client.indexer.candles_resolution import CandlesResolution
1 change: 0 additions & 1 deletion v4-client-py-v2/dydx_v4_client/node/chain_helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from dydx_v4_client.indexer.rest.constants import (
OrderType,
OrderExecution,
OrderTimeInForce,
)
from v4_proto.dydxprotocol.clob.order_pb2 import Order

Expand Down
30 changes: 29 additions & 1 deletion v4-client-py-v2/dydx_v4_client/node/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import grpc
from google._upb._message import Message
from google.protobuf.json_format import MessageToDict, MessageToJson
from google.protobuf.json_format import MessageToDict
from typing_extensions import List, Optional, Self
from v4_proto.cosmos.auth.v1beta1 import query_pb2_grpc as auth
from v4_proto.cosmos.auth.v1beta1.auth_pb2 import BaseAccount
Expand Down Expand Up @@ -66,6 +66,7 @@
QuerySubaccountAllResponse,
)
from v4_proto.dydxprotocol.subaccounts.subaccount_pb2 import SubaccountId
from v4_proto.dydxprotocol.clob.tx_pb2 import OrderBatch

from dydx_v4_client.network import NodeConfig
from dydx_v4_client.node.builder import Builder
Expand All @@ -77,6 +78,7 @@
send_token,
transfer,
withdraw,
batch_cancel,
)
from dydx_v4_client.wallet import Wallet

Expand Down Expand Up @@ -743,3 +745,29 @@ async def cancel_order(
return await self.broadcast_message(
wallet, cancel_order(order_id, good_til_block, good_til_block_time)
)

async def batch_cancel_orders(
self,
wallet: Wallet,
subaccount_id: SubaccountId,
short_term_cancels: List[OrderBatch],
good_til_block: int,
):
"""
Batch cancels orders for a subaccount.
Args:
wallet (Wallet): The wallet to use for signing the transaction.
subaccount_id (SubaccountId): The subaccount ID for which to cancel orders.
short_term_cancels (List[OrderBatch]): List of OrderBatch objects containing the orders to cancel.
good_til_block (int): The last block the short term order cancellations can be executed at.
Returns:
The response from the transaction broadcast.
"""
batch_cancel_msg = batch_cancel(
subaccount_id=subaccount_id,
short_term_cancels=short_term_cancels,
good_til_block=good_til_block,
)
return await self.broadcast_message(wallet, batch_cancel_msg)
16 changes: 16 additions & 0 deletions v4-client-py-v2/dydx_v4_client/node/message.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import List

from v4_proto.cosmos.bank.v1beta1.tx_pb2 import MsgSend
from v4_proto.cosmos.base.v1beta1.coin_pb2 import Coin
from v4_proto.dydxprotocol.clob.order_pb2 import Order, OrderId
Expand All @@ -9,6 +11,7 @@
)
from v4_proto.dydxprotocol.sending.tx_pb2 import MsgCreateTransfer
from v4_proto.dydxprotocol.subaccounts.subaccount_pb2 import SubaccountId
from v4_proto.dydxprotocol.clob.tx_pb2 import MsgBatchCancel, OrderBatch


def order(
Expand Down Expand Up @@ -75,6 +78,19 @@ def cancel_order(
return message


def batch_cancel(
subaccount_id: SubaccountId,
short_term_cancels: List[OrderBatch],
good_til_block: int,
):
message = MsgBatchCancel(
subaccount_id=subaccount_id,
short_term_cancels=short_term_cancels,
good_til_block=good_til_block,
)
return message


def transfer(
sender_subaccount: SubaccountId,
recipient_subaccount: SubaccountId,
Expand Down
66 changes: 66 additions & 0 deletions v4-client-py-v2/examples/batch_cancel_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import asyncio
import random

from dydx_v4_client import MAX_CLIENT_ID, NodeClient, Order, OrderFlags
from dydx_v4_client.indexer.rest.constants import OrderType
from dydx_v4_client.indexer.rest.indexer_client import IndexerClient
from dydx_v4_client.network import TESTNET
from dydx_v4_client.node.market import Market
from dydx_v4_client.wallet import Wallet
from tests.conftest import DYDX_TEST_MNEMONIC, TEST_ADDRESS
from v4_proto.dydxprotocol.clob.tx_pb2 import OrderBatch
from v4_proto.dydxprotocol.subaccounts.subaccount_pb2 import SubaccountId


MARKET_ID = "BTC-USD"
PERPETUAL_PAIR_BTC_USD = 0


async def test_batch_cancel():
node = await NodeClient.connect(TESTNET.node)
indexer = IndexerClient(TESTNET.rest_indexer)

market = Market(
(await indexer.markets.get_perpetual_markets(MARKET_ID))["markets"][MARKET_ID]
)
wallet = await Wallet.from_mnemonic(node, DYDX_TEST_MNEMONIC, TEST_ADDRESS)

# Place multiple orders
orders = []
client_ids = []
for _ in range(3):
client_id = random.randint(0, MAX_CLIENT_ID)
order_id = market.order_id(TEST_ADDRESS, 0, client_id, OrderFlags.SHORT_TERM)
client_ids.append(client_id)
current_block = await node.latest_block_height()
order = market.order(
order_id,
side=Order.Side.SIDE_SELL,
order_type=OrderType.LIMIT,
size=0.01,
price=40000 + random.randint(-100, 100),
time_in_force=Order.TIME_IN_FORCE_IOC,
reduce_only=False,
good_til_block=current_block + 20,
)
orders.append(order)

# Place orders
for order in orders:
place = await node.place_order(wallet, order)
print(f"Placed order: {place}")
wallet.sequence += 1

# Prepare batch cancel
subaccount_id = SubaccountId(owner=TEST_ADDRESS, number=0)
order_batch = OrderBatch(clob_pair_id=PERPETUAL_PAIR_BTC_USD, client_ids=client_ids)
cancellation_current_block = await node.latest_block_height()

# Execute batch cancel
batch_cancel_response = await node.batch_cancel_orders(
wallet, subaccount_id, [order_batch], cancellation_current_block + 10
)
print(f"Batch cancel response: {batch_cancel_response}")


asyncio.run(test_batch_cancel())
Loading

0 comments on commit 56d8c2d

Please sign in to comment.