Skip to content

Commit

Permalink
Resolve "Websocket API faster than REST backend causing orders not be…
Browse files Browse the repository at this point in the history
…ing resolved" (#83)
  • Loading branch information
btschwertfeger authored Feb 8, 2025
1 parent d7d89ea commit 495e514
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ updates:
directory: "/"
schedule:
interval: "monthly"
groups:
all:
dependency-type: "production"
12 changes: 8 additions & 4 deletions src/kraken_infinity_grid/order_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,10 +621,14 @@ def handle_filled_order_event(
tries += 1

if order_details["status"] != "closed":
self.__s.save_exit(
"handle_filled_order_event - fetched order is not closed!"
f" {order_details}",
LOG.warning(
"Can not handle filled order, since the fetched order is not"
" closed in upstream!"
" This may happen due to Kraken's websocket API being faster"
" than their REST backend. Retrying in a few seconds...",
)
self.handle_filled_order_event(txid=txid)
return

# ======================================================================
if self.__s.dry_run:
Expand Down Expand Up @@ -830,6 +834,6 @@ def get_orders_info_with_retry(
f"Failed to retrieve order info for '{txid}' after"
f" {max_tries} retries!",
)
order_details["txid"] = txid

order_details["txid"] = txid
return order_details # type: ignore[no-any-return]
9 changes: 5 additions & 4 deletions src/kraken_infinity_grid/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,14 @@ def send_telegram_update(self: Self) -> None:

message += "\n```\n"
message += f" 🏷️ Price in {self.__s.quote_currency}\n"
max_orders_to_list: int = 5

next_sells = [
order["price"]
for order in self.__s.orderbook.get_orders(
filters={"side": "sell"},
order_by=("price", "ASC"),
limit=5,
limit=max_orders_to_list,
)
]
next_sells.reverse()
Expand All @@ -122,7 +123,7 @@ def send_telegram_update(self: Self) -> None:
change = (sell_price / self.__s.ticker.last - 1) * 100
if index == 0:
message += f" │ ┌[ {sell_price} (+{change:.2f}%)\n"
elif index <= n_sells - 1 and index != 4:
elif index <= n_sells - 1 and index != max_orders_to_list:
message += f" │ ├[ {sell_price} (+{change:.2f}%)\n"
message += f" └──┼> {self.__s.ticker.last}\n"

Expand All @@ -131,13 +132,13 @@ def send_telegram_update(self: Self) -> None:
for order in self.__s.orderbook.get_orders(
filters={"side": "buy"},
order_by=("price", "DESC"),
limit=5,
limit=max_orders_to_list,
)
]
if (n_buys := len(next_buys)) != 0:
for index, buy_price in enumerate(next_buys):
change = (buy_price / self.__s.ticker.last - 1) * 100
if index < n_buys - 1 and index != 4:
if index < n_buys - 1 and index != max_orders_to_list:
message += f" ├[ {buy_price} ({change:.2f}%)\n"
else:
message += f" └[ {buy_price} ({change:.2f}%)"
Expand Down
20 changes: 16 additions & 4 deletions tests/test_order_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,11 @@ def test_handle_filled_order_event_buy_order_not_closed_retry_failing(
mock_handle_arbitrage: mock.Mock,
mock_get_orders_info_with_retry: mock.Mock,
order_manager: OrderManager,
caplog: pytest.LogCaptureFixture,
) -> None:
"""
Test handling a filled order event failing due to too much retries of
retrieving the order information.
Test handling a filled order event that fails too often an triggers a recall
of themselves.
"""
mock_get_orders_info_with_retry.side_effect = [
{
Expand All @@ -851,15 +852,26 @@ def test_handle_filled_order_event_buy_order_not_closed_retry_failing(
"vol_exec": 0.1,
}
for _ in range(4)
] + [ # Mark as closed after some time
{
"descr": {"pair": "BTCUSD", "type": "buy", "price": 50000.0},
"status": "closed",
"userref": 13456789,
"vol_exec": 0.1,
},
]

with (
pytest.raises(SystemExit, match=r".*fetched order is not closed.*"),
mock.patch("kraken_infinity_grid.order_management.sleep", return_value=None),
):
order_manager.handle_filled_order_event(txid="txid1")

mock_handle_arbitrage.assert_not_called()
mock_handle_arbitrage.assert_called_once()

assert (
"Can not handle filled order, since the fetched order is not closed in upstream!"
in caplog.text
)


@mock.patch.object(OrderManager, "get_orders_info_with_retry")
Expand Down

0 comments on commit 495e514

Please sign in to comment.