diff --git a/common/antes.ts b/common/antes.ts index 3604d941..91fdee48 100644 --- a/common/antes.ts +++ b/common/antes.ts @@ -3,7 +3,7 @@ import { getProbability } from './calculate' import { Contract } from './contract' import { User } from './user' -export const PHANTOM_ANTE = 100 +export const PHANTOM_ANTE = 1 export const MINIMUM_ANTE = 10 export const calcStartPool = (initialProbInt: number, ante = 0) => { diff --git a/common/calculate.ts b/common/calculate.ts index fbbfd66f..b1adda99 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -133,19 +133,14 @@ export function calculateStandardPayout( const { amount, outcome: betOutcome, shares } = bet if (betOutcome !== outcome) return 0 - const { totalShares, totalBets, phantomShares } = contract + const { totalShares, phantomShares } = contract if (totalShares[outcome] === 0) return 0 - const truePool = contract.pool.YES + contract.pool.NO + const pool = contract.pool.YES + contract.pool.NO + const total = totalShares[outcome] - phantomShares[outcome] - if (totalBets[outcome] >= truePool) - return (amount / totalBets[outcome]) * truePool - - const total = - totalShares[outcome] - phantomShares[outcome] - totalBets[outcome] - const winningsPool = truePool - totalBets[outcome] - - return amount + (1 - FEES) * ((shares - amount) / total) * winningsPool + const winnings = (shares / total) * pool + return deductFees(amount, winnings) } export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) { @@ -179,35 +174,18 @@ function calculateMktPayout(contract: Contract, bet: Bet) { ? contract.resolutionProbability : getProbability(contract.totalShares) - const weightedTotal = - p * contract.totalBets.YES + (1 - p) * contract.totalBets.NO - - const truePool = contract.pool.YES + contract.pool.NO - - const betP = bet.outcome === 'YES' ? p : 1 - p - - if (weightedTotal >= truePool) { - return ((betP * bet.amount) / weightedTotal) * truePool - } - - const winningsPool = truePool - weightedTotal + const pool = contract.pool.YES + contract.pool.NO const weightedShareTotal = - p * - (contract.totalShares.YES - - contract.phantomShares.YES - - contract.totalBets.YES) + - (1 - p) * - (contract.totalShares.NO - - contract.phantomShares.NO - - contract.totalBets.NO) + p * (contract.totalShares.YES - contract.phantomShares.YES) + + (1 - p) * (contract.totalShares.NO - contract.phantomShares.NO) - return ( - betP * bet.amount + - (1 - FEES) * - ((betP * (bet.shares - bet.amount)) / weightedShareTotal) * - winningsPool - ) + const { outcome, amount, shares } = bet + + const betP = outcome === 'YES' ? p : 1 - p + const winnings = ((betP * shares) / weightedShareTotal) * pool + + return deductFees(amount, winnings) } export function resolvedPayout(contract: Contract, bet: Bet) { @@ -224,3 +202,9 @@ export function currentValue(contract: Contract, bet: Bet) { return prob * yesPayout + (1 - prob) * noPayout } + +export const deductFees = (betAmount: number, winnings: number) => { + return winnings > betAmount + ? betAmount + (1 - FEES) * (winnings - betAmount) + : betAmount +} diff --git a/common/payouts.ts b/common/payouts.ts index 77630502..09cd1620 100644 --- a/common/payouts.ts +++ b/common/payouts.ts @@ -1,14 +1,16 @@ +import * as _ from 'lodash' + import { Bet } from './bet' -import { getProbability } from './calculate' +import { deductFees, getProbability } from './calculate' import { Contract, outcome } from './contract' -import { CREATOR_FEE, FEES } from './fees' +import { CREATOR_FEE } from './fees' export const getCancelPayouts = (contract: Contract, bets: Bet[]) => { const { pool } = contract const poolTotal = pool.YES + pool.NO console.log('resolved N/A, pool M$', poolTotal) - const betSum = sumBy(bets, (b) => b.amount) + const betSum = _.sumBy(bets, (b) => b.amount) return bets.map((bet) => ({ userId: bet.userId, @@ -21,35 +23,24 @@ export const getStandardPayouts = ( contract: Contract, bets: Bet[] ) => { - const [yesBets, noBets] = partition(bets, (bet) => bet.outcome === 'YES') + const [yesBets, noBets] = _.partition(bets, (bet) => bet.outcome === 'YES') const winningBets = outcome === 'YES' ? yesBets : noBets - const betSum = sumBy(winningBets, (b) => b.amount) - - const poolTotal = contract.pool.YES + contract.pool.NO - - if (betSum >= poolTotal) return getCancelPayouts(contract, winningBets) - - const shareDifferenceSum = sumBy(winningBets, (b) => b.shares - b.amount) - - const winningsPool = poolTotal - betSum + const pool = contract.pool.YES + contract.pool.NO + const totalShares = _.sumBy(winningBets, (b) => b.shares) const winnerPayouts = winningBets.map((bet) => ({ userId: bet.userId, - payout: - bet.amount + - (1 - FEES) * - ((bet.shares - bet.amount) / shareDifferenceSum) * - winningsPool, + payout: deductFees(bet.amount, (bet.shares / totalShares) * pool), })) - const creatorPayout = CREATOR_FEE * winningsPool + const creatorPayout = CREATOR_FEE * pool console.log( 'resolved', outcome, 'pool: M$', - poolTotal, + pool, 'creator fee: M$', creatorPayout ) @@ -69,50 +60,32 @@ export const getMktPayouts = ( ? getProbability(contract.totalShares) : resolutionProbability - const poolTotal = contract.pool.YES + contract.pool.NO - console.log('Resolved MKT at p=', p, 'pool: $M', poolTotal) + const pool = contract.pool.YES + contract.pool.NO + console.log('Resolved MKT at p=', p, 'pool: $M', pool) - 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 >= poolTotal) { - return bets.map((bet) => ({ - userId: bet.userId, - payout: - (((bet.outcome === 'YES' ? p : 1 - p) * bet.amount) / - weightedBetTotal) * - poolTotal, - })) - } - - const winningsPool = poolTotal - weightedBetTotal + const [yesBets, noBets] = _.partition(bets, (bet) => bet.outcome === 'YES') const weightedShareTotal = - p * sumBy(yesBets, (b) => b.shares - b.amount) + - (1 - p) * sumBy(noBets, (b) => b.shares - b.amount) + p * _.sumBy(yesBets, (b) => b.shares) + + (1 - p) * _.sumBy(noBets, (b) => b.shares) const yesPayouts = yesBets.map((bet) => ({ userId: bet.userId, - payout: - p * bet.amount + - (1 - FEES) * - ((p * (bet.shares - bet.amount)) / weightedShareTotal) * - winningsPool, + payout: deductFees( + bet.amount, + ((p * bet.shares) / weightedShareTotal) * pool + ), })) const noPayouts = noBets.map((bet) => ({ userId: bet.userId, - payout: - (1 - p) * bet.amount + - (1 - FEES) * - (((1 - p) * (bet.shares - bet.amount)) / weightedShareTotal) * - winningsPool, + payout: deductFees( + bet.amount, + (((1 - p) * bet.shares) / weightedShareTotal) * pool + ), })) - const creatorPayout = CREATOR_FEE * winningsPool + const creatorPayout = CREATOR_FEE * pool return [ ...yesPayouts, @@ -137,20 +110,3 @@ export const getPayouts = ( return getCancelPayouts(contract, bets) } } - -const partition = (array: T[], f: (t: T) => boolean) => { - const yes = [] - const no = [] - - for (let t of array) { - if (f(t)) yes.push(t) - else no.push(t) - } - - return [yes, no] as [T[], T[]] -} - -const sumBy = (array: T[], f: (t: T) => number) => { - const values = array.map(f) - return values.reduce((prev, cur) => prev + cur, 0) -}