diff --git a/functions/src/resolve-market.ts b/functions/src/resolve-market.ts index 6af0b919..4862703f 100644 --- a/functions/src/resolve-market.ts +++ b/functions/src/resolve-market.ts @@ -155,7 +155,6 @@ const getStandardPayouts = ( const shareDifferenceSum = _.sumBy(winningBets, (b) => b.shares - b.amount) const winningsPool = truePool - betSum - const fees = PLATFORM_FEE + CREATOR_FEE const winnerPayouts = winningBets.map((bet) => ({ userId: bet.userId, @@ -173,11 +172,53 @@ const getStandardPayouts = ( const getMktPayouts = (truePool: number, contract: Contract, bets: Bet[]) => { const p = contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2) - console.log('Resolved MKT at p=', p) + console.log('Resolved MKT at p=', p, 'pool: $M', truePool) + + const [yesBets, noBets] = _.partition(bets, (bet) => bet.outcome === 'YES') + + const weightedBetTotal = + p * _.sumBy(yesBets, (b) => b.amount) + + (1 - p) * _.sumBy(noBets, (b) => b.amount) + + if (weightedBetTotal >= truePool) { + return bets.map((bet) => ({ + userId: bet.userId, + payout: + (((bet.outcome === 'YES' ? p : 1 - p) * bet.amount) / + weightedBetTotal) * + truePool, + })) + } + + const winningsPool = truePool - weightedBetTotal + + const weightedShareTotal = + p * _.sumBy(yesBets, (b) => b.shares - b.amount) + + (1 - p) * _.sumBy(noBets, (b) => b.shares - b.amount) + + const yesPayouts = yesBets.map((bet) => ({ + userId: bet.userId, + payout: + (1 - fees) * + (p * bet.amount + + ((p * (bet.shares - bet.amount)) / weightedShareTotal) * winningsPool), + })) + + const noPayouts = noBets.map((bet) => ({ + userId: bet.userId, + payout: + (1 - fees) * + ((1 - p) * bet.amount + + (((1 - p) * (bet.shares - bet.amount)) / weightedShareTotal) * + winningsPool), + })) + + const creatorPayout = CREATOR_FEE * truePool return [ - ...getStandardPayouts('YES', p * truePool, contract, bets), - ...getStandardPayouts('NO', (1 - p) * truePool, contract, bets), + ...yesPayouts, + ...noPayouts, + { userId: contract.creatorId, payout: creatorPayout }, ] } @@ -192,3 +233,5 @@ const payUser = ([userId, payout]: [string, number]) => { transaction.update(userDoc, { balance: newUserBalance }) }) } + +const fees = PLATFORM_FEE + CREATOR_FEE diff --git a/web/lib/calculate.ts b/web/lib/calculate.ts index d854c6b1..b265f228 100644 --- a/web/lib/calculate.ts +++ b/web/lib/calculate.ts @@ -41,10 +41,15 @@ export function calculatePayout( ) { const { amount, outcome: betOutcome, shares } = bet - if (outcome === 'CANCEL' || outcome === 'MKT') return amount + if (outcome === 'CANCEL') return amount + if (outcome === 'MKT') return calculateMktPayout(contract, bet) + + if (betOutcome !== outcome) return 0 const { totalShares, totalBets } = contract + if (totalShares[outcome] === 0) return 0 + const startPool = contract.startPool.YES + contract.startPool.NO const truePool = contract.pool.YES + contract.pool.NO - startPool @@ -57,6 +62,34 @@ export function calculatePayout( return (1 - fees) * (amount + ((shares - amount) / total) * winningsPool) } +function calculateMktPayout(contract: Contract, bet: Bet) { + const p = + contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2) + const weightedTotal = + p * contract.totalBets.YES + (1 - p) * contract.totalBets.NO + + const startPool = contract.startPool.YES + contract.startPool.NO + const truePool = contract.pool.YES + contract.pool.NO - startPool + + const betP = bet.outcome === 'YES' ? p : 1 - p + + if (weightedTotal >= truePool) { + return ((betP * bet.amount) / weightedTotal) * truePool + } + + const winningsPool = truePool - weightedTotal + + const weightedShareTotal = + p * (contract.totalShares.YES - contract.totalBets.YES) + + (1 - p) * (contract.totalShares.NO - contract.totalBets.NO) + + return ( + (1 - fees) * + (betP * bet.amount + + ((betP * (bet.shares - bet.amount)) / weightedShareTotal) * winningsPool) + ) +} + export function resolvedPayout(contract: Contract, bet: Bet) { if (contract.resolution) return calculatePayout(contract, bet, contract.resolution)