diff --git a/py_clob_client/client.py b/py_clob_client/client.py index 310b4ed..a63958f 100644 --- a/py_clob_client/client.py +++ b/py_clob_client/client.py @@ -1,4 +1,5 @@ import logging +from typing import Optional from .order_builder.builder import OrderBuilder from .headers.headers import create_level_1_headers, create_level_2_headers @@ -29,6 +30,7 @@ UPDATE_BALANCE_ALLOWANCE, IS_ORDER_SCORING, GET_TICK_SIZE, + GET_NEG_RISK, ARE_ORDERS_SCORING, GET_SIMPLIFIED_MARKETS, GET_MARKETS, @@ -115,7 +117,11 @@ def __init__( self.builder = OrderBuilder( self.signer, sig_type=signature_type, funder=funder ) + + # local cache self.__tick_sizes = {} + self.__neg_risk = {} + self.logger = logging.getLogger(self.__class__.__name__) def get_address(self): @@ -290,6 +296,15 @@ def get_tick_size(self, token_id: str) -> TickSize: return self.__tick_sizes[token_id] + def get_neg_risk(self, token_id: str) -> bool: + if token_id in self.__neg_risk: + return self.__neg_risk[token_id] + + result = get("{}{}?token_id={}".format(self.host, GET_NEG_RISK, token_id)) + self.__neg_risk[token_id] = result["neg_risk"] + + return result["neg_risk"] + def __resolve_tick_size( self, token_id: str, tick_size: TickSize = None ) -> TickSize: @@ -307,7 +322,7 @@ def __resolve_tick_size( return tick_size def create_order( - self, order_args: OrderArgs, options: PartialCreateOrderOptions = None + self, order_args: OrderArgs, options: Optional[PartialCreateOrderOptions] = None ): """ Creates and signs an order @@ -320,7 +335,6 @@ def create_order( order_args.token_id, options.tick_size if options else None, ) - neg_risk = options.neg_risk if options else False if not price_valid(order_args.price, tick_size): raise Exception( @@ -332,6 +346,12 @@ def create_order( + str(1 - float(tick_size)) ) + neg_risk = ( + options.neg_risk + if options and options.neg_risk + else self.get_neg_risk(order_args.token_id) + ) + return self.builder.create_order( order_args, CreateOrderOptions( @@ -341,7 +361,9 @@ def create_order( ) def create_market_order( - self, order_args: MarketOrderArgs, options: PartialCreateOrderOptions = None + self, + order_args: MarketOrderArgs, + options: Optional[PartialCreateOrderOptions] = None, ): """ Creates and signs an order @@ -354,7 +376,6 @@ def create_market_order( order_args.token_id, options.tick_size if options else None, ) - neg_risk = options.neg_risk if options else False if order_args.price is None or order_args.price <= 0: order_args.price = self.calculate_market_price( @@ -371,6 +392,12 @@ def create_market_order( + str(1 - float(tick_size)) ) + neg_risk = ( + options.neg_risk + if options and options.neg_risk + else self.get_neg_risk(order_args.token_id) + ) + return self.builder.create_market_order( order_args, CreateOrderOptions( diff --git a/py_clob_client/clob_types.py b/py_clob_client/clob_types.py index 979f373..6eab47c 100644 --- a/py_clob_client/clob_types.py +++ b/py_clob_client/clob_types.py @@ -1,4 +1,3 @@ -from dataclasses import dataclass from typing import Any from dataclasses import dataclass, asdict from json import dumps @@ -190,13 +189,13 @@ class OrdersScoringParams: @dataclass class CreateOrderOptions: tick_size: TickSize - neg_risk: bool = False + neg_risk: bool @dataclass class PartialCreateOrderOptions: tick_size: Optional[TickSize] = None - neg_risk: bool = False + neg_risk: Optional[bool] = None @dataclass diff --git a/py_clob_client/endpoints.py b/py_clob_client/endpoints.py index b1052a5..32eed93 100644 --- a/py_clob_client/endpoints.py +++ b/py_clob_client/endpoints.py @@ -28,6 +28,7 @@ IS_ORDER_SCORING = "/order-scoring" ARE_ORDERS_SCORING = "/orders-scoring" GET_TICK_SIZE = "/tick-size" +GET_NEG_RISK = "/neg-risk" GET_SAMPLING_SIMPLIFIED_MARKETS = "/sampling-simplified-markets" GET_SAMPLING_MARKETS = "/sampling-markets" GET_SIMPLIFIED_MARKETS = "/simplified-markets" diff --git a/setup.py b/setup.py index 83c8902..1768a25 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="py_clob_client", - version="0.17.3", + version="0.17.4", author="Polymarket Engineering", author_email="engineering@polymarket.com", maintainer="Polymarket Engineering", diff --git a/tests/order_builder/test_builder.py b/tests/order_builder/test_builder.py index 269c5d5..3659614 100644 --- a/tests/order_builder/test_builder.py +++ b/tests/order_builder/test_builder.py @@ -396,7 +396,7 @@ def test_create_order_decimal_accuracy(self): size=15, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -415,7 +415,7 @@ def test_create_order_decimal_accuracy(self): size=15, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -434,7 +434,7 @@ def test_create_order_decimal_accuracy(self): size=101, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -453,7 +453,7 @@ def test_create_order_decimal_accuracy(self): size=101, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -472,7 +472,7 @@ def test_create_order_decimal_accuracy(self): size=12.8205, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -491,7 +491,7 @@ def test_create_order_decimal_accuracy(self): size=12.8205, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -510,7 +510,7 @@ def test_create_order_decimal_accuracy(self): size=2435.89, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -529,7 +529,7 @@ def test_create_order_decimal_accuracy(self): size=19.1, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -548,7 +548,7 @@ def test_create_order_decimal_accuracy(self): size=18233.33, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertEqual( signed_order.order["makerAmount"], @@ -575,7 +575,7 @@ def test_create_order_buy_0_1(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -644,7 +644,7 @@ def test_create_order_buy_0_01(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -713,7 +713,7 @@ def test_create_order_buy_0_001(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -782,7 +782,7 @@ def test_create_order_buy_0_0001(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -851,7 +851,7 @@ def test_create_order_sell_0_1(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -920,7 +920,7 @@ def test_create_order_sell_0_01(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -989,7 +989,7 @@ def test_create_order_sell_0_001(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -1058,7 +1058,7 @@ def test_create_order_sell_0_0001(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -1992,7 +1992,7 @@ def test_dict_order_buy(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertIsNotNone(signed_order) @@ -2060,7 +2060,7 @@ def test_dict_order_sell(self): nonce=123, expiration=50000, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertIsNotNone(signed_order) @@ -2126,7 +2126,7 @@ def test_create_market_order_buy_0_1(self): fee_rate_bps=111, nonce=123, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -2193,7 +2193,7 @@ def test_create_market_order_buy_0_01(self): fee_rate_bps=111, nonce=123, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -2260,7 +2260,7 @@ def test_create_market_order_buy_0_001(self): fee_rate_bps=111, nonce=123, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -2327,7 +2327,7 @@ def test_create_market_order_buy_0_0001(self): fee_rate_bps=111, nonce=123, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ) self.assertTrue(isinstance(signed_order.order["salt"], int)) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index d113be8..ec77d0e 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -176,7 +176,7 @@ def test_order_to_json_0_1(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -215,7 +215,7 @@ def test_order_to_json_0_1(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -254,7 +254,7 @@ def test_order_to_json_0_1(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -293,7 +293,7 @@ def test_order_to_json_0_1(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.1"), + options=CreateOrderOptions(tick_size="0.1", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -342,7 +342,7 @@ def test_order_to_json_0_01(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -381,7 +381,7 @@ def test_order_to_json_0_01(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -420,7 +420,7 @@ def test_order_to_json_0_01(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -459,7 +459,7 @@ def test_order_to_json_0_01(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.01"), + options=CreateOrderOptions(tick_size="0.01", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -508,7 +508,7 @@ def test_order_to_json_0_001(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -547,7 +547,7 @@ def test_order_to_json_0_001(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -586,7 +586,7 @@ def test_order_to_json_0_001(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -625,7 +625,7 @@ def test_order_to_json_0_001(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.001"), + options=CreateOrderOptions(tick_size="0.001", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -674,7 +674,7 @@ def test_order_to_json_0_0001(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -713,7 +713,7 @@ def test_order_to_json_0_0001(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ), owner=owner, orderType=OrderType.GTC, @@ -752,7 +752,7 @@ def test_order_to_json_0_0001(self): size=100, side=BUY, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ), owner=owner, orderType=OrderType.GTD, @@ -791,7 +791,7 @@ def test_order_to_json_0_0001(self): size=100, side=SELL, ), - options=CreateOrderOptions(tick_size="0.0001"), + options=CreateOrderOptions(tick_size="0.0001", neg_risk=False), ), owner=owner, orderType=OrderType.GTD,