diff --git a/common/antes.ts b/common/antes.ts index 21dc1d4b..08247d7a 100644 --- a/common/antes.ts +++ b/common/antes.ts @@ -1,6 +1,6 @@ import { Bet } from './bet' import { getDpmProbability } from './calculate-dpm' -import { getCpmmLiquidity, getCpmmProbability } from './calculate-cpmm' +import { getCpmmProbability } from './calculate-cpmm' import { Binary, CPMM, DPM, FreeResponse, FullContract } from './contract' import { User } from './user' import { LiquidityProvision } from './liquidity-provision' @@ -9,42 +9,13 @@ import { noFees } from './fees' export const PHANTOM_ANTE = 0.001 export const MINIMUM_ANTE = 10 -export function getCpmmAnteBet( - creator: User, - contract: FullContract, - anteId: string, - amount: number, - outcome: 'YES' | 'NO' -) { - const p = getCpmmProbability(contract.pool) - - const { createdTime } = contract - - const bet: Bet = { - id: anteId, - userId: creator.id, - contractId: contract.id, - amount: amount, - shares: amount, - outcome, - probBefore: p, - probAfter: p, - createdTime, - isAnte: true, - fees: noFees, - } - - return bet -} - export function getCpmmInitialLiquidity( creator: User, contract: FullContract, anteId: string, amount: number ) { - const { createdTime, pool } = contract - const liquidity = getCpmmLiquidity(pool) + const { createdTime, pool, p } = contract const lp: LiquidityProvision = { id: anteId, @@ -54,7 +25,8 @@ export function getCpmmInitialLiquidity( isAnte: true, amount: amount, - liquidity, + liquidity: amount, + probability: getCpmmProbability(pool, p), } return lp diff --git a/common/calculate-cpmm.ts b/common/calculate-cpmm.ts index 217258bc..a590a4aa 100644 --- a/common/calculate-cpmm.ts +++ b/common/calculate-cpmm.ts @@ -2,12 +2,14 @@ import * as _ from 'lodash' import { Bet } from './bet' import { Binary, CPMM, FullContract } from './contract' -import { CREATOR_FEE, Fees, LIQUIDITY_FEE, PLATFORM_FEE } from './fees' +import { CREATOR_FEE, Fees, LIQUIDITY_FEE, noFees, PLATFORM_FEE } from './fees' -export function getCpmmProbability(pool: { [outcome: string]: number }) { - // For binary contracts only. +export function getCpmmProbability( + pool: { [outcome: string]: number }, + p: number +) { const { YES, NO } = pool - return NO / (YES + NO) + return (p * NO) / ((1 - p) * YES + p * NO) } export function getCpmmOutcomeProbabilityAfterBet( @@ -16,7 +18,7 @@ export function getCpmmOutcomeProbabilityAfterBet( bet: number ) { const { newPool } = calculateCpmmPurchase(contract, bet, outcome) - const p = getCpmmProbability(newPool) + const p = getCpmmProbability(newPool, contract.p) return outcome === 'NO' ? 1 - p : p } @@ -25,14 +27,17 @@ function calculateCpmmShares( pool: { [outcome: string]: number }, + p: number, bet: number, betChoice: string ) { const { YES: y, NO: n } = pool - const numerator = bet ** 2 + bet * (y + n) - const denominator = betChoice === 'YES' ? bet + n : bet + y - const shares = numerator / denominator - return shares + const k = y ** (1 - p) * n ** p + + return betChoice === 'YES' + ? // https://www.wolframalpha.com/input?i=%28y%2Bb-s%29%5E%281-p%29*%28n%2Bb%29%5Ep+%3D+k%2C+solve+s + y + bet - (k * (bet + n) ** -p) ** (1 / (1 - p)) + : n + bet - (k * (bet + y) ** (p - 1)) ** (1 / p) } export function getCpmmLiquidityFee( @@ -40,7 +45,7 @@ export function getCpmmLiquidityFee( bet: number, outcome: string ) { - const p = getCpmmProbability(contract.pool) + const p = getCpmmProbability(contract.pool, contract.p) const betP = outcome === 'YES' ? 1 - p : p const liquidityFee = LIQUIDITY_FEE * betP * bet @@ -59,10 +64,10 @@ export function calculateCpmmSharesAfterFee( bet: number, outcome: string ) { - const { pool } = contract - const { remainingBet } = getCpmmLiquidityFee(contract, bet, outcome) + const { pool, p } = contract + // const { remainingBet } = getCpmmLiquidityFee(contract, bet, outcome) - return calculateCpmmShares(pool, remainingBet, outcome) + return calculateCpmmShares(pool, p, bet, outcome) } export function calculateCpmmPurchase( @@ -70,10 +75,12 @@ export function calculateCpmmPurchase( bet: number, outcome: string ) { - const { pool } = contract - const { remainingBet, fees } = getCpmmLiquidityFee(contract, bet, outcome) + const { pool, p } = contract + // const { remainingBet, fees } = getCpmmLiquidityFee(contract, bet, outcome) + const remainingBet = bet + const fees = noFees - const shares = calculateCpmmShares(pool, remainingBet, outcome) + const shares = calculateCpmmShares(pool, p, remainingBet, outcome) const { YES: y, NO: n } = pool const { liquidityFee: fee } = fees @@ -84,6 +91,7 @@ export function calculateCpmmPurchase( : [y + remainingBet + fee, n - shares + remainingBet + fee] const newPool = { YES: newY, NO: newN } + // console.log(getCpmmLiquidity(pool, p), getCpmmLiquidity(newPool, p)) return { shares, newPool, fees } } @@ -96,6 +104,7 @@ export function calculateCpmmShareValue( const { pool } = contract const { YES: y, NO: n } = pool + // TODO: calculate using new function const poolChange = outcome === 'YES' ? shares + y - n : shares + n - y const k = y * n const shareValue = 0.5 * (shares + y + n - Math.sqrt(4 * k + poolChange ** 2)) @@ -136,63 +145,57 @@ export function getCpmmProbabilityAfterSale( bet: Bet ) { const { newPool } = calculateCpmmSale(contract, bet) - return getCpmmProbability(newPool) + return getCpmmProbability(newPool, contract.p) } -export const calcCpmmInitialPool = (initialProbInt: number, ante: number) => { - const p = initialProbInt / 100.0 - - const [poolYes, poolNo] = - p >= 0.5 ? [ante * (1 / p - 1), ante] : [ante, ante * (1 / (1 - p) - 1)] - - return { poolYes, poolNo } -} - -export function getCpmmLiquidity(pool: { [outcome: string]: number }) { - // For binary contracts only. +export function getCpmmLiquidity( + pool: { [outcome: string]: number }, + p: number +) { const { YES, NO } = pool - return Math.sqrt(YES * NO) + return YES ** (1 - p) * NO ** p } -export function addCpmmLiquidity( - contract: FullContract, - amount: number -) { - const { YES, NO } = contract.pool - const p = getCpmmProbability({ YES, NO }) +// TODO: use new pricing equation +// export function addCpmmLiquidity( +// contract: FullContract, +// amount: number +// ) { +// const { YES, NO } = contract.pool +// const p = getCpmmProbability({ YES, NO }, contract.p) - const [newYes, newNo] = - p >= 0.5 - ? [amount * (1 / p - 1), amount] - : [amount, amount * (1 / (1 - p) - 1)] +// const [newYes, newNo] = +// p >= 0.5 +// ? [amount * (1 / p - 1), amount] +// : [amount, amount * (1 / (1 - p) - 1)] - const betAmount = Math.abs(newYes - newNo) - const betOutcome = p >= 0.5 ? 'YES' : 'NO' +// const betAmount = Math.abs(newYes - newNo) +// const betOutcome = p >= 0.5 ? 'YES' : 'NO' - const poolLiquidity = getCpmmLiquidity({ YES, NO }) - const newPool = { YES: YES + newYes, NO: NO + newNo } - const resultingLiquidity = getCpmmLiquidity(newPool) - const liquidity = resultingLiquidity - poolLiquidity +// const poolLiquidity = getCpmmLiquidity({ YES, NO }) +// const newPool = { YES: YES + newYes, NO: NO + newNo } +// const resultingLiquidity = getCpmmLiquidity(newPool) +// const liquidity = resultingLiquidity - poolLiquidity - return { newPool, liquidity, betAmount, betOutcome } -} +// return { newPool, liquidity, betAmount, betOutcome } +// } -export function removeCpmmLiquidity( - contract: FullContract, - liquidity: number -) { - const { YES, NO } = contract.pool - const poolLiquidity = getCpmmLiquidity({ YES, NO }) - const p = getCpmmProbability({ YES, NO }) +// export function removeCpmmLiquidity( +// contract: FullContract, +// liquidity: number +// ) { +// const { YES, NO } = contract.pool +// const poolLiquidity = getCpmmLiquidity({ YES, NO }) +// const p = getCpmmProbability({ YES, NO }, contract.p) - const f = liquidity / poolLiquidity - const [payoutYes, payoutNo] = [f * YES, f * NO] +// const f = liquidity / poolLiquidity +// const [payoutYes, payoutNo] = [f * YES, f * NO] - const betAmount = Math.abs(payoutYes - payoutNo) - const betOutcome = p >= 0.5 ? 'NO' : 'YES' // opposite side as adding liquidity - const payout = Math.min(payoutYes, payoutNo) +// const betAmount = Math.abs(payoutYes - payoutNo) +// const betOutcome = p >= 0.5 ? 'NO' : 'YES' // opposite side as adding liquidity +// const payout = Math.min(payoutYes, payoutNo) - const newPool = { YES: YES - payoutYes, NO: NO - payoutNo } +// const newPool = { YES: YES - payoutYes, NO: NO - payoutNo } - return { newPool, payout, betAmount, betOutcome } -} +// return { newPool, payout, betAmount, betOutcome } +// } diff --git a/common/calculate.ts b/common/calculate.ts index 323e8027..3bf57c2b 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -21,7 +21,7 @@ import { Binary, Contract, CPMM, DPM, FullContract } from './contract' export function getProbability(contract: FullContract) { return contract.mechanism === 'cpmm-1' - ? getCpmmProbability(contract.pool) + ? getCpmmProbability(contract.pool, contract.p) : getDpmProbability(contract.totalShares) } @@ -31,14 +31,14 @@ export function getInitialProbability( return ( contract.initialProbability ?? (contract.mechanism === 'cpmm-1' - ? getCpmmProbability(contract.pool) + ? getCpmmProbability(contract.pool, contract.p) : getDpmProbability(contract.phantomShares ?? contract.totalShares)) ) } export function getOutcomeProbability(contract: Contract, outcome: string) { return contract.mechanism === 'cpmm-1' - ? getCpmmProbability(contract.pool) + ? getCpmmProbability(contract.pool, contract.p) : getDpmOutcomeProbability(contract.totalShares, outcome) } diff --git a/common/contract.ts b/common/contract.ts index 445f6212..f92e948a 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -49,6 +49,7 @@ export type DPM = { export type CPMM = { mechanism: 'cpmm-1' + p: number // probability constant in y^(1-p) * n^p = k pool: { [outcome: string]: number } } diff --git a/common/liquidity-provision.ts b/common/liquidity-provision.ts index 27ba280f..d3b960a5 100644 --- a/common/liquidity-provision.ts +++ b/common/liquidity-provision.ts @@ -8,4 +8,5 @@ export type LiquidityProvision = { amount: number // M$ quantity liquidity: number // sqrt(k) + probability: number } diff --git a/common/new-bet.ts b/common/new-bet.ts index 6f3126b5..c8a580bd 100644 --- a/common/new-bet.ts +++ b/common/new-bet.ts @@ -34,8 +34,9 @@ export const getNewBinaryCpmmBetInfo = ( const newBalance = user.balance - (amount - loanAmount) - const probBefore = getCpmmProbability(contract.pool) - const probAfter = getCpmmProbability(newPool) + const { pool, p } = contract + const probBefore = getCpmmProbability(pool, p) + const probAfter = getCpmmProbability(newPool, p) const newBet: Bet = { id: newBetId, diff --git a/common/new-contract.ts b/common/new-contract.ts index 2a57a5af..13ebf8ff 100644 --- a/common/new-contract.ts +++ b/common/new-contract.ts @@ -10,7 +10,6 @@ import { import { User } from './user' import { parseTags } from './util/parse' import { removeUndefinedProps } from './util/object' -import { calcCpmmInitialPool } from './calculate-cpmm' import { calcDpmInitialPool } from './calculate-dpm' export function getNewContract( @@ -86,13 +85,14 @@ const getBinaryDpmProps = (initialProb: number, ante: number) => { } const getBinaryCpmmProps = (initialProb: number, ante: number) => { - const { poolYes, poolNo } = calcCpmmInitialPool(initialProb, ante) - const pool = { YES: poolYes, NO: poolNo } + const pool = { YES: ante, NO: ante } + const p = initialProb / 100 const system: CPMM & Binary = { mechanism: 'cpmm-1', outcomeType: 'BINARY', - initialProbability: initialProb / 100, + initialProbability: p, + p, pool: pool, } diff --git a/common/sell-bet.ts b/common/sell-bet.ts index 8f8a74f1..246e8649 100644 --- a/common/sell-bet.ts +++ b/common/sell-bet.ts @@ -89,13 +89,13 @@ export const getCpmmSellBetInfo = ( contract: FullContract, newBetId: string ) => { - const { pool } = contract + const { pool, p } = contract const { id: betId, amount, shares, outcome } = bet const { saleValue, newPool, fees } = calculateCpmmSale(contract, bet) - const probBefore = getCpmmProbability(pool) - const probAfter = getCpmmProbability(newPool) + const probBefore = getCpmmProbability(pool, p) + const probAfter = getCpmmProbability(newPool, p) console.log( 'SELL M$', diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index 4762a03e..85bc211d 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -20,7 +20,6 @@ import { randomString } from '../../common/util/random' import { getNewContract } from '../../common/new-contract' import { getAnteBets, - getCpmmAnteBet, getCpmmInitialLiquidity, getFreeAnswerAnte, MINIMUM_ANTE, @@ -131,27 +130,6 @@ export const createContract = functions await yesBetDoc.set(yesBet) await noBetDoc.set(noBet) } else if (outcomeType === 'BINARY') { - const { YES: y, NO: n } = contract.pool - const anteBet = Math.abs(y - n) - - if (anteBet) { - const betDoc = firestore - .collection(`contracts/${contract.id}/bets`) - .doc() - - const outcome = y > n ? 'NO' : 'YES' // more in YES pool if prob leans NO - - const bet = getCpmmAnteBet( - creator, - contract as FullContract, - betDoc.id, - anteBet, - outcome - ) - - await betDoc.set(bet) - } - const liquidityDoc = firestore .collection(`contracts/${contract.id}/liquidity`) .doc() diff --git a/web/components/contract-card.tsx b/web/components/contract-card.tsx index 0bea1ec3..1e36fb6b 100644 --- a/web/components/contract-card.tsx +++ b/web/components/contract-card.tsx @@ -20,7 +20,6 @@ import { Avatar } from './avatar' import { Spacer } from './layout/spacer' import { useState } from 'react' import { TweetButton } from './tweet-button' -import { getCpmmLiquidity } from '../../common/calculate-cpmm' export function ContractCard(props: { contract: Contract diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts index 9b84090c..657d134e 100644 --- a/web/lib/firebase/contracts.ts +++ b/web/lib/firebase/contracts.ts @@ -43,17 +43,17 @@ export function contractMetrics(contract: Contract) { const liquidityLabel = contract.mechanism === 'dpm-2' ? `${formatMoney(truePool)} pool` - : `${formatMoney(getCpmmLiquidity(contract.pool))} liquidity` + : `${formatMoney(getCpmmLiquidity(pool, contract.p))} liquidity` return { truePool, liquidityLabel, createdDate, resolvedDate } } export function getBinaryProbPercent(contract: FullContract) { - const { totalShares, pool, resolutionProbability, mechanism } = contract + const { totalShares, pool, p, resolutionProbability, mechanism } = contract const prob = resolutionProbability ?? mechanism === 'cpmm-1' - ? getCpmmProbability(pool) + ? getCpmmProbability(pool, p) : getDpmProbability(totalShares) const probPercent = Math.round(prob * 100) + '%'