formatting
This commit is contained in:
		
							parent
							
								
									df4ecb3fe2
								
							
						
					
					
						commit
						9a834526c0
					
				|  | @ -1,19 +1,19 @@ | |||
| export const PHANTOM_ANTE = 200; | ||||
| export const PHANTOM_ANTE = 200 | ||||
| 
 | ||||
| export const calcStartPool = (initialProbInt: number, ante?: number) => { | ||||
|   const p = initialProbInt / 100.0; | ||||
|   const totalAnte = PHANTOM_ANTE + (ante || 0); | ||||
|   const p = initialProbInt / 100.0 | ||||
|   const totalAnte = PHANTOM_ANTE + (ante || 0) | ||||
| 
 | ||||
|   const poolYes = | ||||
|     p === 0.5 | ||||
|       ? p * totalAnte | ||||
|       : -(totalAnte * (-p + Math.sqrt((-1 + p) * -p))) / (-1 + 2 * p); | ||||
|       : -(totalAnte * (-p + Math.sqrt((-1 + p) * -p))) / (-1 + 2 * p) | ||||
| 
 | ||||
|   const poolNo = totalAnte - poolYes; | ||||
|   const poolNo = totalAnte - poolYes | ||||
| 
 | ||||
|   const f = PHANTOM_ANTE / totalAnte; | ||||
|   const startYes = f * poolYes; | ||||
|   const startNo = f * poolNo; | ||||
|   const f = PHANTOM_ANTE / totalAnte | ||||
|   const startYes = f * poolYes | ||||
|   const startNo = f * poolNo | ||||
| 
 | ||||
|   return { startYes, startNo, poolYes, poolNo }; | ||||
| }; | ||||
|   return { startYes, startNo, poolYes, poolNo } | ||||
| } | ||||
|  |  | |||
|  | @ -1,22 +1,22 @@ | |||
| export type Bet = { | ||||
|   id: string; | ||||
|   userId: string; | ||||
|   contractId: string; | ||||
|   id: string | ||||
|   userId: string | ||||
|   contractId: string | ||||
| 
 | ||||
|   amount: number; // bet size; negative if SELL bet
 | ||||
|   outcome: "YES" | "NO"; | ||||
|   shares: number; // dynamic parimutuel pool weight; negative if SELL bet
 | ||||
|   amount: number // bet size; negative if SELL bet
 | ||||
|   outcome: 'YES' | 'NO' | ||||
|   shares: number // dynamic parimutuel pool weight; negative if SELL bet
 | ||||
| 
 | ||||
|   probBefore: number; | ||||
|   probAfter: number; | ||||
|   probBefore: number | ||||
|   probAfter: number | ||||
| 
 | ||||
|   sale?: { | ||||
|     amount: number; // amount user makes from sale
 | ||||
|     betId: string; // id of bet being sold
 | ||||
|     amount: number // amount user makes from sale
 | ||||
|     betId: string // id of bet being sold
 | ||||
|     // TODO: add sale time?
 | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   isSold?: boolean; // true if this BUY bet has been sold
 | ||||
|   isSold?: boolean // true if this BUY bet has been sold
 | ||||
| 
 | ||||
|   createdTime: number; | ||||
| }; | ||||
|   createdTime: number | ||||
| } | ||||
|  |  | |||
|  | @ -1,140 +1,140 @@ | |||
| import { Bet } from "./bet"; | ||||
| import { Contract } from "./contract"; | ||||
| import { FEES } from "./fees"; | ||||
| import { Bet } from './bet' | ||||
| import { Contract } from './contract' | ||||
| import { FEES } from './fees' | ||||
| 
 | ||||
| export const blah = () => 999; | ||||
| export const blah = () => 999 | ||||
| 
 | ||||
| export const getProbability = (pool: { YES: number; NO: number }) => { | ||||
|   const [yesPool, noPool] = [pool.YES, pool.NO]; | ||||
|   const numerator = Math.pow(yesPool, 2); | ||||
|   const denominator = Math.pow(yesPool, 2) + Math.pow(noPool, 2); | ||||
|   return numerator / denominator; | ||||
| }; | ||||
|   const [yesPool, noPool] = [pool.YES, pool.NO] | ||||
|   const numerator = Math.pow(yesPool, 2) | ||||
|   const denominator = Math.pow(yesPool, 2) + Math.pow(noPool, 2) | ||||
|   return numerator / denominator | ||||
| } | ||||
| 
 | ||||
| export function getProbabilityAfterBet( | ||||
|   pool: { YES: number; NO: number }, | ||||
|   outcome: "YES" | "NO", | ||||
|   outcome: 'YES' | 'NO', | ||||
|   bet: number | ||||
| ) { | ||||
|   const [YES, NO] = [ | ||||
|     pool.YES + (outcome === "YES" ? bet : 0), | ||||
|     pool.NO + (outcome === "NO" ? bet : 0), | ||||
|   ]; | ||||
|   return getProbability({ YES, NO }); | ||||
|     pool.YES + (outcome === 'YES' ? bet : 0), | ||||
|     pool.NO + (outcome === 'NO' ? bet : 0), | ||||
|   ] | ||||
|   return getProbability({ YES, NO }) | ||||
| } | ||||
| 
 | ||||
