Skip to content

Commit

Permalink
Merge pull request #112 from Polymarket/feat/fok-sells
Browse files Browse the repository at this point in the history
FOK sell orders
  • Loading branch information
poly-rodr authored Jan 16, 2025
2 parents e1c5568 + 506b428 commit 7bed3e8
Show file tree
Hide file tree
Showing 7 changed files with 771 additions and 50 deletions.
4 changes: 3 additions & 1 deletion examples/market_order.py → examples/market_buy_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from py_clob_client.clob_types import ApiCreds, MarketOrderArgs, OrderType
from dotenv import load_dotenv
from py_clob_client.constants import AMOY
from py_clob_client.order_builder.constants import BUY


load_dotenv()
Expand All @@ -23,7 +24,8 @@ def main():
# create a market buy order for the equivalent of 100 USDC at the market price
order_args = MarketOrderArgs(
token_id="71321045679252212594626385532706912750332728571942532289631379312455583992563",
amount=100,
amount=100, # $$$
side=BUY,
)
signed_order = client.create_market_order(order_args)
resp = client.post_order(signed_order, orderType=OrderType.FOK)
Expand Down
36 changes: 36 additions & 0 deletions examples/market_sell_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds, MarketOrderArgs, OrderType
from dotenv import load_dotenv
from py_clob_client.constants import AMOY
from py_clob_client.order_builder.constants import SELL


load_dotenv()


def main():
host = "http://localhost:8080"
key = os.getenv("PK")
creds = ApiCreds(
api_key=os.getenv("CLOB_API_KEY"),
api_secret=os.getenv("CLOB_SECRET"),
api_passphrase=os.getenv("CLOB_PASS_PHRASE"),
)
chain_id = AMOY
client = ClobClient(host, key=key, chain_id=chain_id, creds=creds)

# create a market buy order for the equivalent of 100 USDC at the market price
order_args = MarketOrderArgs(
token_id="71321045679252212594626385532706912750332728571942532289631379312455583992563",
amount=100, # SHARES
side=SELL,
)
signed_order = client.create_market_order(order_args)
resp = client.post_order(signed_order, orderType=OrderType.FOK)
print(resp)
print("Done!")


main()
6 changes: 3 additions & 3 deletions py_clob_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def create_market_order(

if order_args.price is None or order_args.price <= 0:
order_args.price = self.calculate_market_price(
order_args.token_id, "BUY", order_args.amount
order_args.token_id, order_args.side, order_args.amount
)

if not price_valid(order_args.price, tick_size):
Expand Down Expand Up @@ -740,8 +740,8 @@ def calculate_market_price(self, token_id: str, side: str, amount: float) -> flo
if side == "BUY":
if book.asks is None:
raise Exception("no match")
return self.builder.calculate_market_price(book.asks, amount)
return self.builder.calculate_buy_market_price(book.asks, amount)
else:
if book.bids is None:
raise Exception("no match")
return self.builder.calculate_market_price(book.bids, amount)
return self.builder.calculate_sell_market_price(book.bids, amount)
8 changes: 7 additions & 1 deletion py_clob_client/clob_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@ class MarketOrderArgs:

amount: float
"""
Amount in terms of Collateral
BUY orders: $$$ Amount to buy
SELL orders: Shares to sell
"""

side: str
"""
Side of the order
"""

price: float = 0
Expand Down
52 changes: 40 additions & 12 deletions py_clob_client/order_builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,38 @@ def get_order_amounts(
raise ValueError(f"order_args.side must be '{BUY}' or '{SELL}'")

def get_market_order_amounts(
self, amount: float, price: float, round_config: RoundConfig
self, side: str, amount: float, price: float, round_config: RoundConfig
):
raw_maker_amt = round_down(amount, round_config.size)
raw_price = round_normal(price, round_config.price)

raw_taker_amt = raw_maker_amt / raw_price
if decimal_places(raw_taker_amt) > round_config.amount:
raw_taker_amt = round_up(raw_taker_amt, round_config.amount + 4)
if side == BUY:
raw_maker_amt = round_down(amount, round_config.size)
raw_taker_amt = raw_maker_amt / raw_price
if decimal_places(raw_taker_amt) > round_config.amount:
raw_taker_amt = round_down(raw_taker_amt, round_config.amount)
raw_taker_amt = round_up(raw_taker_amt, round_config.amount + 4)
if decimal_places(raw_taker_amt) > round_config.amount:
raw_taker_amt = round_down(raw_taker_amt, round_config.amount)

maker_amount = to_token_decimals(raw_maker_amt)
taker_amount = to_token_decimals(raw_taker_amt)

return UtilsBuy, maker_amount, taker_amount

maker_amount = to_token_decimals(raw_maker_amt)
taker_amount = to_token_decimals(raw_taker_amt)
elif side == SELL:
raw_maker_amt = round_down(amount, round_config.size)

return maker_amount, taker_amount
raw_taker_amt = raw_maker_amt * raw_price
if decimal_places(raw_taker_amt) > round_config.amount:
raw_taker_amt = round_up(raw_taker_amt, round_config.amount + 4)
if decimal_places(raw_taker_amt) > round_config.amount:
raw_taker_amt = round_down(raw_taker_amt, round_config.amount)

maker_amount = to_token_decimals(raw_maker_amt)
taker_amount = to_token_decimals(raw_taker_amt)

return UtilsSell, maker_amount, taker_amount
else:
raise ValueError(f"order_args.side must be '{BUY}' or '{SELL}'")

def create_order(
self, order_args: OrderArgs, options: CreateOrderOptions
Expand Down Expand Up @@ -143,7 +160,8 @@ def create_market_order(
"""
Creates and signs a market order
"""
maker_amount, taker_amount = self.get_market_order_amounts(
side, maker_amount, taker_amount = self.get_market_order_amounts(
order_args.side,
order_args.amount,
order_args.price,
ROUNDING_CONFIG[options.tick_size],
Expand All @@ -155,7 +173,7 @@ def create_market_order(
tokenId=order_args.token_id,
makerAmount=str(maker_amount),
takerAmount=str(taker_amount),
side=UtilsBuy,
side=side,
feeRateBps=str(order_args.fee_rate_bps),
nonce=str(order_args.nonce),
signer=self.signer.address(),
Expand All @@ -175,7 +193,7 @@ def create_market_order(

return order_builder.build_signed_order(data)

def calculate_market_price(
def calculate_buy_market_price(
self, positions: list[OrderSummary], amount_to_match: float
) -> float:
sum = 0
Expand All @@ -184,3 +202,13 @@ def calculate_market_price(
if sum >= amount_to_match:
return float(p.price)
raise Exception("no match")

def calculate_sell_market_price(
self, positions: list[OrderSummary], amount_to_match: float
) -> float:
sum = 0
for p in reversed(positions):
sum += float(p.size)
if sum >= amount_to_match:
return float(p.price)
raise Exception("no match")
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="py_clob_client",
version="0.19.0",
version="0.20.0",
author="Polymarket Engineering",
author_email="[email protected]",
maintainer="Polymarket Engineering",
Expand Down
Loading

0 comments on commit 7bed3e8

Please sign in to comment.