Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add batch cancel example #223

Merged
merged 3 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions v4-client-py-v2/documentation/cancelling_orders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 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
batch_cancel_msg = batch_cancel(
subaccount_id,
short_term_cancels,
Copy link
Contributor

@jonfung-dydx jonfung-dydx Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few code lines about how to create this short_term_cancels would be great

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
Loading