From 256dba2a46841557509e74e63800cea5372bf334 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 24 Aug 2024 23:30:00 -0500 Subject: [PATCH] Implement LMSR cost function --- lib/lmsr/lmsr.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 lib/lmsr/lmsr.go diff --git a/lib/lmsr/lmsr.go b/lib/lmsr/lmsr.go new file mode 100644 index 0000000..034e1b7 --- /dev/null +++ b/lib/lmsr/lmsr.go @@ -0,0 +1,51 @@ +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) +}