From ebdbf8a8c53804b7c2d7c8721e8b6ea19ff0c599 Mon Sep 17 00:00:00 2001 From: Rodrigo <95635797+poly-rodr@users.noreply.github.com> Date: Tue, 21 May 2024 20:21:18 -0300 Subject: [PATCH] calculating market price --- py_clob_client/client.py | 21 ++++- py_clob_client/order_builder/builder.py | 11 +++ tests/order_builder/test_builder.py | 111 +++++++++++++++++++++++- 3 files changed, 140 insertions(+), 3 deletions(-) diff --git a/py_clob_client/client.py b/py_clob_client/client.py index c12c0fd..c00d51f 100644 --- a/py_clob_client/client.py +++ b/py_clob_client/client.py @@ -356,8 +356,9 @@ def create_market_order( neg_risk = options.neg_risk if options else False if order_args.price is None or order_args.price <= 0: - p = self.get_price(order_args.token_id, "SELL") - order_args.price = float(p["price"]) + order_args.price = self.calculate_market_price( + order_args.token_id, "BUY", order_args.amount + ) if not price_valid(order_args.price, tick_size): raise Exception( @@ -673,3 +674,19 @@ def get_market_trades_events(self, condition_id): Get the market's trades events by condition id """ return get("{}{}{}".format(self.host, GET_MARKET_TRADES_EVENTS, condition_id)) + + def calculate_market_price(self, token_id: str, side: str, amount: float) -> float: + """ + Calculates the matching price considering an amount and the current orderbook + """ + book = self.get_order_book(token_id) + if book is None: + raise Exception("no orderbook") + if side == "BUY": + if book.asks is None: + raise Exception("no match") + return self.builder.calculate_market_price(book.asks, amount) + else: + if book.bids is None: + raise Exception("no match") + return self.builder.calculate_market_price(book.bids, amount) diff --git a/py_clob_client/order_builder/builder.py b/py_clob_client/order_builder/builder.py index 73595e8..84a99cb 100644 --- a/py_clob_client/order_builder/builder.py +++ b/py_clob_client/order_builder/builder.py @@ -24,6 +24,7 @@ TickSize, RoundConfig, MarketOrderArgs, + OrderSummary, ) ROUNDING_CONFIG: dict[TickSize, RoundConfig] = { @@ -173,3 +174,13 @@ def create_market_order( ) return order_builder.build_signed_order(data) + + def calculate_market_price( + self, positions: list[OrderSummary], amount_to_match: float + ) -> float: + sum = 0 + for p in positions: + sum += float(p.size) * float(p.price) + if sum >= amount_to_match: + return float(p.price) + raise Exception("no match") diff --git a/tests/order_builder/test_builder.py b/tests/order_builder/test_builder.py index 980a94b..269c5d5 100644 --- a/tests/order_builder/test_builder.py +++ b/tests/order_builder/test_builder.py @@ -1,6 +1,11 @@ from unittest import TestCase -from py_clob_client.clob_types import OrderArgs, MarketOrderArgs, CreateOrderOptions +from py_clob_client.clob_types import ( + OrderArgs, + MarketOrderArgs, + CreateOrderOptions, + OrderSummary, +) from py_clob_client.constants import AMOY from py_clob_client.order_builder.constants import BUY, SELL @@ -16,6 +21,110 @@ class TestOrderBuilder(TestCase): + def test_calculate_market_price_buy(self): + # empty + with self.assertRaises(Exception): + builder = OrderBuilder(signer) + builder.calculate_market_price([], 100) + + # not enough + with self.assertRaises(Exception): + positions = [ + OrderSummary(price="0.5", size="100"), + OrderSummary(price="0.4", size="100"), + ] + builder = OrderBuilder(signer) + builder.calculate_market_price(positions, 100) + + # OK + positions = [ + OrderSummary(price="0.5", size="100"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.3", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.3) + + positions = [ + OrderSummary(price="0.5", size="100"), + OrderSummary(price="0.4", size="200"), + OrderSummary(price="0.3", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.4) + + positions = [ + OrderSummary(price="0.5", size="120"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.3", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.4) + + positions = [ + OrderSummary(price="0.5", size="200"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.3", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.5) + + def test_calculate_market_price_sell(self): + # empty + with self.assertRaises(Exception): + builder = OrderBuilder(signer) + builder.calculate_market_price([], 100) + + # not enough + with self.assertRaises(Exception): + positions = [ + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + builder.calculate_market_price(positions, 100) + + # OK + positions = [ + OrderSummary(price="0.3", size="100"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.5) + + positions = [ + OrderSummary(price="0.3", size="100"), + OrderSummary(price="0.4", size="300"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.4) + + positions = [ + OrderSummary(price="0.3", size="100"), + OrderSummary(price="0.4", size="200"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.4) + + positions = [ + OrderSummary(price="0.3", size="300"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.4) + + positions = [ + OrderSummary(price="0.3", size="334"), + OrderSummary(price="0.4", size="100"), + OrderSummary(price="0.5", size="100"), + ] + builder = OrderBuilder(signer) + self.assertEqual(builder.calculate_market_price(positions, 100), 0.3) + def test_get_market_order_amounts_0_1(self): builder = OrderBuilder(signer)