package lmsr import "math" // Robin Hanson's Logarithmic Market Scoring Rule (LMSR) market maker // https://mason.gmu.edu/~rhanson/mktscore.pdf // "The market maker keeps track of how many shares have been purchased by // traders in total so far for each outcome: that is, the number of shares // outstanding for each outcome. Let q1 and q2 be the number (“quantity”) // of shares outstanding for each of the two outcomes. The market maker also // maintains a cost function C(q1,q2) which records how much money traders // have collectively spent so far, and depends only on the number of shares // outstanding, q1 and q2. For LMSR, the cost function is [this]: // // // ... // // The parameter “b” controls the maximum possible amount of money the market // maker can lose (which happens to be b*ln2 in the two-outcome case). The // larger “b” is, the more money the market maker can lose. But a larger “b” // also means the market has more liquidity or depth, meaning that traders can // buy more shares at or near the current price without causing massive price swings." // // -- David Pennock, http://blog.oddhead.com/2006/10/30/implementing-hansons-market-maker/ func binaryLMSRcost(b float64, q1 float64, q2 float64) float64 { return b * math.Log(math.Pow(math.E, q1/b)+math.Pow(math.E, q2/b)) } func Quote(b float64, q1 int, q2 int, dq1 int) float64 { // q1 must always be the quantity of shares that are bought / sold. // If you want to change q2, you need to swap q1 and q2 as input arguments. fq1 := float64(q1) fq2 := float64(q2) fdq1 := float64(dq1) return binaryLMSRcost(b, fq1+fdq1, fq2) - binaryLMSRcost(b, fq1, fq2) } func Price(b float64, q1 int, q2 int) float64 { // // q1 must always be the quantity of shares that are bought / sold. // If you want to change q2, you need to swap q1 and q2 as input arguments. // // An infinitesimal share would cost this much: // // p = e^{q1/b} / ( e^{q1/b} + e^{q2/b} ) // // However, to find the price of buying one full share // we need to use the cost function. return Quote(b, q1, q2, 1) }