orderbook: consolidate slice array types to orderbook package (#1992)

* orderbook: consolidate slice array types to orderbook package

* Update exchanges/bybit/bybit_types.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* linter: fix and add test

* cranktakular: nits

* cranktakular: nits

* Update exchanges/orderbook/orderbook_types.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/gateio_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits consolidation

* gk: rm unifySpotOrderbook func

* gk: nit but different

* linter: fix

* gk: nits

* glorious: nits

* Update exchanges/binance/binance.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* Update exchanges/binance/binance_cfutures.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* Update exchanges/binanceus/binanceus.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* thrasher-:nits

* thrasher-: more nit

---------

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
Ryan O'Hara-Reid
2025-10-02 14:22:20 +10:00
committed by GitHub
parent eb60a3c40e
commit ac91fabcd5
43 changed files with 413 additions and 854 deletions

View File

@@ -318,34 +318,25 @@ outer:
}
// GetOrderBookDepth to get the order book depth. Please note the limits in the table below.
func (e *Exchange) GetOrderBookDepth(ctx context.Context, arg *OrderBookDataRequestParams) (*OrderBook, error) {
func (e *Exchange) GetOrderBookDepth(ctx context.Context, pair currency.Pair, limit uint64) (*OrderBook, error) {
params := url.Values{}
symbol, err := e.FormatSymbol(arg.Symbol, asset.Spot)
symbol, err := e.FormatSymbol(pair, asset.Spot)
if err != nil {
return nil, err
}
params.Set("symbol", symbol)
params.Set("limit", strconv.FormatInt(arg.Limit, 10))
params.Set("limit", strconv.FormatUint(limit, 10))
var resp *OrderBookData
if err := e.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, common.EncodeURLValues(orderBookDepth, params), orderbookLimit(arg.Limit), &resp); err != nil {
if err := e.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, common.EncodeURLValues(orderBookDepth, params), orderbookLimit(limit), &resp); err != nil {
return nil, err
}
ob := &OrderBook{
Bids: make([]OrderbookItem, len(resp.Bids)),
Asks: make([]OrderbookItem, len(resp.Asks)),
return &OrderBook{
Bids: resp.Bids.Levels(),
Asks: resp.Asks.Levels(),
LastUpdateID: resp.LastUpdateID,
}
for x := range resp.Bids {
ob.Bids[x].Price = resp.Bids[x][0].Float64()
ob.Bids[x].Quantity = resp.Bids[x][1].Float64()
}
for x := range resp.Asks {
ob.Asks[x].Price = resp.Asks[x][0].Float64()
ob.Asks[x].Quantity = resp.Asks[x][1].Float64()
}
return ob, nil
}, nil
}
// GetIntervalEnum allowed interval params by Binanceus

View File

