Skip to content
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

Merge master into develop #1721

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Next version

- feat: Moved MangroveJsDeploy from mangrove-strats to this package. Renamed script to EmptyChainDeployer
- fix: rounding when deducing tick from price for LiquidityProvider

# 2.0.0

Expand Down
4 changes: 2 additions & 2 deletions src/liquidityProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ class LiquidityProvider {
} else if ("price" in p) {
// deduce tick & gives from volume & price
const price = Big(p.price);
// round down to ensure price is not exceeded
tick = tickPriceHelper.tickFromPrice(price, "roundDown");
// round up to ensure we get at least the tick we want
tick = tickPriceHelper.tickFromPrice(price, "roundUp");
if (p.ba === "bids") {
gives = Big(p.volume).mul(price);
} else {
Expand Down
153 changes: 46 additions & 107 deletions src/util/trade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,50 +25,55 @@ class Trade {
tradeEventManagement = new TradeEventManagement();

/**
* Get raw parameters to send to Mangrove for a buy order for the given trade and market parameters.
* Get raw parameters to send to Mangrove for a buy or sell order for the given trade and market parameters.
*/
getParamsForBuy(
getParamsForTrade(
params: Market.TradeParams,
market: Market.KeyResolvedForCalculation,
bs: Market.BS,
) {
// validate parameters and setup tickPriceHelper
let fillVolume: Big, maxTick: number, fillWants: boolean;
let fillVolume: Big,
maxTick: number,
fillWants: boolean = bs === "buy";
const ba = this.bsToBa(bs);
const slippage = this.validateSlippage(params.slippage);
const tickPriceHelper = new TickPriceHelper("asks", market);
const tickPriceHelper = new TickPriceHelper(ba, market);
if ("limitPrice" in params) {
if (Big(params.limitPrice).lte(0)) {
throw new Error("Cannot buy at or below price 0");
}
const priceWithSlippage = this.adjustForSlippage(
const limitPriceWithSlippage = this.adjustForSlippage(
Big(params.limitPrice),
slippage,
"buy",
bs,
);
// round down to not exceed the price
maxTick = tickPriceHelper.tickFromPrice(priceWithSlippage, "roundDown");
maxTick = tickPriceHelper.tickFromPrice(
limitPriceWithSlippage,
"roundDown",
);
if ("volume" in params) {
fillVolume = Big(params.volume);
fillWants = true;
} else {
fillVolume = Big(params.total);
fillWants = false;
fillWants = !fillWants;
}
} else if ("maxTick" in params) {
// in this case, we're merely asking to get the tick adjusted for slippage
fillVolume = Big(params.fillVolume);
fillWants = params.fillWants ?? true;
fillWants = params.fillWants ?? fillWants;
if (slippage > 0) {
// round down to not exceed the price
// round down to not exceed the price when buying, and up to get at least price for when selling
const limitPrice = tickPriceHelper.priceFromTick(
params.maxTick,
"roundDown",
bs === "buy" ? "roundDown" : "roundUp",
);
const limitPriceWithSlippage = this.adjustForSlippage(
limitPrice,
slippage,
"buy",
bs,
);
// round down to not exceed the price
// round down to not exceed the price expectations
maxTick = tickPriceHelper.tickFromPrice(
limitPriceWithSlippage,
"roundDown",
Expand All @@ -78,26 +83,32 @@ class Trade {
maxTick = params.maxTick;
}
} else {
const givesWithSlippage = this.adjustForSlippage(
Big(params.gives),
slippage,
"buy",
);
fillWants = params.fillWants ?? true;
fillVolume = fillWants ? Big(params.wants) : givesWithSlippage;
// round down to not exceed price expectations
maxTick = tickPriceHelper.tickFromVolumes(
givesWithSlippage,
params.wants,
"roundDown",
);
let wants = Big(params.wants);
let gives = Big(params.gives);
if (bs === "buy") {
gives = this.adjustForSlippage(gives, slippage, bs);
} else {
wants = this.adjustForSlippage(wants, slippage, bs);
}
fillWants = params.fillWants ?? fillWants;
fillVolume = fillWants ? wants : gives;
// round down to not exceed the price expectations
maxTick = tickPriceHelper.tickFromVolumes(gives, wants, "roundDown");
}

return {
maxTick,
fillVolume: fillWants
? market.base.toUnits(fillVolume)
: market.quote.toUnits(fillVolume),
? Market.getOutboundInbound(
ba,
market.base,
market.quote,
).outbound_tkn.toUnits(fillVolume)
: Market.getOutboundInbound(
ba,
market.base,
market.quote,
).inbound_tkn.toUnits(fillVolume),
fillWants: fillWants,
};
}
Expand All @@ -118,79 +129,6 @@ class Trade {
return value.mul(100 + adjustment).div(100);
}

/**
* Get raw parameters to send to Mangrove for a sell order for the given trade and market parameters.
*/
getParamsForSell(
params: Market.TradeParams,
market: Market.KeyResolvedForCalculation,
) {
let fillVolume: Big, maxTick: number, fillWants: boolean;
const slippage = this.validateSlippage(params.slippage);
const tickPriceHelper = new TickPriceHelper("bids", market);
if ("limitPrice" in params) {
if (Big(params.limitPrice).lte(0)) {
throw new Error("Cannot buy at or below price 0");
}
const priceWithSlippage = this.adjustForSlippage(
Big(params.limitPrice),
slippage,
"sell",
);
// round down to not exceed the price
maxTick = tickPriceHelper.tickFromPrice(priceWithSlippage, "roundDown");
if ("volume" in params) {
fillVolume = Big(params.volume);
fillWants = false;
} else {
fillVolume = Big(params.total);
fillWants = true;
}
} else if ("maxTick" in params) {
// in this case, we're merely asking to get the tick adjusted for slippage
fillVolume = Big(params.fillVolume);
fillWants = params.fillWants ?? false;
if (slippage > 0) {
// Round up since a higher price is better for sell
const limitPrice = tickPriceHelper.priceFromTick(
params.maxTick,
"roundUp",
);
const priceWithSlippage = this.adjustForSlippage(
limitPrice,
slippage,
"sell",
);
// round down to not exceed the price expectations
maxTick = tickPriceHelper.tickFromPrice(priceWithSlippage, "roundDown");
} else {
maxTick = params.maxTick;
}
} else {
const wantsWithSlippage = this.adjustForSlippage(
Big(params.wants),
slippage,
"sell",
);
fillWants = params.fillWants ?? false;
fillVolume = fillWants ? wantsWithSlippage : Big(params.gives);
// round down to not exceed the price expectations
maxTick = tickPriceHelper.tickFromVolumes(
params.gives,
wantsWithSlippage,
"roundDown",
);
}

return {
fillVolume: fillWants
? market.quote.toUnits(fillVolume)
: market.base.toUnits(fillVolume),
maxTick,
fillWants: fillWants,
};
}

validateSlippage = (slippage = 0) => {
if (typeof slippage === "undefined") {
return 0;
Expand Down Expand Up @@ -254,10 +192,11 @@ class Trade {
* @returns raw parameters for a market order to send to Mangrove
*/
getRawParams(bs: Market.BS, params: Market.TradeParams, market: Market) {
const { maxTick, fillVolume, fillWants } =
bs === "buy"
? this.getParamsForBuy(params, market)
: this.getParamsForSell(params, market);
const { maxTick, fillVolume, fillWants } = this.getParamsForTrade(
params,
market,
bs,
);
const restingOrderParams =
"restingOrder" in params ? params.restingOrder : null;

Expand Down
5 changes: 4 additions & 1 deletion test/integration/restingOrder.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ describe("RestingOrder", () => {
fund: askProvision,
});
await meAsLP.newAsk({
price: 10 / 10,
// Set price so that takers will hit it with a price of 1
price: market
.getSemibook("asks")
.tickPriceHelper.coercePrice(1, "roundDown"),
volume: 10,
fund: askProvision,
});
Expand Down
12 changes: 6 additions & 6 deletions test/unit/liquidityProvider.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(1));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, -276400);
assert.deepStrictEqual(tick, -276300);
});

it("normalizeOfferParams, with volume and price 1, as bids", async function () {
Expand All @@ -92,7 +92,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(1));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, 276324);
assert.deepStrictEqual(tick, 276325);
});

it("normalizeOfferParams, with volume and price 2, as asks", async function () {
Expand All @@ -110,7 +110,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(1));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, 6931);
assert.deepStrictEqual(tick, 6932);
});

it("normalizeOfferParams, with volume and price 2, as bids", async function () {
Expand All @@ -128,7 +128,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(2));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, -6932);
assert.deepStrictEqual(tick, -6931);
});

it("normalizeOfferParams, with volume and price 2, as asks", async function () {
Expand All @@ -146,7 +146,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(1));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, 6931);
assert.deepStrictEqual(tick, 6932);
});

it("normalizeOfferParams, with volume and price 2, as bids", async function () {
Expand All @@ -164,7 +164,7 @@ describe("Liquidity provider unit tests suite", () => {
);
assert.deepStrictEqual(gives, Big(2));
assert.deepStrictEqual(fund, undefined);
assert.deepStrictEqual(tick, -6932);
assert.deepStrictEqual(tick, -6931);
});

it("normalizeOfferParams, with gives and wants, as bids", async function () {
Expand Down
Loading
Loading