Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class AbstractAuthenticatedExchangeTester:
SUPPORTS_GET_MAX_ORDERS_COUNT = False # when True, will ensure that default values are not used
DEFAULT_MAX_DEFAULT_ORDERS_COUNT = trading_constants.DEFAULT_MAX_DEFAULT_ORDERS_COUNT
DEFAULT_MAX_STOP_ORDERS_COUNT = trading_constants.DEFAULT_MAX_STOP_ORDERS_COUNT
SLEEP_SECONDS_BEFORE_CHECKING_PORTFOLIO = 0 # used to wait before fetching portfolio after creating/cancelling an order

# Implement all "test_[name]" methods, call super() to run the test, pass to ignore it.
# Override the "inner_test_[name]" method to override a test content.
Expand Down Expand Up @@ -515,7 +516,7 @@ async def inner_test_get_special_orders(self):
for exchange_id, order_details in self.SPECIAL_ORDER_TYPES_BY_EXCHANGE_ID.items():
symbol, info_key, info_type, expected_type, expected_side, expected_trigger_above = order_details
print(order_details)
fetched_order = await self.exchange_manager.exchange.get_order(exchange_id, symbol=symbol)
fetched_order = await self.exchange_manager.exchange.get_order(exchange_id, symbol=symbol, order_type=trading_enums.TradeOrderType(expected_type))
assert fetched_order is not None
self._check_fetched_order_dicts([fetched_order])
# ensure parsing order doesn't crash
Expand Down Expand Up @@ -614,6 +615,7 @@ async def inner_test_create_and_cancel_limit_orders(self, symbol=None, settlemen
self.check_created_limit_order(limit_order, price, size, side)
assert await self.order_in_open_orders(open_orders, limit_order, symbol=symbol)
await self.check_can_get_order(limit_order)
await self.sleep_before_checking_portfolio()
# assert free portfolio amount is smaller than total amount
balance = await self.get_portfolio()
locked_currency = settlement_currency if side == trading_enums.TradeOrderSide.BUY else self.ORDER_CURRENCY
Expand Down Expand Up @@ -662,6 +664,7 @@ async def inner_test_create_and_fill_market_orders(self):
filled_order[trading_enums.ExchangeConstantsOrderColumns.EXCHANGE_ID.value]
)
self.check_raw_closed_orders([filled_order])
await self.sleep_before_checking_portfolio()
post_buy_portfolio = await self.get_portfolio()
portfolio_increased = side == trading_enums.TradeOrderSide.SELL
self.check_portfolio_changed(portfolio, post_buy_portfolio, portfolio_increased)
Expand All @@ -672,6 +675,7 @@ async def inner_test_create_and_fill_market_orders(self):
second_market_order = await self.create_market_order(current_price, mirror_size, other_side)
self.check_created_market_order(second_market_order, mirror_size, other_side)
await self.wait_for_fill(second_market_order)
await self.sleep_before_checking_portfolio()
post_sell_portfolio = await self.get_portfolio()
if post_buy_portfolio:
portfolio_increased = other_side == trading_enums.TradeOrderSide.SELL
Expand Down Expand Up @@ -707,7 +711,7 @@ async def inner_test_create_and_cancel_stop_orders(self):
)
try:
self.check_created_stop_order(stop_loss, price, size, trading_enums.TradeOrderSide.SELL)
stop_loss_from_get_order = await self.get_order(stop_loss.exchange_order_id, stop_loss.symbol)
stop_loss_from_get_order = await self.get_order(stop_loss.exchange_order_id, stop_loss.symbol, stop_loss.order_type)
self.check_created_stop_order(stop_loss_from_get_order, price, size, trading_enums.TradeOrderSide.SELL)
assert await self.order_in_open_orders(open_orders, stop_loss)
## for manual checks
Expand Down Expand Up @@ -782,7 +786,7 @@ async def inner_test_edit_limit_order(self):
edited_size = self.get_order_size(portfolio, price, order_size=1.3*self.ORDER_SIZE, settlement_currency=self._get_edit_order_settlement_currency())
sell_limit = await self.edit_order(sell_limit, edited_price=edited_price, edited_quantity=edited_size)
await self.wait_for_edit(sell_limit, edited_size)
sell_limit = await self.get_order(sell_limit.exchange_order_id, sell_limit.symbol)
sell_limit = await self.get_order(sell_limit.exchange_order_id, sell_limit.symbol, sell_limit.order_type)
self.check_created_limit_order(sell_limit, edited_price, edited_size, trading_enums.TradeOrderSide.SELL)
finally:
if sell_limit is not None:
Expand Down Expand Up @@ -811,7 +815,7 @@ async def inner_test_edit_stop_order(self):
edited_size = self.get_order_size(portfolio, price, order_size=1.3*self.ORDER_SIZE, settlement_currency=self._get_edit_order_settlement_currency())
stop_loss = await self.edit_order(stop_loss, edited_price=edited_price, edited_quantity=edited_size)
await self.wait_for_edit(stop_loss, edited_size)
stop_loss = await self.get_order(stop_loss.exchange_order_id, stop_loss.symbol)
stop_loss = await self.get_order(stop_loss.exchange_order_id, stop_loss.symbol, stop_loss.order_type)
self.check_created_stop_order(stop_loss, edited_price, edited_size, trading_enums.TradeOrderSide.SELL)
finally:
if stop_loss is not None:
Expand Down Expand Up @@ -1157,10 +1161,10 @@ async def get_price(self, symbol=None):
]
))