| export function calculateShares( | ||||
|   pool: { YES: number; NO: number }, | ||||
|   bet: number, | ||||
|   betChoice: "YES" | "NO" | ||||
|   betChoice: 'YES' | 'NO' | ||||
| ) { | ||||
|   const [yesPool, noPool] = [pool.YES, pool.NO]; | ||||
|   const [yesPool, noPool] = [pool.YES, pool.NO] | ||||
| 
 | ||||
|   return betChoice === "YES" | ||||
|   return betChoice === 'YES' | ||||
|     ? bet + (bet * noPool ** 2) / (yesPool ** 2 + bet * yesPool) | ||||
|     : bet + (bet * yesPool ** 2) / (noPool ** 2 + bet * noPool); | ||||
|     : bet + (bet * yesPool ** 2) / (noPool ** 2 + bet * noPool) | ||||
| } | ||||
| 
 | ||||
| export function calculatePayout( | ||||
|   contract: Contract, | ||||
|   bet: Bet, | ||||
|   outcome: "YES" | "NO" | "CANCEL" | "MKT" | ||||
|   outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT' | ||||
| ) { | ||||
|   const { amount, outcome: betOutcome, shares } = bet; | ||||
|   const { amount, outcome: betOutcome, shares } = bet | ||||
| 
 | ||||
|   if (outcome === "CANCEL") return amount; | ||||
|   if (outcome === "MKT") return calculateMktPayout(contract, bet); | ||||
|   if (outcome === 'CANCEL') return amount | ||||
|   if (outcome === 'MKT') return calculateMktPayout(contract, bet) | ||||
| 
 | ||||
|   if (betOutcome !== outcome) return 0; | ||||
|   if (betOutcome !== outcome) return 0 | ||||
| 
 | ||||
|   const { totalShares, totalBets } = contract; | ||||
|   const { totalShares, totalBets } = contract | ||||
| 
 | ||||
|   if (totalShares[outcome] === 0) return 0; | ||||
|   if (totalShares[outcome] === 0) return 0 | ||||
| 
 | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO; | ||||
|   const truePool = contract.pool.YES + contract.pool.NO - startPool; | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO | ||||
|   const truePool = contract.pool.YES + contract.pool.NO - startPool | ||||
| 
 | ||||
|   if (totalBets[outcome] >= truePool) | ||||
|     return (amount / totalBets[outcome]) * truePool; | ||||
|     return (amount / totalBets[outcome]) * truePool | ||||
| 
 | ||||
|   const total = totalShares[outcome] - totalBets[outcome]; | ||||
|   const winningsPool = truePool - totalBets[outcome]; | ||||
|   const total = totalShares[outcome] - totalBets[outcome] | ||||
|   const winningsPool = truePool - totalBets[outcome] | ||||
| 
 | ||||
|   return (1 - FEES) * (amount + ((shares - amount) / total) * winningsPool); | ||||
|   return (1 - FEES) * (amount + ((shares - amount) / total) * winningsPool) | ||||
| } | ||||
| 
 | ||||
| export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) { | ||||
|   const { amount, outcome, shares } = bet; | ||||
|   const { totalShares, totalBets } = contract; | ||||
|   const { amount, outcome, shares } = bet | ||||
|   const { totalShares, totalBets } = contract | ||||
| 
 | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO; | ||||
|   const truePool = amount + contract.pool.YES + contract.pool.NO - startPool; | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO | ||||
|   const truePool = amount + contract.pool.YES + contract.pool.NO - startPool | ||||
| 
 | ||||
|   const totalBetsOutcome = totalBets[outcome] + amount; | ||||
|   const totalSharesOutcome = totalShares[outcome] + shares; | ||||
|   const totalBetsOutcome = totalBets[outcome] + amount | ||||
|   const totalSharesOutcome = totalShares[outcome] + shares | ||||
| 
 | ||||
|   if (totalBetsOutcome >= truePool) | ||||
|     return (amount / totalBetsOutcome) * truePool; | ||||
|     return (amount / totalBetsOutcome) * truePool | ||||
| 
 | ||||
|   const total = totalSharesOutcome - totalBetsOutcome; | ||||
|   const winningsPool = truePool - totalBetsOutcome; | ||||
|   const total = totalSharesOutcome - totalBetsOutcome | ||||
|   const winningsPool = truePool - totalBetsOutcome | ||||
| 
 | ||||
|   return (1 - FEES) * (amount + ((shares - amount) / total) * winningsPool); | ||||
|   return (1 - FEES) * (amount + ((shares - amount) / total) * winningsPool) | ||||
| } | ||||
| 
 | ||||
