From 389e11db48d14c4767b140adee1fe0f776caac07 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Sat, 1 Jan 2022 18:22:18 -0600 Subject: [PATCH] enable resolve MKT --- functions/src/resolve-market.ts | 2 +- web/components/bets-list.tsx | 7 ++- web/components/contract-overview.tsx | 1 + web/components/contracts-list.tsx | 2 + web/components/resolution-panel.tsx | 11 ++++- web/components/yes-no-selector.tsx | 68 +++++++++++++++++----------- web/lib/calculate.ts | 27 +++++++---- web/lib/firebase/init.ts | 4 +- 8 files changed, 81 insertions(+), 41 deletions(-) diff --git a/functions/src/resolve-market.ts b/functions/src/resolve-market.ts index 845a26fc..dec3b52b 100644 --- a/functions/src/resolve-market.ts +++ b/functions/src/resolve-market.ts @@ -24,7 +24,7 @@ export const resolveMarket = functions const { outcome, contractId } = data - if (!['YES', 'NO', 'CANCEL'].includes(outcome)) + if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome)) return { status: 'error', message: 'Invalid outcome' } const contractDoc = firestore.doc(`contracts/${contractId}`) diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx index 18c74563..c132123d 100644 --- a/web/components/bets-list.tsx +++ b/web/components/bets-list.tsx @@ -357,11 +357,12 @@ function SellButton(props: { contract: Contract; bet: Bet }) { ) } -function OutcomeLabel(props: { outcome: 'YES' | 'NO' | 'CANCEL' }) { +function OutcomeLabel(props: { outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT' }) { const { outcome } = props if (outcome === 'YES') return if (outcome === 'NO') return + if (outcome === 'MKT') return return } @@ -376,3 +377,7 @@ function NoLabel() { function CancelLabel() { return N/A } + +function MarketLabel() { + return MKT +} diff --git a/web/components/contract-overview.tsx b/web/components/contract-overview.tsx index aa8dfe6c..ec2fc4cb 100644 --- a/web/components/contract-overview.tsx +++ b/web/components/contract-overview.tsx @@ -98,6 +98,7 @@ export const ContractOverview = (props: { const resolutionColor = { YES: 'text-primary', NO: 'text-red-400', + MKT: 'text-blue-400', CANCEL: 'text-yellow-400', '': '', // Empty if unresolved }[contract.resolution || ''] diff --git a/web/components/contracts-list.tsx b/web/components/contracts-list.tsx index 07c052b0..dc83bafb 100644 --- a/web/components/contracts-list.tsx +++ b/web/components/contracts-list.tsx @@ -44,6 +44,7 @@ function ContractCard(props: { contract: Contract }) { const resolutionColor = { YES: 'text-primary', NO: 'text-red-400', + MKT: 'text-blue-400', CANCEL: 'text-yellow-400', '': '', // Empty if unresolved }[contract.resolution || ''] @@ -51,6 +52,7 @@ function ContractCard(props: { contract: Contract }) { const resolutionText = { YES: 'YES', NO: 'NO', + MKT: 'MKT', CANCEL: 'N/A', '': '', }[contract.resolution || ''] diff --git a/web/components/resolution-panel.tsx b/web/components/resolution-panel.tsx index 7f9f74c6..d5ccbfd5 100644 --- a/web/components/resolution-panel.tsx +++ b/web/components/resolution-panel.tsx @@ -20,7 +20,9 @@ export function ResolutionPanel(props: { }) { const { contract, className } = props - const [outcome, setOutcome] = useState<'YES' | 'NO' | 'CANCEL' | undefined>() + const [outcome, setOutcome] = useState< + 'YES' | 'NO' | 'MKT' | 'CANCEL' | undefined + >() const [isSubmitting, setIsSubmitting] = useState(false) const [error, setError] = useState(undefined) @@ -48,6 +50,8 @@ export function ResolutionPanel(props: { ? 'bg-red-400 hover:bg-red-500' : outcome === 'CANCEL' ? 'bg-yellow-400 hover:bg-yellow-500' + : outcome === 'MKT' + ? 'bg-blue-400 hover:bg-blue-500' : 'btn-disabled' return ( @@ -74,6 +78,11 @@ export function ResolutionPanel(props: { <>Winnings will be paid out to NO bettors. You earn 1% of the pool. ) : outcome === 'CANCEL' ? ( <>The pool will be returned to traders with no fees. + ) : outcome === 'MKT' ? ( + <> + Traders will be paid out at the current implied probability. You + earn 1% of the pool. + ) : ( <>Resolving this market will immediately pay out traders. )} diff --git a/web/components/yes-no-selector.tsx b/web/components/yes-no-selector.tsx index 391db469..528b199d 100644 --- a/web/components/yes-no-selector.tsx +++ b/web/components/yes-no-selector.tsx @@ -1,5 +1,6 @@ import clsx from 'clsx' import React from 'react' +import { Col } from './layout/col' import { Row } from './layout/row' export function YesNoSelector(props: { @@ -29,48 +30,60 @@ export function YesNoSelector(props: { } export function YesNoCancelSelector(props: { - selected: 'YES' | 'NO' | 'CANCEL' | undefined - onSelect: (selected: 'YES' | 'NO' | 'CANCEL') => void + selected: 'YES' | 'NO' | 'MKT' | 'CANCEL' | undefined + onSelect: (selected: 'YES' | 'NO' | 'MKT' | 'CANCEL') => void className?: string btnClassName?: string }) { const { selected, onSelect, className } = props - const btnClassName = clsx('px-6', props.btnClassName) + const btnClassName = clsx('px-6 flex-1', props.btnClassName) return ( - - + + + - + + - - + + + + + + ) } function Button(props: { className?: string onClick?: () => void - color: 'green' | 'red' | 'yellow' | 'gray' + color: 'green' | 'red' | 'blue' | 'yellow' | 'gray' children?: any }) { const { className, onClick, children, color } = props @@ -83,6 +96,7 @@ function Button(props: { color === 'green' && 'btn-primary', color === 'red' && 'bg-red-400 hover:bg-red-500', color === 'yellow' && 'bg-yellow-400 hover:bg-yellow-500', + color === 'blue' && 'bg-blue-400 hover:bg-blue-500', color === 'gray' && 'text-gray-700 bg-gray-300 hover:bg-gray-400', className )} diff --git a/web/lib/calculate.ts b/web/lib/calculate.ts index 0fd1b7a7..d13f3484 100644 --- a/web/lib/calculate.ts +++ b/web/lib/calculate.ts @@ -37,27 +37,36 @@ export function calculateShares( export function calculatePayout( contract: Contract, bet: Bet, - outcome: 'YES' | 'NO' | 'CANCEL' + outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT' ) { const { amount, outcome: betOutcome, shares } = bet if (outcome === 'CANCEL') return amount - if (betOutcome !== outcome) return 0 + + const impliedProbabilility = + contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2) + + const p = + outcome === 'MKT' + ? betOutcome === 'YES' + ? impliedProbabilility + : 1 - impliedProbabilility + : outcome === 'YES' + ? 1 + : 0 const { totalShares, totalBets } = contract - if (totalShares[outcome] === 0) return 0 - const startPool = contract.startPool.YES + contract.startPool.NO const truePool = contract.pool.YES + contract.pool.NO - startPool - if (totalBets[outcome] <= truePool) - return (amount / totalBets[outcome]) * truePool + if (totalBets[betOutcome] <= truePool) + return p * (amount / totalBets[betOutcome]) * truePool - const total = totalShares[outcome] - totalBets[outcome] - const winningsPool = truePool - totalBets[outcome] + const total = totalShares[betOutcome] - totalBets[betOutcome] + const winningsPool = truePool - totalBets[betOutcome] - return (1 - fees) * (amount + ((shares - amount) / total) * winningsPool) + return p * (1 - fees) * (amount + ((shares - amount) / total) * winningsPool) } export function resolvedPayout(contract: Contract, bet: Bet) { diff --git a/web/lib/firebase/init.ts b/web/lib/firebase/init.ts index 98734946..ba10545a 100644 --- a/web/lib/firebase/init.ts +++ b/web/lib/firebase/init.ts @@ -2,8 +2,8 @@ import { getFirestore } from '@firebase/firestore' import { initializeApp } from 'firebase/app' // TODO: Reenable this when we have a way to set the Firebase db in dev -// export const isProd = process.env.NODE_ENV === 'production' -export const isProd = true +export const isProd = process.env.NODE_ENV === 'production' +// export const isProd = true const firebaseConfig = isProd ? {