Skip to content

Commit

Permalink
Implement Bybit batch cancel orders
Browse files Browse the repository at this point in the history
  • Loading branch information
cjdsellers committed Apr 7, 2024
1 parent 78e2c06 commit de931be
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from nautilus_trader.core.nautilus_pyo3 import HttpMethod


class BybitAmendOrder(msgspec.Struct, omit_defaults=True, frozen=True):
class BybitBatchAmendOrder(msgspec.Struct, omit_defaults=True, frozen=True):
symbol: str
orderId: str | None = None
orderLinkId: str | None = None
Expand All @@ -42,7 +42,7 @@ class BybitAmendOrder(msgspec.Struct, omit_defaults=True, frozen=True):

class BybitBatchAmendOrderPostParams(msgspec.Struct, omit_defaults=True, frozen=True):
category: BybitProductType
request: list[BybitAmendOrder]
request: list[BybitBatchAmendOrder]


class BybitBatchAmendOrderEndpoint(BybitHttpEndpoint):
Expand All @@ -51,7 +51,7 @@ def __init__(
client: BybitHttpClient,
base_endpoint: str,
) -> None:
url_path = base_endpoint + "/order/create-batch"
url_path = base_endpoint + "/order/amend-batch"
super().__init__(
client=client,
endpoint_type=BybitEndpointType.TRADE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,31 @@
import msgspec

from nautilus_trader.adapters.bybit.common.enums import BybitEndpointType
from nautilus_trader.adapters.bybit.common.enums import BybitOrderSide
from nautilus_trader.adapters.bybit.common.enums import BybitOrderType
from nautilus_trader.adapters.bybit.common.enums import BybitProductType
from nautilus_trader.adapters.bybit.common.enums import BybitTimeInForce
from nautilus_trader.adapters.bybit.common.enums import BybitTriggerType
from nautilus_trader.adapters.bybit.endpoints.endpoint import BybitHttpEndpoint
from nautilus_trader.adapters.bybit.http.client import BybitHttpClient
from nautilus_trader.adapters.bybit.schemas.order import BybitBatchCancelOrderResponse
from nautilus_trader.core.nautilus_pyo3 import HttpMethod


class BybitBatchCancelOrderPostParams(msgspec.Struct, omit_defaults=True, frozen=True):
category: BybitProductType
class BybitBatchCancelOrder(msgspec.Struct, omit_defaults=True, frozen=True):
symbol: str
side: BybitOrderSide
qty: str
marketUnit: str | None = None
orderType: BybitOrderType | None = None
price: str | None = None
triggerDirection: int | None = None # TODO type this
triggerPrice: str | None = None
triggerBy: BybitTriggerType | None = None
timeInForce: BybitTimeInForce | None = None
orderId: str | None = None
orderLinkId: str | None = None


class BybitBatchCancelOrderPostParams(msgspec.Struct, omit_defaults=True, frozen=True):
category: BybitProductType
request: list[BybitBatchCancelOrder]


class BybitBatchCancelOrderEndpoint(BybitHttpEndpoint):
def __init__(
self,
client: BybitHttpClient,
base_endpoint: str,
) -> None:
url_path = base_endpoint + "/order/create-batch"
url_path = base_endpoint + "/order/cancel-batch"
super().__init__(
client=client,
endpoint_type=BybitEndpointType.TRADE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from nautilus_trader.core.nautilus_pyo3 import HttpMethod


class BybitPlaceOrder(msgspec.Struct, omit_defaults=True, frozen=True):
class BybitBatchPlaceOrder(msgspec.Struct, omit_defaults=True, frozen=True):
symbol: str
side: BybitOrderSide
orderType: BybitOrderType
Expand All @@ -47,7 +47,7 @@ class BybitPlaceOrder(msgspec.Struct, omit_defaults=True, frozen=True):

class BybitBatchPlaceOrderPostParams(msgspec.Struct, omit_defaults=True, frozen=True):
category: BybitProductType
request: list[BybitPlaceOrder]
request: list[BybitBatchPlaceOrder]


class BybitBatchPlaceOrderEndpoint(BybitHttpEndpoint):
Expand Down
35 changes: 35 additions & 0 deletions nautilus_trader/adapters/bybit/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,41 @@ async def _cancel_all_orders(self, command: CancelAllOrders) -> None:
bybit_symbol.raw_symbol,
)

# TODO: Determine signing issue for batch requests
# async def _cancel_all_orders(self, command: CancelAllOrders) -> None:
# open_orders_strategy: list[Order] = self._cache.orders_open(
# instrument_id=command.instrument_id,
# strategy_id=command.strategy_id,
# )
#
# bybit_symbol = BybitSymbol(command.instrument_id.symbol.value)
#
# # Check total orders for instrument
# open_orders_total_count = self._cache.orders_open_count(
# instrument_id=command.instrument_id,
# )
# if open_orders_total_count > 10:
# # This could be reimplemented later to group requests into batches of 10
# self._log.warning(
# f"Total {command.instrument_id.symbol.value} orders open exceeds 10, "
# f"is {open_orders_total_count}: canceling all for symbol",
# )
# await self._http_account.cancel_all_orders(
# bybit_symbol.product_type,
# bybit_symbol.raw_symbol,
# )
# return
#
# cancel_batch: list[Order] = []
# for order in open_orders_strategy:
# cancel_batch.append(order)
#
# await self._http_account.batch_cancel_orders(
# product_type=bybit_symbol.product_type,
# symbol=bybit_symbol.raw_symbol,
# orders=cancel_batch,
# )

async def _submit_order(self, command: SubmitOrder) -> None:
order = command.order
if order.is_closed:
Expand Down
27 changes: 27 additions & 0 deletions nautilus_trader/adapters/bybit/http/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
from nautilus_trader.adapters.bybit.endpoints.trade.amend_order import BybitAmendOrderEndpoint
from nautilus_trader.adapters.bybit.endpoints.trade.amend_order import BybitAmendOrderPostParams
from nautilus_trader.adapters.bybit.endpoints.trade.batch_amend_order import BybitBatchAmendOrderEndpoint
from nautilus_trader.adapters.bybit.endpoints.trade.batch_cancel_order import BybitBatchCancelOrder
from nautilus_trader.adapters.bybit.endpoints.trade.batch_cancel_order import BybitBatchCancelOrderEndpoint
from nautilus_trader.adapters.bybit.endpoints.trade.batch_cancel_order import BybitBatchCancelOrderPostParams
from nautilus_trader.adapters.bybit.endpoints.trade.batch_place_order import BybitBatchPlaceOrderEndpoint
from nautilus_trader.adapters.bybit.endpoints.trade.cancel_all_orders import BybitCancelAllOrdersEndpoint
from nautilus_trader.adapters.bybit.endpoints.trade.cancel_all_orders import BybitCancelAllOrdersPostParams
Expand All @@ -55,6 +57,7 @@
from nautilus_trader.adapters.bybit.schemas.trade import BybitExecution
from nautilus_trader.common.component import LiveClock
from nautilus_trader.core.correctness import PyCondition
from nautilus_trader.model.orders import Order


# fmt: on
Expand Down Expand Up @@ -287,3 +290,27 @@ async def cancel_all_orders(
),
)
return response.result.list

