-
-
Notifications
You must be signed in to change notification settings - Fork 1k
[Tests] Add polymarket authenticated tests #3173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,6 +72,7 @@ class AbstractAuthenticatedExchangeTester: | |
| ORDER_SIZE = 10 # % of portfolio to include in test orders | ||
| PORTFOLIO_TYPE_FOR_SIZE = trading_constants.CONFIG_PORTFOLIO_FREE | ||
| CONVERTS_ORDER_SIZE_BEFORE_PUSHING_TO_EXCHANGES = False | ||
| CONVERTS_ORDER_PRICE_BEFORE_PUSHING_TO_EXCHANGE = False | ||
| ORDER_PRICE_DIFF = 20 # % of price difference compared to current price for limit and stop orders | ||
| EXPECT_MISSING_ORDER_FEES_DUE_TO_ORDERS_TOO_OLD_FOR_RECENT_TRADES = False # when recent trades are limited and | ||
| # closed orders fees are taken from recent trades | ||
|
|
@@ -86,6 +87,7 @@ class AbstractAuthenticatedExchangeTester: | |
| OPEN_TIMEOUT = 15 | ||
| # if >0: retry fetching open/cancelled orders when created/cancelled orders are not synchronised instantly | ||
| ORDER_IN_OPEN_AND_CANCELLED_ORDERS_TIMEOUT = 10 | ||
| ORDER_IMPACTS_PORTFOLIO_FREE_BALANCE = True | ||
| CANCEL_TIMEOUT = 15 | ||
| EDIT_TIMEOUT = 15 | ||
| MIN_PORTFOLIO_SIZE = 1 | ||
|
|
@@ -616,13 +618,22 @@ async def inner_test_create_and_cancel_limit_orders(self, symbol=None, settlemen | |
| 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 | ||
| assert balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE] < \ | ||
| balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL], ( | ||
| f"FALSE: {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE]} < {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL]}" | ||
| ) | ||
| if self.ORDER_IMPACTS_PORTFOLIO_FREE_BALANCE: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point |
||
| # 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 | ||
| assert balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE] < \ | ||
| balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL], ( | ||
| f"FALSE: {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE]} < {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL]}" | ||
| ) | ||
| else: | ||
| # assert free portfolio amount equals total amount when orders don't impact free balance | ||
| balance = await self.get_portfolio() | ||
| locked_currency = settlement_currency if side == trading_enums.TradeOrderSide.BUY else self.ORDER_CURRENCY | ||
| assert balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE] == \ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL], ( | ||
| f"FALSE: {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_FREE]} == {balance[locked_currency][trading_constants.CONFIG_PORTFOLIO_TOTAL]}" | ||
| ) | ||
| finally: | ||
| # don't leave buy_limit as open order | ||
| await self.cancel_order(limit_order) | ||
|
|
@@ -1344,7 +1355,13 @@ def _check_fetched_order_dicts(self, orders: list[dict]): | |
|
|
||
| def check_created_limit_order(self, order, price, size, side): | ||
| self._check_order(order, size, side) | ||
| assert order.origin_price == price, f"{order.origin_price} != {price}" | ||
| if self.CONVERTS_ORDER_PRICE_BEFORE_PUSHING_TO_EXCHANGE: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| # actual origin_price may vary due to price conversion | ||
| assert price * decimal.Decimal("0.8") <= order.origin_price <= price * decimal.Decimal("1.2"), ( | ||
| f"FALSE: {price * decimal.Decimal('0.8')} <= {order.origin_price} <= {price * decimal.Decimal('1.2')}" | ||
| ) | ||
| else: | ||
| assert order.origin_price == price, f"{order.origin_price} != {price}" | ||
| assert isinstance(order.filled_quantity, decimal.Decimal) | ||
| expected_type = personal_data.BuyLimitOrder \ | ||
| if side is trading_enums.TradeOrderSide.BUY else personal_data.SellLimitOrder | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| # 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 <https://www.gnu.org/licenses/>. | ||
| import pytest | ||
|
|
||
| from additional_tests.exchanges_tests import abstract_authenticated_exchange_tester | ||
|
|
||
| try: | ||
| import tentacles.Trading.Exchange.polymarket.ccxt.polymarket_async | ||
| except ImportError: | ||
| pytest.skip( | ||
| reason=( | ||
| "Polymarket tentacle is not installed, skipping TestPolymarketAuthenticatedExchange" | ||
| ) | ||
| ) | ||
|
|
||
| # All test coroutines will be treated as marked. | ||
| pytestmark = pytest.mark.asyncio | ||
|
|
||
|
|
||
| class TestPolymarketAuthenticatedExchange( | ||
| abstract_authenticated_exchange_tester.AbstractAuthenticatedExchangeTester | ||
| ): | ||
| # 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}" | ||
| 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 | ||
|
|
||
| async def test_get_portfolio(self): | ||
| await super().test_get_portfolio() | ||
|
|
||
| async def test_get_portfolio_with_market_filter(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_untradable_symbols(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_get_max_orders_count(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_get_account_id(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_is_authenticated_request(self): | ||
| await super().test_is_authenticated_request() | ||
|
|
||
| async def test_invalid_api_key_error(self): | ||
| await super().test_invalid_api_key_error() | ||
|
|
||
| async def test_get_api_key_permissions(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_missing_trading_api_key_permissions(self): | ||
| pass | ||
|
|
||
| async def test_api_key_ip_whitelist_error(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_get_not_found_order(self): | ||
| await super().test_get_not_found_order() | ||
|
|
||
| async def test_is_valid_account(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_get_special_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_create_and_cancel_limit_orders(self): | ||
| await super().test_create_and_cancel_limit_orders() | ||
|
|
||
| async def test_create_and_fill_market_orders(self): | ||
| await super().test_create_and_fill_market_orders() | ||
|
|
||
| async def test_get_my_recent_trades(self): | ||
| await super().test_get_my_recent_trades() | ||
|
|
||
| async def test_get_closed_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_get_cancelled_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
|
Comment on lines
+109
to
+110
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As fetching cancelled orders is not supported, we can run this test as well, it will make sure fetching cancelled orders raises "unsupported error" and will start failing if fetching cancelled orders becomes available in the ccxt lib
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not able to run it as closed orders fetching is not available. It seems that the test requires at least canceled orders fetching or closed orders fetching to be supported.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok 👍
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok 👍 |
||
|
|
||
| async def test_create_and_cancel_stop_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_edit_limit_order(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_edit_stop_order(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_create_single_bundled_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
|
|
||
| async def test_create_double_bundled_orders(self): | ||
| # pass if not implemented | ||
| pass | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