graph and bet panel for pseudo numeric
This commit is contained in:
parent
a1bdf552c0
commit
0ee6dfae94
|
@ -14,6 +14,7 @@ import {
|
|||
DPMBinaryContract,
|
||||
FreeResponseContract,
|
||||
NumericContract,
|
||||
PseudoNumericContract,
|
||||
} from './contract'
|
||||
import { noFees } from './fees'
|
||||
import { addObjects } from './util/object'
|
||||
|
@ -32,7 +33,7 @@ export type BetInfo = {
|
|||
export const getNewBinaryCpmmBetInfo = (
|
||||
outcome: 'YES' | 'NO',
|
||||
amount: number,
|
||||
contract: CPMMBinaryContract,
|
||||
contract: CPMMBinaryContract | PseudoNumericContract,
|
||||
loanAmount: number
|
||||
) => {
|
||||
const { shares, newPool, newP, fees } = calculateCpmmPurchase(
|
||||
|
|
|
@ -70,7 +70,10 @@ export const placebet = newEndpoint(['POST'], async (req, auth) => {
|
|||
if (outcomeType == 'BINARY' && mechanism == 'dpm-2') {
|
||||
const { outcome } = validate(binarySchema, req.body)
|
||||
return getNewBinaryDpmBetInfo(outcome, amount, contract, loanAmount)
|
||||
} else if (outcomeType == 'BINARY' && mechanism == 'cpmm-1') {
|
||||
} else if (
|
||||
(outcomeType == 'BINARY' || outcomeType == 'PSEUDO_NUMERIC') &&
|
||||
mechanism == 'cpmm-1'
|
||||
) {
|
||||
const { outcome } = validate(binarySchema, req.body)
|
||||
return getNewBinaryCpmmBetInfo(outcome, amount, contract, loanAmount)
|
||||
} else if (outcomeType == 'FREE_RESPONSE' && mechanism == 'dpm-2') {
|
||||
|
|
|
@ -3,7 +3,11 @@ import React, { useEffect, useState } from 'react'
|
|||
import { partition, sumBy } from 'lodash'
|
||||
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { BinaryContract, CPMMBinaryContract } from 'common/contract'
|
||||
import {
|
||||
BinaryContract,
|
||||
CPMMBinaryContract,
|
||||
PseudoNumericContract,
|
||||
} from 'common/contract'
|
||||
import { Col } from './layout/col'
|
||||
import { Row } from './layout/row'
|
||||
import { Spacer } from './layout/spacer'
|
||||
|
@ -190,12 +194,13 @@ export function BetPanelSwitcher(props: {
|
|||
}
|
||||
|
||||
function BuyPanel(props: {
|
||||
contract: BinaryContract
|
||||
contract: BinaryContract | PseudoNumericContract
|
||||
user: User | null | undefined
|
||||
selected?: 'YES' | 'NO'
|
||||
onBuySuccess?: () => void
|
||||
}) {
|
||||
const { contract, user, selected, onBuySuccess } = props
|
||||
const isPseudoNumeric = contract.outcomeType === 'PSEUDO_NUMERIC'
|
||||
|
||||
const [betChoice, setBetChoice] = useState<'YES' | 'NO' | undefined>(selected)
|
||||
const [betAmount, setBetAmount] = useState<number | undefined>(undefined)
|
||||
|
@ -302,6 +307,12 @@ function BuyPanel(props: {
|
|||
: 0)
|
||||
)} ${betChoice ?? 'YES'} shares`
|
||||
: undefined
|
||||
|
||||
const format = isPseudoNumeric
|
||||
? (p: number) =>
|
||||
Math.round(p * (contract.max - contract.min) + contract.min).toString()
|
||||
: (p: number) => formatPercent(p)
|
||||
|
||||
return (
|
||||
<>
|
||||
<YesNoSelector
|
||||
|
@ -309,6 +320,7 @@ function BuyPanel(props: {
|
|||
btnClassName="flex-1"
|
||||
selected={betChoice}
|
||||
onSelect={(choice) => onBetChoice(choice)}
|
||||
isPseudoNumeric={isPseudoNumeric}
|
||||
/>
|
||||
<div className="my-3 text-left text-sm text-gray-500">Amount</div>
|
||||
<BuyAmountInput
|
||||
|
@ -323,11 +335,13 @@ function BuyPanel(props: {
|
|||
|
||||
<Col className="mt-3 w-full gap-3">
|
||||
<Row className="items-center justify-between text-sm">
|
||||
<div className="text-gray-500">Probability</div>
|
||||
<div className="text-gray-500">
|
||||
{isPseudoNumeric ? 'Value' : 'Probability'}
|
||||
</div>
|
||||
<div>
|
||||
{formatPercent(initialProb)}
|
||||
{format(initialProb)}
|
||||
<span className="mx-2">→</span>
|
||||
{formatPercent(resultProb)}
|
||||
{format(resultProb)}
|
||||
</div>
|
||||
</Row>
|
||||
|
||||
|
@ -340,6 +354,8 @@ function BuyPanel(props: {
|
|||
<br /> payout if{' '}
|
||||
<BinaryOutcomeLabel outcome={betChoice ?? 'YES'} />
|
||||
</>
|
||||
) : isPseudoNumeric ? (
|
||||
'Max payout'
|
||||
) : (
|
||||
<>
|
||||
Payout if <BinaryOutcomeLabel outcome={betChoice ?? 'YES'} />
|
||||
|
|
|
@ -32,6 +32,7 @@ export const ContractOverview = (props: {
|
|||
const user = useUser()
|
||||
const isCreator = user?.id === creatorId
|
||||
const isBinary = outcomeType === 'BINARY'
|
||||
const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC'
|
||||
|
||||
return (
|
||||
<Col className={clsx('mb-6', className)}>
|
||||
|
@ -86,7 +87,9 @@ export const ContractOverview = (props: {
|
|||
/>
|
||||
</Col>
|
||||
<Spacer h={4} />
|
||||
{isBinary && <ContractProbGraph contract={contract} bets={bets} />}{' '}
|
||||
{(isBinary || isPseudoNumeric) && (
|
||||
<ContractProbGraph contract={contract} bets={bets} />
|
||||
)}{' '}
|
||||
{outcomeType === 'FREE_RESPONSE' && (
|
||||
<AnswersGraph contract={contract} bets={bets} />
|
||||
)}
|
||||
|
|
|
@ -5,11 +5,11 @@ import dayjs from 'dayjs'
|
|||
import { memo } from 'react'
|
||||
import { Bet } from 'common/bet'
|
||||
import { getInitialProbability } from 'common/calculate'
|
||||
import { BinaryContract } from 'common/contract'
|
||||
import { BinaryContract, PseudoNumericContract } from 'common/contract'
|
||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||
|
||||
export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||
contract: BinaryContract
|
||||
contract: BinaryContract | PseudoNumericContract
|
||||
bets: Bet[]
|
||||
height?: number
|
||||
}) {
|
||||
|
@ -24,7 +24,13 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
|||
contract.createdTime,
|
||||
...bets.map((bet) => bet.createdTime),
|
||||
].map((time) => new Date(time))
|
||||
const probs = [startProb, ...bets.map((bet) => bet.probAfter)]
|
||||
|
||||
const f =
|
||||
contract.outcomeType === 'PSEUDO_NUMERIC'
|
||||
? (p: number) => (p * (contract.max - contract.min) + contract.min) / 100
|
||||
: (p: number) => p
|
||||
|
||||
const probs = [startProb, ...bets.map((bet) => bet.probAfter)].map(f)
|
||||
|
||||
const isClosed = !!closeTime && Date.now() > closeTime
|
||||
const latestTime = dayjs(
|
||||
|
@ -39,7 +45,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
|||
times.push(latestTime.toDate())
|
||||
probs.push(probs[probs.length - 1])
|
||||
|
||||
const yTickValues = [0, 25, 50, 75, 100]
|
||||
const yTickValues = [0, 25, 50, 75, 100].map(f)
|
||||
|
||||
const { width } = useWindowSize()
|
||||
|
||||
|
@ -80,6 +86,9 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
|||
const multiYear = !dayjs(startDate).isSame(latestTime, 'year')
|
||||
const lessThanAWeek = dayjs(startDate).add(8, 'day').isAfter(latestTime)
|
||||
|
||||
const formatter =
|
||||
contract.outcomeType === 'BINARY' ? formatPercent : formatNumeric
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full overflow-visible"
|
||||
|
@ -88,11 +97,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
|||
<ResponsiveLine
|
||||
data={data}
|
||||
yScale={{ min: 0, max: 100, type: 'linear' }}
|
||||
yFormat={formatPercent}
|
||||
yFormat={formatter}
|
||||
gridYValues={yTickValues}
|
||||
axisLeft={{
|
||||
tickValues: yTickValues,
|
||||
format: formatPercent,
|
||||
format: formatter,
|
||||
}}
|
||||
xScale={{
|
||||
type: 'time',
|
||||
|
@ -138,6 +147,10 @@ function formatPercent(y: DatumValue) {
|
|||
return `${Math.round(+y.toString())}%`
|
||||
}
|
||||
|
||||
function formatNumeric(y: DatumValue) {
|
||||
return `${Math.round(+y.toString())}`
|
||||
}
|
||||
|
||||
function formatTime(
|
||||
time: number,
|
||||
includeYear: boolean,
|
||||
|
|
|
@ -19,11 +19,15 @@ export function OutcomeLabel(props: {
|
|||
value?: number
|
||||
}) {
|
||||
const { outcome, contract, truncate, value } = props
|
||||
const {outcomeType} = contract
|
||||
|
||||
if (contract.outcomeType === 'BINARY')
|
||||
if (outcomeType === 'PSEUDO_NUMERIC')
|
||||
return <PseudoNumericOutcomeLabel outcome={outcome as any} />
|
||||
|
||||
if (outcomeType === 'BINARY')
|
||||
return <BinaryOutcomeLabel outcome={outcome as any} />
|
||||
|
||||
if (contract.outcomeType === 'NUMERIC')
|
||||
if (outcomeType === 'NUMERIC')
|
||||
return (
|
||||
<span className="text-blue-500">
|
||||
{value ?? getValueFromBucket(outcome, contract)}
|
||||
|
@ -49,6 +53,15 @@ export function BinaryOutcomeLabel(props: { outcome: resolution }) {
|
|||
return <CancelLabel />
|
||||
}
|
||||
|
||||
export function PseudoNumericOutcomeLabel(props: { outcome: resolution }) {
|
||||
const { outcome } = props
|
||||
|
||||
if (outcome === 'YES') return <HigherLabel />
|
||||
if (outcome === 'NO') return <LowerLabel />
|
||||
if (outcome === 'MKT') return <ProbLabel />
|
||||
return <CancelLabel />
|
||||
}
|
||||
|
||||
export function BinaryContractOutcomeLabel(props: {
|
||||
contract: BinaryContract
|
||||
resolution: resolution
|
||||
|
@ -98,6 +111,16 @@ export function YesLabel() {
|
|||
return <span className="text-primary">YES</span>
|
||||
}
|
||||
|
||||
export function HigherLabel() {
|
||||
return <span className="text-primary">HIGH</span>
|
||||
}
|
||||
|
||||
export function LowerLabel() {
|
||||
return <span className="text-red-400">LOW</span>
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function NoLabel() {
|
||||
return <span className="text-red-400">NO</span>
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ export function YesNoSelector(props: {
|
|||
btnClassName?: string
|
||||
replaceYesButton?: React.ReactNode
|
||||
replaceNoButton?: React.ReactNode
|
||||
isPseudoNumeric?: boolean
|
||||
}) {
|
||||
const {
|
||||
selected,
|
||||
|
@ -20,6 +21,7 @@ export function YesNoSelector(props: {
|
|||
btnClassName,
|
||||
replaceNoButton,
|
||||
replaceYesButton,
|
||||
isPseudoNumeric,
|
||||
} = props
|
||||
|
||||
const commonClassNames =
|
||||
|
@ -41,7 +43,7 @@ export function YesNoSelector(props: {
|
|||
)}
|
||||
onClick={() => onSelect('YES')}
|
||||
>
|
||||
Bet YES
|
||||
{isPseudoNumeric ? 'Higher' : 'Bet YES'}
|
||||
</button>
|
||||
)}
|
||||
{replaceNoButton ? (
|
||||
|
@ -58,7 +60,7 @@ export function YesNoSelector(props: {
|
|||
)}
|
||||
onClick={() => onSelect('NO')}
|
||||
>
|
||||
Bet NO
|
||||
{isPseudoNumeric ? 'Lower' : 'Bet NO'}
|
||||
</button>
|
||||
)}
|
||||
</Row>
|
||||
|
|
|
@ -199,6 +199,7 @@ export function ContractPageContent(
|
|||
)}
|
||||
|
||||
<ContractOverview contract={contract} bets={bets} />
|
||||
|
||||
{isNumeric && (
|
||||
<AlertBox
|
||||
title="Warning"
|
||||
|
|
Loading…
Reference in New Issue
Block a user