log scale

This commit is contained in:
mantikoros 2022-07-01 13:02:08 -04:00
parent 1afe62296e
commit 543b9960d1
9 changed files with 101 additions and 43 deletions

View File

@ -1,10 +0,0 @@
import { PseudoNumericContract } from './contract'
export function formatNumericProbability(
p: number,
contract: PseudoNumericContract
) {
const { min, max } = contract
const value = p * (max - min) + min
return Math.round(value).toString()
}

45
common/pseudo-numeric.ts Normal file
View File

@ -0,0 +1,45 @@
import { BinaryContract, PseudoNumericContract } from './contract'
import { formatLargeNumber, formatPercent } from './util/format'
export function formatNumericProbability(
p: number,
contract: PseudoNumericContract
) {
const value = getMappedValue(contract)(p)
return formatLargeNumber(value)
}
export const getMappedValue =
(contract: PseudoNumericContract | BinaryContract) => (p: number) => {
if (contract.outcomeType === 'BINARY') return p
const { min, max, isLogScale } = contract
if (isLogScale) {
const logValue = p * Math.log10(max - min)
return 10 ** logValue + min
}
return p * (max - min) + min
}
export const getFormattedMappedValue =
(contract: PseudoNumericContract | BinaryContract) => (p: number) => {
if (contract.outcomeType === 'BINARY') return formatPercent(p)
const value = getMappedValue(contract)(p)
return formatLargeNumber(value)
}
export const getPseudoProbability = (
value: number,
min: number,
max: number,
isLogScale = false
) => {
if (isLogScale) {
return Math.log10(value - min) / Math.log10(max - min)
}
return (value - min) / (max - min)
}

View File

