33 lines
1.1 KiB
Go
33 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
)
|
|
|
|
// logarithmic market scoring rule (LMSR) market maker from Robin Hanson:
|
|
// https://mason.gmu.edu/~rhanson/mktscore.pdf
|
|
func BinaryLMSRBuy(invariant int, funding int, tokensAQ float64, tokensBQ float64, sats int) (float64, error) {
|
|
k := float64(invariant)
|
|
f := float64(funding)
|
|
numOutcomes := 2.0
|
|
expA := -tokensAQ / f
|
|
expB := -tokensBQ / f
|
|
if k != math.Pow(numOutcomes, expA)+math.Pow(numOutcomes, expB) {
|
|
// invariant should not already be broken
|
|
return -1, errors.New("invariant already broken")
|
|
}
|
|
// AMM converts order into equal amount of tokens per outcome and then solves equation to fix invariant
|
|
// see https://docs.gnosis.io/conditionaltokens/docs/introduction3/#an-example-with-lmsr
|
|
newTokensA := tokensAQ + float64(sats)
|
|
newTokensB := tokensBQ + float64(sats)
|
|
expB = -newTokensB / f
|
|
x := newTokensA + f*math.Log(k-math.Pow(numOutcomes, expB))/math.Log(numOutcomes)
|
|
expA = -(newTokensA - x) / f
|
|
if k != math.Pow(numOutcomes, expA)+math.Pow(numOutcomes, expB) {
|
|
// invariant should not be broken
|
|
return -1, errors.New("invariant broken")
|
|
}
|
|
return x, nil
|
|
}
|