Skip to content

Commit d2fe8a9

Browse files
committed
[CCXT] update to 4.5.28
1 parent b897b09 commit d2fe8a9

File tree

11 files changed

+68
-22
lines changed

11 files changed

+68
-22
lines changed

octobot_trading/exchanges/types/rest_exchange.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,12 @@ async def _verify_order(self, created_order, order_type, symbol, price, quantity
370370
if order_exchange_id is None:
371371
self.logger.error(f"No order exchange id on created order: {created_order}")
372372
return None
373-
params = get_order_params or {}
373+
exchange_order_id = created_order[ecoc.EXCHANGE_ID.value]
374+
params = self._order_request_kwargs_factory(
375+
exchange_order_id, order_type, **(get_order_params or {})
376+
)
374377
fetched_order = await self.get_order(
375-
created_order[ecoc.EXCHANGE_ID.value], symbol=symbol, **params
378+
exchange_order_id, symbol=symbol, **params
376379
)
377380
if fetched_order is None:
378381
created_order[ecoc.STATUS.value] = enums.OrderStatus.PENDING_CREATION.value
@@ -688,9 +691,25 @@ async def get_price_ticker(self, symbol: str, **kwargs: dict) -> typing.Optional
688691
async def get_all_currencies_price_ticker(self, **kwargs: dict) -> typing.Optional[dict[str, dict]]:
689692
return await self.connector.get_all_currencies_price_ticker(**kwargs)
690693

691-
async def get_order(self, exchange_order_id: str, symbol: str = None, **kwargs: dict) -> dict:
694+
def _order_request_kwargs_factory(
695+
self,
696+
exchange_order_id: str,
697+
order_type: typing.Optional[enums.TraderOrderType] = None,
698+
**kwargs
699+
) -> dict:
700+
# implement if the exchange needs additional kwargs to fetch an order, like to fetch stop orders
701+
return kwargs
702+
703+
async def get_order(
704+
self,
705+
exchange_order_id: str,
706+
symbol: typing.Optional[str] = None,
707+
order_type: typing.Optional[enums.TraderOrderType] = None,
708+
**kwargs: dict
709+
) -> dict:
710+
extended_kwargs = self._order_request_kwargs_factory(exchange_order_id, order_type, **(kwargs or {}))
692711
return await self._ensure_order_completeness(
693-
await self.connector.get_order(exchange_order_id, symbol=symbol, **kwargs),
712+
await self.connector.get_order(exchange_order_id, symbol=symbol, **extended_kwargs),
694713
symbol, **kwargs
695714
)
696715

@@ -806,7 +825,8 @@ async def cancel_all_orders(self, symbol: str = None, **kwargs: dict) -> None:
806825
async def cancel_order(
807826
self, exchange_order_id: str, symbol: str, order_type: enums.TraderOrderType, **kwargs: dict
808827
) -> enums.OrderStatus:
809-
return await self.connector.cancel_order(exchange_order_id, symbol, order_type, **kwargs)
828+
extended_kwargs = self._order_request_kwargs_factory(exchange_order_id, order_type, **(kwargs or {}))
829+
return await self.connector.cancel_order(exchange_order_id, symbol, order_type, **extended_kwargs)
810830

811831
def get_trade_fee(self, symbol: str, order_type: enums.TraderOrderType, quantity, price, taker_or_maker) -> dict:
812832
return self.connector.get_trade_fee(symbol, order_type, quantity, price, taker_or_maker)

octobot_trading/personal_data/orders/channel/orders_updater.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@ async def _order_fetch_and_push(self, order, should_notify=False):
196196
"""
197197
exchange_name = self.channel.exchange_manager.exchange_name
198198
self.logger.info(f"Requested update for {order} on {exchange_name}")
199-
raw_order = await self.channel.exchange_manager.exchange.get_order(order.exchange_order_id, order.symbol)
199+
raw_order = await self.channel.exchange_manager.exchange.get_order(
200+
order.exchange_order_id, order.symbol, order_type=order.order_type
201+
)
200202

201203
if raw_order is not None:
202204
self.logger.info(f"Received update for {order} on {exchange_name}: {raw_order}")

octobot_trading/personal_data/orders/order.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,9 @@ def get_profitability(self):
857857
return self.order_profitability
858858

859859
async def default_exchange_update_order_status(self):
860-
raw_order = await self.exchange_manager.exchange.get_order(self.exchange_order_id, self.symbol)
860+
raw_order = await self.exchange_manager.exchange.get_order(
861+
self.exchange_order_id, self.symbol, order_type=self.order_type
862+
)
861863
new_status = order_util.parse_order_status(raw_order)
862864
self.is_synchronized_with_exchange = True
863865
if new_status in {enums.OrderStatus.FILLED, enums.OrderStatus.CLOSED}:

octobot_trading/util/test_tools/exchanges_test_tools.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,11 @@ async def get_order(
267267
exchange_manager,
268268
exchange_order_id: str,
269269
symbol: str,
270+
order_type: enums.TraderOrderType,
270271
) -> typing.Optional[dict]:
271-
return await exchange_manager.exchange.get_order(exchange_order_id, symbol=symbol)
272+
return await exchange_manager.exchange.get_order(
273+
exchange_order_id, symbol=symbol, order_type=order_type
274+
)
272275

273276

274277
@exchanges.retried_failed_network_request(
@@ -402,7 +405,9 @@ async def wait_for_other_status(order: personal_data.Order, timeout) -> personal
402405
iterations = 0
403406
origin_status = order.status.value
404407
while time.time() - t0 < timeout:
405-
raw_order = await order.exchange_manager.exchange.get_order(order.exchange_order_id, order.symbol)
408+
raw_order = await order.exchange_manager.exchange.get_order(
409+
order.exchange_order_id, order.symbol, order_type=order.order_type
410+
)
406411
iterations += 1
407412
if raw_order is not None and raw_order[enums.ExchangeConstantsOrderColumns.STATUS.value] != origin_status:
408413
logging.get_logger(order.get_logger_name()).info(

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ OctoBot-Tentacles-Manager>=2.9, <2.10
88
trading-backend>=1.2.35
99

1010
# Exchange connection requirements
11-
ccxt==4.5.22 # always ensure real exchanges tests (in tests_additional and authenticated exchange tests) are passing before changing the ccxt version
11+
ccxt==4.5.28 # always ensure real exchanges tests (in tests_additional and authenticated exchange tests) are passing before changing the ccxt version
1212

1313
cryptography # Never specify a version (managed by https://github.com/Drakkar-Software/OctoBot-PyPi-Linux-Deployer)
1414

tests_additional/real_exchanges/__init__.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import contextlib
1717
import dotenv
1818
import os
19+
import mock
1920

2021
import octobot_commons.constants as commons_constants
2122
import octobot_commons.asyncio_tools as asyncio_tools
@@ -24,13 +25,14 @@
2425
import octobot_trading.exchanges as exchanges
2526
import octobot_trading.enums as enums
2627
import octobot_trading.errors as errors
28+
import octobot_trading.exchanges.util.exchange_util
2729

2830

2931
LOADED_EXCHANGE_CREDS_ENV_VARIABLES = False
3032

3133

3234
@contextlib.asynccontextmanager
33-
async def get_exchange_manager(exchange_name, config=None, authenticated=False, market_filter=None):
35+
async def get_exchange_manager(exchange_name, config=None, authenticated=False, market_filter=None, uses_tentacle=False):
3436
config = {**test_config.load_test_config(), **config} if config else test_config.load_test_config()
3537
if exchange_name not in config[commons_constants.CONFIG_EXCHANGES]:
3638
config[commons_constants.CONFIG_EXCHANGES][exchange_name] = {}
@@ -43,7 +45,18 @@ async def get_exchange_manager(exchange_name, config=None, authenticated=False,
4345
if config[commons_constants.CONFIG_EXCHANGES][exchange_name]. \
4446
get(commons_constants.CONFIG_EXCHANGE_TYPE, enums.ExchangeTypes.SPOT.value) == enums.ExchangeTypes.FUTURE.value:
4547
exchange_manager_instance.is_future = True
46-
await exchange_manager_instance.initialize(exchange_config_by_exchange=None)
48+
if not uses_tentacle:
49+
# don't use exchange specific tentacles, even if they are available
50+
with mock.patch.object(
51+
octobot_trading.exchanges.util.exchange_util,
52+
"search_exchange_class_from_exchange_name",
53+
mock.Mock(return_value=exchanges.DefaultRestExchange)
54+
) as search_exchange_class_from_exchange_name_mock:
55+
await exchange_manager_instance.initialize(exchange_config_by_exchange=None)
56+
assert search_exchange_class_from_exchange_name_mock.call_count > 0
57+
else:
58+
# allow the use of exchange specific tentacles
59+
await exchange_manager_instance.initialize(exchange_config_by_exchange=None)
4760
try:
4861
yield exchange_manager_instance
4962
except errors.UnreachableExchange as err:

tests_additional/real_exchanges/real_exchange_tester.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import pytest
2121
from ccxt import Exchange
22-
22+
import ccxt
2323
import octobot_commons.constants as constants
2424
import octobot_commons.enums as commons_enums
2525
import octobot_trading.enums as trading_enums
@@ -49,6 +49,7 @@ class RealExchangeTester:
4949
HISTORICAL_CANDLES_TO_FETCH_COUNT = 650
5050
DEFAULT_CUSTOM_BOOK_LIMIT = 50
5151
ORDER_BOOK_DESYNC_ALLOWANCE = 60 # allow 60s desync
52+
USES_TENTACLE = False # set True when an exchange tentacles should be used in this test
5253

5354
# Public methods: to be implemented as tests
5455
# Use await self._[method_name] to get the test request result
@@ -135,7 +136,7 @@ async def test_get_historical_ohlcv(self):
135136
self.HISTORICAL_CANDLES_TO_FETCH_COUNT * 0.85
136137
< len(historical_ohlcv)
137138
<= self.HISTORICAL_CANDLES_TO_FETCH_COUNT
138-
)
139+
), f"{len(historical_ohlcv)=} not in [{self.HISTORICAL_CANDLES_TO_FETCH_COUNT * 0.85}:{self.HISTORICAL_CANDLES_TO_FETCH_COUNT}]"
139140
for candle in historical_ohlcv:
140141
assert start <= candle[commons_enums.PriceIndexes.IND_PRICE_TIME.value] <= end
141142

@@ -263,7 +264,8 @@ def _ensure_book_custom_limit(
263264
async def get_exchange_manager(self, market_filter=None):
264265
async with get_exchange_manager(
265266
self.EXCHANGE_NAME, config=self.get_config(),
266-
authenticated=self.REQUIRES_AUTH, market_filter=market_filter
267+
authenticated=self.REQUIRES_AUTH, market_filter=market_filter,
268+
uses_tentacle=self.USES_TENTACLE
267269
) as exchange_manager:
268270
yield exchange_manager
269271

tests_additional/real_exchanges/test_ascendex.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ async def test_active_symbols(self):
6060
async def test_get_market_status(self):
6161
for market_status in await self.get_market_statuses():
6262
self.ensure_required_market_status_values(market_status)
63+
print(f"market_status: {market_status}")
6364
# on AscendEx, precision is a decimal instead of a number of digits
6465
assert 0 < market_status[Ecmsc.PRECISION.value][
6566
Ecmsc.PRECISION_AMOUNT.value] <= 1 # to be fixed in AscendEx tentacle

tests_additional/real_exchanges/test_htx.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ async def test_time_frames(self):
4949
))
5050

5151
async def test_active_symbols(self):
52-
await self.inner_test_active_symbols(900, 1900)
52+
await self.inner_test_active_symbols(850, 1900)
5353

5454
async def test_get_market_status(self):
5555
for market_status in await self.get_market_statuses():

tests_additional/real_exchanges/test_hyperliquid.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async def test_time_frames(self):
6868
))
6969

7070
async def test_active_symbols(self):
71-
await self.inner_test_active_symbols(450, 450)
71+
await self.inner_test_active_symbols(400, 450)
7272

7373
async def test_get_market_status(self):
7474
for market_status in await self.get_market_statuses():
@@ -83,7 +83,7 @@ async def test_get_market_status(self):
8383
assert 0 < market_status[Ecmsc.PRECISION.value][
8484
Ecmsc.PRECISION_PRICE.value] <= 1 # to be fixed in Hyperliquid tentacle
8585
assert all(elem in market_status[Ecmsc.LIMITS.value]
86-
for elem in (Ecmsc.LIMITS_AMOUNT.value,
86+
for elem in (Ecmsc.LIMITS_AMOUNT.value,
8787
Ecmsc.LIMITS_PRICE.value,
8888
Ecmsc.LIMITS_COST.value))
8989
self.check_market_status_limits(

0 commit comments

Comments
 (0)