diff --git a/common/calculate-cpmm.ts b/common/calculate-cpmm.ts index ed4e0120..78825161 100644 --- a/common/calculate-cpmm.ts +++ b/common/calculate-cpmm.ts @@ -1,7 +1,6 @@ import * as _ from 'lodash' import { Bet } from './bet' import { Binary, CPMM, FullContract } from './contract' -import { FEES } from './fees' export function getCpmmProbability(pool: { [outcome: string]: number }) { // For binary contracts only. @@ -95,48 +94,3 @@ export function getCpmmProbabilityAfterSale( const { newPool } = calculateCpmmSale(contract, bet) return getCpmmProbability(newPool) } - -export function calculateFixedPayout( - contract: FullContract, - bet: Bet, - outcome: string -) { - if (outcome === 'CANCEL') return calculateFixedCancelPayout(bet) - if (outcome === 'MKT') return calculateFixedMktPayout(contract, bet) - - return calculateStandardFixedPayout(bet, outcome) -} - -export function calculateFixedCancelPayout(bet: Bet) { - return bet.amount -} - -export function calculateStandardFixedPayout(bet: Bet, outcome: string) { - const { amount, outcome: betOutcome, shares } = bet - if (betOutcome !== outcome) return 0 - return deductCpmmFees(amount, shares - amount) -} - -function calculateFixedMktPayout( - contract: FullContract, - bet: Bet -) { - const { resolutionProbability, pool } = contract - const p = - resolutionProbability !== undefined - ? resolutionProbability - : getCpmmProbability(pool) - - const { outcome, amount, shares } = bet - - const betP = outcome === 'YES' ? p : 1 - p - const winnings = betP * shares - - return deductCpmmFees(amount, winnings) -} - -export const deductCpmmFees = (betAmount: number, winnings: number) => { - return winnings > betAmount - ? betAmount + (1 - FEES) * (winnings - betAmount) - : winnings -} diff --git a/common/calculate-fixed-payouts.ts b/common/calculate-fixed-payouts.ts new file mode 100644 index 00000000..30e900f3 --- /dev/null +++ b/common/calculate-fixed-payouts.ts @@ -0,0 +1,49 @@ +import { Bet } from './bet' +import { getProbability } from './calculate' +import { Binary, FixedPayouts, FullContract } from './contract' +import { FEES } from './fees' + +export function calculateFixedPayout( + contract: FullContract, + bet: Bet, + outcome: string +) { + if (outcome === 'CANCEL') return calculateFixedCancelPayout(bet) + if (outcome === 'MKT') return calculateFixedMktPayout(contract, bet) + + return calculateStandardFixedPayout(bet, outcome) +} + +export function calculateFixedCancelPayout(bet: Bet) { + return bet.amount +} + +export function calculateStandardFixedPayout(bet: Bet, outcome: string) { + const { amount, outcome: betOutcome, shares } = bet + if (betOutcome !== outcome) return 0 + return deductFixedFees(amount, shares - amount) +} + +function calculateFixedMktPayout( + contract: FullContract, + bet: Bet +) { + const { resolutionProbability } = contract + const p = + resolutionProbability !== undefined + ? resolutionProbability + : getProbability(contract) + + const { outcome, amount, shares } = bet + + const betP = outcome === 'YES' ? p : 1 - p + const winnings = betP * shares + + return deductFixedFees(amount, winnings) +} + +export const deductFixedFees = (betAmount: number, winnings: number) => { + return winnings > betAmount + ? betAmount + (1 - FEES) * (winnings - betAmount) + : winnings +} diff --git a/common/calculate.ts b/common/calculate.ts index e16c0ac4..b8a9fc8f 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -1,20 +1,26 @@ import { Bet } from './bet' import { calculateCpmmShares, + calculateCpmmShareValue, getCpmmProbability, getCpmmProbabilityAfterBet, getCpmmProbabilityAfterSale, } from './calculate-cpmm' import { + calculateDpmPayout, calculateDpmPayoutAfterCorrectBet, + calculateDpmSaleAmount, calculateDpmShares, getDpmOutcomeProbability, getDpmProbability, getDpmProbabilityAfterBet, getDpmProbabilityAfterSale, } from './calculate-dpm' +import { + calculateFixedPayout, + deductFixedFees, +} from './calculate-fixed-payouts' import { Binary, Contract, CPMM, DPM, FullContract } from './contract' -import { FEES } from './fees' export function getProbability(contract: FullContract) { return contract.mechanism === 'cpmm-1' @@ -60,9 +66,18 @@ export function calculateShares( : calculateDpmShares(contract.totalShares, bet, betChoice) } +export function calculateSaleAmount(contract: Contract, bet: Bet) { + return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY' + ? deductFixedFees( + bet.amount, + calculateCpmmShareValue(contract, bet.shares, bet.outcome) + ) + : calculateDpmSaleAmount(contract, bet) +} + export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) { return contract.mechanism === 'cpmm-1' - ? deductFees(bet.amount, bet.shares) + ? deductFixedFees(bet.amount, bet.shares) : calculateDpmPayoutAfterCorrectBet(contract, bet) } @@ -79,8 +94,17 @@ export function getProbabilityAfterSale( : getDpmProbabilityAfterSale(contract.totalShares, outcome, shares) } -export const deductFees = (betAmount: number, winnings: number) => { - return winnings > betAmount - ? betAmount + (1 - FEES) * (winnings - betAmount) - : winnings +export function calculatePayout(contract: Contract, bet: Bet, outcome: string) { + return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY' + ? calculateFixedPayout(contract, bet, outcome) + : calculateDpmPayout(contract, bet, outcome) +} + +export function resolvedPayout(contract: Contract, bet: Bet) { + const outcome = contract.resolution + if (!outcome) throw new Error('Contract not resolved') + + return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY' + ? calculateFixedPayout(contract, bet, outcome) + : calculateDpmPayout(contract, bet, outcome) } diff --git a/common/contract.ts b/common/contract.ts index c39f11d0..21f84b71 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -52,6 +52,8 @@ export type CPMM = { liquidity: { [userId: string]: { [outcome: string]: number } } // track liquidity providers } +export type FixedPayouts = CPMM + export type Binary = { outcomeType: 'BINARY' resolutionProbability?: number // Used for BINARY markets resolved to MKT diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx index 71a1118f..1c054b37 100644 --- a/web/components/bets-list.tsx +++ b/web/components/bets-list.tsx @@ -22,11 +22,6 @@ import { } from '../lib/firebase/contracts' import { Row } from './layout/row' import { UserLink } from './user-page' -import { - calculateDpmPayout, - calculateDpmSaleAmount, - resolvedDpmPayout, -} from '../../common/calculate-dpm' import { sellBet } from '../lib/firebase/api-call' import { ConfirmationButton } from './confirmation-button' import { OutcomeLabel, YesLabel, NoLabel } from './outcome-label' @@ -34,9 +29,12 @@ import { filterDefined } from '../../common/util/array' import { LoadingIndicator } from './loading-indicator' import { SiteLink } from './site-link' import { + calculatePayout, + calculateSaleAmount, getOutcomeProbability, getProbability, getProbabilityAfterSale, + resolvedPayout, } from '../../common/calculate' type BetSort = 'newest' | 'profit' | 'settled' | 'value' @@ -84,7 +82,7 @@ export function BetsList(props: { user: User }) { if (bet.isSold || bet.sale) return 0 const contract = contracts.find((c) => c.id === contractId) - const payout = contract ? calculateDpmPayout(contract, bet, 'MKT') : 0 + const payout = contract ? calculatePayout(contract, bet, 'MKT') : 0 return payout - (bet.loanAmount ?? 0) }) } @@ -290,21 +288,21 @@ export function MyBetsSummary(props: { const betsTotal = _.sumBy(excludeSales, (bet) => bet.amount) const betsPayout = resolution - ? _.sumBy(excludeSales, (bet) => resolvedDpmPayout(contract, bet)) + ? _.sumBy(excludeSales, (bet) => resolvedPayout(contract, bet)) : 0 const yesWinnings = _.sumBy(excludeSales, (bet) => - calculateDpmPayout(contract, bet, 'YES') + calculatePayout(contract, bet, 'YES') ) const noWinnings = _.sumBy(excludeSales, (bet) => - calculateDpmPayout(contract, bet, 'NO') + calculatePayout(contract, bet, 'NO') ) // const p = getProbability(contract.totalShares) // const expectation = p * yesWinnings + (1 - p) * noWinnings const marketWinnings = _.sumBy(excludeSales, (bet) => - calculateDpmPayout(contract, bet, 'MKT') + calculatePayout(contract, bet, 'MKT') ) const currentValue = resolution ? betsPayout : marketWinnings @@ -475,15 +473,15 @@ function BetRow(props: { bet: Bet; contract: Contract; saleBet?: Bet }) { ) : ( formatMoney( isResolved - ? resolvedDpmPayout(contract, bet) - : calculateDpmSaleAmount(contract, bet) + ? resolvedPayout(contract, bet) + : calculateSaleAmount(contract, bet) ) ) const payoutIfChosenDisplay = bet.outcome === '0' && bet.isAnte ? 'N/A' - : formatMoney(calculateDpmPayout(contract, bet, bet.outcome)) + : formatMoney(calculatePayout(contract, bet, bet.outcome)) return ( @@ -528,7 +526,7 @@ function SellButton(props: { contract: Contract; bet: Bet }) { const outcomeProb = getProbabilityAfterSale(contract, outcome, shares) - const saleAmount = calculateDpmSaleAmount(contract, bet) + const saleAmount = calculateSaleAmount(contract, bet) return (