diff --git a/additional_tests/exchanges_tests/abstract_authenticated_future_exchange_tester.py b/additional_tests/exchanges_tests/abstract_authenticated_future_exchange_tester.py index b8cf0ead5..09c15162e 100644 --- a/additional_tests/exchanges_tests/abstract_authenticated_future_exchange_tester.py +++ b/additional_tests/exchanges_tests/abstract_authenticated_future_exchange_tester.py @@ -33,6 +33,7 @@ class AbstractAuthenticatedFutureExchangeTester( INVERSE_SYMBOL = None MIN_PORTFOLIO_SIZE = 2 # ensure fetching currency for linear and inverse SUPPORTS_GET_LEVERAGE = True + SUPPORTS_GET_POSITION = True SUPPORTS_EMPTY_POSITION_SET_MARGIN_TYPE = True async def test_get_empty_linear_and_inverse_positions(self): @@ -58,19 +59,23 @@ async def _inner_test_get_empty_linear_and_inverse_positions_for_margin_type( ): positions = await self.get_positions() self._check_positions_content(positions) - position = await self.get_position(self.SYMBOL) - self._check_position_content(position, self.SYMBOL, margin_type=margin_type) - for contract_type in (trading_enums.FutureContractType.LINEAR_PERPETUAL, - trading_enums.FutureContractType.INVERSE_PERPETUAL): - if not self.has_empty_position(self.get_filtered_positions(positions, contract_type)): - empty_position_symbol = self.get_other_position_symbol(positions, contract_type) - # test with get_position - empty_position = await self.get_position(empty_position_symbol) - assert self.is_position_empty(empty_position) - # test with get_positions - empty_positions = await self.get_positions([empty_position_symbol]) - assert len(empty_positions) == 1 - assert self.is_position_empty(empty_positions[0]) + if self.SUPPORTS_GET_POSITION: + position = await self.get_position(self.SYMBOL) + self._check_position_content(position, self.SYMBOL, margin_type=margin_type) + + if self.EXCHANGE_TYPE == trading_enums.ExchangeTypes.FUTURE.value: + for contract_type in (trading_enums.FutureContractType.LINEAR_PERPETUAL, + trading_enums.FutureContractType.INVERSE_PERPETUAL): + if not self.has_empty_position(self.get_filtered_positions(positions, contract_type)): + empty_position_symbol = self.get_other_position_symbol(positions, contract_type) + if self.SUPPORTS_GET_POSITION: + # test with get_position + empty_position = await self.get_position(empty_position_symbol) + assert self.is_position_empty(empty_position) + # test with get_positions + empty_positions = await self.get_positions([empty_position_symbol]) + assert len(empty_positions) == 1 + assert self.is_position_empty(empty_positions[0]) async def test_get_and_set_leverage(self): # ensure set_leverage works @@ -265,10 +270,10 @@ async def get_positions(self, symbols=None): async def init_and_get_contract(self, symbol=None): symbol = symbol or self.SYMBOL - await self.exchange_manager.exchange.load_pair_future_contract(symbol) - if not self.exchange_manager.exchange.has_pair_future_contract(symbol): + await self.exchange_manager.exchange.load_pair_contract(symbol) + if not self.exchange_manager.exchange.has_pair_contract(symbol): raise AssertionError(f"{symbol} contract not initialized") - return self.exchange_manager.exchange.get_pair_future_contract(symbol) + return self.exchange_manager.exchange.get_pair_contract(symbol) async def get_margin_type_and_leverage_from_position(self, symbol=None): position = await self.get_position(symbol=symbol) @@ -298,7 +303,7 @@ async def required_empty_position(self): async def load_contract(self, symbol=None): symbol = symbol or self.SYMBOL if self.exchange_manager.is_future and symbol not in self.exchange_manager.exchange.pair_contracts: - await self.exchange_manager.exchange.load_pair_future_contract(symbol) + await self.exchange_manager.exchange.load_pair_contract(symbol) async def enable_partial_take_profits_and_stop_loss(self, mode, symbol=None): await self.exchange_manager.exchange.set_symbol_partial_take_profit_stop_loss( diff --git a/additional_tests/exchanges_tests/abstract_authenticated_option_exchange_tester.py b/additional_tests/exchanges_tests/abstract_authenticated_option_exchange_tester.py new file mode 100644 index 000000000..3d0fc2723 --- /dev/null +++ b/additional_tests/exchanges_tests/abstract_authenticated_option_exchange_tester.py @@ -0,0 +1,23 @@ +# This file is part of OctoBot (https://github.com/Drakkar-Software/OctoBot) +# Copyright (c) 2025 Drakkar-Software, All rights reserved. +# +# OctoBot is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either +# version 3.0 of the License, or (at your option) any later version. +# +# OctoBot is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with OctoBot. If not, see . +import octobot_trading.enums as trading_enums +from additional_tests.exchanges_tests import abstract_authenticated_future_exchange_tester + + +class AbstractAuthenticatedOptionExchangeTester( + abstract_authenticated_future_exchange_tester.AbstractAuthenticatedFutureExchangeTester +): + EXCHANGE_TYPE = trading_enums.ExchangeTypes.OPTION.value diff --git a/additional_tests/exchanges_tests/test_polymarket.py b/additional_tests/exchanges_tests/test_polymarket.py index e342e9048..27ac8399e 100644 --- a/additional_tests/exchanges_tests/test_polymarket.py +++ b/additional_tests/exchanges_tests/test_polymarket.py @@ -15,7 +15,7 @@ # License along with OctoBot. If not, see . import pytest -from additional_tests.exchanges_tests import abstract_authenticated_exchange_tester +from additional_tests.exchanges_tests import abstract_authenticated_option_exchange_tester try: import tentacles.Trading.Exchange.polymarket.ccxt.polymarket_async @@ -31,19 +31,20 @@ class TestPolymarketAuthenticatedExchange( - abstract_authenticated_exchange_tester.AbstractAuthenticatedExchangeTester + abstract_authenticated_option_exchange_tester.AbstractAuthenticatedOptionExchangeTester ): # enter exchange name as a class variable here EXCHANGE_NAME = "polymarket" ORDER_CURRENCY = "will-bitcoin-replace-sha-256-before-2027" SETTLEMENT_CURRENCY = "USDC" EXPIRATION_DATE = "261231" - SYMBOL = f"{ORDER_CURRENCY}/{SETTLEMENT_CURRENCY}:{SETTLEMENT_CURRENCY}-{EXPIRATION_DATE}" + SYMBOL = f"{ORDER_CURRENCY}/{SETTLEMENT_CURRENCY}:{SETTLEMENT_CURRENCY}-{EXPIRATION_DATE}-0-YES" ORDER_SIZE = 10 # % of portfolio to include in test orders EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = False CONVERTS_ORDER_SIZE_BEFORE_PUSHING_TO_EXCHANGES = True CONVERTS_ORDER_PRICE_BEFORE_PUSHING_TO_EXCHANGE = True ORDER_IMPACTS_PORTFOLIO_FREE_BALANCE = False + SUPPORTS_GET_POSITION = False async def test_get_portfolio(self): await super().test_get_portfolio() @@ -128,3 +129,6 @@ async def test_create_single_bundled_orders(self): async def test_create_double_bundled_orders(self): # pass if not implemented pass + + async def test_get_empty_linear_and_inverse_positions(self): + await super().test_get_empty_linear_and_inverse_positions() diff --git a/full_requirements.txt b/full_requirements.txt index 4d1d0c6e5..eb7d650c3 100644 --- a/full_requirements.txt +++ b/full_requirements.txt @@ -1,10 +1,10 @@ # Drakkar-Software full requirements -OctoBot-Commons[full]==1.9.93 -OctoBot-Trading[full]==2.4.244 -OctoBot-Evaluators[full]==1.9.9 -OctoBot-Tentacles-Manager[full]==2.9.19 -OctoBot-Services[full]==1.6.30 -OctoBot-Backtesting[full]==1.9.8 +OctoBot-Commons[full]==1.10.5 +OctoBot-Trading[full]==2.5.0 +OctoBot-Evaluators[full]==1.10.1 +OctoBot-Tentacles-Manager[full]==2.10.0 +OctoBot-Services[full]==1.7.1 +OctoBot-Backtesting[full]==1.10.0 ## Others colorlog==6.8.0 diff --git a/octobot/logger.py b/octobot/logger.py index a30f578f7..22ff3c297 100644 --- a/octobot/logger.py +++ b/octobot/logger.py @@ -283,6 +283,14 @@ async def mark_price_callback( ) +async def markets_callback( + exchange: str, exchange_id: str, markets +): + BOT_CHANNEL_LOGGER.debug( + f"MARKETS : EXCHANGE = {exchange} || MARKET RELOADED" + ) + + def _filter_balance(balance: dict): if not balance: return balance, 0 @@ -392,6 +400,8 @@ async def matrix_callback( evaluator_type, eval_note, eval_note_type, + eval_note_description, + eval_note_metadata, exchange_name, cryptocurrency, symbol, @@ -402,6 +412,7 @@ async def matrix_callback( f"EVALUATOR = {evaluator_name} || EVALUATOR_TYPE = {evaluator_type} || " f"CRYPTOCURRENCY = {cryptocurrency} || SYMBOL = {symbol} || TF = {time_frame} " f"|| NOTE = {eval_note} [MATRIX id = {matrix_id}] " + f"|| DESCRIPTION = {eval_note_description}" if eval_note_description else "" ) diff --git a/requirements.txt b/requirements.txt index e2591e87f..8a7d0b132 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ # Drakkar-Software requirements -OctoBot-Commons==1.9.93 -OctoBot-Trading==2.4.244 -OctoBot-Evaluators==1.9.9 -OctoBot-Tentacles-Manager==2.9.19 -OctoBot-Services==1.6.30 -OctoBot-Backtesting==1.9.8 +OctoBot-Commons==1.10.5 +OctoBot-Trading==2.5.0 +OctoBot-Evaluators==1.10.1 +OctoBot-Tentacles-Manager==2.10.0 +OctoBot-Services==1.7.1 +OctoBot-Backtesting==1.10.0 Async-Channel==2.2.2 trading-backend==1.2.43