Add factors to weight new contracts higher, contracts with unseen comments, and contracts with prob closer to 50%
This commit is contained in:
parent
0390ec0f47
commit
01e43abd17
|
@ -18,7 +18,14 @@ import {
|
||||||
getDpmProbabilityAfterSale,
|
getDpmProbabilityAfterSale,
|
||||||
} from './calculate-dpm'
|
} from './calculate-dpm'
|
||||||
import { calculateFixedPayout } from './calculate-fixed-payouts'
|
import { calculateFixedPayout } from './calculate-fixed-payouts'
|
||||||
import { Binary, Contract, CPMM, DPM, FullContract } from './contract'
|
import {
|
||||||
|
Binary,
|
||||||
|
Contract,
|
||||||
|
CPMM,
|
||||||
|
DPM,
|
||||||
|
FreeResponseContract,
|
||||||
|
FullContract,
|
||||||
|
} from './contract'
|
||||||
|
|
||||||
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
|
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
|
||||||
return contract.mechanism === 'cpmm-1'
|
return contract.mechanism === 'cpmm-1'
|
||||||
|
@ -170,3 +177,15 @@ export function getContractBetNullMetrics() {
|
||||||
profitPercent: 0,
|
profitPercent: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTopAnswer(contract: FreeResponseContract) {
|
||||||
|
const { answers } = contract
|
||||||
|
const top = _.maxBy(
|
||||||
|
answers.map((answer) => ({
|
||||||
|
answer,
|
||||||
|
prob: getOutcomeProbability(contract, answer.id),
|
||||||
|
})),
|
||||||
|
({ prob }) => prob
|
||||||
|
)
|
||||||
|
return top?.answer
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
BinaryContractOutcomeLabel,
|
BinaryContractOutcomeLabel,
|
||||||
FreeResponseOutcomeLabel,
|
FreeResponseOutcomeLabel,
|
||||||
} from '../outcome-label'
|
} from '../outcome-label'
|
||||||
import { getOutcomeProbability } from '../../../common/calculate'
|
import { getOutcomeProbability, getTopAnswer } from '../../../common/calculate'
|
||||||
import { AbbrContractDetails } from './contract-details'
|
import { AbbrContractDetails } from './contract-details'
|
||||||
|
|
||||||
export function ContractCard(props: {
|
export function ContractCard(props: {
|
||||||
|
@ -122,18 +122,6 @@ export function BinaryResolutionOrChance(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTopAnswer(contract: FreeResponseContract) {
|
|
||||||
const { answers } = contract
|
|
||||||
const top = _.maxBy(
|
|
||||||
answers.map((answer) => ({
|
|
||||||
answer,
|
|
||||||
prob: getOutcomeProbability(contract, answer.id),
|
|
||||||
})),
|
|
||||||
({ prob }) => prob
|
|
||||||
)
|
|
||||||
return top?.answer
|
|
||||||
}
|
|
||||||
|
|
||||||
export function FreeResponseResolutionOrChance(props: {
|
export function FreeResponseResolutionOrChance(props: {
|
||||||
contract: FreeResponseContract
|
contract: FreeResponseContract
|
||||||
truncate: 'short' | 'long' | 'none'
|
truncate: 'short' | 'long' | 'none'
|
||||||
|
|
|
@ -8,6 +8,12 @@ import { logInterpolation } from '../../common/util/math'
|
||||||
import { getRecommendedContracts } from '../../common/recommended-contracts'
|
import { getRecommendedContracts } from '../../common/recommended-contracts'
|
||||||
import { useSeenContracts } from './use-seen-contracts'
|
import { useSeenContracts } from './use-seen-contracts'
|
||||||
import { useGetUserBetContractIds, useUserBetContracts } from './use-user-bets'
|
import { useGetUserBetContractIds, useUserBetContracts } from './use-user-bets'
|
||||||
|
import { DAY_MS } from '../../common/util/time'
|
||||||
|
import {
|
||||||
|
getProbability,
|
||||||
|
getOutcomeProbability,
|
||||||
|
getTopAnswer,
|
||||||
|
} from '../../common/calculate'
|
||||||
|
|
||||||
const MAX_FEED_CONTRACTS = 75
|
const MAX_FEED_CONTRACTS = 75
|
||||||
|
|
||||||
|
@ -120,11 +126,13 @@ function getContractsActivityScores(
|
||||||
)
|
)
|
||||||
|
|
||||||
const scoredContracts = contracts.map((contract) => {
|
const scoredContracts = contracts.map((contract) => {
|
||||||
|
const { outcomeType } = contract
|
||||||
|
|
||||||
const seenTime = seenContracts[contract.id]
|
const seenTime = seenContracts[contract.id]
|
||||||
const lastCommentTime = contractMostRecentComment[contract.id]?.createdTime
|
const lastCommentTime = contractMostRecentComment[contract.id]?.createdTime
|
||||||
const hasNewComments =
|
const hasNewComments =
|
||||||
!seenTime || (lastCommentTime && lastCommentTime > seenTime)
|
!seenTime || (lastCommentTime && lastCommentTime > seenTime)
|
||||||
const newCommentScore = hasNewComments ? 1 : 0.75
|
const newCommentScore = hasNewComments ? 1 : 0.5
|
||||||
|
|
||||||
const commentCount = contractComments[contract.id]?.length ?? 0
|
const commentCount = contractComments[contract.id]?.length ?? 0
|
||||||
const betCount = contractBets[contract.id]?.length ?? 0
|
const betCount = contractBets[contract.id]?.length ?? 0
|
||||||
|
@ -132,25 +140,39 @@ function getContractsActivityScores(
|
||||||
const activityCountScore =
|
const activityCountScore =
|
||||||
0.5 + 0.5 * logInterpolation(0, 200, activtyCount)
|
0.5 + 0.5 * logInterpolation(0, 200, activtyCount)
|
||||||
|
|
||||||
const lastBetTime = contractMostRecentBet[contract.id]?.createdTime
|
const lastBetTime =
|
||||||
const timeSinceLastBet = !lastBetTime
|
contractMostRecentBet[contract.id]?.createdTime ?? contract.createdTime
|
||||||
? contract.createdTime
|
const timeSinceLastBet = Date.now() - lastBetTime
|
||||||
: Date.now() - lastBetTime
|
const daysAgo = timeSinceLastBet / DAY_MS
|
||||||
const daysAgo = timeSinceLastBet / oneDayMs
|
|
||||||
const timeAgoScore = 1 - logInterpolation(0, 3, daysAgo)
|
const timeAgoScore = 1 - logInterpolation(0, 3, daysAgo)
|
||||||
|
|
||||||
const score = newCommentScore * activityCountScore * timeAgoScore
|
let prob = 0.5
|
||||||
|
if (outcomeType === 'BINARY') {
|
||||||
|
prob = getProbability(contract)
|
||||||
|
} else if (outcomeType === 'FREE_RESPONSE') {
|
||||||
|
const topAnswer = getTopAnswer(contract)
|
||||||
|
if (topAnswer)
|
||||||
|
prob = Math.max(0.5, getOutcomeProbability(contract, topAnswer.id))
|
||||||
|
}
|
||||||
|
const frac = 1 - Math.abs(prob - 0.5) ** 2 / 0.25
|
||||||
|
const probScore = 0.5 + frac * 0.5
|
||||||
|
|
||||||
|
const score =
|
||||||
|
newCommentScore * activityCountScore * timeAgoScore * probScore
|
||||||
|
|
||||||
// Map score to [0.5, 1] since no recent activty is not a deal breaker.
|
// Map score to [0.5, 1] since no recent activty is not a deal breaker.
|
||||||
const mappedScore = 0.5 + score / 2
|
const mappedScore = 0.5 + score / 2
|
||||||
return [contract.id, mappedScore] as [string, number]
|
const newMappedScore = 0.75 + score / 4
|
||||||
|
|
||||||
|
const isNew = Date.now() < contract.createdTime + DAY_MS
|
||||||
|
const activityScore = isNew ? newMappedScore : mappedScore
|
||||||
|
|
||||||
|
return [contract.id, activityScore] as [string, number]
|
||||||
})
|
})
|
||||||
|
|
||||||
return _.fromPairs(scoredContracts)
|
return _.fromPairs(scoredContracts)
|
||||||
}
|
}
|
||||||
|
|
||||||
const oneDayMs = 24 * 60 * 60 * 1000
|
|
||||||
|
|
||||||
function getSeenContractsScore(
|
function getSeenContractsScore(
|
||||||
contract: Contract,
|
contract: Contract,
|
||||||
seenContracts: { [contractId: string]: number }
|
seenContracts: { [contractId: string]: number }
|
||||||
|
@ -160,7 +182,7 @@ function getSeenContractsScore(
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const daysAgo = (Date.now() - lastSeen) / oneDayMs
|
const daysAgo = (Date.now() - lastSeen) / DAY_MS
|
||||||
|
|
||||||
if (daysAgo < 0.5) {
|
if (daysAgo < 0.5) {
|
||||||
const frac = logInterpolation(0, 0.5, daysAgo)
|
const frac = logInterpolation(0, 0.5, daysAgo)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user