| function calculateMktPayout(contract: Contract, bet: Bet) { | ||||
|   const p = | ||||
|     contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2); | ||||
|     contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2) | ||||
|   const weightedTotal = | ||||
|     p * contract.totalBets.YES + (1 - p) * contract.totalBets.NO; | ||||
|     p * contract.totalBets.YES + (1 - p) * contract.totalBets.NO | ||||
| 
 | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO; | ||||
|   const truePool = contract.pool.YES + contract.pool.NO - startPool; | ||||
|   const startPool = contract.startPool.YES + contract.startPool.NO | ||||
|   const truePool = contract.pool.YES + contract.pool.NO - startPool | ||||
| 
 | ||||
|   const betP = bet.outcome === "YES" ? p : 1 - p; | ||||
|   const betP = bet.outcome === 'YES' ? p : 1 - p | ||||
| 
 | ||||
|   if (weightedTotal >= truePool) { | ||||
|     return ((betP * bet.amount) / weightedTotal) * truePool; | ||||
|     return ((betP * bet.amount) / weightedTotal) * truePool | ||||
|   } | ||||
| 
 | ||||
|   const winningsPool = truePool - weightedTotal; | ||||
|   const winningsPool = truePool - weightedTotal | ||||
| 
 | ||||
|   const weightedShareTotal = | ||||
|     p * (contract.totalShares.YES - contract.totalBets.YES) + | ||||
|     (1 - p) * (contract.totalShares.NO - contract.totalBets.NO); | ||||
|     (1 - p) * (contract.totalShares.NO - contract.totalBets.NO) | ||||
| 
 | ||||
|   return ( | ||||
|     (1 - FEES) * | ||||
|     (betP * bet.amount + | ||||
|       ((betP * (bet.shares - bet.amount)) / weightedShareTotal) * winningsPool) | ||||
|   ); | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function resolvedPayout(contract: Contract, bet: Bet) { | ||||
|   if (contract.resolution) | ||||
|     return calculatePayout(contract, bet, contract.resolution); | ||||
|   throw new Error("Contract was not resolved"); | ||||
|     return calculatePayout(contract, bet, contract.resolution) | ||||
|   throw new Error('Contract was not resolved') | ||||
| } | ||||
| 
 | ||||
| export function currentValue(contract: Contract, bet: Bet) { | ||||
|   const prob = getProbability(contract.pool); | ||||
|   const yesPayout = calculatePayout(contract, bet, "YES"); | ||||
|   const noPayout = calculatePayout(contract, bet, "NO"); | ||||
|   const prob = getProbability(contract.pool) | ||||
|   const yesPayout = calculatePayout(contract, bet, 'YES') | ||||
|   const noPayout = calculatePayout(contract, bet, 'NO') | ||||
| 
 | ||||
|   return prob * yesPayout + (1 - prob) * noPayout; | ||||
|   return prob * yesPayout + (1 - prob) * noPayout | ||||
| } | ||||
| 
 | ||||
| export function calculateSaleAmount(contract: Contract, bet: Bet) { | ||||
|   const { shares, outcome } = bet; | ||||
|   const { shares, outcome } = bet | ||||
| 
 | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool; | ||||
|   const { YES: yesStart, NO: noStart } = contract.startPool; | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares; | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool | ||||
|   const { YES: yesStart, NO: noStart } = contract.startPool | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares | ||||
| 
 | ||||
|   const [y, n, s] = [yesPool, noPool, shares]; | ||||
|   const [y, n, s] = [yesPool, noPool, shares] | ||||
| 
 | ||||
|   const shareValue = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? // https://www.wolframalpha.com/input/?i=b+%2B+%28b+n%5E2%29%2F%28y+%28-b+%2B+y%29%29+%3D+c+solve+b
 | ||||
|         (n ** 2 + | ||||
|           s * y + | ||||
|  | @ -149,18 +149,18 @@ export function calculateSaleAmount(contract: Contract, bet: Bet) { | |||
|           Math.sqrt( | ||||
|             y ** 4 + (s - n) ** 2 * n ** 2 + 2 * y ** 2 * n * (s + n) | ||||
|           )) / | ||||
|         (2 * n); | ||||
|         (2 * n) | ||||
| 
 | ||||
|   const startPool = yesStart + noStart; | ||||
|   const pool = yesPool + noPool - startPool; | ||||
|   const startPool = yesStart + noStart | ||||
|   const pool = yesPool + noPool - startPool | ||||
| 
 | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2); | ||||
|   const f = pool / (probBefore * yesShares + (1 - probBefore) * noShares); | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2) | ||||
|   const f = pool / (probBefore * yesShares + (1 - probBefore) * noShares) | ||||
| 
 | ||||
|   const myPool = outcome === "YES" ? yesPool - yesStart : noPool - noStart; | ||||
|   const myPool = outcome === 'YES' ? yesPool - yesStart : noPool - noStart | ||||
| 
 | ||||
