resolve to PROB

This commit is contained in:
mantikoros 2022-01-30 00:22:01 -06:00
parent a3011d1da7
commit 97c8b86259
8 changed files with 89 additions and 19 deletions

View File

@ -174,7 +174,10 @@ export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) {
}
function calculateMktPayout(contract: Contract, bet: Bet) {
const p = getProbability(contract.totalShares)
const p =
contract.resolutionProbability !== undefined
? contract.resolutionProbability
: getProbability(contract.totalShares)
const weightedTotal =
p * contract.totalBets.YES + (1 - p) * contract.totalBets.NO

View File

@ -27,6 +27,7 @@ export type Contract = {
isResolved: boolean
resolutionTime?: number // When the contract creator resolved the market
resolution?: outcome // Chosen by creator; must be one of outcomes
resolutionProbability?: number
volume24Hours: number
volume7Days: number

View File

@ -59,8 +59,16 @@ export const getStandardPayouts = (
]) // add creator fee
}
export const getMktPayouts = (contract: Contract, bets: Bet[]) => {
const p = getProbability(contract.totalShares)
export const getMktPayouts = (
contract: Contract,
bets: Bet[],
resolutionProbability?: number
) => {
const p =
resolutionProbability === undefined
? getProbability(contract.totalShares)
: resolutionProbability
const poolTotal = contract.pool.YES + contract.pool.NO
console.log('Resolved MKT at p=', p, 'pool: $M', poolTotal)
@ -116,14 +124,15 @@ export const getMktPayouts = (contract: Contract, bets: Bet[]) => {
export const getPayouts = (
outcome: outcome,
contract: Contract,
bets: Bet[]
bets: Bet[],
resolutionProbability?: number
) => {
switch (outcome) {
case 'YES':
case 'NO':
return getStandardPayouts(outcome, contract, bets)
case 'MKT':
return getMktPayouts(contract, bets)
return getMktPayouts(contract, bets, resolutionProbability)
case 'CANCEL':
return getCancelPayouts(contract, bets)
}

View File

@ -20,7 +20,8 @@ export const sendMarketResolutionEmail = async (
payout: number,
creator: User,
contract: Contract,
resolution: 'YES' | 'NO' | 'CANCEL' | 'MKT'
resolution: 'YES' | 'NO' | 'CANCEL' | 'MKT',
resolutionProbability?: number
) => {
const privateUser = await getPrivateUser(userId)
if (
@ -33,8 +34,15 @@ export const sendMarketResolutionEmail = async (
const user = await getUser(userId)
if (!user) return
const prob = formatPercent(getProbability(contract.totalShares))
const outcome = toDisplayResolution[resolution].replace('PROB', prob)
const prob = resolutionProbability ?? getProbability(contract.totalShares)
const toDisplayResolution = {
YES: 'YES',
NO: 'NO',
CANCEL: 'N/A',
MKT: formatPercent(prob),
}
const outcome = toDisplayResolution[resolution]
const subject = `Resolved ${outcome}: ${contract.question}`
@ -59,5 +67,3 @@ export const sendMarketResolutionEmail = async (
templateData
)
}
const toDisplayResolution = { YES: 'YES', NO: 'NO', CANCEL: 'N/A', MKT: 'PROB' }

View File

@ -16,17 +16,24 @@ export const resolveMarket = functions
data: {
outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT'
contractId: string
probabilityInt?: number
},
context
) => {
const userId = context?.auth?.uid
if (!userId) return { status: 'error', message: 'Not authorized' }
const { outcome, contractId } = data
const { outcome, contractId, probabilityInt } = data
if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome))
return { status: 'error', message: 'Invalid outcome' }
if (
probabilityInt !== undefined &&
(probabilityInt < 1 || probabilityInt > 99 || !isFinite(probabilityInt))
)
return { status: 'error', message: 'Invalid probability' }
const contractDoc = firestore.doc(`contracts/${contractId}`)
const contractSnap = await contractDoc.get()
if (!contractSnap.exists)
@ -42,10 +49,16 @@ export const resolveMarket = functions
const creator = await getUser(contract.creatorId)
if (!creator) return { status: 'error', message: 'Creator not found' }
const resolutionProbability =
probabilityInt !== undefined ? probabilityInt / 100 : undefined
await contractDoc.update({
isResolved: true,
resolution: outcome,
resolutionTime: Date.now(),
...(resolutionProbability === undefined
? {}
: { resolutionProbability }),
})
console.log('contract ', contractId, 'resolved to:', outcome)
@ -57,7 +70,12 @@ export const resolveMarket = functions
const bets = betsSnap.docs.map((doc) => doc.data() as Bet)
const openBets = bets.filter((b) => !b.isSold && !b.sale)
const payouts = getPayouts(outcome, contract, openBets)
const payouts = getPayouts(
outcome,
contract,
openBets,
resolutionProbability
)
console.log('payouts:', payouts)
@ -79,7 +97,8 @@ export const resolveMarket = functions
userPayouts,
creator,
contract,
outcome
outcome,
resolutionProbability
)
return result
@ -91,7 +110,8 @@ const sendResolutionEmails = async (
userPayouts: { [userId: string]: number },
creator: User,
contract: Contract,
outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT'
outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT',
resolutionProbability?: number
) => {
const nonWinners = _.difference(
_.uniq(openBets.map(({ userId }) => userId)),
@ -103,7 +123,14 @@ const sendResolutionEmails = async (
]
await Promise.all(
emailPayouts.map(([userId, payout]) =>
sendMarketResolutionEmail(userId, payout, creator, contract, outcome)
sendMarketResolutionEmail(
userId,
payout,
creator,
contract,
outcome,
resolutionProbability
)
)
)
}

View File

@ -9,6 +9,8 @@ import { YesNoCancelSelector } from './yes-no-selector'
import { Spacer } from './layout/spacer'
import { ConfirmationButton as ConfirmationButton } from './confirmation-button'
import { resolveMarket } from '../lib/firebase/api-call'
import { ProbabilitySelector } from './probability-selector'
import { getProbability } from '../../common/calculate'
export function ResolutionPanel(props: {
creator: User
@ -26,6 +28,8 @@ export function ResolutionPanel(props: {
'YES' | 'NO' | 'MKT' | 'CANCEL' | undefined
>()
const [prob, setProb] = useState(getProbability(contract.totalShares) * 100)
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState<string | undefined>(undefined)
@ -35,6 +39,7 @@ export function ResolutionPanel(props: {
const result = await resolveMarket({
outcome,
contractId: contract.id,
probabilityInt: prob,
}).then((r) => r.data as any)
console.log('resolved', outcome, 'result:', result)
@ -113,7 +118,20 @@ export function ResolutionPanel(props: {
}}
onSubmit={resolve}
>
<p>Are you sure you want to resolve this market?</p>
{outcome === 'MKT' ? (
<>
<p className="mb-4">
What probability would you like to resolve the market to?
</p>
<ProbabilitySelector
probabilityInt={Math.round(prob)}
setProbabilityInt={setProb}
/>
</>
) : (
<p>Are you sure you want to resolve this market?</p>
)}
</ConfirmationButton>
</Col>
)

View File

@ -35,10 +35,11 @@ export function contractMetrics(contract: Contract) {
createdTime,
resolutionTime,
isResolved,
resolutionProbability,
} = contract
const truePool = pool.YES + pool.NO
const prob = getProbability(totalShares)
const prob = resolutionProbability ?? getProbability(totalShares)
const probPercent = Math.round(prob * 100) + '%'
const startProb = getProbability(phantomShares)

View File

@ -27,13 +27,18 @@ export function scoreTraders(contracts: Contract[], bets: Bet[][]) {
}
function scoreUsersByContract(contract: Contract, bets: Bet[]) {
const { resolution } = contract
const { resolution, resolutionProbability } = contract
const [closedBets, openBets] = _.partition(
bets,
(bet) => bet.isSold || bet.sale
)
const resolvePayouts = getPayouts(resolution ?? 'MKT', contract, openBets)
const resolvePayouts = getPayouts(
resolution ?? 'MKT',
contract,
openBets,
resolutionProbability
)
const salePayouts = closedBets.map((bet) => {
const { userId, sale } = bet