manifold/common/new-bet.ts
James Grugett 76f27d1a93
Numeric range markets!! (#146)
* Numeric contract type

* Create market numeric type

* Add numeric graph (coded without testing)

* Outline of numeric bet panel

* Update bet panel logic

* create numeric contracts

* remove batching for antes for numeric markets

* Remove focus

* numeric market range [1, 100]

* Zoom graph

* Hide bet panels

* getNumericBets

* Add numeric resolution panel

* Use getNumericBets in bet panel calc

* Switch bucket count to 100

* Parallelize ante creation

* placeBet for numeric markets

* halve std of numeric bets

* Update resolveMarket with numeric type

* Set min and max for contract

* lower std for numeric bets

* calculateNumericDpmShares: use sorted order

* Use min and max to map the input

* Fix probability calc

* normpdf variance mislabeled

* range input

* merge

* change numeric graph color

* fix getNewContract params

* bet panel labels

* validation

* number input

* fix bucketing

* bucket input, numeric resolution panel

* outcome label

* merge

* numeric bet panel on mobile

* Make text underneath filled green answer bar selectable

* Default to 'all' feed category when loading page.

* fix numeric resolution panel

* fix numeric bet panel calculations

* display numeric resolution

* don't render NumericBetPanel for non numeric markets

* numeric bets: store shares, bet amounts across buckets in each bet object

* restore your bets for numeric markets

* numeric pnl calculations

* remove hasUserHitManaLimit

* contrain contract type

* handle undefined allOutcomeShares

* numeric ante bet amount

* use correct amount for numeric dpm payouts

* change numeric graph/outcome color

* numeric constants

* hack to show correct numeric payout in calculateDpmPayoutAfterCorrectBet

* remove comment

* fix ante display in bet list

* halve bucket count

* cast to NumericContract

* fix merge imports

* OUTCOME_TYPES

* typo

* lower bucket count to 200

* store raw numeric value with bet

* store raw numeric resolution value

* number input max length

* create page: min, max to undefined if not numeric market

* numeric resolution formatting

* expected value for numeric markets

* expected value for numeric markets

* rearrange lines for readability

* move normalpdf to util/math

* show bets tab

* check if outcomeMode is undefined

* remove extraneous auto-merge cruft

* hide comment status for numeric markets

* import

Co-authored-by: mantikoros <sgrugett@gmail.com>
2022-05-19 12:42:03 -05:00

220 lines
5.5 KiB
TypeScript

import * as _ from 'lodash'
import { Bet, MAX_LOAN_PER_CONTRACT, NumericBet } from './bet'
import {
calculateDpmShares,
getDpmProbability,
getDpmOutcomeProbability,
getNumericBets,
calculateNumericDpmShares,
} from './calculate-dpm'
import { calculateCpmmPurchase, getCpmmProbability } from './calculate-cpmm'
import {
Binary,
CPMM,
DPM,
FreeResponse,
FullContract,
Multi,
NumericContract,
} from './contract'
import { User } from './user'
import { noFees } from './fees'
import { addObjects } from './util/object'
import { NUMERIC_FIXED_VAR } from './numeric-constants'
export const getNewBinaryCpmmBetInfo = (
user: User,
outcome: 'YES' | 'NO',
amount: number,
contract: FullContract<CPMM, Binary>,
loanAmount: number,
newBetId: string
) => {
const { shares, newPool, newP, fees } = calculateCpmmPurchase(
contract,
amount,
outcome
)
const newBalance = user.balance - (amount - loanAmount)
const { pool, p, totalLiquidity } = contract
const probBefore = getCpmmProbability(pool, p)
const probAfter = getCpmmProbability(newPool, newP)
const newBet: Bet = {
id: newBetId,
userId: user.id,
contractId: contract.id,
amount,
shares,
outcome,
fees,
loanAmount,
probBefore,
probAfter,
createdTime: Date.now(),
}
const { liquidityFee } = fees
const newTotalLiquidity = (totalLiquidity ?? 0) + liquidityFee
return { newBet, newPool, newP, newBalance, newTotalLiquidity, fees }
}
export const getNewBinaryDpmBetInfo = (
user: User,
outcome: 'YES' | 'NO',
amount: number,
contract: FullContract<DPM, Binary>,
loanAmount: number,
newBetId: string
) => {
const { YES: yesPool, NO: noPool } = contract.pool
const newPool =
outcome === 'YES'
? { YES: yesPool + amount, NO: noPool }
: { YES: yesPool, NO: noPool + amount }
const shares = calculateDpmShares(contract.totalShares, amount, outcome)
const { YES: yesShares, NO: noShares } = contract.totalShares
const newTotalShares =
outcome === 'YES'
? { YES: yesShares + shares, NO: noShares }
: { YES: yesShares, NO: noShares + shares }
const { YES: yesBets, NO: noBets } = contract.totalBets
const newTotalBets =
outcome === 'YES'
? { YES: yesBets + amount, NO: noBets }
: { YES: yesBets, NO: noBets + amount }
const probBefore = getDpmProbability(contract.totalShares)
const probAfter = getDpmProbability(newTotalShares)
const newBet: Bet = {
id: newBetId,
userId: user.id,
contractId: contract.id,
amount,
loanAmount,
shares,
outcome,
probBefore,
probAfter,
createdTime: Date.now(),
fees: noFees,
}
const newBalance = user.balance - (amount - loanAmount)
return { newBet, newPool, newTotalShares, newTotalBets, newBalance }
}
export const getNewMultiBetInfo = (
user: User,
outcome: string,
amount: number,
contract: FullContract<DPM, Multi | FreeResponse>,
loanAmount: number,
newBetId: string
) => {
const { pool, totalShares, totalBets } = contract
const prevOutcomePool = pool[outcome] ?? 0
const newPool = { ...pool, [outcome]: prevOutcomePool + amount }
const shares = calculateDpmShares(contract.totalShares, amount, outcome)
const prevShares = totalShares[outcome] ?? 0
const newTotalShares = { ...totalShares, [outcome]: prevShares + shares }
const prevTotalBets = totalBets[outcome] ?? 0
const newTotalBets = { ...totalBets, [outcome]: prevTotalBets + amount }
const probBefore = getDpmOutcomeProbability(totalShares, outcome)
const probAfter = getDpmOutcomeProbability(newTotalShares, outcome)
const newBet: Bet = {
id: newBetId,
userId: user.id,
contractId: contract.id,
amount,
loanAmount,
shares,
outcome,
probBefore,
probAfter,
createdTime: Date.now(),
fees: noFees,
}
const newBalance = user.balance - (amount - loanAmount)
return { newBet, newPool, newTotalShares, newTotalBets, newBalance }
}
export const getNumericBetsInfo = (
user: User,
value: number,
outcome: string,
amount: number,
contract: NumericContract,
newBetId: string
) => {
const { pool, totalShares, totalBets } = contract
const bets = getNumericBets(contract, outcome, amount, NUMERIC_FIXED_VAR)
const allBetAmounts = Object.fromEntries(bets)
const newTotalBets = addObjects(totalBets, allBetAmounts)
const newPool = addObjects(pool, allBetAmounts)
const { shares, totalShares: newTotalShares } = calculateNumericDpmShares(
contract.totalShares,
bets
)
const allOutcomeShares = Object.fromEntries(
bets.map(([outcome], i) => [outcome, shares[i]])
)
const probBefore = getDpmOutcomeProbability(totalShares, outcome)
const probAfter = getDpmOutcomeProbability(newTotalShares, outcome)
const newBet: NumericBet = {
id: newBetId,
userId: user.id,
contractId: contract.id,
value,
amount,
allBetAmounts,
shares: shares.find((s, i) => bets[i][0] === outcome) ?? 0,
allOutcomeShares,
outcome,
probBefore,
probAfter,
createdTime: Date.now(),
fees: noFees,
}
const newBalance = user.balance - amount
return { newBet, newPool, newTotalShares, newTotalBets, newBalance }
}
export const getLoanAmount = (yourBets: Bet[], newBetAmount: number) => {
const openBets = yourBets.filter((bet) => !bet.isSold && !bet.sale)
const prevLoanAmount = _.sumBy(openBets, (bet) => bet.loanAmount ?? 0)
const loanAmount = Math.min(
newBetAmount,
MAX_LOAN_PER_CONTRACT - prevLoanAmount
)
return loanAmount
}