type Bid = { yesBid: number; noBid: number } // An entry has a yes/no for bid, weight, payout, return. Also a current probability export type Entry = { yesBid: number noBid: number yesWeight: number noWeight: number yesPayout: number noPayout: number yesReturn: number noReturn: number prob: number } function makeWeights(bids: Bid[]) { const weights = [] let yesPot = 0 let noPot = 0 // First pass: calculate all the weights for (const { yesBid, noBid } of bids) { const yesWeight = (yesBid * Math.pow(noPot, 2)) / (Math.pow(yesPot, 2) + yesBid * yesPot) || 0 const noWeight = (noBid * Math.pow(yesPot, 2)) / (Math.pow(noPot, 2) + noBid * noPot) || 0 // Note: Need to calculate weights BEFORE updating pot yesPot += yesBid noPot += noBid const prob = Math.pow(yesPot, 2) / (Math.pow(yesPot, 2) + Math.pow(noPot, 2)) weights.push({ yesBid, noBid, yesWeight, noWeight, prob, }) } return weights } export function makeEntries(bids: Bid[]): Entry[] { const YES_SEED = bids[0].yesBid const NO_SEED = bids[0].noBid const weights = makeWeights(bids) const yesPot = weights.reduce((sum, { yesBid }) => sum + yesBid, 0) const noPot = weights.reduce((sum, { noBid }) => sum + noBid, 0) const yesWeightsSum = weights.reduce((sum, entry) => sum + entry.yesWeight, 0) const noWeightsSum = weights.reduce((sum, entry) => sum + entry.noWeight, 0) // Second pass: calculate all the payouts const entries: Entry[] = [] for (const weight of weights) { const { yesBid, noBid, yesWeight, noWeight } = weight // Payout: You get your initial bid back, as well as your share of the // (noPot - seed) according to your yesWeight const yesPayout = yesBid + (yesWeight / yesWeightsSum) * (noPot - NO_SEED) const noPayout = noBid + (noWeight / noWeightsSum) * (yesPot - YES_SEED) const yesReturn = (yesPayout - yesBid) / yesBid const noReturn = (noPayout - noBid) / noBid entries.push({ ...weight, yesPayout, noPayout, yesReturn, noReturn }) } return entries }