exchanges/futures: Implement open interest (#1417)

* adds open interest to exchanges

* ADDS TESTING YEAH

* New endpoints, BTSE, RPCS, cached

* slight design change, begin gateio

You will need to get cached for
each exchange that supports it

* gateio, huobi, rpc

* fix up kraken, cache retrieval

* okx, gateio

* finalising all implementations and tests

* definitely my final ever commit on this

* Well, well, well

* final v2

* quick fix of bug

* test coverage, assert notempty, test helper

Added a new testhelper for currency
management because its very annoying
in a parallel test setting which wastes
so much space otherwise

* minimises REST requests for Open Interest

* types.Number merge misses

* Minimises Kraken REST calls

* len change, value -> pointer receiver

* further fixup

* fixes gateio, batch calculates open interest

* single gateio, lint const fixes

* rejig and more thorough oi for huobi

* formatting expansion

* minor fix for handling expiring contracts

* rm unused Binance strings

* add bybit support, fix bybit issues

* oopsie doopsie, dont look at my whoopsie

* Fix issue, remove feature

* move an irrelevant function for the pr

* mini bybit upgrades

* fixes cli request bug
This commit is contained in:
Scott
2024-01-12 15:27:35 +11:00
committed by GitHub
parent 614042110a
commit b71bf1f3d1
62 changed files with 22660 additions and 10095 deletions

View File

@@ -14,12 +14,16 @@ import (
)
var (
// ErrNoTickerFound is when a ticker is not found
ErrNoTickerFound = errors.New("no ticker found")
// ErrBidEqualsAsk error for locked markets
ErrBidEqualsAsk = errors.New("bid equals ask this is a crossed or locked market")
ErrBidEqualsAsk = errors.New("bid equals ask this is a crossed or locked market")
errInvalidTicker = errors.New("invalid ticker")
errTickerNotFound = errors.New("ticker not found")
errExchangeNameIsEmpty = errors.New("exchange name is empty")
errBidGreaterThanAsk = errors.New("bid greater than ask this is a crossed or locked market")
errExchangeNotFound = errors.New("exchange not found")
)
func init() {
@@ -85,14 +89,41 @@ func GetTicker(exchange string, p currency.Pair, a asset.Item) (*Price, error) {
Asset: a,
}]
if !ok {
return nil, fmt.Errorf("no tickers associated with asset type %s %s %s",
exchange, p, a)
return nil, fmt.Errorf("%w %s %s %s",
ErrNoTickerFound, exchange, p, a)
}
cpy := tick.Price // Don't let external functions have access to underlying
return &cpy, nil
}
// GetExchangeTickers returns all tickers for a given exchange
func GetExchangeTickers(exchange string) ([]*Price, error) {
return service.getExchangeTickers(exchange)
}
func (s *Service) getExchangeTickers(exchange string) ([]*Price, error) {
if exchange == "" {
return nil, errExchangeNameIsEmpty
}
exchange = strings.ToLower(exchange)
s.mu.Lock()
defer s.mu.Unlock()
_, ok := s.Exchange[exchange]
if !ok {
return nil, fmt.Errorf("%w %v", errExchangeNotFound, exchange)
}
tickers := make([]*Price, 0, len(s.Tickers))
for k, v := range s.Tickers {
if k.Exchange != exchange {
continue
}
cpy := v.Price // Don't let external functions have access to underlying
tickers = append(tickers, &cpy)
}
return tickers, nil
}
// FindLast searches for a currency pair and returns the first available
func FindLast(p currency.Pair, a asset.Item) (float64, error) {
service.mu.Lock()
@@ -206,7 +237,7 @@ func (s *Service) setItemID(t *Ticker, p *Price, exch string) error {
return nil
}
// getAssociations links a singular book with it's dispatch associations
// getAssociations links a singular book with its dispatch associations
func (s *Service) getAssociations(exch string) ([]uuid.UUID, error) {
if exch == "" {
return nil, errExchangeNameIsEmpty