log scale
This commit is contained in:
parent
1afe62296e
commit
543b9960d1
|
|
@ -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
45
common/pseudo-numeric.ts
Normal 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)
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import { getNewContract } from '../../common/new-contract'
|
||||||
import { NUMERIC_BUCKET_COUNT } from '../../common/numeric-constants'
|
import { NUMERIC_BUCKET_COUNT } from '../../common/numeric-constants'
|
||||||
import { User } from '../../common/user'
|
import { User } from '../../common/user'
|
||||||
import { Group, MAX_ID_LENGTH } from '../../common/group'
|
import { Group, MAX_ID_LENGTH } from '../../common/group'
|
||||||
|
import { getPseudoProbability } from '../../common/pseudo-numeric'
|
||||||
|
|
||||||
const bodySchema = z.object({
|
const bodySchema = z.object({
|
||||||
question: z.string().min(1).max(MAX_QUESTION_LENGTH),
|
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)
|
if (max - min <= 0.01 || initialValue < min || initialValue > max)
|
||||||
throw new APIError(400, 'Invalid range.')
|
throw new APIError(400, 'Invalid range.')
|
||||||
|
|
||||||
initialProb = ((initialValue - min) / (max - min)) * 100
|
initialProb = getPseudoProbability(initialValue, min, max, isLogScale) * 100
|
||||||
}
|
}
|
||||||
if (outcomeType === 'BINARY') {
|
if (outcomeType === 'BINARY') {
|
||||||
;({ initialProb } = validate(binarySchema, req.body))
|
;({ initialProb } = validate(binarySchema, req.body))
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,13 @@ import { Comment } from '../../common/comment'
|
||||||
import { Contract } from '../../common/contract'
|
import { Contract } from '../../common/contract'
|
||||||
import { DPM_CREATOR_FEE } from '../../common/fees'
|
import { DPM_CREATOR_FEE } from '../../common/fees'
|
||||||
import { PrivateUser, User } from '../../common/user'
|
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 { getValueFromBucket } from '../../common/calculate-dpm'
|
||||||
import { formatNumericProbability } from '../../common/numeric'
|
import { formatNumericProbability } from '../../common/pseudo-numeric'
|
||||||
|
|
||||||
import { sendTemplateEmail } from './send-email'
|
import { sendTemplateEmail } from './send-email'
|
||||||
import { getPrivateUser, getUser } from './utils'
|
import { getPrivateUser, getUser } from './utils'
|
||||||
|
|
@ -103,13 +107,14 @@ const toDisplayResolution = (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contract.outcomeType === 'PSEUDO_NUMERIC') {
|
if (contract.outcomeType === 'PSEUDO_NUMERIC') {
|
||||||
return (
|
const { resolutionValue } = contract
|
||||||
contract.resolutionValue?.toString() ??
|
|
||||||
formatNumericProbability(
|
return resolutionValue
|
||||||
|
? formatLargeNumber(resolutionValue)
|
||||||
|
: formatNumericProbability(
|
||||||
resolutionProbability ?? getProbability(contract),
|
resolutionProbability ?? getProbability(contract),
|
||||||
contract
|
contract
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolution === 'MKT' && resolutions) return 'MULTI'
|
if (resolution === 'MKT' && resolutions) return 'MULTI'
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import {
|
||||||
getCpmmProbability,
|
getCpmmProbability,
|
||||||
getCpmmLiquidityFee,
|
getCpmmLiquidityFee,
|
||||||
} from 'common/calculate-cpmm'
|
} from 'common/calculate-cpmm'
|
||||||
|
import { getFormattedMappedValue } from 'common/pseudo-numeric'
|
||||||
import { SellRow } from './sell-row'
|
import { SellRow } from './sell-row'
|
||||||
import { useSaveShares } from './use-save-shares'
|
import { useSaveShares } from './use-save-shares'
|
||||||
import { SignUpPrompt } from './sign-up-prompt'
|
import { SignUpPrompt } from './sign-up-prompt'
|
||||||
|
|
@ -314,10 +315,7 @@ function BuyPanel(props: {
|
||||||
)} ${betChoice ?? 'YES'} shares`
|
)} ${betChoice ?? 'YES'} shares`
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const format = isPseudoNumeric
|
const format = getFormattedMappedValue(contract)
|
||||||
? (p: number) =>
|
|
||||||
Math.round(p * (contract.max - contract.min) + contract.min).toString()
|
|
||||||
: (p: number) => formatPercent(p)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -512,10 +510,7 @@ export function SellPanel(props: {
|
||||||
|
|
||||||
const { outcomeType } = contract
|
const { outcomeType } = contract
|
||||||
const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC'
|
const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC'
|
||||||
const format = isPseudoNumeric
|
const format = getFormattedMappedValue(contract)
|
||||||
? (p: number) =>
|
|
||||||
Math.round(p * (contract.max - contract.min) + contract.min).toString()
|
|
||||||
: (p: number) => formatPercent(p)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import { useContractWithPreload } from 'web/hooks/use-contract'
|
||||||
import { useUser } from 'web/hooks/use-user'
|
import { useUser } from 'web/hooks/use-user'
|
||||||
import { track } from '@amplitude/analytics-browser'
|
import { track } from '@amplitude/analytics-browser'
|
||||||
import { trackCallback } from 'web/lib/service/analytics'
|
import { trackCallback } from 'web/lib/service/analytics'
|
||||||
import { formatNumericProbability } from 'common/numeric'
|
import { formatNumericProbability } from 'common/pseudo-numeric'
|
||||||
|
|
||||||
export function ContractCard(props: {
|
export function ContractCard(props: {
|
||||||
contract: Contract
|
contract: Contract
|
||||||
|
|
@ -283,7 +283,9 @@ export function NumericResolutionOrExpectation(props: {
|
||||||
{resolution === 'CANCEL' ? (
|
{resolution === 'CANCEL' ? (
|
||||||
<CancelLabel />
|
<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 />
|
<CancelLabel />
|
||||||
) : (
|
) : (
|
||||||
<div className="text-blue-400">
|
<div className="text-blue-400">
|
||||||
{resolutionValue ??
|
{resolutionValue
|
||||||
formatNumericProbability(resolutionProbability ?? 0, contract)}
|
? formatLargeNumber(resolutionValue)
|
||||||
|
: formatNumericProbability(
|
||||||
|
resolutionProbability ?? 0,
|
||||||
|
contract
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { Bet } from 'common/bet'
|
||||||
import { getInitialProbability } from 'common/calculate'
|
import { getInitialProbability } from 'common/calculate'
|
||||||
import { BinaryContract, PseudoNumericContract } from 'common/contract'
|
import { BinaryContract, PseudoNumericContract } from 'common/contract'
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||||
|
import { getMappedValue } from 'common/pseudo-numeric'
|
||||||
|
|
||||||
export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||||
contract: BinaryContract | PseudoNumericContract
|
contract: BinaryContract | PseudoNumericContract
|
||||||
|
|
@ -26,10 +27,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||||
...bets.map((bet) => bet.createdTime),
|
...bets.map((bet) => bet.createdTime),
|
||||||
].map((time) => new Date(time))
|
].map((time) => new Date(time))
|
||||||
|
|
||||||
const f =
|
const f = getMappedValue(contract)
|
||||||
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 probs = [startProb, ...bets.map((bet) => bet.probAfter)].map(f)
|
||||||
|
|
||||||
|
|
@ -46,9 +44,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||||
times.push(latestTime.toDate())
|
times.push(latestTime.toDate())
|
||||||
probs.push(probs[probs.length - 1])
|
probs.push(probs[probs.length - 1])
|
||||||
|
|
||||||
|
const quartiles = [0, 25, 50, 75, 100]
|
||||||
|
|
||||||
const yTickValues = isBinary
|
const yTickValues = isBinary
|
||||||
? [0, 25, 50, 75, 100]
|
? quartiles
|
||||||
: [0, 0.25, 0.5, 0.75, 1].map(f).map((x) => x * 100)
|
: quartiles.map((x) => x / 100).map(f)
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
|
|
@ -64,9 +64,12 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||||
const totalPoints = width ? (width > 800 ? 300 : 50) : 1
|
const totalPoints = width ? (width > 800 ? 300 : 50) : 1
|
||||||
|
|
||||||
const timeStep: number = latestTime.diff(startDate, 'ms') / totalPoints
|
const timeStep: number = latestTime.diff(startDate, 'ms') / totalPoints
|
||||||
|
|
||||||
const points: { x: Date; y: number }[] = []
|
const points: { x: Date; y: number }[] = []
|
||||||
|
const s = isBinary ? 100 : 1
|
||||||
|
|
||||||
for (let i = 0; i < times.length - 1; i++) {
|
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(
|
const numPoints: number = Math.floor(
|
||||||
dayjs(times[i + 1]).diff(dayjs(times[i]), 'ms') / timeStep
|
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])
|
x: dayjs(times[i])
|
||||||
.add(thisTimeStep * n, 'ms')
|
.add(thisTimeStep * n, 'ms')
|
||||||
.toDate(),
|
.toDate(),
|
||||||
y: probs[i] * 100,
|
y: s * probs[i],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +106,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
||||||
yScale={
|
yScale={
|
||||||
isBinary
|
isBinary
|
||||||
? { min: 0, max: 100, type: 'linear' }
|
? { 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}
|
yFormat={formatter}
|
||||||
gridYValues={yTickValues}
|
gridYValues={yTickValues}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import { useSaveShares } from '../use-save-shares'
|
||||||
import { sellShares } from 'web/lib/firebase/api-call'
|
import { sellShares } from 'web/lib/firebase/api-call'
|
||||||
import { calculateCpmmSale, getCpmmProbability } from 'common/calculate-cpmm'
|
import { calculateCpmmSale, getCpmmProbability } from 'common/calculate-cpmm'
|
||||||
import { track } from 'web/lib/service/analytics'
|
import { track } from 'web/lib/service/analytics'
|
||||||
import { formatNumericProbability } from 'common/numeric'
|
import { formatNumericProbability } from 'common/pseudo-numeric'
|
||||||
|
|
||||||
const BET_SIZE = 10
|
const BET_SIZE = 10
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { ResolveConfirmationButton } from './confirmation-button'
|
||||||
import { resolveMarket } from 'web/lib/firebase/fn-call'
|
import { resolveMarket } from 'web/lib/firebase/fn-call'
|
||||||
import { NumericContract, PseudoNumericContract } from 'common/contract'
|
import { NumericContract, PseudoNumericContract } from 'common/contract'
|
||||||
import { BucketInput } from './bucket-input'
|
import { BucketInput } from './bucket-input'
|
||||||
|
import { getPseudoProbability } from 'common/pseudo-numeric'
|
||||||
|
|
||||||
export function NumericResolutionPanel(props: {
|
export function NumericResolutionPanel(props: {
|
||||||
creator: User
|
creator: User
|
||||||
|
|
@ -44,7 +45,15 @@ export function NumericResolutionPanel(props: {
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
|
|
||||||
const boundedValue = Math.max(Math.min(max, value ?? 0), min)
|
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({
|
const result = await resolveMarket({
|
||||||
outcome: finalOutcome,
|
outcome: finalOutcome,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user