Simplify buying logic

This commit is contained in:
Austin Chen 2022-06-08 20:19:26 -07:00
parent 06c49be05b
commit 7acd3aed93

View File

@ -114,8 +114,9 @@ export function buyYes(
let stateIndex = 0 let stateIndex = 0
let amountLeft = amount let amountLeft = amount
let yesPurchased = 0 let yesPurchased = 0
while (amountLeft > 0) { // Stop if there's epsilon M$ left, due to rounding issues
// Find the current tick state while (amountLeft > 1e-6) {
// Find the current & next states for this tick
while (tick >= tickStates[stateIndex + 1].tick) { while (tick >= tickStates[stateIndex + 1].tick) {
stateIndex++ stateIndex++
if (stateIndex > tickStates.length - 2) { if (stateIndex > tickStates.length - 2) {
@ -126,32 +127,22 @@ export function buyYes(
const state = tickStates[stateIndex] const state = tickStates[stateIndex]
const nextState = tickStates[stateIndex + 1] const nextState = tickStates[stateIndex + 1]
// Copied from above; TODO extract to common function // nextState.tick purchases through the bucket; fullTick uses the remaining amountLeft
const noCost = toRatio(nextState.tick) ** 0.5 - toRatio(tick) ** 0.5 const fullCostN = amountLeft / state.liquidityGross
const yesCost = // Note: fullTick is NOT floored here; it's for the sqrtPrice to buy up to
1 / toRatio(tick) ** 0.5 - 1 / toRatio(nextState.tick) ** 0.5 const fullTick = fromRatioUnfloored((fullCostN + toRatio(tick) ** 0.5) ** 2)
const nextTick = Math.min(nextState.tick, fullTick)
if (noCost * state.liquidityGross <= amountLeft) { // Copied from above; TODO extract to common function?
// We can fully purchase up until the next tick state const noCost = toRatio(nextTick) ** 0.5 - toRatio(tick) ** 0.5
amountLeft -= noCost * state.liquidityGross const yesCost = 1 / toRatio(tick) ** 0.5 - 1 / toRatio(nextTick) ** 0.5
yesPurchased += yesCost * state.liquidityGross
tick = nextState.tick
} else {
// Buy as much as we can at the current tick state. Derivation:
// noCostLeft = toRatio(upTick) ** 0.5 - toRatio(tick) ** 0.5
// (noCostLeft + toRatio(tick) ** 0.5) ** 2 = toRatio(upTick)
// TODO check flooring done here
const noCostLeft = amountLeft / state.liquidityGross
const finalTick = fromRatio((noCostLeft + toRatio(tick) ** 0.5) ** 2)
const yesCostLeft =
1 / toRatio(tick) ** 0.5 - 1 / toRatio(finalTick) ** 0.5
amountLeft = 0 amountLeft -= noCost * state.liquidityGross
yesPurchased += yesCostLeft * state.liquidityGross yesPurchased += yesCost * state.liquidityGross
tick = finalTick tick = Math.floor(nextTick)
}
} }
// Right now we eat the epsilon amounntLeft as a fee. Could return it, shrug.
return { return {
newPoolTick: tick, newPoolTick: tick,
yesPurchased, yesPurchased,
@ -228,3 +219,7 @@ export function fromProb(prob: number) {
function fromRatio(ratio: number) { function fromRatio(ratio: number) {
return Math.floor(Math.log(ratio) / Math.log(1.0001)) return Math.floor(Math.log(ratio) / Math.log(1.0001))
} }
function fromRatioUnfloored(ratio: number) {
return Math.log(ratio) / Math.log(1.0001)
}