async def get_order(self, exchange_order_id, symbol=None):
async def get_order(self, exchange_order_id, symbol=None, order_type: trading_enums.TraderOrderType = None):
assert self.exchange_manager.exchange.connector.client.has["fetchOrder"] is \
self.EXPECT_FETCH_ORDER_TO_BE_AVAILABLE
order = await self.exchange_manager.exchange.get_order(exchange_order_id, symbol or self.SYMBOL)
order = await self.exchange_manager.exchange.get_order(exchange_order_id, symbol or self.SYMBOL, order_type)
self._check_fetched_order_dicts([order])
return personal_data.create_order_instance_from_raw(self.exchange_manager.trader, order)

Expand Down Expand Up @@ -1246,7 +1250,7 @@ async def _create_order_on_exchange(self, order, params=None, expected_creation_
raise AssertionError(f"Created order is None. input order: {order}, params: {params}")
if created_order.status is trading_enums.OrderStatus.PENDING_CREATION:
await self.wait_for_open(created_order)
return await self.get_order(created_order.exchange_order_id, order.symbol)
return await self.get_order(created_order.exchange_order_id, order.symbol, order.order_type)
return created_order

def get_order_size(self, portfolio, price, symbol=None, order_size=None, settlement_currency=None):
Expand Down Expand Up @@ -1461,7 +1465,7 @@ async def _get_order_until(self, order, validation_func, timeout, can_order_be_n
t0 = time.time()
iterations = 0
while time.time() - t0 < timeout:
raw_order = await self.exchange_manager.exchange.get_order(order.exchange_order_id, order.symbol)
raw_order = await self.exchange_manager.exchange.get_order(order.exchange_order_id, order.symbol, order.order_type)
iterations += 1
if raw_order is None:
print(f"{self.exchange_manager.exchange_name} {order.order_type} {validation_func.__name__} "
Expand All @@ -1487,7 +1491,7 @@ async def _get_order_until(self, order, validation_func, timeout, can_order_be_n
raise TimeoutError(f"Order not filled/cancelled within {timeout}s: {order} ({validation_func.__name__})")

async def check_can_get_order(self, order):
fetched_order = await self.get_order(order.exchange_order_id, order.symbol)
fetched_order = await self.get_order(order.exchange_order_id, order.symbol, order.order_type)
self.check_created_limit_order(fetched_order, order.origin_price, order.origin_quantity, order.side)

async def order_in_fetched_orders(self, method, previous_orders, order, symbol=None, check_presence=True):
Expand Down Expand Up @@ -1665,6 +1669,11 @@ def _get_exchange_tentacle_class(self):
def _supports_ip_whitelist_error(self):
return bool(self._get_exchange_tentacle_class().EXCHANGE_IP_WHITELIST_ERRORS)

async def sleep_before_checking_portfolio(self):
if self.SLEEP_SECONDS_BEFORE_CHECKING_PORTFOLIO > 0:
print(f"{self.__class__.__name__} Waiting {self.SLEEP_SECONDS_BEFORE_CHECKING_PORTFOLIO} seconds to check portfolio")
await asyncio.sleep(self.SLEEP_SECONDS_BEFORE_CHECKING_PORTFOLIO)


def _get_encoded_value(raw) -> str:
return commons_configuration.encrypt(raw).decode()
3 changes: 2 additions & 1 deletion additional_tests/exchanges_tests/test_coinbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class TestCoinbaseAuthenticatedExchange(
SETTLEMENT_CURRENCY = "USDC"
SYMBOL = f"{ORDER_CURRENCY}/{SETTLEMENT_CURRENCY}"
ORDER_SIZE = 70 # % of portfolio to include in test orders
MIN_TRADE_USD_VALUE = decimal.Decimal("0.004")
MIN_TRADE_USD_VALUE = decimal.Decimal("0.0004")
CONVERTS_ORDER_SIZE_BEFORE_PUSHING_TO_EXCHANGES = True
VALID_ORDER_ID = "8bb80a81-27f7-4415-aa50-911ea46d841c"
USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = True # set True when api key rights can't be checked using a
EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = False
IS_BROKER_ENABLED_ACCOUNT = False
IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented
SLEEP_SECONDS_BEFORE_CHECKING_PORTFOLIO = 8

SPECIAL_ORDER_TYPES_BY_EXCHANGE_ID: dict[
str, (
Expand Down
2 changes: 1 addition & 1 deletion additional_tests/exchanges_tests/test_coinex.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class TestCoinExAuthenticatedExchange(
ORDER_CURRENCY = "BTC"
SETTLEMENT_CURRENCY = "USDT"
SYMBOL = f"{ORDER_CURRENCY}/{SETTLEMENT_CURRENCY}"
ORDER_SIZE = 70 # % of portfolio to include in test orders
ORDER_SIZE = 90 # % of portfolio to include in test orders
CONVERTS_ORDER_SIZE_BEFORE_PUSHING_TO_EXCHANGES = True
EXPECTED_GENERATED_ACCOUNT_ID = True # set True when account_id can't be fetch and a generated account id is used
IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented
Expand Down
1 change: 1 addition & 0 deletions additional_tests/exchanges_tests/test_kucoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
class TestKucoinAuthenticatedExchange(
abstract_authenticated_exchange_tester.AbstractAuthenticatedExchangeTester
):
# WARNING: can't be tested since dec 2025 due to regulatory changes on EU countries
# enter exchange name as a class variable here
EXCHANGE_NAME = "kucoin"
ORDER_CURRENCY = "BTC"
Expand Down
1 change: 1 addition & 0 deletions additional_tests/exchanges_tests/test_kucoin_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
class TestKucoinFuturesAuthenticatedExchange(
abstract_authenticated_future_exchange_tester.AbstractAuthenticatedFutureExchangeTester
):
# WARNING: can't be tested since dec 2025 due to regulatory changes on EU countries
# enter exchange name as a class variable here
EXCHANGE_NAME = "kucoin"
CREDENTIALS_EXCHANGE_NAME = "KUCOIN_FUTURES"
Expand Down
2 changes: 1 addition & 1 deletion full_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Drakkar-Software full requirements
OctoBot-Commons[full]==1.9.92
OctoBot-Trading[full]==2.4.238
OctoBot-Trading[full]==2.4.240
OctoBot-Evaluators[full]==1.9.9
OctoBot-Tentacles-Manager[full]==2.9.19
OctoBot-Services[full]==1.6.30
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Drakkar-Software requirements
OctoBot-Commons==1.9.92
OctoBot-Trading==2.4.238
OctoBot-Trading==2.4.240
OctoBot-Evaluators==1.9.9
OctoBot-Tentacles-Manager==2.9.19
OctoBot-Services==1.6.30
Expand Down