Skip to content
Open
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
43 changes: 18 additions & 25 deletions ts-client/src/dlmm/helpers/rebalance/liquidity_strategy/bidAsk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import BN from "bn.js";
import { BidAskParameters, LiquidityStrategyParameterBuilder } from ".";
import { SCALE_OFFSET } from "../../../constants";
import { getQPriceFromId } from "../../math";
import {
getAmountInBinsAskSide,
getAmountInBinsBidSide,
toAmountIntoBins,
} from "../rebalancePosition";
import { getAmountInBinsAskSide, toAmountIntoBins } from "../rebalancePosition";

function findMinY0(amountY: BN, minDeltaId: BN, maxDeltaId: BN) {
const binCount = maxDeltaId.sub(minDeltaId).addn(1);
Expand Down Expand Up @@ -61,30 +57,27 @@ function findY0AndDeltaY(
}

let baseDeltaY = findBaseDeltaY(amountY, minDeltaId, maxDeltaId);
const y0 = baseDeltaY.neg().mul(maxDeltaId.neg().subn(1));

while (true) {
const amountInBins = getAmountInBinsBidSide(
activeId,
minDeltaId,
maxDeltaId,
baseDeltaY,
y0
);

const totalAmountY = amountInBins.reduce((acc, { amountY }) => {
return acc.add(amountY);
}, new BN(0));
const maxDeltaAbs = maxDeltaId.neg();
const binCount = maxDeltaId.sub(minDeltaId).addn(1);
const sumDeltaId = minDeltaId.add(maxDeltaId).mul(binCount).divn(2);
const sumNegDelta = sumDeltaId.neg();
const coefficient = sumNegDelta.sub(binCount.mul(maxDeltaAbs.subn(1)));

if (coefficient.gt(new BN(0))) {
const totalAmountY = baseDeltaY.mul(coefficient);
if (totalAmountY.gt(amountY)) {
baseDeltaY = baseDeltaY.sub(new BN(1));
} else {
return {
base: y0,
delta: baseDeltaY,
};
const overshoot = totalAmountY.sub(amountY);
const adjustment = overshoot.add(coefficient.subn(1)).div(coefficient);
baseDeltaY = BN.max(baseDeltaY.sub(adjustment), new BN(0));
}
}

const y0 = baseDeltaY.neg().mul(maxDeltaAbs.subn(1));

return {
base: y0,
delta: baseDeltaY,
};
}

function findMinX0(
Expand Down
98 changes: 98 additions & 0 deletions ts-client/src/test/liquidity_strategy_timeout.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import BN from "bn.js";

function sleepMs(ms: number) {
const start = Date.now();
while (Date.now() - start < ms) {}
}

describe("Liquidity strategy timeouts", () => {
const activeId = new BN(1000);
const binStep = new BN(10);

it("Spot and Curve builders complete within 15s", () => {
jest.resetModules();
const {
buildLiquidityStrategyParameters,
getLiquidityStrategyParameterBuilder,
} = require("../dlmm/helpers/rebalance");
const { StrategyType } = require("../dlmm/types");
const amountX = new BN(10_000);
const amountY = new BN(10_000);
const minDeltaId = new BN(-3);
const maxDeltaId = new BN(3);
const favorXInActiveBin = false;

const builders = [
getLiquidityStrategyParameterBuilder(StrategyType.Spot),
getLiquidityStrategyParameterBuilder(StrategyType.Curve),
];

for (const builder of builders) {
const start = Date.now();
buildLiquidityStrategyParameters(
amountX,
amountY,
minDeltaId,
maxDeltaId,
binStep,
favorXInActiveBin,
activeId,
builder
);
const elapsedMs = Date.now() - start;
expect(elapsedMs).toBeLessThan(15_000);
}
});

it("BidAsk can exceed 15s with pathological bid-side loops", () => {
jest.resetModules();
const amountX = new BN(0);
const amountY = new BN(20_000);
const minDeltaId = new BN(-1);
const maxDeltaId = new BN(-1);
const favorXInActiveBin = false;

jest.doMock("../dlmm/helpers/rebalance/rebalancePosition", () => {
const actual = jest.requireActual(
"../dlmm/helpers/rebalance/rebalancePosition"
);
return {
...actual,
getAmountInBinsBidSide: jest.fn((_activeId, _min, _max, deltaY) => {
sleepMs(100);
if (deltaY.gt(new BN(0))) {
return [
{ binId: activeId, amountX: new BN(0), amountY: amountY.addn(1) },
];
}

return [{ binId: activeId, amountX: new BN(0), amountY }];
}),
};
});

const rebalancePosition = require("../dlmm/helpers/rebalance/rebalancePosition");
const getAmountInBinsBidSide = rebalancePosition.getAmountInBinsBidSide;
expect(jest.isMockFunction(getAmountInBinsBidSide)).toBe(true);
const {
buildLiquidityStrategyParameters,
getLiquidityStrategyParameterBuilder,
} = require("../dlmm/helpers/rebalance");
const { StrategyType } = require("../dlmm/types");
const builder = getLiquidityStrategyParameterBuilder(StrategyType.BidAsk);

const start = Date.now();
buildLiquidityStrategyParameters(
amountX,
amountY,
minDeltaId,
maxDeltaId,
binStep,
favorXInActiveBin,
activeId,
builder
);
const elapsedMs = Date.now() - start;
expect(elapsedMs).toBeLessThan(15_000);
}, 15_000);
});
Loading