new cfmm: k = y^(1-p) * n^p
This commit is contained in:
parent
bb8f7cc966
commit
062d4f88fd
|
@ -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<CPMM, Binary>,
|
||||
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<CPMM, Binary>,
|
||||
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
|
||||
|
|
|
@ -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<CPMM, Binary>,
|
||||
amount: number
|
||||
) {
|
||||
const { YES, NO } = contract.pool
|
||||
const p = getCpmmProbability({ YES, NO })
|
||||
// TODO: use new pricing equation
|
||||
// export function addCpmmLiquidity(
|
||||
// contract: FullContract<CPMM, Binary>,
|
||||
// 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<CPMM, Binary>,
|
||||
liquidity: number
|
||||
) {
|
||||
const { YES, NO } = contract.pool
|
||||
const poolLiquidity = getCpmmLiquidity({ YES, NO })
|
||||
const p = getCpmmProbability({ YES, NO })
|
||||
// export function removeCpmmLiquidity(
|
||||
// contract: FullContract<CPMM, Binary>,
|
||||
// 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 }
|
||||
// }
|
||||
|
|
|
@ -21,7 +21,7 @@ import { Binary, Contract, CPMM, DPM, FullContract } from './contract'
|
|||
|
||||
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -8,4 +8,5 @@ export type LiquidityProvision = {
|
|||
|
||||
amount: number // M$ quantity
|
||||
liquidity: number // sqrt(k)
|
||||
probability: number
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -89,13 +89,13 @@ export const getCpmmSellBetInfo = (
|
|||
contract: FullContract<CPMM, Binary>,
|
||||
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$',
|
||||
|
|
|
@ -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<CPMM, Binary>,
|
||||
betDoc.id,
|
||||
anteBet,
|
||||
outcome
|
||||
)
|
||||
|
||||
await betDoc.set(bet)
|
||||
}
|
||||
|
||||
const liquidityDoc = firestore
|
||||
.collection(`contracts/${contract.id}/liquidity`)
|
||||
.doc()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<any, Binary>) {
|
||||
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) + '%'
|
||||
|
|
Loading…
Reference in New Issue
Block a user