Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 6 additions & 22 deletions exchanges/binance/binance.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,36 +121,20 @@ func (e *Exchange) GetExchangeInfo(ctx context.Context) (ExchangeInfo, error) {
// OrderBookDataRequestParams contains the following members
// symbol: string of currency pair
// limit: returned limit amount
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With OrderBookDataRequestParams being removed, these comments explaining it should be too.

func (e *Exchange) GetOrderBook(ctx context.Context, obd OrderBookDataRequestParams) (*OrderBook, error) {
func (e *Exchange) GetOrderBook(ctx context.Context, pair currency.Pair, limit int) (*OrderBookResponse, error) {
params := url.Values{}
symbol, err := e.FormatSymbol(obd.Symbol, asset.Spot)
symbol, err := e.FormatSymbol(pair, asset.Spot)
if err != nil {
return nil, err
}
params.Set("symbol", symbol)
params.Set("limit", strconv.Itoa(obd.Limit))
params.Set("limit", strconv.Itoa(limit))

var resp *OrderBookData
if err := e.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, common.EncodeURLValues(orderBookDepth, params), orderbookLimit(obd.Limit), &resp); err != nil {
var resp *OrderBookResponse
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)),
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
return resp, nil
}

// GetMostRecentTrades returns recent trade activity
Expand Down
24 changes: 4 additions & 20 deletions exchanges/binance/binance_cfutures.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (e *Exchange) FuturesExchangeInfo(ctx context.Context) (CExchangeInfo, erro
}

// GetFuturesOrderbook gets orderbook data for CoinMarginedFutures,
func (e *Exchange) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBook, error) {
func (e *Exchange) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBookResponse, error) {
symbolValue, err := e.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return nil, err
Expand All @@ -105,27 +105,11 @@ func (e *Exchange) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair
rateBudget = cFuturesOrderbook500Rate
}

var data *OrderbookData
if err := e.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), rateBudget, &data); err != nil {
var resp *OrderBookResponse
if err := e.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), rateBudget, &resp); err != nil {
return nil, err
}

ob := &OrderBook{
Bids: make([]OrderbookItem, len(data.Bids)),
Asks: make([]OrderbookItem, len(data.Asks)),
}

for x := range data.Bids {
ob.Bids[x].Price = data.Bids[x][0].Float64()
ob.Bids[x].Quantity = data.Bids[x][1].Float64()
}

for x := range data.Asks {
ob.Asks[x].Price = data.Asks[x][0].Float64()
ob.Asks[x].Quantity = data.Asks[x][1].Float64()
}

return ob, nil
return resp, nil
}

