From a94d1b424fb659a4050ba05b6e439a9da2be2205 Mon Sep 17 00:00:00 2001 From: c9s Date: Sat, 5 Oct 2024 14:26:15 +0800 Subject: [PATCH] pricesolver: use float64 internally to make it faster and more precise --- pkg/pricesolver/simple.go | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/pkg/pricesolver/simple.go b/pkg/pricesolver/simple.go index d551f8c991..601172086b 100644 --- a/pkg/pricesolver/simple.go +++ b/pkg/pricesolver/simple.go @@ -19,12 +19,12 @@ type SimplePriceSolver struct { // pricesByBase stores the prices by currency names as a 2-level map // BTC -> USDT -> 48000.0 // BTC -> TWD -> 1536000 - pricesByBase map[string]map[string]fixedpoint.Value + pricesByBase map[string]map[string]float64 // pricesByQuote is for reversed pairs, like USDT/TWD or BNB/BTC // the reason that we don't store the reverse pricing in the same map is: // expression like (1/price) could produce precision issue since the data type is fixed-point, only 8 fraction numbers are supported. - pricesByQuote map[string]map[string]fixedpoint.Value + pricesByQuote map[string]map[string]float64 mu sync.Mutex } @@ -33,8 +33,8 @@ func NewSimplePriceResolver(markets types.MarketMap) *SimplePriceSolver { return &SimplePriceSolver{ markets: markets, symbolPrices: make(map[string]fixedpoint.Value), - pricesByBase: make(map[string]map[string]fixedpoint.Value), - pricesByQuote: make(map[string]map[string]fixedpoint.Value), + pricesByBase: make(map[string]map[string]float64), + pricesByQuote: make(map[string]map[string]float64), } } @@ -51,19 +51,19 @@ func (m *SimplePriceSolver) Update(symbol string, price fixedpoint.Value) { quoteMap, ok2 := m.pricesByBase[market.BaseCurrency] if !ok2 { - quoteMap = make(map[string]fixedpoint.Value) + quoteMap = make(map[string]float64) m.pricesByBase[market.BaseCurrency] = quoteMap } - quoteMap[market.QuoteCurrency] = price + quoteMap[market.QuoteCurrency] = price.Float64() baseMap, ok3 := m.pricesByQuote[market.QuoteCurrency] if !ok3 { - baseMap = make(map[string]fixedpoint.Value) + baseMap = make(map[string]float64) m.pricesByQuote[market.QuoteCurrency] = baseMap } - baseMap[market.BaseCurrency] = price + baseMap[market.BaseCurrency] = price.Float64() } func (m *SimplePriceSolver) UpdateFromTrade(trade types.Trade) { @@ -98,19 +98,19 @@ func (m *SimplePriceSolver) UpdateFromTickers(ctx context.Context, ex types.Exch return nil } -func (m *SimplePriceSolver) inferencePrice(asset string, assetPrice fixedpoint.Value, preferredFiats ...string) (fixedpoint.Value, bool) { +func (m *SimplePriceSolver) inferencePrice(asset string, assetPrice float64, preferredFiats ...string) (float64, bool) { quotePrices, ok := m.pricesByBase[asset] if ok { for quote, price := range quotePrices { for _, fiat := range preferredFiats { if quote == fiat { - return price.Mul(assetPrice), true + return price * assetPrice, true } } } for quote, price := range quotePrices { - if infPrice, ok := m.inferencePrice(quote, price.Mul(assetPrice), preferredFiats...); ok { + if infPrice, ok := m.inferencePrice(quote, price*assetPrice, preferredFiats...); ok { return infPrice, true } } @@ -123,19 +123,19 @@ func (m *SimplePriceSolver) inferencePrice(asset string, assetPrice fixedpoint.V for base, basePrice := range basePrices { for _, fiat := range preferredFiats { if base == fiat { - return assetPrice.Div(basePrice), true + return assetPrice / basePrice, true } } } for base, basePrice := range basePrices { - if infPrice, ok2 := m.inferencePrice(base, assetPrice.Div(basePrice), preferredFiats...); ok2 { + if infPrice, ok2 := m.inferencePrice(base, assetPrice/basePrice, preferredFiats...); ok2 { return infPrice, true } } } - return fixedpoint.Zero, false + return 0.0, false } func (m *SimplePriceSolver) ResolvePrice(asset string, preferredFiats ...string) (fixedpoint.Value, bool) { @@ -147,5 +147,10 @@ func (m *SimplePriceSolver) ResolvePrice(asset string, preferredFiats ...string) m.mu.Lock() defer m.mu.Unlock() - return m.inferencePrice(asset, fixedpoint.One, preferredFiats...) + fn, ok := m.inferencePrice(asset, 1.0, preferredFiats...) + if ok { + return fixedpoint.NewFromFloat(fn), ok + } + + return fixedpoint.Zero, false }