Skip to content

Commit

Permalink
Add max_reconnection_tries to data client config for dYdX (#2066)
Browse files Browse the repository at this point in the history
Add support for stop limit and stop market orders
  • Loading branch information
davidsblom authored Nov 21, 2024
1 parent 35cf1a9 commit f153b99
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 3 deletions.
4 changes: 4 additions & 0 deletions nautilus_trader/adapters/dydx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ class DYDXDataClientConfig(LiveDataClientConfig, frozen=True):
If the client is connecting to the dYdX testnet API.
update_instruments_interval_mins: PositiveInt or None, default 60
The interval (minutes) between reloading instruments from the venue.
max_reconnection_tries: int, default 3
The number of retries to reconnect the websocket connection if the
connection is broken.
"""

wallet_address: str | None = None
is_testnet: bool = False
update_instruments_interval_mins: PositiveInt | None = 60
max_ws_reconnection_tries: int | None = 3


class DYDXExecClientConfig(LiveExecClientConfig, frozen=True):
Expand Down
1 change: 1 addition & 0 deletions nautilus_trader/adapters/dydx/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def __init__(
handler_reconnect=None,
base_url=ws_base_url,
loop=loop,
max_reconnection_tries=config.max_ws_reconnection_tries,
)

# HTTP API
Expand Down
12 changes: 11 additions & 1 deletion nautilus_trader/adapters/dydx/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ async def _submit_order_list(self, command: SubmitOrderList) -> None:
for order in command.order_list.orders:
await self._submit_order_single(order=order)

async def _submit_order_single(self, order) -> None:
async def _submit_order_single(self, order: Order) -> None:
"""
Submit a single order.
"""
Expand Down Expand Up @@ -1057,6 +1057,8 @@ async def _submit_order_single(self, order) -> None:
order_type_map = {
OrderType.LIMIT: DYDXGRPCOrderType.LIMIT,
OrderType.MARKET: DYDXGRPCOrderType.MARKET,
OrderType.STOP_MARKET: DYDXGRPCOrderType.STOP_MARKET,
OrderType.STOP_LIMIT: DYDXGRPCOrderType.STOP_LIMIT,
}
order_side_map = {
OrderSide.NO_ORDER_SIDE: DYDXOrder.Side.SIDE_UNSPECIFIED,
Expand All @@ -1071,11 +1073,18 @@ async def _submit_order_single(self, order) -> None:
}

price = 0
trigger_price = None

if order.order_type == OrderType.LIMIT:
price = order.price.as_double()
elif order.order_type == OrderType.MARKET:
price = 0
elif order.order_type == OrderType.STOP_LIMIT:
price = order.price.as_double()
trigger_price = order.trigger_price.as_double()
elif order.order_type == OrderType.STOP_MARKET:
price = 0
trigger_price = order.trigger_price.as_double()
else:
rejection_reason = (
f"Cannot submit order: order type `{order.order_type}` not (yet) supported"
Expand All @@ -1100,6 +1109,7 @@ async def _submit_order_single(self, order) -> None:
post_only=order.is_post_only,
good_til_block=good_til_block,
good_til_block_time=good_til_date_secs,
trigger_price=trigger_price,
)

await self._place_order(order_msg=order_msg, order=order)
Expand Down
10 changes: 8 additions & 2 deletions nautilus_trader/adapters/dydx/grpc/order_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def create_order(
good_til_block: int | None = None,
good_til_block_time: int | None = None,
execution: OrderExecution = OrderExecution.DEFAULT,
conditional_order_trigger_subticks: int = 0,
trigger_price: float | None = None,
) -> Order:
"""
Create a new Order instance.
Expand Down Expand Up @@ -271,7 +271,9 @@ def create_order(
not yet filled.
execution : OrderExecution, default OrderExecution.DEFAULT
OrderExecution enum: DEFAULT, IOC, FOK or POST_ONLY
conditional_order_trigger_subticks : int, default value is 0.
trigger_price : float, optional.
The price of the conditional limit order. Only applicable to STOP_LIMIT,
STOP_MARKET, TAKE_PROFIT_MARKET or TAKE_PROFIT_LIMIT orders.
"""
order_time_in_force = OrderHelper.calculate_time_in_force(
Expand All @@ -282,6 +284,10 @@ def create_order(
)
client_metadata = OrderHelper.calculate_client_metadata(order_type)
condition_type = OrderHelper.calculate_condition_type(order_type)
conditional_order_trigger_subticks = 0

if trigger_price is not None:
conditional_order_trigger_subticks = self.calculate_subticks(trigger_price)

return Order(
order_id=order_id,
Expand Down
6 changes: 6 additions & 0 deletions nautilus_trader/adapters/dydx/websocket/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class DYDXWebsocketClient:
The event loop for the client.
subscription_rate_limit_per_second : int, default 2
The maximum number of subscription message to send to the venue.
max_reconnection_tries: int, default 3
The number of retries to reconnect the websocket connection if the
connection is broken.
"""

Expand All @@ -63,6 +66,7 @@ def __init__(
handler_reconnect: Callable[..., Awaitable[None]] | None,
loop: asyncio.AbstractEventLoop,
subscription_rate_limit_per_second: int = 2,
max_reconnection_tries: int | None = 3,
) -> None:
"""
Provide a dYdX streaming WebSocket client.
Expand All @@ -77,6 +81,7 @@ def __init__(
self._is_running = False
self._subscriptions: set[tuple[str, str]] = set()
self._subscription_rate_limit_per_second = subscription_rate_limit_per_second
self._max_reconnection_tries = max_reconnection_tries
self._msg_timestamp = self._clock.utc_now()
self._msg_timeout_secs: int = 60
self._reconnect_task: asyncio.Task | None = None
Expand Down Expand Up @@ -145,6 +150,7 @@ async def connect(self) -> None:
heartbeat=10,
headers=[],
ping_handler=self._handle_ping,
max_reconnection_tries=self._max_reconnection_tries,
)
client = await WebSocketClient.connect(
config=config,
Expand Down
1 change: 1 addition & 0 deletions nautilus_trader/core/nautilus_pyo3.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,7 @@ class WebSocketConfig:
heartbeat: int | None = None,
heartbeat_msg: str | None = None,
ping_handler: Callable[..., Any] | None = None,
max_reconnection_tries: int | None = None,
) -> None: ...

class WebSocketClient:
Expand Down

0 comments on commit f153b99

Please sign in to comment.