@ -28,6 +28,7 @@ import { getNewContract } from '../../common/new-contract'
import { NUMERIC_BUCKET_COUNT } from '../../common/numeric-constants'
import { User } from '../../common/user'
import { Group, MAX_ID_LENGTH } from '../../common/group'
import { getPseudoProbability } from '../../common/pseudo-numeric'
const bodySchema = z.object({
question: z.string().min(1).max(MAX_QUESTION_LENGTH),
@ -67,7 +68,7 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => {
if (max - min <= 0.01 || initialValue < min || initialValue > max)
throw new APIError(400, 'Invalid range.')
initialProb = ((initialValue - min) / (max - min)) * 100
initialProb = getPseudoProbability(initialValue, min, max, isLogScale) * 100
}
if (outcomeType === 'BINARY') {
;({ initialProb } = validate(binarySchema, req.body))

View File

@ -6,9 +6,13 @@ import { Comment } from '../../common/comment'
import { Contract } from '../../common/contract'
import { DPM_CREATOR_FEE } from '../../common/fees'
import { PrivateUser, User } from '../../common/user'
import { formatMoney, formatPercent } from '../../common/util/format'
import {
formatLargeNumber,
formatMoney,
formatPercent,
} from '../../common/util/format'
import { getValueFromBucket } from '../../common/calculate-dpm'
import { formatNumericProbability } from '../../common/numeric'
import { formatNumericProbability } from '../../common/pseudo-numeric'
import { sendTemplateEmail } from './send-email'
import { getPrivateUser, getUser } from './utils'
@ -103,13 +107,14 @@ const toDisplayResolution = (
}
if (contract.outcomeType === 'PSEUDO_NUMERIC') {
return (
contract.resolutionValue?.toString() ??
formatNumericProbability(
resolutionProbability ?? getProbability(contract),
contract
)
)
const { resolutionValue } = contract
return resolutionValue
? formatLargeNumber(resolutionValue)
: formatNumericProbability(
resolutionProbability ?? getProbability(contract),
contract
)
}
if (resolution === 'MKT' && resolutions) return 'MULTI'

View File

@ -39,6 +39,7 @@ import {
getCpmmProbability,
getCpmmLiquidityFee,
} from 'common/calculate-cpmm'
import { getFormattedMappedValue } from 'common/pseudo-numeric'
import { SellRow } from './sell-row'
import { useSaveShares } from './use-save-shares'
import { SignUpPrompt } from './sign-up-prompt'
@ -314,10 +315,7 @@ function BuyPanel(props: {
)} ${betChoice ?? 'YES'} shares`
: undefined
const format = isPseudoNumeric
? (p: number) =>
Math.round(p * (contract.max - contract.min) + contract.min).toString()
: (p: number) => formatPercent(p)
const format = getFormattedMappedValue(contract)
return (
<>
@ -512,10 +510,7 @@ export function SellPanel(props: {
const { outcomeType } = contract
const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC'
const format = isPseudoNumeric
? (p: number) =>
Math.round(p * (contract.max - contract.min) + contract.min).toString()
: (p: number) => formatPercent(p)
const format = getFormattedMappedValue(contract)
return (
<>

View File

@ -29,7 +29,7 @@ import { useContractWithPreload } from 'web/hooks/use-contract'
import { useUser } from 'web/hooks/use-user'
import { track } from '@amplitude/analytics-browser'
import { trackCallback } from 'web/lib/service/analytics'
import { formatNumericProbability } from 'common/numeric'
import { formatNumericProbability } from 'common/pseudo-numeric'
export function ContractCard(props: {
contract: Contract
@ -283,7 +283,9 @@ export function NumericResolutionOrExpectation(props: {
{resolution === 'CANCEL' ? (
<CancelLabel />
) : (
<div className="text-blue-400">{resolutionValue}</div>
<div className="text-blue-400">
{formatLargeNumber(resolutionValue)}
</div>
)}
</>
) : (
@ -316,8 +318,12 @@ export function PseudoNumericResolutionOrExpectation(props: {
<CancelLabel />
) : (
<div className="text-blue-400">
{resolutionValue ??
formatNumericProbability(resolutionProbability ?? 0, contract)}
{resolutionValue
? formatLargeNumber(resolutionValue)
: formatNumericProbability(
resolutionProbability ?? 0,
contract
)}
</div>
)}
</>

View File

@ -7,6 +7,7 @@ import { Bet } from 'common/bet'
import { getInitialProbability } from 'common/calculate'
import { BinaryContract, PseudoNumericContract } from 'common/contract'
import { useWindowSize } from 'web/hooks/use-window-size'
import { getMappedValue } from 'common/pseudo-numeric'
export const ContractProbGraph = memo(function ContractProbGraph(props: {
contract: BinaryContract | PseudoNumericContract
@ -26,10 +27,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
...bets.map((bet) => bet.createdTime),
].map((time) => new Date(time))
const f =
contract.outcomeType === 'PSEUDO_NUMERIC'
? (p: number) => (p * (contract.max - contract.min) + contract.min) / 100
: (p: number) => p
const f = getMappedValue(contract)
const probs = [startProb, ...bets.map((bet) => bet.probAfter)].map(f)
@ -46,9 +44,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
times.push(latestTime.toDate())
probs.push(probs[probs.length - 1])
const quartiles = [0, 25, 50, 75, 100]
const yTickValues = isBinary
? [0, 25, 50, 75, 100]
: [0, 0.25, 0.5, 0.75, 1].map(f).map((x) => x * 100)
? quartiles
: quartiles.map((x) => x / 100).map(f)
const { width } = useWindowSize()
@ -64,9 +64,12 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
const totalPoints = width ? (width > 800 ? 300 : 50) : 1
const timeStep: number = latestTime.diff(startDate, 'ms') / totalPoints
const points: { x: Date; y: number }[] = []
const s = isBinary ? 100 : 1
for (let i = 0; i < times.length - 1; i++) {
points[points.length] = { x: times[i], y: probs[i] * 100 }
points[points.length] = { x: times[i], y: s * probs[i] }
const numPoints: number = Math.floor(
dayjs(times[i + 1]).diff(dayjs(times[i]), 'ms') / timeStep
)
@ -78,7 +81,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
x: dayjs(times[i])
.add(thisTimeStep * n, 'ms')
.toDate(),
y: probs[i] * 100,
y: s * probs[i],
}
}
}
@ -103,7 +106,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
yScale={
isBinary
? { min: 0, max: 100, type: 'linear' }
: { min: contract.min, max: contract.max, type: 'linear' }
: {
min: contract.min,
max: contract.max,
type: contract.isLogScale ? 'log' : 'linear',
}
}
yFormat={formatter}
gridYValues={yTickValues}

View File

@ -26,7 +26,7 @@ import { useSaveShares } from '../use-save-shares'
import { sellShares } from 'web/lib/firebase/api-call'
import { calculateCpmmSale, getCpmmProbability } from 'common/calculate-cpmm'
import { track } from 'web/lib/service/analytics'
import { formatNumericProbability } from 'common/numeric'
import { formatNumericProbability } from 'common/pseudo-numeric'
const BET_SIZE = 10

View File

@ -9,6 +9,7 @@ import { ResolveConfirmationButton } from './confirmation-button'
import { resolveMarket } from 'web/lib/firebase/fn-call'
import { NumericContract, PseudoNumericContract } from 'common/contract'
import { BucketInput } from './bucket-input'
import { getPseudoProbability } from 'common/pseudo-numeric'
export function NumericResolutionPanel(props: {
creator: User
@ -44,7 +45,15 @@ export function NumericResolutionPanel(props: {
setIsSubmitting(true)
const boundedValue = Math.max(Math.min(max, value ?? 0), min)
const probabilityInt = ((boundedValue - min) / (max - min)) * 100
const probabilityInt =
100 *
getPseudoProbability(
boundedValue,
min,
max,
outcomeType === 'PSEUDO_NUMERIC' && contract.isLogScale
)
const result = await resolveMarket({
outcome: finalOutcome,