|   const adjShareValue = Math.min(Math.min(1, f) * shareValue, myPool); | ||||
|   const adjShareValue = Math.min(Math.min(1, f) * shareValue, myPool) | ||||
| 
 | ||||
|   const saleAmount = (1 - FEES) * adjShareValue; | ||||
|   return saleAmount; | ||||
|   const saleAmount = (1 - FEES) * adjShareValue | ||||
|   return saleAmount | ||||
| } | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| // Currently, comments are created after the bet, not atomically with the bet.
 | ||||
| // They're uniquely identified by the pair contractId/betId.
 | ||||
| export type Comment = { | ||||
|   contractId: string; | ||||
|   betId: string; | ||||
|   text: string; | ||||
|   createdTime: number; | ||||
|   contractId: string | ||||
|   betId: string | ||||
|   text: string | ||||
|   createdTime: number | ||||
|   // Denormalized, for rendering comments
 | ||||
|   userName?: string; | ||||
|   userUsername?: string; | ||||
|   userAvatarUrl?: string; | ||||
| }; | ||||
|   userName?: string | ||||
|   userUsername?: string | ||||
|   userAvatarUrl?: string | ||||
| } | ||||
|  |  | |||
|  | @ -1,29 +1,29 @@ | |||
| export type Contract = { | ||||
|   id: string; | ||||
|   slug: string; // auto-generated; must be unique
 | ||||
|   id: string | ||||
|   slug: string // auto-generated; must be unique
 | ||||
| 
 | ||||
|   creatorId: string; | ||||
|   creatorName: string; | ||||
|   creatorUsername: string; | ||||
|   creatorId: string | ||||
|   creatorName: string | ||||
|   creatorUsername: string | ||||
| 
 | ||||
|   question: string; | ||||
|   description: string; // More info about what the contract is about
 | ||||
|   outcomeType: "BINARY"; // | 'MULTI' | 'interval' | 'date'
 | ||||
|   question: string | ||||
|   description: string // More info about what the contract is about
 | ||||
|   outcomeType: 'BINARY' // | 'MULTI' | 'interval' | 'date'
 | ||||
|   // outcomes: ['YES', 'NO']
 | ||||
| 
 | ||||
|   startPool: { YES: number; NO: number }; | ||||
|   pool: { YES: number; NO: number }; | ||||
|   totalShares: { YES: number; NO: number }; | ||||
|   totalBets: { YES: number; NO: number }; | ||||
|   startPool: { YES: number; NO: number } | ||||
|   pool: { YES: number; NO: number } | ||||
|   totalShares: { YES: number; NO: number } | ||||
|   totalBets: { YES: number; NO: number } | ||||
| 
 | ||||
|   createdTime: number; // Milliseconds since epoch
 | ||||
|   lastUpdatedTime: number; // If the question or description was changed
 | ||||
|   closeTime?: number; // When no more trading is allowed
 | ||||
|   createdTime: number // Milliseconds since epoch
 | ||||
|   lastUpdatedTime: number // If the question or description was changed
 | ||||
|   closeTime?: number // When no more trading is allowed
 | ||||
| 
 | ||||
|   isResolved: boolean; | ||||
|   resolutionTime?: number; // When the contract creator resolved the market
 | ||||
|   resolution?: "YES" | "NO" | "CANCEL"; // Chosen by creator; must be one of outcomes
 | ||||
|   isResolved: boolean | ||||
|   resolutionTime?: number // When the contract creator resolved the market
 | ||||
|   resolution?: 'YES' | 'NO' | 'CANCEL' // Chosen by creator; must be one of outcomes
 | ||||
| 
 | ||||
|   volume24Hours: number; | ||||
|   volume7Days: number; | ||||
| }; | ||||
|   volume24Hours: number | ||||
|   volume7Days: number | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| export const PLATFORM_FEE = 0.01; // == 1%
 | ||||
| export const CREATOR_FEE = 0.01; | ||||
| export const PLATFORM_FEE = 0.01 // == 1%
 | ||||
| export const CREATOR_FEE = 0.01 | ||||
| 
 | ||||
| export const FEES = PLATFORM_FEE + CREATOR_FEE; | ||||
| export const FEES = PLATFORM_FEE + CREATOR_FEE | ||||
|  |  | |||
|  | @ -1,42 +1,42 @@ | |||
| import { Bet } from "./bet"; | ||||
| import { Contract } from "./contract"; | ||||
| import { User } from "./user"; | ||||
| import { Bet } from './bet' | ||||
| import { Contract } from './contract' | ||||
| import { User } from './user' | ||||
| 
 | ||||