async def batch_cancel_orders(
self,
product_type: BybitProductType,
symbol: str,
orders: list[Order],
) -> list[Any]:
request: list[BybitBatchCancelOrder] = []

for order in orders:
request.append(
BybitBatchCancelOrder(
symbol=symbol,
orderId=order.venue_order_id.value if order.venue_order_id else None,
orderLinkId=order.client_order_id.value,
),
)
response = await self._endpoint_batch_cancel_order.post(
BybitBatchCancelOrderPostParams(
category=product_type,
request=request,
),
)
return response.result
8 changes: 4 additions & 4 deletions nautilus_trader/adapters/bybit/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def _sign_post_request(self, payload: dict[str, Any]) -> list[str]:
payload_str = create_string_from_dict(payload)
result = timestamp + self._api_key + str(self._recv_window) + payload_str
signature = hmac.new(
self._api_secret.encode("utf-8"),
result.encode("utf-8"),
self._api_secret.encode(),
result.encode(),
hashlib.sha256,
).hexdigest()
return [timestamp, signature]
Expand All @@ -192,8 +192,8 @@ def _sign_get_request(self, payload: dict[str, Any]) -> list[str]:
payload_str = parse.urlencode(payload)
result = timestamp + self._api_key + str(self._recv_window) + payload_str
signature = hmac.new(
self._api_secret.encode("utf-8"),
result.encode("utf-8"),
self._api_secret.encode(),
result.encode(),
hashlib.sha256,
).hexdigest()
return [timestamp, signature]

0 comments on commit de931be

Please sign in to comment.