f5e2e178e1
Split market pair logic into spot and futures files and rename price files to plural data-dimension names without changing behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
package market
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/adshao/go-binance/v2"
|
|
"github.com/adshao/go-binance/v2/futures"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type MarketData struct {
|
|
// Trading pair caches
|
|
spotPairs map[string]bool
|
|
futuresPairs map[string]bool
|
|
spotToken2Symbol map[string]string
|
|
futureToken2Symbol map[string]string
|
|
pairCacheMutex sync.RWMutex
|
|
lastPairCacheUpdate time.Time
|
|
|
|
// Alpha token cache
|
|
alphaTokens map[string]AlphaTokenInfo
|
|
alphaCacheMutex sync.RWMutex
|
|
lastAlphaCacheUpdate time.Time
|
|
|
|
// Binance REST clients
|
|
spotClient *binance.Client
|
|
futuresClient *futures.Client
|
|
}
|
|
|
|
func NewMarketData() *MarketData {
|
|
log.Info().Msg("Start market service")
|
|
ms := &MarketData{
|
|
spotPairs: make(map[string]bool),
|
|
futuresPairs: make(map[string]bool),
|
|
spotToken2Symbol: make(map[string]string),
|
|
futureToken2Symbol: make(map[string]string),
|
|
alphaTokens: make(map[string]AlphaTokenInfo),
|
|
spotClient: binance.NewClient("", ""),
|
|
futuresClient: futures.NewClient("", ""),
|
|
}
|
|
|
|
ms.refreshAllCaches()
|
|
go ms.cacheRefreshLoop()
|
|
|
|
return ms
|
|
}
|
|
|
|
func (ms *MarketData) alphaCacheRefreshLoop() {
|
|
ms.refreshAlphaTokenCache()
|
|
ticker := time.NewTicker(time.Hour)
|
|
defer ticker.Stop()
|
|
for range ticker.C {
|
|
ms.refreshAlphaTokenCache()
|
|
}
|
|
}
|
|
|
|
func (ms *MarketData) refreshTradingPairCache() error {
|
|
if err := ms.refreshSpotPairCache(); err != nil {
|
|
return err
|
|
}
|
|
if err := ms.refreshFuturePairCache(); err != nil {
|
|
return err
|
|
}
|
|
|
|
ms.pairCacheMutex.RLock()
|
|
spotCount := len(ms.spotPairs)
|
|
futureCount := len(ms.futuresPairs)
|
|
ms.pairCacheMutex.RUnlock()
|
|
|
|
log.Info().
|
|
Int("spot", spotCount).
|
|
Int("futures", futureCount).
|
|
Msg("Trading pair cache refreshed")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ms *MarketData) cacheRefreshLoop() {
|
|
ms.refreshAllCaches()
|
|
ticker := time.NewTicker(time.Hour)
|
|
defer ticker.Stop()
|
|
for range ticker.C {
|
|
ms.refreshAllCaches()
|
|
}
|
|
}
|
|
|
|
func (ms *MarketData) refreshAllCaches() {
|
|
if err := ms.refreshSpotPairCache(); err != nil {
|
|
log.Error().Err(err).Msg("Failed spot pair refresh")
|
|
}
|
|
if err := ms.refreshFuturePairCache(); err != nil {
|
|
log.Error().Err(err).Msg("Failed futures pair refresh")
|
|
}
|
|
ms.refreshAlphaTokenCache()
|
|
}
|
|
|
|
func (ms *MarketData) RefreshTradingPairCache() error {
|
|
return ms.refreshTradingPairCache()
|
|
}
|