| export const getNewBetInfo = ( | ||||
|   user: User, | ||||
|   outcome: "YES" | "NO", | ||||
|   outcome: 'YES' | 'NO', | ||||
|   amount: number, | ||||
|   contract: Contract, | ||||
|   newBetId: string | ||||
| ) => { | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool; | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool | ||||
| 
 | ||||
|   const newPool = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesPool + amount, NO: noPool } | ||||
|       : { YES: yesPool, NO: noPool + amount }; | ||||
|       : { YES: yesPool, NO: noPool + amount } | ||||
| 
 | ||||
|   const shares = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? amount + (amount * noPool ** 2) / (yesPool ** 2 + amount * yesPool) | ||||
|       : amount + (amount * yesPool ** 2) / (noPool ** 2 + amount * noPool); | ||||
|       : amount + (amount * yesPool ** 2) / (noPool ** 2 + amount * noPool) | ||||
| 
 | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares; | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares | ||||
| 
 | ||||
|   const newTotalShares = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesShares + shares, NO: noShares } | ||||
|       : { YES: yesShares, NO: noShares + shares }; | ||||
|       : { YES: yesShares, NO: noShares + shares } | ||||
| 
 | ||||
|   const { YES: yesBets, NO: noBets } = contract.totalBets; | ||||
|   const { YES: yesBets, NO: noBets } = contract.totalBets | ||||
| 
 | ||||
|   const newTotalBets = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesBets + amount, NO: noBets } | ||||
|       : { YES: yesBets, NO: noBets + amount }; | ||||
|       : { YES: yesBets, NO: noBets + amount } | ||||
| 
 | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2); | ||||
|   const probAfter = newPool.YES ** 2 / (newPool.YES ** 2 + newPool.NO ** 2); | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2) | ||||
|   const probAfter = newPool.YES ** 2 / (newPool.YES ** 2 + newPool.NO ** 2) | ||||
| 
 | ||||
|   const newBet: Bet = { | ||||
|     id: newBetId, | ||||
|  | @ -48,9 +48,9 @@ export const getNewBetInfo = ( | |||
|     probBefore, | ||||
|     probAfter, | ||||
|     createdTime: Date.now(), | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   const newBalance = user.balance - amount; | ||||
|   const newBalance = user.balance - amount | ||||
| 
 | ||||
|   return { newBet, newPool, newTotalShares, newTotalBets, newBalance }; | ||||
| }; | ||||
|   return { newBet, newPool, newTotalShares, newTotalBets, newBalance } | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { calcStartPool } from "./antes"; | ||||
| import { Contract } from "./contract"; | ||||
| import { User } from "./user"; | ||||
| import { calcStartPool } from './antes' | ||||
| import { Contract } from './contract' | ||||
| import { User } from './user' | ||||
| 
 | ||||
| export function getNewContract( | ||||
|   id: string, | ||||
|  | @ -15,12 +15,12 @@ export function getNewContract( | |||
|   const { startYes, startNo, poolYes, poolNo } = calcStartPool( | ||||
|     initialProb, | ||||
|     ante | ||||
|   ); | ||||
|   ) | ||||
| 
 | ||||
|   const contract: Contract = { | ||||
|     id, | ||||
|     slug, | ||||
|     outcomeType: "BINARY", | ||||
|     outcomeType: 'BINARY', | ||||
| 
 | ||||
|     creatorId: creator.id, | ||||
|     creatorName: creator.name, | ||||
|  | @ -40,9 +40,9 @@ export function getNewContract( | |||
| 
 | ||||
|     volume24Hours: 0, | ||||
|     volume7Days: 0, | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   if (closeTime) contract.closeTime = closeTime; | ||||
|   if (closeTime) contract.closeTime = closeTime | ||||
| 
 | ||||
|   return contract; | ||||
|   return contract | ||||
| } | ||||
|  |  | |||
|  | @ -1,17 +1,17 @@ | |||
| import { Bet } from "./bet"; | ||||
| import { Contract } from "./contract"; | ||||
| import { CREATOR_FEE, FEES } from "./fees"; | ||||
| import { Bet } from './bet' | ||||
| import { Contract } from './contract' | ||||
| import { CREATOR_FEE, FEES } from './fees' | ||||
| 
 | ||||
| export const getCancelPayouts = (truePool: number, bets: Bet[]) => { | ||||
|   console.log("resolved N/A, pool M$", truePool); | ||||
|   console.log('resolved N/A, pool M$', truePool) | ||||
| 
 | ||||
|   const betSum = sumBy(bets, (b) => b.amount); | ||||
|   const betSum = sumBy(bets, (b) => b.amount) | ||||
| 
 | ||||
|   return bets.map((bet) => ({ | ||||
|     userId: bet.userId, | ||||
|     payout: (bet.amount / betSum) * truePool, | ||||
|   })); | ||||
| }; | ||||
|   })) | ||||
| } | ||||
| 
 | ||||
