Skip to content

Commit

Permalink
market price calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
poly-rodr committed May 21, 2024
1 parent d8b2f28 commit cd6f24f
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 4 deletions.
30 changes: 28 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import {
} from "./endpoints";
import { OrderBuilder } from "./order-builder/builder";
import { END_CURSOR, INITIAL_CURSOR } from "./constants";
import { calculateMarketPrice } from "./order-builder/helpers";

export class ClobClient {
readonly host: string;
Expand Down Expand Up @@ -507,8 +508,11 @@ export class ClobClient {
const negRisk = options?.negRisk ?? false;

if (!userMarketOrder.price) {
const marketPrice = await this.getPrice(tokenID, Side.SELL);
userMarketOrder.price = parseFloat(marketPrice);
userMarketOrder.price = await this.calculateMarketPrice(
tokenID,
Side.BUY,
userMarketOrder.amount,
);
}

if (!priceValid(userMarketOrder.price, tickSize)) {
Expand Down Expand Up @@ -824,6 +828,28 @@ export class ClobClient {
return this.get(`${this.host}${GET_MARKET_TRADES_EVENTS}${conditionID}`);
}

public async calculateMarketPrice(
tokenID: string,
side: Side,
amount: number,
): Promise<number> {
const book = await this.getOrderBook(tokenID);
if (!book) {
throw new Error("no orderbook");
}
if (side === Side.BUY) {
if (!book.asks) {
throw new Error("no match");
}
return calculateMarketPrice(book.asks, amount);
} else {
if (!book.bids) {
throw new Error("no match");
}
return calculateMarketPrice(book.bids, amount);
}
}

private canL1Auth(): void {
if (this.signer === undefined) {
throw L1_AUTH_UNAVAILABLE_ERROR;
Expand Down
13 changes: 13 additions & 0 deletions src/order-builder/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
TickSize,
RoundConfig,
CreateOrderOptions,
OrderSummary,
} from "../types";
import { decimalPlaces, roundDown, roundNormal, roundUp } from "../utilities";
import {
Expand Down Expand Up @@ -301,3 +302,15 @@ export const createMarketBuyOrder = async (

return buildOrder(eoaSigner, exchangeContract, chainId, orderData);
};

export const calculateMarketPrice = (positions: OrderSummary[], amountToMatch: number) => {
let sum = 0;
for (let i = 0; i < positions.length; i++) {
const p = positions[i];
sum += parseFloat(p.size) * parseFloat(p.price);
if (sum >= amountToMatch) {
return parseFloat(p.price);
}
}
throw new Error("no match");
};
97 changes: 95 additions & 2 deletions tests/order-builder/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "mocha";
import { expect } from "chai";
import { UserOrder, Side, Chain, UserMarketOrder } from "../../src/types";
import { UserOrder, Side, Chain, UserMarketOrder, OrderSummary } from "../../src/types";
import {
buildOrderCreationArgs,
buildOrder,
Expand All @@ -10,6 +10,7 @@ import {
getOrderRawAmounts,
getMarketBuyOrderRawAmounts,
ROUNDING_CONFIG,
calculateMarketPrice,
} from "../../src/order-builder/helpers";
import { OrderData, SignatureType, Side as UtilsSide } from "@polymarket/order-utils";
import { Wallet } from "@ethersproject/wallet";
Expand Down Expand Up @@ -3477,7 +3478,7 @@ describe("helpers", () => {
});
});

describe("CTF Exchange", () => {
describe("Neg Risk CTF Exchange", () => {
describe("buy order", async () => {
it("0.1", async () => {
const order: UserMarketOrder = {
Expand Down Expand Up @@ -3621,4 +3622,96 @@ describe("helpers", () => {
});
});
});

describe.only("calculateMarketPrice", () => {
describe("BUY", () => {
it("empty orderbook", () => {
expect(() => calculateMarketPrice([], 100)).to.throw("no match");
});
it("not enough", () => {
const positions = [
{ price: "0.5", size: "100" },
{ price: "0.4", size: "100" },
] as OrderSummary[];
expect(() => calculateMarketPrice(positions, 100)).to.throw("no match");
});
it("ok", () => {
let positions = [
{ price: "0.5", size: "100" },
{ price: "0.4", size: "100" },
{ price: "0.3", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.3);

positions = [
{ price: "0.5", size: "100" },
{ price: "0.4", size: "200" },
{ price: "0.3", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.4);

positions = [
{ price: "0.5", size: "120" },
{ price: "0.4", size: "100" },
{ price: "0.3", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.4);

positions = [
{ price: "0.5", size: "200" },
{ price: "0.4", size: "100" },
{ price: "0.3", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.5);
});
});
describe("SELL", () => {
it("empty orderbook", () => {
expect(() => calculateMarketPrice([], 100)).to.throw("no match");
});
it("not enough", () => {
const positions = [
{ price: "0.4", size: "100" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(() => calculateMarketPrice(positions, 100)).to.throw("no match");
});
it("ok", () => {
let positions = [
{ price: "0.3", size: "100" },
{ price: "0.4", size: "100" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.5);

positions = [
{ price: "0.3", size: "100" },
{ price: "0.4", size: "300" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.4);

positions = [
{ price: "0.3", size: "100" },
{ price: "0.4", size: "200" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.4);

positions = [
{ price: "0.3", size: "300" },
{ price: "0.4", size: "100" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.4);

positions = [
{ price: "0.3", size: "334" },
{ price: "0.4", size: "100" },
{ price: "0.5", size: "100" },
] as OrderSummary[];
expect(calculateMarketPrice(positions, 100)).equal(0.3);
});
});
});
});

0 comments on commit cd6f24f

Please sign in to comment.