From 01e43abd17c630f62ba3f05731fac88aa23e092b Mon Sep 17 00:00:00 2001 From: James Grugett Date: Wed, 20 Apr 2022 16:36:41 -0500 Subject: [PATCH] Add factors to weight new contracts higher, contracts with unseen comments, and contracts with prob closer to 50% --- common/calculate.ts | 21 ++++++++++- web/components/contract/contract-card.tsx | 14 +------- web/hooks/use-algo-feed.ts | 44 +++++++++++++++++------ 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/common/calculate.ts b/common/calculate.ts index d6834295..cc6451c5 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -18,7 +18,14 @@ import { getDpmProbabilityAfterSale, } from './calculate-dpm' 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) { return contract.mechanism === 'cpmm-1' @@ -170,3 +177,15 @@ export function getContractBetNullMetrics() { 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 +} diff --git a/web/components/contract/contract-card.tsx b/web/components/contract/contract-card.tsx index f415a38c..41373679 100644 --- a/web/components/contract/contract-card.tsx +++ b/web/components/contract/contract-card.tsx @@ -23,7 +23,7 @@ import { BinaryContractOutcomeLabel, FreeResponseOutcomeLabel, } from '../outcome-label' -import { getOutcomeProbability } from '../../../common/calculate' +import { getOutcomeProbability, getTopAnswer } from '../../../common/calculate' import { AbbrContractDetails } from './contract-details' 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: { contract: FreeResponseContract truncate: 'short' | 'long' | 'none' diff --git a/web/hooks/use-algo-feed.ts b/web/hooks/use-algo-feed.ts index 68958821..365f4baa 100644 --- a/web/hooks/use-algo-feed.ts +++ b/web/hooks/use-algo-feed.ts @@ -8,6 +8,12 @@ import { logInterpolation } from '../../common/util/math' import { getRecommendedContracts } from '../../common/recommended-contracts' import { useSeenContracts } from './use-seen-contracts' 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 @@ -120,11 +126,13 @@ function getContractsActivityScores( ) const scoredContracts = contracts.map((contract) => { + const { outcomeType } = contract + const seenTime = seenContracts[contract.id] const lastCommentTime = contractMostRecentComment[contract.id]?.createdTime const hasNewComments = !seenTime || (lastCommentTime && lastCommentTime > seenTime) - const newCommentScore = hasNewComments ? 1 : 0.75 + const newCommentScore = hasNewComments ? 1 : 0.5 const commentCount = contractComments[contract.id]?.length ?? 0 const betCount = contractBets[contract.id]?.length ?? 0 @@ -132,25 +140,39 @@ function getContractsActivityScores( const activityCountScore = 0.5 + 0.5 * logInterpolation(0, 200, activtyCount) - const lastBetTime = contractMostRecentBet[contract.id]?.createdTime - const timeSinceLastBet = !lastBetTime - ? contract.createdTime - : Date.now() - lastBetTime - const daysAgo = timeSinceLastBet / oneDayMs + const lastBetTime = + contractMostRecentBet[contract.id]?.createdTime ?? contract.createdTime + const timeSinceLastBet = Date.now() - lastBetTime + const daysAgo = timeSinceLastBet / DAY_MS 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. 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) } -const oneDayMs = 24 * 60 * 60 * 1000 - function getSeenContractsScore( contract: Contract, seenContracts: { [contractId: string]: number } @@ -160,7 +182,7 @@ function getSeenContractsScore( return 1 } - const daysAgo = (Date.now() - lastSeen) / oneDayMs + const daysAgo = (Date.now() - lastSeen) / DAY_MS if (daysAgo < 0.5) { const frac = logInterpolation(0, 0.5, daysAgo)