| export const getStandardPayouts = ( | ||||
|   outcome: string, | ||||
|  | @ -19,26 +19,26 @@ export const getStandardPayouts = ( | |||
|   contract: Contract, | ||||
|   bets: Bet[] | ||||
| ) => { | ||||
|   const [yesBets, noBets] = partition(bets, (bet) => bet.outcome === "YES"); | ||||
|   const winningBets = outcome === "YES" ? yesBets : noBets; | ||||
|   const [yesBets, noBets] = partition(bets, (bet) => bet.outcome === 'YES') | ||||
|   const winningBets = outcome === 'YES' ? yesBets : noBets | ||||
| 
 | ||||
|   const betSum = sumBy(winningBets, (b) => b.amount); | ||||
|   const betSum = sumBy(winningBets, (b) => b.amount) | ||||
| 
 | ||||
|   if (betSum >= truePool) return getCancelPayouts(truePool, winningBets); | ||||
|   if (betSum >= truePool) return getCancelPayouts(truePool, winningBets) | ||||
| 
 | ||||
|   const creatorPayout = CREATOR_FEE * truePool; | ||||
|   const creatorPayout = CREATOR_FEE * truePool | ||||
|   console.log( | ||||
|     "resolved", | ||||
|     'resolved', | ||||
|     outcome, | ||||
|     "pool: M$", | ||||
|     'pool: M$', | ||||
|     truePool, | ||||
|     "creator fee: M$", | ||||
|     'creator fee: M$', | ||||
|     creatorPayout | ||||
|   ); | ||||
|   ) | ||||
| 
 | ||||
|   const shareDifferenceSum = sumBy(winningBets, (b) => b.shares - b.amount); | ||||
|   const shareDifferenceSum = sumBy(winningBets, (b) => b.shares - b.amount) | ||||
| 
 | ||||
|   const winningsPool = truePool - betSum; | ||||
|   const winningsPool = truePool - betSum | ||||
| 
 | ||||
|   const winnerPayouts = winningBets.map((bet) => ({ | ||||
|     userId: bet.userId, | ||||
|  | @ -46,12 +46,12 @@ export const getStandardPayouts = ( | |||
|       (1 - FEES) * | ||||
|       (bet.amount + | ||||
|         ((bet.shares - bet.amount) / shareDifferenceSum) * winningsPool), | ||||
|   })); | ||||
|   })) | ||||
| 
 | ||||
|   return winnerPayouts.concat([ | ||||
|     { userId: contract.creatorId, payout: creatorPayout }, | ||||
|   ]); // add creator fee
 | ||||
| }; | ||||
|   ]) // add creator fee
 | ||||
| } | ||||
| 
 | ||||
| export const getMktPayouts = ( | ||||
|   truePool: number, | ||||
|  | @ -59,30 +59,30 @@ export const getMktPayouts = ( | |||
|   bets: Bet[] | ||||
| ) => { | ||||
|   const p = | ||||
|     contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2); | ||||
|   console.log("Resolved MKT at p=", p, "pool: $M", truePool); | ||||
|     contract.pool.YES ** 2 / (contract.pool.YES ** 2 + contract.pool.NO ** 2) | ||||
|   console.log('Resolved MKT at p=', p, 'pool: $M', truePool) | ||||
| 
 | ||||
|   const [yesBets, noBets] = partition(bets, (bet) => bet.outcome === "YES"); | ||||
|   const [yesBets, noBets] = partition(bets, (bet) => bet.outcome === 'YES') | ||||
| 
 | ||||
|   const weightedBetTotal = | ||||
|     p * sumBy(yesBets, (b) => b.amount) + | ||||
|     (1 - p) * sumBy(noBets, (b) => b.amount); | ||||
|     (1 - p) * sumBy(noBets, (b) => b.amount) | ||||
| 
 | ||||
|   if (weightedBetTotal >= truePool) { | ||||
|     return bets.map((bet) => ({ | ||||
|       userId: bet.userId, | ||||
|       payout: | ||||
|         (((bet.outcome === "YES" ? p : 1 - p) * bet.amount) / | ||||
|         (((bet.outcome === 'YES' ? p : 1 - p) * bet.amount) / | ||||
|           weightedBetTotal) * | ||||
|         truePool, | ||||
|     })); | ||||
|     })) | ||||
|   } | ||||
| 
 | ||||
|   const winningsPool = truePool - weightedBetTotal; | ||||
|   const winningsPool = truePool - weightedBetTotal | ||||
| 
 | ||||
|   const weightedShareTotal = | ||||
|     p * sumBy(yesBets, (b) => b.shares - b.amount) + | ||||
|     (1 - p) * sumBy(noBets, (b) => b.shares - b.amount); | ||||
|     (1 - p) * sumBy(noBets, (b) => b.shares - b.amount) | ||||
| 
 | ||||
|   const yesPayouts = yesBets.map((bet) => ({ | ||||
|     userId: bet.userId, | ||||
|  | @ -90,7 +90,7 @@ export const getMktPayouts = ( | |||
|       (1 - FEES) * | ||||
|       (p * bet.amount + | ||||
|         ((p * (bet.shares - bet.amount)) / weightedShareTotal) * winningsPool), | ||||
|   })); | ||||
|   })) | ||||
| 
 | ||||
