create numeric contracts
This commit is contained in:
parent
1e3a7747ee
commit
51866c8612
|
@ -9,7 +9,7 @@ export type Answer = {
|
|||
userId: string
|
||||
username: string
|
||||
name: string
|
||||
avatarUrl: string
|
||||
avatarUrl?: string
|
||||
|
||||
text: string
|
||||
}
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import { Bet } from './bet'
|
||||
import { getDpmProbability } from './calculate-dpm'
|
||||
import { Binary, CPMM, DPM, FreeResponse, FullContract } from './contract'
|
||||
import {
|
||||
Binary,
|
||||
CPMM,
|
||||
DPM,
|
||||
FreeResponse,
|
||||
FullContract,
|
||||
Numeric,
|
||||
} from './contract'
|
||||
import { User } from './user'
|
||||
import { LiquidityProvision } from './liquidity-provision'
|
||||
import { noFees } from './fees'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
export const FIXED_ANTE = 100
|
||||
|
||||
|
@ -106,3 +114,31 @@ export function getFreeAnswerAnte(
|
|||
|
||||
return anteBet
|
||||
}
|
||||
|
||||
export function getNumericAntes(
|
||||
creator: User,
|
||||
contract: FullContract<DPM, Numeric>,
|
||||
ante: number
|
||||
) {
|
||||
const { bucketCount, createdTime } = contract
|
||||
|
||||
const betAnte = ante / bucketCount
|
||||
const betShares = Math.sqrt(ante ** 2 / bucketCount)
|
||||
|
||||
return _.range(0, bucketCount).map((i) => {
|
||||
const anteBet: Omit<Bet, 'id'> = {
|
||||
userId: creator.id,
|
||||
contractId: contract.id,
|
||||
amount: betAnte,
|
||||
shares: betShares,
|
||||
outcome: i.toString(),
|
||||
probBefore: 0,
|
||||
probAfter: 1 / bucketCount,
|
||||
createdTime,
|
||||
isAnte: true,
|
||||
fees: noFees,
|
||||
}
|
||||
|
||||
return anteBet
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import * as _ from 'lodash'
|
||||
import { Answer } from './answer'
|
||||
import { Fees } from './fees'
|
||||
|
||||
|
@ -12,7 +12,7 @@ export type FullContract<
|
|||
creatorId: string
|
||||
creatorName: string
|
||||
creatorUsername: string
|
||||
creatorAvatarUrl: string
|
||||
creatorAvatarUrl?: string
|
||||
|
||||
question: string
|
||||
description: string // More info about what the contract is about
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { PHANTOM_ANTE } from './antes'
|
||||
import {
|
||||
Binary,
|
||||
|
@ -5,6 +7,7 @@ import {
|
|||
CPMM,
|
||||
DPM,
|
||||
FreeResponse,
|
||||
Numeric,
|
||||
outcomeType,
|
||||
} from './contract'
|
||||
import { User } from './user'
|
||||
|
@ -22,7 +25,12 @@ export function getNewContract(
|
|||
initialProb: number,
|
||||
ante: number,
|
||||
closeTime: number,
|
||||
extraTags: string[]
|
||||
extraTags: string[],
|
||||
|
||||
// used for numeric markets
|
||||
bucketCount: number,
|
||||
min: number,
|
||||
max: number
|
||||
) {
|
||||
const tags = parseTags(
|
||||
`${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}`
|
||||
|
@ -32,6 +40,8 @@ export function getNewContract(
|
|||
const propsByOutcomeType =
|
||||
outcomeType === 'BINARY'
|
||||
? getBinaryCpmmProps(initialProb, ante) // getBinaryDpmProps(initialProb, ante)
|
||||
: outcomeType === 'NUMERIC'
|
||||
? getNumericProps(ante, bucketCount, min, max)
|
||||
: getFreeAnswerProps(ante)
|
||||
|
||||
const volume = outcomeType === 'BINARY' ? 0 : ante
|
||||
|
@ -115,6 +125,37 @@ const getFreeAnswerProps = (ante: number) => {
|
|||
return system
|
||||
}
|
||||
|
||||
const getNumericProps = (
|
||||
ante: number,
|
||||
bucketCount: number,
|
||||
min: number,
|
||||
max: number
|
||||
) => {
|
||||
const buckets = _.range(0, bucketCount).map((i) => i.toString())
|
||||
|
||||
const betAnte = ante / bucketCount
|
||||
const pool = Object.fromEntries(buckets.map((answer) => [answer, betAnte]))
|
||||
const totalBets = pool
|
||||
|
||||
const betShares = Math.sqrt(ante ** 2 / bucketCount)
|
||||
const totalShares = Object.fromEntries(
|
||||
buckets.map((answer) => [answer, betShares])
|
||||
)
|
||||
|
||||
const system: DPM & Numeric = {
|
||||
mechanism: 'dpm-2',
|
||||
outcomeType: 'NUMERIC',
|
||||
pool,
|
||||
totalBets,
|
||||
totalShares,
|
||||
bucketCount,
|
||||
min,
|
||||
max,
|
||||
}
|
||||
|
||||
return system
|
||||
}
|
||||
|
||||
const getMultiProps = (
|
||||
outcomes: string[],
|
||||
initialProbs: number[],
|
||||
|
|
|
@ -4,7 +4,7 @@ export type User = {
|
|||
|
||||
name: string
|
||||
username: string
|
||||
avatarUrl: string
|
||||
avatarUrl?: string
|
||||
|
||||
// For their user page
|
||||
bio?: string
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
MAX_DESCRIPTION_LENGTH,
|
||||
MAX_QUESTION_LENGTH,
|
||||
MAX_TAG_LENGTH,
|
||||
Numeric,
|
||||
outcomeType,
|
||||
} from '../../common/contract'
|
||||
import { slugify } from '../../common/util/slugify'
|
||||
|
@ -22,6 +23,7 @@ import {
|
|||
getAnteBets,
|
||||
getCpmmInitialLiquidity,
|
||||
getFreeAnswerAnte,
|
||||
getNumericAntes,
|
||||
HOUSE_LIQUIDITY_PROVIDER_ID,
|
||||
MINIMUM_ANTE,
|
||||
} from '../../common/antes'
|
||||
|
@ -63,7 +65,9 @@ export const createContract = functions
|
|||
tags = tags?.map((tag) => tag.toString().slice(0, MAX_TAG_LENGTH))
|
||||
|
||||
let outcomeType = data.outcomeType ?? 'BINARY'
|
||||
if (!['BINARY', 'MULTI', 'FREE_RESPONSE'].includes(outcomeType))
|
||||
if (
|
||||
!['BINARY', 'MULTI', 'FREE_RESPONSE', 'NUMERIC'].includes(outcomeType)
|
||||
)
|
||||
return { status: 'error', message: 'Invalid outcomeType' }
|
||||
|
||||
if (
|
||||
|
@ -115,7 +119,10 @@ export const createContract = functions
|
|||
initialProb,
|
||||
ante,
|
||||
closeTime,
|
||||
tags ?? []
|
||||
tags ?? [],
|
||||
1000,
|
||||
1,
|
||||
1000
|
||||
)
|
||||
|
||||
if (!isFree && ante) await chargeUser(creator.id, ante)
|
||||
|
@ -174,6 +181,25 @@ export const createContract = functions
|
|||
anteBetDoc.id
|
||||
)
|
||||
await anteBetDoc.set(anteBet)
|
||||
} else if (outcomeType === 'NUMERIC') {
|
||||
const antes = getNumericAntes(
|
||||
creator,
|
||||
contract as FullContract<DPM, Numeric>,
|
||||
ante
|
||||
)
|
||||
|
||||
await firestore.runTransaction(async (transaction) => {
|
||||
for (let anteBet of antes) {
|
||||
const anteBetDoc = firestore
|
||||
.collection(`contracts/${contract.id}/bets`)
|
||||
.doc()
|
||||
|
||||
await transaction.set(anteBetDoc, {
|
||||
id: anteBetDoc.id,
|
||||
...anteBet,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user