Fill in more of placebet

This commit is contained in:
James Grugett 2022-06-28 19:24:09 -05:00
parent 53e2ff7327
commit fe0b26669a
2 changed files with 104 additions and 35 deletions

View File

@ -37,17 +37,19 @@ export type BetInfo = {
const computeFill = (
betAmount: number,
outcome: 'YES' | 'NO',
limitProb: number,
limitProb: number | undefined,
cpmmState: CpmmState,
matchedBet: LimitBet
) => {
const prob = getCpmmProbability(cpmmState.pool, cpmmState.p)
if (
outcome === 'YES'
limitProb !== undefined &&
(outcome === 'YES'
? Math.min(prob, matchedBet.limitProb) > limitProb
: Math.max(prob, matchedBet.limitProb) < limitProb
: Math.max(prob, matchedBet.limitProb) < limitProb)
) {
// No fill.
return undefined
}
@ -59,20 +61,19 @@ const computeFill = (
// Fill from pool.
const limit =
outcome === 'YES'
? Math.min(matchedBet.limitProb, limitProb)
: Math.max(matchedBet.limitProb, limitProb)
const amount = calculateCpmmAmount(cpmmState, limit, 'YES')
? Math.min(matchedBet.limitProb, limitProb ?? Infinity)
: Math.max(matchedBet.limitProb, limitProb ?? -Infinity)
const amount = calculateCpmmAmount(cpmmState, limit, outcome)
const { shares, newPool, newP, fees } = calculateCpmmPurchase(
cpmmState,
amount,
'YES'
outcome
)
const newState = { pool: newPool, p: newP }
return {
maker: {
betId: 'bet',
matchedBetId: null,
shares,
amount,
@ -80,7 +81,6 @@ const computeFill = (
fees,
},
taker: {
betId: 'bet',
matchedBetId: null,
shares,
amount,
@ -88,17 +88,16 @@ const computeFill = (
}
}
// Fill from bet.
// Fill from matchedBet.
const amount = Math.min(betAmount, matchedBet.amount)
const shares = matchedBet.shares * (amount / matchedBet.amount)
const maker = {
betId: matchedBet.id,
matchedBetId: 'bet',
bet: matchedBet,
matchedBetId: 'taker',
amount,
shares,
}
const taker = {
betId: 'bet',
matchedBetId: matchedBet.id,
amount,
shares,
@ -106,20 +105,33 @@ const computeFill = (
return { maker, taker }
}
export const getBinaryCpmmLimitBetInfo = (
export const getBinaryCpmmBetInfo = (
outcome: 'YES' | 'NO',
betAmount: number,
contract: CPMMBinaryContract,
limitProb: number,
limitProb: number | undefined,
unfilledBets: LimitBet[] // Sorted by limitProb, createdTime
) => {
const fills: LimitBet['fills'] = []
const takers: {
matchedBetId: string | null
amount: number
shares: number
}[] = []
const makers: { bet: LimitBet; amount: number; shares: number }[] = []
let cpmmState = { pool: contract.pool, p: contract.p }
let totalFees = noFees
for (const bet of unfilledBets) {
const fill = computeFill(betAmount, outcome, limitProb, cpmmState, bet)
let i = 0
while (i < unfilledBets.length) {
const matchedBet = unfilledBets[i]
const fill = computeFill(
betAmount,
outcome,
limitProb,
cpmmState,
matchedBet
)
if (!fill) break
const { maker, taker } = fill
@ -130,12 +142,43 @@ export const getBinaryCpmmLimitBetInfo = (
cpmmState = maker.state
totalFees = addObjects(totalFees, maker.fees)
} else {
fills.push(maker)
makers.push(maker)
i++
}
fills.push(taker)
takers.push(taker)
}
return { fills, cpmmState, totalFees }
const probBefore = getCpmmProbability(contract.pool, contract.p)
const probAfter = getCpmmProbability(cpmmState.pool, cpmmState.p)
const takerAmount = sumBy(takers, 'amount')
const takerShares = sumBy(takers, 'shares')
const isFilled = Math.abs(betAmount - takerAmount) < 0.000000001
const newBet = {
amount: betAmount,
isFilled,
fills: takers,
contractId: contract.id,
shares: takerShares,
outcome,
probBefore,
probAfter,
loanAmount: 0,
createdTime: Date.now(),
fees: totalFees,
}
const { liquidityFee } = totalFees
const newTotalLiquidity = (contract.totalLiquidity ?? 0) + liquidityFee
return {
newBet,
newPool: cpmmState.pool,
newP: cpmmState.p,
newTotalLiquidity,
makers,
}
}
export const getNewBinaryCpmmBetInfo = (

View File

@ -6,8 +6,7 @@ import { Contract, CPMM_MIN_POOL_QTY } from '../../common/contract'
import { User } from '../../common/user'
import {
BetInfo,
getBinaryCpmmLimitBetInfo,
getNewBinaryCpmmBetInfo,
getBinaryCpmmBetInfo,
getNewBinaryDpmBetInfo,
getNewMultiBetInfo,
getNumericBetsInfo,
@ -17,6 +16,7 @@ import { redeemShares } from './redeem-shares'
import { log } from './utils'
import { LimitBet } from 'common/bet'
import { Query } from 'firebase-admin/firestore'
import { sumBy } from 'lodash'
const bodySchema = z.object({
contractId: z.string(),
@ -70,18 +70,28 @@ export const placebet = newEndpoint(['POST'], async (req, auth) => {
newTotalBets,
newTotalLiquidity,
newP,
} = await (async (): Promise<BetInfo> => {
makers,
} = await (async (): Promise<
BetInfo & {
makers?: {
bet: LimitBet
amount: number
shares: number
}[]
}
> => {
if (outcomeType == 'BINARY' && mechanism == 'dpm-2') {
const { outcome } = validate(binarySchema, req.body)
return getNewBinaryDpmBetInfo(outcome, amount, contract, loanAmount)
} else if (outcomeType == 'BINARY' && mechanism == 'cpmm-1') {
const { outcome, limitProb } = validate(binarySchema, req.body)
const boundedLimitProb = limitProb ?? (outcome === 'YES' ? 1 : 0)
const unfilledBetsQuery = contractDoc
.collection('bets')
.where('outcome', '==', outcome === 'YES' ? 'NO' : 'YES')
.where('isFilled', '==', false)
.where('isCancelled', '==', false)
.where('limitProb', outcome === 'YES' ? '<=' : '>=', limitProb)
.where('limitProb', outcome === 'YES' ? '<=' : '>=', boundedLimitProb)
.orderBy('createdTime', 'desc')
.orderBy(
'limitProb',
@ -91,16 +101,13 @@ export const placebet = newEndpoint(['POST'], async (req, auth) => {
const unfilledBetsSnap = await trans.get(unfilledBetsQuery)
const unfilledBets = unfilledBetsSnap.docs.map((doc) => doc.data())
if (limitProb !== undefined) {
getBinaryCpmmLimitBetInfo(
outcome,
amount,
contract,
limitProb,
unfilledBets,
)
}
return getNewBinaryCpmmBetInfo(outcome, amount, contract, loanAmount)
return getBinaryCpmmBetInfo(
outcome,
amount,
contract,
limitProb,
unfilledBets
)
} else if (outcomeType == 'FREE_RESPONSE' && mechanism == 'dpm-2') {
const { outcome } = validate(freeResponseSchema, req.body)
const answerDoc = contractDoc.collection('answers').doc(outcome)
@ -129,6 +136,25 @@ export const placebet = newEndpoint(['POST'], async (req, auth) => {
const betDoc = contractDoc.collection('bets').doc()
trans.create(betDoc, { id: betDoc.id, userId: user.id, ...newBet })
log('Created new bet document.')
if (makers) {
for (const maker of makers) {
const { bet, amount, shares } = maker
const newFill = { amount, shares, matchedBetId: betDoc.id }
const fills = [...bet.fills, newFill]
const totalShares = sumBy(fills, 'shares')
const isFilled =
Math.abs(sumBy(fills, 'amount') - bet.amount) < 0.0000001
log('Updated a matched limit bet.')
trans.update(contractDoc.collection('bets').doc(bet.id), {
fills,
isFilled,
shares: totalShares,
})
}
}
trans.update(userDoc, { balance: newBalance })
log('Updated user balance.')
trans.update(