|   const noPayouts = noBets.map((bet) => ({ | ||||
|     userId: bet.userId, | ||||
|  | @ -99,30 +99,30 @@ export const getMktPayouts = ( | |||
|       ((1 - p) * bet.amount + | ||||
|         (((1 - p) * (bet.shares - bet.amount)) / weightedShareTotal) * | ||||
|           winningsPool), | ||||
|   })); | ||||
|   })) | ||||
| 
 | ||||
|   const creatorPayout = CREATOR_FEE * truePool; | ||||
|   const creatorPayout = CREATOR_FEE * truePool | ||||
| 
 | ||||
|   return [ | ||||
|     ...yesPayouts, | ||||
|     ...noPayouts, | ||||
|     { userId: contract.creatorId, payout: creatorPayout }, | ||||
|   ]; | ||||
| }; | ||||
|   ] | ||||
| } | ||||
| 
 | ||||
| const partition = <T>(array: T[], f: (t: T) => boolean) => { | ||||
|   const yes = []; | ||||
|   const no = []; | ||||
|   const yes = [] | ||||
|   const no = [] | ||||
| 
 | ||||
|   for (let t of array) { | ||||
|     if (f(t)) yes.push(t); | ||||
|     else no.push(t); | ||||
|     if (f(t)) yes.push(t) | ||||
|     else no.push(t) | ||||
|   } | ||||
| 
 | ||||
|   return [yes, no] as [T[], T[]]; | ||||
| }; | ||||
|   return [yes, no] as [T[], T[]] | ||||
| } | ||||
| 
 | ||||
| const sumBy = <T>(array: T[], f: (t: T) => number) => { | ||||
|   const values = array.map(f); | ||||
|   return values.reduce((prev, cur) => prev + cur, 0); | ||||
| }; | ||||
|   const values = array.map(f) | ||||
|   return values.reduce((prev, cur) => prev + cur, 0) | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { Bet } from "./bet"; | ||||
| import { Contract } from "./contract"; | ||||
| import { CREATOR_FEE, PLATFORM_FEE } from "./fees"; | ||||
| import { User } from "./user"; | ||||
| import { Bet } from './bet' | ||||
| import { Contract } from './contract' | ||||
| import { CREATOR_FEE, PLATFORM_FEE } from './fees' | ||||
| import { User } from './user' | ||||
| 
 | ||||
| export const getSellBetInfo = ( | ||||
|   user: User, | ||||
|  | @ -9,17 +9,17 @@ export const getSellBetInfo = ( | |||
|   contract: Contract, | ||||
|   newBetId: string | ||||
| ) => { | ||||
|   const { id: betId, amount, shares, outcome } = bet; | ||||
|   const { id: betId, amount, shares, outcome } = bet | ||||
| 
 | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool; | ||||
|   const { YES: yesStart, NO: noStart } = contract.startPool; | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares; | ||||
|   const { YES: yesBets, NO: noBets } = contract.totalBets; | ||||
|   const { YES: yesPool, NO: noPool } = contract.pool | ||||
|   const { YES: yesStart, NO: noStart } = contract.startPool | ||||
|   const { YES: yesShares, NO: noShares } = contract.totalShares | ||||
|   const { YES: yesBets, NO: noBets } = contract.totalBets | ||||
| 
 | ||||
|   const [y, n, s] = [yesPool, noPool, shares]; | ||||
|   const [y, n, s] = [yesPool, noPool, shares] | ||||
| 
 | ||||
|   const shareValue = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? // https://www.wolframalpha.com/input/?i=b+%2B+%28b+n%5E2%29%2F%28y+%28-b+%2B+y%29%29+%3D+c+solve+b
 | ||||
|         (n ** 2 + | ||||
|           s * y + | ||||
|  | @ -34,50 +34,50 @@ export const getSellBetInfo = ( | |||
|           Math.sqrt( | ||||
|             y ** 4 + (s - n) ** 2 * n ** 2 + 2 * y ** 2 * n * (s + n) | ||||
|           )) / | ||||
|         (2 * n); | ||||
|         (2 * n) | ||||
| 
 | ||||
|   const startPool = yesStart + noStart; | ||||
|   const pool = yesPool + noPool - startPool; | ||||
|   const startPool = yesStart + noStart | ||||
|   const pool = yesPool + noPool - startPool | ||||
| 
 | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2); | ||||
|   const probBefore = yesPool ** 2 / (yesPool ** 2 + noPool ** 2) | ||||
| 
 | ||||
|   const f = pool / (probBefore * yesShares + (1 - probBefore) * noShares); | ||||
|   const f = pool / (probBefore * yesShares + (1 - probBefore) * noShares) | ||||
| 
 | ||||
|   const myPool = outcome === "YES" ? yesPool - yesStart : noPool - noStart; | ||||
|   const myPool = outcome === 'YES' ? yesPool - yesStart : noPool - noStart | ||||
| 
 | ||||
|   const adjShareValue = Math.min(Math.min(1, f) * shareValue, myPool); | ||||
|   const adjShareValue = Math.min(Math.min(1, f) * shareValue, myPool) | ||||
| 
 | ||||
|   const newPool = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesPool - adjShareValue, NO: noPool } | ||||
|       : { YES: yesPool, NO: noPool - adjShareValue }; | ||||
|       : { YES: yesPool, NO: noPool - adjShareValue } | ||||
| 
 | ||||
|   const newTotalShares = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesShares - shares, NO: noShares } | ||||
|       : { YES: yesShares, NO: noShares - shares }; | ||||
|       : { YES: yesShares, NO: noShares - shares } | ||||
| 
 | ||||
