Calculate invested differently. Sort trades by value and profit, including sales profit. Display profit when sorting by profit.

This commit is contained in:
James Grugett 2022-04-03 01:08:57 -05:00
parent cb0f9d922f
commit 6b2f6f7185

View File

@ -80,18 +80,29 @@ export function BetsList(props: { user: User }) {
contractBets, contractBets,
(bets, contractId) => { (bets, contractId) => {
return _.sumBy(bets, (bet) => { return _.sumBy(bets, (bet) => {
if (bet.isSold || bet.sale) return 0 if (bet.isSold || bet.sale || bet.isRedemption) return 0
const contract = contractsById[contractId] const contract = contractsById[contractId]
const payout = contract ? calculatePayout(contract, bet, 'MKT') : 0 if (contract.resolution)
return payout - (bet.loanAmount ?? 0) return calculatePayout(contract, bet, contract.resolution)
return contract ? calculatePayout(contract, bet, 'MKT') : 0
}) })
} }
) )
const contractsInvestment = _.mapValues(contractBets, (bets) => { const contractsInvestment = _.mapValues(contractBets, (bets) => {
return _.sumBy(bets, (bet) => { return _.sumBy(bets, (bet) => {
if (bet.isSold || bet.sale) return 0 if (bet.isSold || bet.sale || bet.isRedemption) return 0
return bet.amount - (bet.loanAmount ?? 0) return bet.amount
})
})
const contractsSaleOrRedemption = _.mapValues(contractBets, (bets) => {
return _.sumBy(bets, (bet) => {
if (bet.isSold) return -1 * bet.amount
if (bet.sale) return bet.sale.amount
if (bet.isRedemption) return -1 * bet.amount
return 0
}) })
}) })
@ -104,8 +115,11 @@ export function BetsList(props: { user: User }) {
// Pepe notes: most users want "settled", to see when their bets or sold; or "realized profit" // Pepe notes: most users want "settled", to see when their bets or sold; or "realized profit"
} }
const SORTS: Record<BetSort, (c: Contract) => number> = { const SORTS: Record<BetSort, (c: Contract) => number> = {
profit: (c) => contractsCurrentValue[c.id] - contractsInvestment[c.id], profit: (c) =>
value: (c) => contractsCurrentValue[c.id], contractsCurrentValue[c.id] -
contractsInvestment[c.id] +
contractsSaleOrRedemption[c.id],
value: (c) => contractsCurrentValue[c.id] + contractsSaleOrRedemption[c.id],
newest: (c) => newest: (c) =>
Math.max(...contractBets[c.id].map((bet) => bet.createdTime)), Math.max(...contractBets[c.id].map((bet) => bet.createdTime)),
resolutionTime: (c) => -(c.resolutionTime ?? c.closeTime ?? Infinity), resolutionTime: (c) => -(c.resolutionTime ?? c.closeTime ?? Infinity),
@ -126,8 +140,18 @@ export function BetsList(props: { user: User }) {
unsettled, unsettled,
(c) => contractsCurrentValue[c.id] (c) => contractsCurrentValue[c.id]
) )
const currentBetsValueMinusLoans = _.sumBy(
unsettled,
(c) =>
contractsCurrentValue[c.id] -
// Subtract loans you haven't paid.
_.sumBy(contractBets[c.id], (bet) => {
if (bet.isSold || bet.sale) return 0
return bet.loanAmount ?? 0
})
)
const totalPortfolio = currentBetsValue + user.balance const totalPortfolio = currentBetsValueMinusLoans + user.balance
const totalPnl = totalPortfolio - user.totalDeposits const totalPnl = totalPortfolio - user.totalDeposits
const totalProfitPercent = (totalPnl / user.totalDeposits) * 100 const totalProfitPercent = (totalPnl / user.totalDeposits) * 100
@ -141,7 +165,7 @@ export function BetsList(props: { user: User }) {
<Col> <Col>
<div className="text-sm text-gray-500">Investment value</div> <div className="text-sm text-gray-500">Investment value</div>
<div className="text-lg"> <div className="text-lg">
{formatMoney(currentBetsValue)}{' '} {formatMoney(currentBetsValueMinusLoans)}{' '}
<ProfitBadge profitPercent={investedProfitPercent} /> <ProfitBadge profitPercent={investedProfitPercent} />
</div> </div>
</Col> </Col>
@ -188,6 +212,7 @@ export function BetsList(props: { user: User }) {
key={contract.id} key={contract.id}
contract={contract} contract={contract}
bets={contractBets[contract.id] ?? []} bets={contractBets[contract.id] ?? []}
metric={sort === 'profit' ? 'profit' : 'value'}
/> />
)) ))
)} )}
@ -206,8 +231,12 @@ const NoBets = () => {
) )
} }
function MyContractBets(props: { contract: Contract; bets: Bet[] }) { function MyContractBets(props: {
const { bets, contract } = props contract: Contract
bets: Bet[]
metric: 'profit' | 'value'
}) {
const { bets, contract, metric } = props
const { resolution, outcomeType } = contract const { resolution, outcomeType } = contract
const [collapsed, setCollapsed] = useState(true) const [collapsed, setCollapsed] = useState(true)
@ -267,7 +296,7 @@ function MyContractBets(props: { contract: Contract; bets: Bet[] }) {
className="mr-5 justify-end sm:mr-8" className="mr-5 justify-end sm:mr-8"
contract={contract} contract={contract}
bets={bets} bets={bets}
onlyMKT onlyMetric={metric}
/> />
</Row> </Row>
@ -294,15 +323,26 @@ function MyContractBets(props: { contract: Contract; bets: Bet[] }) {
export function MyBetsSummary(props: { export function MyBetsSummary(props: {
contract: Contract contract: Contract
bets: Bet[] bets: Bet[]
onlyMKT?: boolean onlyMetric?: 'value' | 'profit'
className?: string className?: string
}) { }) {
const { bets, contract, onlyMKT, className } = props const { bets, contract, onlyMetric, className } = props
const { resolution, outcomeType } = contract const { resolution, outcomeType } = contract
const isBinary = outcomeType === 'BINARY' const isBinary = outcomeType === 'BINARY'
const excludeSales = bets.filter((b) => !b.isSold && !b.sale) const excludeSales = bets.filter((b) => !b.isSold && !b.sale)
const betsTotal = _.sumBy(excludeSales, (bet) => bet.amount) const excludeRedemptions = bets.filter((b) => !b.isRedemption)
const excludeSalesAndRedemptions = excludeSales.filter((b) => !b.isRedemption)
const betsTotal = _.sumBy(excludeSalesAndRedemptions, (bet) => bet.amount)
const invested = _.sumBy(excludeSalesAndRedemptions, (bet) =>
bet.amount > 0 ? bet.amount : 0
)
const investedIncludingSales = _.sumBy(excludeRedemptions, (bet) =>
bet.amount > 0 ? bet.amount : 0
)
const redemptionValue = _.sumBy(bets, (bet) =>
bet.isRedemption ? -bet.amount : 0
)
const betsPayout = resolution const betsPayout = resolution
? _.sumBy(excludeSales, (bet) => resolvedPayout(contract, bet)) ? _.sumBy(excludeSales, (bet) => resolvedPayout(contract, bet))
@ -314,58 +354,52 @@ export function MyBetsSummary(props: {
const noWinnings = _.sumBy(excludeSales, (bet) => const noWinnings = _.sumBy(excludeSales, (bet) =>
calculatePayout(contract, bet, 'NO') calculatePayout(contract, bet, 'NO')
) )
// const p = getProbability(contract.totalShares)
// const expectation = p * yesWinnings + (1 - p) * noWinnings
const marketWinnings = _.sumBy(excludeSales, (bet) => const marketWinnings = _.sumBy(excludeSales, (bet) =>
calculatePayout(contract, bet, 'MKT') calculatePayout(contract, bet, 'MKT')
) )
const salesWinnings = _.sumBy(bets, (bet) =>
bet.isSold ? -bet.amount : bet.sale ? bet.sale.amount : 0
)
const currentValue = resolution ? betsPayout : marketWinnings const currentValue = resolution ? betsPayout : marketWinnings
const pnl = currentValue - betsTotal const totalValue = currentValue + redemptionValue + salesWinnings
const profit = (pnl / betsTotal) * 100 const pnl = totalValue - betsTotal
const profit = (pnl / investedIncludingSales) * 100
const valueCol = (
<Col>
<div className="whitespace-nowrap text-right text-lg">
{formatMoney(currentValue)}
</div>
<div className="text-right">
<ProfitBadge profitPercent={profit} />
</div>
</Col>
)
const payoutCol = (
<Col>
<div className="text-sm text-gray-500">Payout</div>
<div className="whitespace-nowrap">
{formatMoney(betsPayout)} <ProfitBadge profitPercent={profit} />
</div>
</Col>
)
return ( return (
<Row <Row
className={clsx( className={clsx(
'gap-4 sm:gap-6', 'gap-4 sm:gap-6',
!onlyMKT && 'flex-wrap sm:flex-nowrap', !onlyMetric && 'flex-wrap sm:flex-nowrap',
className className
)} )}
> >
{onlyMKT ? ( {onlyMetric ? (
<Row className="gap-4 sm:gap-6">{valueCol}</Row> <Row className="gap-4 sm:gap-6">
<Col>
<div className="whitespace-nowrap text-right text-lg">
{formatMoney(onlyMetric === 'profit' ? pnl : totalValue)}
</div>
<div className="text-right">
<ProfitBadge profitPercent={profit} />
</div>
</Col>
</Row>
) : ( ) : (
<Row className="gap-4 sm:gap-6"> <Row className="gap-4 sm:gap-6">
<Col> <Col>
<div className="whitespace-nowrap text-sm text-gray-500"> <div className="whitespace-nowrap text-sm text-gray-500">
Invested Invested
</div> </div>
<div className="whitespace-nowrap">{formatMoney(betsTotal)}</div> <div className="whitespace-nowrap">{formatMoney(invested)}</div>
</Col> </Col>
{resolution ? ( {resolution ? (
payoutCol <Col>
<div className="text-sm text-gray-500">Payout</div>
<div className="whitespace-nowrap">
{formatMoney(betsPayout)} <ProfitBadge profitPercent={profit} />
</div>
</Col>
) : ( ) : (
<> <>
{/* <Col> {/* <Col>