Graph bets by afterProb.
This commit is contained in:
parent
e34f1dbcc9
commit
b216236503
|
@ -64,7 +64,7 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
|
|||
return (
|
||||
<Col
|
||||
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
|
||||
)}
|
||||
>
|
||||
|
|
|
@ -1,51 +1,22 @@
|
|||
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 { Col } from './layout/col'
|
||||
import { Row } from './layout/row'
|
||||
import { Spacer } from './layout/spacer'
|
||||
import { formatWithCommas } from '../lib/util/format'
|
||||
import { ContractProbGraph } from './contract-prob-graph'
|
||||
|
||||
// Auto import doesn't work for some reason...
|
||||
// So we manually register ChartJS components instead:
|
||||
Chart.register(
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
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
|
||||
export const ContractOverview = (props: {
|
||||
contract: Contract
|
||||
className?: string
|
||||
}) => {
|
||||
const { contract, className } = props
|
||||
const { pot, seedAmounts } = contract
|
||||
|
||||
const volume = pot.YES + pot.NO - seedAmounts.YES - seedAmounts.NO
|
||||
|
||||
return (
|
||||
<Col className="max-w-3xl w-full">
|
||||
<Col className={className}>
|
||||
<div className="text-3xl font-medium p-2">{contract.question}</div>
|
||||
|
||||
<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="p-2 whitespace-nowrap">Dec 9</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>
|
||||
|
||||
<Spacer h={4} />
|
||||
|
||||
<Line data={chartData} height={150} />
|
||||
<ContractProbGraph contract={contract} />
|
||||
|
||||
<Spacer h={12} />
|
||||
|
||||
|
|
52
web/components/contract-prob-graph.tsx
Normal file
52
web/components/contract-prob-graph.tsx
Normal 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
12
web/hooks/use-bets.ts
Normal 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
|
||||
}
|
|
@ -1,22 +1,32 @@
|
|||
import { doc, setDoc } from 'firebase/firestore'
|
||||
import { collection, onSnapshot } from 'firebase/firestore'
|
||||
import { db } from './init'
|
||||
|
||||
export type Bet = {
|
||||
id: string
|
||||
userId: string
|
||||
contractId: string
|
||||
|
||||
amount: number // Amount of USD bid
|
||||
amount: number // Amount of bet
|
||||
outcome: 'YES' | 'NO' // Chosen outcome
|
||||
|
||||
// Calculate and replace these on server?
|
||||
createdTime: number
|
||||
dpmWeight: number // Dynamic Parimutuel weight
|
||||
probBefore: number
|
||||
probAverage: number
|
||||
probAfter: number
|
||||
createdTime: number
|
||||
}
|
||||
|
||||
// Push bet to Firestore
|
||||
// TODO: Should bets be subcollections under its contract?
|
||||
export async function saveBet(bet: Bet) {
|
||||
const docRef = doc(db, 'contracts', bet.contractId, 'bets', bet.id)
|
||||
await setDoc(docRef, bet)
|
||||
function getBetsCollection(contractId: string) {
|
||||
return collection(db, 'contracts', contractId, 'bets')
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -24,15 +24,13 @@ export default function ContractPage() {
|
|||
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<Header />
|
||||
|
||||
<div className="w-full flex flex-col p-4 mt-4">
|
||||
<Col className="md:justify-between md:flex-row">
|
||||
<ContractOverview contract={contract} />
|
||||
<Col className="w-full md:justify-between md:flex-row p-4 mt-4">
|
||||
<ContractOverview contract={contract} className="max-w-4xl w-full" />
|
||||
|
||||
<div className="mt-12 md:mt-0" />
|
||||
<div className="mt-12 md:mt-0" />
|
||||
|
||||
<BetPanel className="self-start" contract={contract} />
|
||||
</Col>
|
||||
</div>
|
||||
<BetPanel className="self-start" contract={contract} />
|
||||
</Col>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user