@@ -18,6 +18,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
@@ -448,13 +449,8 @@ func TestGetAggregateTrades(t *testing.T) {
func TestGetOrderBookDepth(t *testing.T) {
t.Parallel()
_, er := e.GetOrderBookDepth(t.Context(), &OrderBookDataRequestParams{
Symbol: currency.NewBTCUSDT(),
Limit: 1000,
})
if er != nil {
t.Error("Binanceus GetOrderBook() error", er)
}
_, err := e.GetOrderBookDepth(t.Context(), currency.NewBTCUSDT(), 1000)
assert.NoError(t, err)
}
func TestGetCandlestickData(t *testing.T) {
@@ -1338,29 +1334,29 @@ func TestWebsocketOrderBookDepthDiffStream(t *testing.T) {
e.setupOrderbookManager(t.Context())
seedLastUpdateID := int64(161)
book := OrderBook{
Asks: []OrderbookItem{
{Price: 6621.80000000, Quantity: 0.00198100},
{Price: 6622.14000000, Quantity: 4.00000000},
{Price: 6622.46000000, Quantity: 2.30000000},
{Price: 6622.47000000, Quantity: 1.18633300},
{Price: 6622.64000000, Quantity: 4.00000000},
{Price: 6622.73000000, Quantity: 0.02900000},
{Price: 6622.76000000, Quantity: 0.12557700},
{Price: 6622.81000000, Quantity: 2.08994200},
{Price: 6622.82000000, Quantity: 0.01500000},
{Price: 6623.17000000, Quantity: 0.16831300},
Asks: []orderbook.Level{
{Price: 6621.80000000, Amount: 0.00198100},
{Price: 6622.14000000, Amount: 4.00000000},
{Price: 6622.46000000, Amount: 2.30000000},
{Price: 6622.47000000, Amount: 1.18633300},
{Price: 6622.64000000, Amount: 4.00000000},
{Price: 6622.73000000, Amount: 0.02900000},
{Price: 6622.76000000, Amount: 0.12557700},
{Price: 6622.81000000, Amount: 2.08994200},
{Price: 6622.82000000, Amount: 0.01500000},
{Price: 6623.17000000, Amount: 0.16831300},
},
Bids: []OrderbookItem{
{Price: 6621.55000000, Quantity: 0.16356700},
{Price: 6621.45000000, Quantity: 0.16352600},
{Price: 6621.41000000, Quantity: 0.86091200},
{Price: 6621.25000000, Quantity: 0.16914100},
{Price: 6621.23000000, Quantity: 0.09193600},
{Price: 6621.22000000, Quantity: 0.00755100},
{Price: 6621.13000000, Quantity: 0.08432000},
{Price: 6621.03000000, Quantity: 0.00172000},
{Price: 6620.94000000, Quantity: 0.30506700},
{Price: 6620.93000000, Quantity: 0.00200000},
Bids: []orderbook.Level{
{Price: 6621.55000000, Amount: 0.16356700},
{Price: 6621.45000000, Amount: 0.16352600},
{Price: 6621.41000000, Amount: 0.86091200},
{Price: 6621.25000000, Amount: 0.16914100},
{Price: 6621.23000000, Amount: 0.09193600},
{Price: 6621.22000000, Amount: 0.00755100},
{Price: 6621.13000000, Amount: 0.08432000},
{Price: 6621.03000000, Amount: 0.00172000},
{Price: 6620.94000000, Amount: 0.30506700},
{Price: 6620.93000000, Amount: 0.00200000},
},
LastUpdateID: seedLastUpdateID,
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/encoding/json"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
"github.com/thrasher-corp/gocryptotrader/types"
)
@@ -161,23 +162,11 @@ func (a *AggregatedTrade) toTradeData(p currency.Pair, exchange string, aType as
}
}
// OrderBookDataRequestParams represents Klines request data.
type OrderBookDataRequestParams struct {
Symbol currency.Pair `json:"symbol"` // Required field; example LTCBTC,BTCUSDT
Limit int64 `json:"limit"` // Default 100; max 5000. If limit > 5000, then the response will truncate to 5000
}
// OrderbookItem stores an individual orderbook item
type OrderbookItem struct {
Price float64
Quantity float64
}
// OrderBookData is resp data from orderbook endpoint
type OrderBookData struct {
LastUpdateID int64 `json:"lastUpdateId"`
Bids [][2]types.Number `json:"bids"`
Asks [][2]types.Number `json:"asks"`
LastUpdateID int64 `json:"lastUpdateId"`
Bids orderbook.LevelsArrayPriceAmount `json:"bids"`
Asks orderbook.LevelsArrayPriceAmount `json:"asks"`
}
// OrderBook actual structured data that can be used for orderbook
@@ -186,8 +175,8 @@ type OrderBook struct {
LastUpdateID int64
Code int
Msg string
Bids []OrderbookItem
Asks []OrderbookItem
Bids []orderbook.Level
Asks []orderbook.Level
}
// KlinesRequestParams represents Klines request data.
@@ -833,20 +822,20 @@ type update struct {
// WebsocketDepthStream is the difference for the update depth stream
type WebsocketDepthStream struct {
Event string `json:"e"`
Timestamp types.Time `json:"E"`
Pair string `json:"s"`
FirstUpdateID int64 `json:"U"`
LastUpdateID int64 `json:"u"`
UpdateBids [][2]types.Number `json:"b"`
UpdateAsks [][2]types.Number `json:"a"`
Event string `json:"e"`
Timestamp types.Time `json:"E"`
Pair string `json:"s"`
FirstUpdateID int64 `json:"U"`
LastUpdateID int64 `json:"u"`
UpdateBids orderbook.LevelsArrayPriceAmount `json:"b"`
UpdateAsks orderbook.LevelsArrayPriceAmount `json:"a"`
}
// WebsocketDepthDiffStream websocket response of depth diff stream
type WebsocketDepthDiffStream struct {
LastUpdateID int64 `json:"lastUpdateId"`
Bids [][2]types.Number `json:"bids"`
Asks [][2]types.Number `json:"asks"`
LastUpdateID int64 `json:"lastUpdateId"`
Bids orderbook.LevelsArrayPriceAmount `json:"bids"`
Asks orderbook.LevelsArrayPriceAmount `json:"asks"`
}
// WsAccountInfoData defines websocket account info data

View File

@@ -654,21 +654,9 @@ func (e *Exchange) SynchroniseWebsocketOrderbook(ctx context.Context) {
// ProcessOrderbookUpdate processes the websocket orderbook update
func (e *Exchange) ProcessOrderbookUpdate(cp currency.Pair, a asset.Item, wsDSUpdate *WebsocketDepthStream) error {
updateBid := make([]orderbook.Level, len(wsDSUpdate.UpdateBids))
for i := range wsDSUpdate.UpdateBids {
updateBid[i].Price = wsDSUpdate.UpdateBids[i][0].Float64()
updateBid[i].Amount = wsDSUpdate.UpdateBids[i][1].Float64()
}
updateAsk := make([]orderbook.Level, len(wsDSUpdate.UpdateAsks))
for i := range wsDSUpdate.UpdateAsks {
updateAsk[i].Price = wsDSUpdate.UpdateAsks[i][0].Float64()
updateAsk[i].Amount = wsDSUpdate.UpdateAsks[i][1].Float64()
}
return e.Websocket.Orderbook.Update(&orderbook.Update{
Bids: updateBid,
Asks: updateAsk,
Bids: wsDSUpdate.UpdateBids.Levels(),
Asks: wsDSUpdate.UpdateAsks.Levels(),
Pair: cp,
UpdateID: wsDSUpdate.LastUpdateID,
UpdateTime: wsDSUpdate.Timestamp.Time(),
@@ -789,11 +777,7 @@ func (e *Exchange) processJob(ctx context.Context, p currency.Pair) error {
// SeedLocalCache seeds depth data
func (e *Exchange) SeedLocalCache(ctx context.Context, p currency.Pair) error {
ob, err := e.GetOrderBookDepth(ctx,
&OrderBookDataRequestParams{
Symbol: p,
Limit: 1000,
})
ob, err := e.GetOrderBookDepth(ctx, p, 1000)
if err != nil {
return err
}
@@ -802,29 +786,16 @@ func (e *Exchange) SeedLocalCache(ctx context.Context, p currency.Pair) error {
// SeedLocalCacheWithBook seeds the local orderbook cache
func (e *Exchange) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBook) error {
newOrderBook := orderbook.Book{
return e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
Pair: p,
Asset: asset.Spot,
Exchange: e.Name,
LastUpdateID: orderbookNew.LastUpdateID,
ValidateOrderbook: e.ValidateOrderbook,
Bids: make(orderbook.Levels, len(orderbookNew.Bids)),
Asks: make(orderbook.Levels, len(orderbookNew.Asks)),
Bids: orderbookNew.Bids,
Asks: orderbookNew.Asks,
LastUpdated: time.Now(), // Time not provided in REST book.
}
for i := range orderbookNew.Bids {
newOrderBook.Bids[i] = orderbook.Level{
Amount: orderbookNew.Bids[i].Quantity,
Price: orderbookNew.Bids[i].Price,
}
}
for i := range orderbookNew.Asks {
newOrderBook.Asks[i] = orderbook.Level{
Amount: orderbookNew.Asks[i].Quantity,
Price: orderbookNew.Asks[i].Price,
}
}
return e.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
})
}
// handleFetchingBook checks if a full book is being fetched or needs to be

View File

@@ -317,37 +317,20 @@ func (e *Exchange) UpdateOrderbook(ctx context.Context, pair currency.Pair, asse
if err := e.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
return nil, err
}
book := &orderbook.Book{
orderbookNew, err := e.GetOrderBookDepth(ctx, pair, 1000)
if err != nil {
return nil, err
}
ob := &orderbook.Book{
Exchange: e.Name,
Pair: pair,
Asset: assetType,
ValidateOrderbook: e.ValidateOrderbook,
Bids: orderbookNew.Bids,
Asks: orderbookNew.Asks,
}
orderbookNew, err := e.GetOrderBookDepth(ctx, &OrderBookDataRequestParams{
Symbol: pair,
Limit: 1000,
})
if err != nil {
return book, err
}
book.Bids = make([]orderbook.Level, len(orderbookNew.Bids))
for x := range orderbookNew.Bids {
book.Bids[x] = orderbook.Level{
Amount: orderbookNew.Bids[x].Quantity,
Price: orderbookNew.Bids[x].Price,
}
}
book.Asks = make([]orderbook.Level, len(orderbookNew.Asks))
for x := range orderbookNew.Asks {
book.Asks[x] = orderbook.Level{
Amount: orderbookNew.Asks[x].Quantity,
Price: orderbookNew.Asks[x].Price,
}
}
err = book.Process()
if err != nil {
return book, err
if err := ob.Process(); err != nil {
return nil, err
}
return orderbook.Get(e.Name, pair, assetType)
}

View File

@@ -66,7 +66,7 @@ func GetRateLimit() request.RateLimitDefinitions {
}
// orderbookLimit returns the endpoint rate limit representing enum given order depth
func orderbookLimit(depth int64) request.EndpointLimit {
func orderbookLimit(depth uint64) request.EndpointLimit {
switch {
case depth <= 100:
return spotDefaultRate