Graph bets by afterProb.

This commit is contained in:
jahooma 2021-12-12 16:14:52 -06:00
parent e34f1dbcc9
commit b216236503
6 changed files with 102 additions and 57 deletions

View File

@ -64,7 +64,7 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
return ( return (
<Col <Col
className={clsx( className={clsx(
'bg-gray-200 shadow-xl px-8 py-6 rounded w-full md:w-auto', 'bg-gray-200 shadow-xl px-8 py-6 rounded-md w-full md:w-auto',
className className
)} )}
> >

View File

@ -1,51 +1,22 @@
import React from 'react' import React from 'react'
import { Line } from 'react-chartjs-2'
import {
CategoryScale,
Chart,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from 'chart.js'
import { Contract } from '../lib/firebase/contracts' import { Contract } from '../lib/firebase/contracts'
import { Col } from './layout/col' import { Col } from './layout/col'
import { Row } from './layout/row' import { Row } from './layout/row'
import { Spacer } from './layout/spacer' import { Spacer } from './layout/spacer'
import { formatWithCommas } from '../lib/util/format' import { formatWithCommas } from '../lib/util/format'
import { ContractProbGraph } from './contract-prob-graph'
// Auto import doesn't work for some reason... export const ContractOverview = (props: {
// So we manually register ChartJS components instead: contract: Contract
Chart.register( className?: string
CategoryScale, }) => {
LinearScale, const { contract, className } = props
PointElement,
LineElement,
Title,
Tooltip,
Legend
)
const chartData = {
labels: Array.from({ length: 0 }, (_, i) => i + 1),
datasets: [
{
label: 'Implied probability',
data: [],
borderColor: 'rgb(75, 192, 192)',
},
],
}
export const ContractOverview = (props: { contract: Contract }) => {
const { contract } = props
const { pot, seedAmounts } = contract const { pot, seedAmounts } = contract
const volume = pot.YES + pot.NO - seedAmounts.YES - seedAmounts.NO const volume = pot.YES + pot.NO - seedAmounts.YES - seedAmounts.NO
return ( return (
<Col className="max-w-3xl w-full"> <Col className={className}>
<div className="text-3xl font-medium p-2">{contract.question}</div> <div className="text-3xl font-medium p-2">{contract.question}</div>
<Row className="flex-wrap text-sm text-gray-600"> <Row className="flex-wrap text-sm text-gray-600">
@ -53,12 +24,14 @@ export const ContractOverview = (props: { contract: Contract }) => {
<div className="py-2"></div> <div className="py-2"></div>
<div className="p-2 whitespace-nowrap">Dec 9</div> <div className="p-2 whitespace-nowrap">Dec 9</div>
<div className="py-2"></div> <div className="py-2"></div>
<div className="p-2 whitespace-nowrap">{formatWithCommas(volume)} volume</div> <div className="p-2 whitespace-nowrap">
{formatWithCommas(volume)} volume
</div>
</Row> </Row>
<Spacer h={4} /> <Spacer h={4} />
<Line data={chartData} height={150} /> <ContractProbGraph contract={contract} />
<Spacer h={12} /> <Spacer h={12} />

View File

@ -0,0 +1,52 @@
import { Line } from 'react-chartjs-2'
import {
CategoryScale,
Chart,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from 'chart.js'
import { useBets } from '../hooks/use-bets'
import { Contract } from '../lib/firebase/contracts'
// Auto import doesn't work for some reason...
// So we manually register ChartJS components instead:
Chart.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
)
export function ContractProbGraph(props: { contract: Contract }) {
const { contract } = props
const { id, seedAmounts } = contract
let bets = useBets(id)
if (bets === 'loading') bets = []
const seedProb =
seedAmounts.YES ** 2 / (seedAmounts.YES ** 2 + seedAmounts.NO ** 2)
const probs = [seedProb, ...bets.map((bet) => bet.probAfter)]
const chartData = {
labels: Array.from({ length: probs.length }, (_, i) => i + 1),
datasets: [
{
label: 'Implied probability',
data: probs,
borderColor: 'rgb(75, 192, 192)',
},
],
}
return <Line data={chartData} height={150} />
}

12
web/hooks/use-bets.ts Normal file
View File

@ -0,0 +1,12 @@
import { useEffect, useState } from 'react'
import { Bet, listenForBets } from '../lib/firebase/bets'
export const useBets = (contractId: string) => {
const [bets, setBets] = useState<Bet[] | 'loading'>('loading')
useEffect(() => {
if (contractId) return listenForBets(contractId, setBets)
}, [contractId])
return bets
}

View File

@ -1,22 +1,32 @@
import { doc, setDoc } from 'firebase/firestore' import { collection, onSnapshot } from 'firebase/firestore'
import { db } from './init' import { db } from './init'
export type Bet = { export type Bet = {
id: string id: string
userId: string userId: string
contractId: string contractId: string
amount: number // Amount of bet
amount: number // Amount of USD bid
outcome: 'YES' | 'NO' // Chosen outcome outcome: 'YES' | 'NO' // Chosen outcome
// Calculate and replace these on server?
createdTime: number
dpmWeight: number // Dynamic Parimutuel weight dpmWeight: number // Dynamic Parimutuel weight
probBefore: number
probAverage: number
probAfter: number
createdTime: number
} }
// Push bet to Firestore function getBetsCollection(contractId: string) {
// TODO: Should bets be subcollections under its contract? return collection(db, 'contracts', contractId, 'bets')
export async function saveBet(bet: Bet) { }
const docRef = doc(db, 'contracts', bet.contractId, 'bets', bet.id)
await setDoc(docRef, bet) export function listenForBets(
contractId: string,
setBets: (bets: Bet[]) => void
) {
return onSnapshot(getBetsCollection(contractId), (snap) => {
const bets = snap.docs.map((doc) => doc.data() as Bet)
bets.sort((bet1, bet2) => bet1.createdTime - bet2.createdTime)
setBets(bets)
})
} }

View File

@ -24,15 +24,13 @@ export default function ContractPage() {
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<Header /> <Header />
<div className="w-full flex flex-col p-4 mt-4"> <Col className="w-full md:justify-between md:flex-row p-4 mt-4">
<Col className="md:justify-between md:flex-row"> <ContractOverview contract={contract} className="max-w-4xl w-full" />
<ContractOverview contract={contract} />
<div className="mt-12 md:mt-0" /> <div className="mt-12 md:mt-0" />
<BetPanel className="self-start" contract={contract} /> <BetPanel className="self-start" contract={contract} />
</Col> </Col>
</div> </div>
</div>
) )
} }