// GetFuturesPublicTrades gets recent public trades for CoinMarginedFutures,
Expand Down
57 changes: 26 additions & 31 deletions exchanges/binance/binance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
Expand Down Expand Up @@ -1118,14 +1119,8 @@ func TestFetchTradablePairs(t *testing.T) {

func TestGetOrderBook(t *testing.T) {
t.Parallel()
_, err := e.GetOrderBook(t.Context(),
OrderBookDataRequestParams{
Symbol: currency.NewBTCUSDT(),
Limit: 1000,
})
if err != nil {
t.Error("Binance GetOrderBook() error", err)
}
_, err := e.GetOrderBook(t.Context(), currency.NewBTCUSDT(), 1000)
assert.NoError(t, err)
}

func TestGetMostRecentTrades(t *testing.T) {
Expand Down Expand Up @@ -2102,30 +2097,30 @@ func TestWsDepthUpdate(t *testing.T) {
require.NoError(t, testexch.Setup(e), "Test instance Setup must not error")
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},
book := OrderBookResponse{
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,
}
Expand Down
52 changes: 16 additions & 36 deletions exchanges/binance/binance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/encoding/json"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/types"
)

Expand Down Expand Up @@ -123,35 +124,14 @@ type CoinInfo struct {
Withdrawing float64 `json:"withdrawing,string"`
}

// OrderBookDataRequestParams represents Klines request data.
type OrderBookDataRequestParams struct {
Symbol currency.Pair `json:"symbol"` // Required field; example LTCBTC,BTCUSDT
Limit int `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 {
Code int `json:"code"`
Msg string `json:"msg"`
LastUpdateID int64 `json:"lastUpdateId"`
Bids [][2]types.Number `json:"bids"`
Asks [][2]types.Number `json:"asks"`
}

// OrderBook actual structured data that can be used for orderbook
type OrderBook struct {
Symbol string
LastUpdateID int64
Code int
Msg string
Bids []OrderbookItem
Asks []OrderbookItem
// OrderBookResponse is resp data from orderbook endpoint
type OrderBookResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
LastUpdateID int64 `json:"lastUpdateId"`
Timestamp types.Time `json:"T"`
Bids orderbook.LevelsArrayPriceAmount `json:"bids"`
Asks orderbook.LevelsArrayPriceAmount `json:"asks"`
}

// DepthUpdateParams is used as an embedded type for WebsocketDepthStream
Expand All @@ -163,13 +143,13 @@ type DepthUpdateParams []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"`
}

// RecentTradeRequestParams represents Klines request data.
Expand Down
24 changes: 4 additions & 20 deletions exchanges/binance/binance_ufutures.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (e *Exchange) UExchangeInfo(ctx context.Context) (UFuturesExchangeInfo, err
}

// UFuturesOrderbook gets orderbook data for usdt margined futures
func (e *Exchange) UFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBook, error) {
func (e *Exchange) UFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBookResponse, error) {
symbolValue, err := e.FormatSymbol(symbol, asset.USDTMarginedFutures)
if err != nil {
return nil, err
Expand All @@ -113,27 +113,11 @@ func (e *Exchange) UFuturesOrderbook(ctx context.Context, symbol currency.Pair,
rateBudget = uFuturesOrderbook500Rate
}

var data *OrderbookData
if err := e.SendHTTPRequest(ctx, exchange.RestUSDTMargined, ufuturesOrderbook+params.Encode(), rateBudget, &data); err != nil {
var resp *OrderBookResponse
if err := e.SendHTTPRequest(ctx, exchange.RestUSDTMargined, ufuturesOrderbook+params.Encode(), rateBudget, &resp); err != nil {
return nil, err
}

ob := &OrderBook{
Symbol: symbolValue,
LastUpdateID: data.LastUpdateID,
Bids: make([]OrderbookItem, len(data.Bids)),
Asks: make([]OrderbookItem, len(data.Asks)),
}

for x := range data.Asks {
ob.Asks[x].Price = data.Asks[x][0].Float64()
ob.Asks[x].Quantity = data.Asks[x][1].Float64()
}
for x := range data.Bids {
ob.Bids[x].Price = data.Bids[x][0].Float64()
ob.Bids[x].Quantity = data.Bids[x][1].Float64()
}
return ob, nil
return resp, nil
}

// URecentTrades gets recent trades for usdt margined futures
Expand Down
48 changes: 11 additions & 37 deletions exchanges/binance/binance_websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,40 +449,28 @@ func stringToOrderStatus(status string) (order.Status, error) {

// SeedLocalCache seeds depth data
func (e *Exchange) SeedLocalCache(ctx context.Context, p currency.Pair) error {
ob, err := e.GetOrderBook(ctx,
OrderBookDataRequestParams{
Symbol: p,
Limit: 1000,
})
ob, err := e.GetOrderBook(ctx, p, 1000)
if err != nil {
return err
}
return e.SeedLocalCacheWithBook(p, ob)
}

// SeedLocalCacheWithBook seeds the local orderbook cache
func (e *Exchange) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBook) error {
func (e *Exchange) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBookResponse) error {
t := orderbookNew.Timestamp.Time()
if t.IsZero() {
t = time.Now() // Time not provided for this REST book.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this handling still necessary? Are there ever books which don't return their time?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it seems like all spot orderbooks don't return a time value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, but GetOrderBook() is in the non-futures file, and has a timestamp in its response struct. If that can just receive futures responses too, don't worry, but if it's spot-only, I think including a timestamp field there if one is never returned is bad.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are right I was most likely thinking when I convert this over to manage other assets as well when I do a full ob pass that this will auto utilise the shared field. I can drop it if you really want but it might be missed in a future upgrade pass.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're better informed on the tradeoffs than me, so use your own judgement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will leave this unresolved for other peoples perspective. Either way when somebody is doing some hectic trading and they see a latency discrepancy they will be all like 👻 and open a holy PR that rectifies this issue. 🙏

}
newOrderBook := 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)),
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,
}
Bids: orderbookNew.Bids.Levels(),
Asks: orderbookNew.Asks.Levels(),
LastUpdated: t,
}
return e.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
Expand Down Expand Up @@ -618,23 +606,9 @@ func (e *Exchange) manageSubs(ctx context.Context, op string, subs subscription.

// ProcessOrderbookUpdate processes the websocket orderbook update
func (e *Exchange) ProcessOrderbookUpdate(cp currency.Pair, a asset.Item, ws *WebsocketDepthStream) error {
updateBid := make([]orderbook.Level, len(ws.UpdateBids))
for i := range ws.UpdateBids {
updateBid[i] = orderbook.Level{
Price: ws.UpdateBids[i][0].Float64(),
Amount: ws.UpdateBids[i][1].Float64(),
}
}
updateAsk := make([]orderbook.Level, len(ws.UpdateAsks))
for i := range ws.UpdateAsks {
updateAsk[i] = orderbook.Level{
Price: ws.UpdateAsks[i][0].Float64(),
Amount: ws.UpdateAsks[i][1].Float64(),
}
}
return e.Websocket.Orderbook.Update(&orderbook.Update{
Bids: updateBid,
Asks: updateAsk,
Bids: ws.UpdateBids.Levels(),
Asks: ws.UpdateAsks.Levels(),
Pair: cp,
UpdateID: ws.LastUpdateID,
UpdateTime: ws.Timestamp.Time(),
Expand Down
Loading
Loading