|   const newTotalBets = | ||||
|     outcome === "YES" | ||||
|     outcome === 'YES' | ||||
|       ? { YES: yesBets - amount, NO: noBets } | ||||
|       : { YES: yesBets, NO: noBets - amount }; | ||||
|       : { YES: yesBets, NO: noBets - amount } | ||||
| 
 | ||||
|   const probAfter = newPool.YES ** 2 / (newPool.YES ** 2 + newPool.NO ** 2); | ||||
|   const probAfter = newPool.YES ** 2 / (newPool.YES ** 2 + newPool.NO ** 2) | ||||
| 
 | ||||
|   const creatorFee = CREATOR_FEE * adjShareValue; | ||||
|   const saleAmount = (1 - CREATOR_FEE - PLATFORM_FEE) * adjShareValue; | ||||
|   const creatorFee = CREATOR_FEE * adjShareValue | ||||
|   const saleAmount = (1 - CREATOR_FEE - PLATFORM_FEE) * adjShareValue | ||||
| 
 | ||||
|   console.log( | ||||
|     "SELL M$", | ||||
|     'SELL M$', | ||||
|     amount, | ||||
|     outcome, | ||||
|     "for M$", | ||||
|     'for M$', | ||||
|     saleAmount, | ||||
|     "M$/share:", | ||||
|     'M$/share:', | ||||
|     f, | ||||
|     "creator fee: M$", | ||||
|     'creator fee: M$', | ||||
|     creatorFee | ||||
|   ); | ||||
|   ) | ||||
| 
 | ||||
|   const newBet: Bet = { | ||||
|     id: newBetId, | ||||
|  | @ -93,9 +93,9 @@ export const getSellBetInfo = ( | |||
|       amount: saleAmount, | ||||
|       betId, | ||||
|     }, | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   const newBalance = user.balance + saleAmount; | ||||
|   const newBalance = user.balance + saleAmount | ||||
| 
 | ||||
|   return { | ||||
|     newBet, | ||||
|  | @ -104,5 +104,5 @@ export const getSellBetInfo = ( | |||
|     newTotalBets, | ||||
|     newBalance, | ||||
|     creatorFee, | ||||
|   }; | ||||
| }; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| export type User = { | ||||
|   id: string; | ||||
|   email: string; | ||||
|   name: string; | ||||
|   username: string; | ||||
|   avatarUrl: string; | ||||
|   balance: number; | ||||
|   createdTime: number; | ||||
|   lastUpdatedTime: number; | ||||
| }; | ||||
|   id: string | ||||
|   email: string | ||||
|   name: string | ||||
|   username: string | ||||
|   avatarUrl: string | ||||
|   balance: number | ||||
|   createdTime: number | ||||
|   lastUpdatedTime: number | ||||
| } | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| export const randomString = () => Math.random().toString(16).substr(2, 14); | ||||
| export const randomString = () => Math.random().toString(16).substr(2, 14) | ||||
|  |  | |||
|  | @ -1,16 +1,16 @@ | |||
| export const slugify = ( | ||||
|   text: string, | ||||
|   separator = "-", | ||||
|   separator = '-', | ||||
|   maxLength = 35 | ||||
| ): string => { | ||||
|   return text | ||||
|     .toString() | ||||
|     .normalize("NFD") // split an accented letter in the base letter and the acent
 | ||||
|     .replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
 | ||||
|     .normalize('NFD') // split an accented letter in the base letter and the acent
 | ||||
|     .replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
 | ||||
|     .toLowerCase() | ||||
|     .trim() | ||||
|     .replace(/[^a-z0-9 ]/g, "") // remove all chars not letters, numbers and spaces (to be replaced)
 | ||||
|     .replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
 | ||||
|     .replace(/\s+/g, separator) | ||||
|     .substring(0, maxLength) | ||||
|     .replace(new RegExp(separator + "+$", "g"), ""); // remove terminal separators
 | ||||
| }; | ||||
|     .replace(new RegExp(separator + '+$', 'g'), '') // remove terminal separators
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user