manifold/common/calculate-metrics.ts
James Grugett 54c227cf6c
Updates to experimental home (#858)
* Line clamp question in prob change table

* Tweaks

* Expand option for daily movers

* Snap scrolling for carousel

* Add arrows to section headers

* Remove carousel from experimental/home

* React querify fetching your groups

* Edit home is its own page

* Add daily profit and balance

* Merge branch 'main' into new-home

* Make experimental search by your followed groups/creators

* Just submit, allow xs on pills

* Weigh in

* Use next/future/image component to optimize avatar images

* Inga/challenge icon (#857)

* changed challenge icon to custom icon
* fixed tip button alignment

* weighing in and trading "weigh in" for "trade"

Co-authored-by: Ian Philips <iansphilips@gmail.com>
Co-authored-by: Austin Chen <akrolsmir@gmail.com>
Co-authored-by: ingawei <46611122+ingawei@users.noreply.github.com>
Co-authored-by: mantikoros <sgrugett@gmail.com>
2022-09-08 01:36:34 -05:00

159 lines
4.2 KiB
TypeScript

import { last, sortBy, sum, sumBy } from 'lodash'
import { calculatePayout } from './calculate'
import { Bet } from './bet'
import { Contract } from './contract'
import { PortfolioMetrics, User } from './user'
import { DAY_MS } from './util/time'
const computeInvestmentValue = (
bets: Bet[],
contractsDict: { [k: string]: Contract }
) => {
return sumBy(bets, (bet) => {
const contract = contractsDict[bet.contractId]
if (!contract || contract.isResolved) return 0
if (bet.sale || bet.isSold) return 0
const payout = calculatePayout(contract, bet, 'MKT')
const value = payout - (bet.loanAmount ?? 0)
if (isNaN(value)) return 0
return value
})
}
const computeTotalPool = (userContracts: Contract[], startTime = 0) => {
const periodFilteredContracts = userContracts.filter(
(contract) => contract.createdTime >= startTime
)
return sum(
periodFilteredContracts.map((contract) => sum(Object.values(contract.pool)))
)
}
export const computeVolume = (contractBets: Bet[], since: number) => {
return sumBy(contractBets, (b) =>
b.createdTime > since && !b.isRedemption ? Math.abs(b.amount) : 0
)
}
const calculateProbChangeSince = (descendingBets: Bet[], since: number) => {
const newestBet = descendingBets[0]
if (!newestBet) return 0
const betBeforeSince = descendingBets.find((b) => b.createdTime < since)
if (!betBeforeSince) {
const oldestBet = last(descendingBets) ?? newestBet
return newestBet.probAfter - oldestBet.probBefore
}
return newestBet.probAfter - betBeforeSince.probAfter
}
export const calculateProbChanges = (descendingBets: Bet[]) => {
const now = Date.now()
const yesterday = now - DAY_MS
const weekAgo = now - 7 * DAY_MS
const monthAgo = now - 30 * DAY_MS
return {
day: calculateProbChangeSince(descendingBets, yesterday),
week: calculateProbChangeSince(descendingBets, weekAgo),
month: calculateProbChangeSince(descendingBets, monthAgo),
}
}
export const calculateCreatorVolume = (userContracts: Contract[]) => {
const allTimeCreatorVolume = computeTotalPool(userContracts, 0)
const monthlyCreatorVolume = computeTotalPool(
userContracts,
Date.now() - 30 * DAY_MS
)
const weeklyCreatorVolume = computeTotalPool(
userContracts,
Date.now() - 7 * DAY_MS
)
const dailyCreatorVolume = computeTotalPool(
userContracts,
Date.now() - 1 * DAY_MS
)
return {
daily: dailyCreatorVolume,
weekly: weeklyCreatorVolume,
monthly: monthlyCreatorVolume,
allTime: allTimeCreatorVolume,
}
}
export const calculateNewPortfolioMetrics = (
user: User,
contractsById: { [k: string]: Contract },
currentBets: Bet[]
) => {
const investmentValue = computeInvestmentValue(currentBets, contractsById)
const newPortfolio = {
investmentValue: investmentValue,
balance: user.balance,
totalDeposits: user.totalDeposits,
timestamp: Date.now(),
userId: user.id,
}
return newPortfolio
}
const calculateProfitForPeriod = (
startTime: number,
descendingPortfolio: PortfolioMetrics[],
currentProfit: number
) => {
const startingPortfolio = descendingPortfolio.find(
(p) => p.timestamp < startTime
)
if (startingPortfolio === undefined) {
return currentProfit
}
const startingProfit = calculatePortfolioProfit(startingPortfolio)
return currentProfit - startingProfit
}
export const calculatePortfolioProfit = (portfolio: PortfolioMetrics) => {
return portfolio.investmentValue + portfolio.balance - portfolio.totalDeposits
}
export const calculateNewProfit = (
portfolioHistory: PortfolioMetrics[],
newPortfolio: PortfolioMetrics
) => {
const allTimeProfit = calculatePortfolioProfit(newPortfolio)
const descendingPortfolio = sortBy(
portfolioHistory,
(p) => p.timestamp
).reverse()
const newProfit = {
daily: calculateProfitForPeriod(
Date.now() - 1 * DAY_MS,
descendingPortfolio,
allTimeProfit
),
weekly: calculateProfitForPeriod(
Date.now() - 7 * DAY_MS,
descendingPortfolio,
allTimeProfit
),
monthly: calculateProfitForPeriod(
Date.now() - 30 * DAY_MS,
descendingPortfolio,
allTimeProfit
),
allTime: allTimeProfit,
}
return newProfit
}