Cfmm migration (#80)
* cfmm migration script * save dpm shares, pool * formatMoney: use floor instead of round * migrate cfmm: use sale amount as shares for sold bets * migration: make up fake share qty for sold shares * migration: also convert resolved markets * migration: don't migrate resolved markets after all * migration: error checking
This commit is contained in:
parent
b637ab1536
commit
790aec9baf
|
@ -8,14 +8,14 @@ const formatter = new Intl.NumberFormat('en-US', {
|
||||||
})
|
})
|
||||||
|
|
||||||
export function formatMoney(amount: number) {
|
export function formatMoney(amount: number) {
|
||||||
const newAmount = Math.round(amount) === 0 ? 0 : amount // handle -0 case
|
const newAmount = Math.round(amount) === 0 ? 0 : Math.floor(amount) // handle -0 case
|
||||||
return (
|
return (
|
||||||
ENV_CONFIG.moneyMoniker + ' ' + formatter.format(newAmount).replace('$', '')
|
ENV_CONFIG.moneyMoniker + ' ' + formatter.format(newAmount).replace('$', '')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatWithCommas(amount: number) {
|
export function formatWithCommas(amount: number) {
|
||||||
return formatter.format(amount).replace('$', '')
|
return formatter.format(Math.floor(amount)).replace('$', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatPercent(zeroToOne: number) {
|
export function formatPercent(zeroToOne: number) {
|
||||||
|
|
154
functions/src/scripts/migrate-to-cfmm.ts
Normal file
154
functions/src/scripts/migrate-to-cfmm.ts
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
import * as admin from 'firebase-admin'
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
|
import { initAdmin } from './script-init'
|
||||||
|
initAdmin('stephenDev')
|
||||||
|
|
||||||
|
import {
|
||||||
|
Binary,
|
||||||
|
Contract,
|
||||||
|
CPMM,
|
||||||
|
DPM,
|
||||||
|
FullContract,
|
||||||
|
} from '../../../common/contract'
|
||||||
|
import { Bet } from '../../../common/bet'
|
||||||
|
import {
|
||||||
|
calculateDpmPayout,
|
||||||
|
getDpmProbability,
|
||||||
|
} from '../../../common/calculate-dpm'
|
||||||
|
import { User } from '../../../common/user'
|
||||||
|
import { getCpmmInitialLiquidity } from '../../../common/antes'
|
||||||
|
import { noFees } from '../../../common/fees'
|
||||||
|
import { addObjects } from '../../../common/util/object'
|
||||||
|
|
||||||
|
type DocRef = admin.firestore.DocumentReference
|
||||||
|
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
|
||||||
|
async function recalculateContract(contractRef: DocRef, isCommit = false) {
|
||||||
|
await firestore.runTransaction(async (transaction) => {
|
||||||
|
const contractDoc = await transaction.get(contractRef)
|
||||||
|
const contract = contractDoc.data() as FullContract<DPM, Binary>
|
||||||
|
|
||||||
|
if (!contract?.slug) {
|
||||||
|
console.log('missing slug; id=', contractRef.id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('recalculating', contract.slug)
|
||||||
|
|
||||||
|
if (
|
||||||
|
contract.mechanism !== 'dpm-2' ||
|
||||||
|
contract.outcomeType !== 'BINARY' ||
|
||||||
|
contract.resolution
|
||||||
|
) {
|
||||||
|
console.log('invalid candidate to port to cfmm')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const betsRef = contractRef.collection('bets')
|
||||||
|
const betDocs = await transaction.get(betsRef)
|
||||||
|
const bets = _.sortBy(
|
||||||
|
betDocs.docs.map((d) => d.data() as Bet),
|
||||||
|
(b) => b.createdTime
|
||||||
|
)
|
||||||
|
|
||||||
|
const getSoldBetPayout = (bet: Bet) => {
|
||||||
|
const soldBet = bets.find((b) => bet.sale?.betId === b.id)
|
||||||
|
return soldBet
|
||||||
|
? -soldBet.amount / Math.sqrt(soldBet.probBefore * soldBet.probAfter)
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let bet of bets) {
|
||||||
|
const shares = bet.sale
|
||||||
|
? getSoldBetPayout(bet)
|
||||||
|
: bet.isSold
|
||||||
|
? bet.amount / Math.sqrt(bet.probBefore * bet.probAfter) // make up fake share qty
|
||||||
|
: calculateDpmPayout(contract, bet, contract.resolution ?? bet.outcome)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'converting',
|
||||||
|
bet.shares,
|
||||||
|
bet.outcome,
|
||||||
|
bet.isSold ? '(sold)' : '',
|
||||||
|
'shares to',
|
||||||
|
shares
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isCommit)
|
||||||
|
transaction.update(betsRef.doc(bet.id), {
|
||||||
|
shares,
|
||||||
|
dpmShares: bet.shares,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const prob =
|
||||||
|
contract.resolutionProbability ?? getDpmProbability(contract.totalShares)
|
||||||
|
|
||||||
|
const ante = 100
|
||||||
|
const newPool = { YES: ante, NO: ante }
|
||||||
|
console.log('creating liquidity pool at p=', prob, 'for M$', ante)
|
||||||
|
|
||||||
|
const contractUpdate: Partial<Contract> = {
|
||||||
|
pool: newPool,
|
||||||
|
p: prob,
|
||||||
|
mechanism: 'cpmm-1',
|
||||||
|
totalLiquidity: ante,
|
||||||
|
collectedFees: addObjects(contract.collectedFees ?? noFees, noFees),
|
||||||
|
}
|
||||||
|
|
||||||
|
const additionalInfo = {
|
||||||
|
cfmmConversionTime: Date.now(),
|
||||||
|
dpmPool: contract.pool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const liquidityDocRef = contractRef.collection('liquidity').doc()
|
||||||
|
|
||||||
|
const lp = getCpmmInitialLiquidity(
|
||||||
|
{ id: 'IPTOzEqrpkWmEzh6hwvAyY9PqFb2' } as User, // use @ManifoldMarkets' id
|
||||||
|
{
|
||||||
|
...contract,
|
||||||
|
...contractUpdate,
|
||||||
|
} as FullContract<CPMM, Binary>,
|
||||||
|
liquidityDocRef.id,
|
||||||
|
ante
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isCommit) {
|
||||||
|
transaction.update(contractRef, {
|
||||||
|
...contractUpdate,
|
||||||
|
...additionalInfo,
|
||||||
|
})
|
||||||
|
transaction.set(liquidityDocRef, lp)
|
||||||
|
|
||||||
|
console.log('updated', contract.slug)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const slug = process.argv[2]
|
||||||
|
const isCommit = process.argv[3] === 'commit'
|
||||||
|
|
||||||
|
const contractRefs =
|
||||||
|
slug === 'all'
|
||||||
|
? await firestore.collection('contracts').listDocuments()
|
||||||
|
: await firestore
|
||||||
|
.collection('contracts')
|
||||||
|
.where('slug', '==', slug)
|
||||||
|
.get()
|
||||||
|
.then((snap) =>
|
||||||
|
!snap.empty ? [firestore.doc(`contracts/${snap.docs[0].id}`)] : []
|
||||||
|
)
|
||||||
|
|
||||||
|
for (let contractRef of contractRefs) {
|
||||||
|
await recalculateContract(contractRef, isCommit).catch((e) =>
|
||||||
|
console.log('error: ', e, 'id=', contractRef.id)
|
||||||
|
)
|
||||||
|
console.log()
|
||||||
|
console.log()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) main().then(() => process.exit())
|
|
@ -397,7 +397,10 @@ export function ContractBetsTable(props: {
|
||||||
sales.map((sale) => [sale.sale?.betId ?? '', sale])
|
sales.map((sale) => [sale.sale?.betId ?? '', sale])
|
||||||
)
|
)
|
||||||
|
|
||||||
const [redemptions, normalBets] = _.partition(buys, (b) => b.isRedemption)
|
const [redemptions, normalBets] = _.partition(
|
||||||
|
contract.mechanism === 'cpmm-1' ? bets : buys,
|
||||||
|
(b) => b.isRedemption
|
||||||
|
)
|
||||||
const amountRedeemed = Math.floor(
|
const amountRedeemed = Math.floor(
|
||||||
-0.5 * _.sumBy(redemptions, (b) => b.shares)
|
-0.5 * _.sumBy(redemptions, (b) => b.shares)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user