diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index 487019b2..24319300 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -27,8 +27,7 @@ type Binance struct { exchange.Base // Valid string list that is required by the exchange validLimits []int - - obm *orderbookManager + obm *orderbookManager } const ( @@ -74,7 +73,7 @@ const ( // GetInterestHistory gets interest history for currency/currencies provided func (b *Binance) GetInterestHistory() (MarginInfoData, error) { var resp MarginInfoData - if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedInterestHistory, limitDefault, &resp); err != nil { + if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedInterestHistory, spotDefaultRate, &resp); err != nil { return resp, err } return resp, nil @@ -83,7 +82,7 @@ func (b *Binance) GetInterestHistory() (MarginInfoData, error) { // GetCrossMarginInterestHistory gets cross-margin interest history for currency/currencies provided func (b *Binance) GetCrossMarginInterestHistory() (CrossMarginInterestData, error) { var resp CrossMarginInterestData - if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedCrossMarginInterestHistory, limitDefault, &resp); err != nil { + if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedCrossMarginInterestHistory, spotDefaultRate, &resp); err != nil { return resp, err } return resp, nil @@ -92,14 +91,14 @@ func (b *Binance) GetCrossMarginInterestHistory() (CrossMarginInterestData, erro // GetMarginMarkets returns exchange information. Check binance_types for more information func (b *Binance) GetMarginMarkets() (PerpsExchangeInfo, error) { var resp PerpsExchangeInfo - return resp, b.SendHTTPRequest(exchange.RestSpot, perpExchangeInfo, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpot, perpExchangeInfo, spotDefaultRate, &resp) } // GetExchangeInfo returns exchange information. Check binance_types for more // information func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) { var resp ExchangeInfo - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, exchangeInfo, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, exchangeInfo, spotDefaultRate, &resp) } // GetOrderBook returns full orderbook information @@ -179,7 +178,7 @@ func (b *Binance) GetMostRecentTrades(rtr RecentTradeRequestParams) ([]RecentTra path := recentTrades + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &resp) } // GetHistoricalTrades returns historical trade activity @@ -243,7 +242,7 @@ func (b *Binance) GetAggregatedTrades(arg *AggregatedTradeRequestParams) ([]Aggr } var resp []AggregatedTrade path := aggregatedTrades + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &resp) } // batchAggregateTrades fetches trades in multiple requests @@ -269,7 +268,7 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params params.Set("startTime", timeString(start)) params.Set("endTime", timeString(start.Add(time.Hour))) path := aggregatedTrades + "?" + params.Encode() - err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp) + err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &resp) if err != nil { log.Warn(log.ExchangeSys, err.Error()) return resp, err @@ -287,7 +286,7 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params params.Set("fromId", strconv.FormatInt(fromID, 10)) path := aggregatedTrades + "?" + params.Encode() var additionalTrades []AggregatedTrade - err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &additionalTrades) + err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &additionalTrades) if err != nil { return resp, err } @@ -344,7 +343,7 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error) path := candleStick + "?" + params.Encode() - if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp); err != nil { + if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &resp); err != nil { return klineData, err } @@ -405,7 +404,7 @@ func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) { path := averagePrice + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, spotDefaultRate, &resp) } // GetPriceChangeStats returns price change statistics for the last 24 hours @@ -414,21 +413,24 @@ func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) { func (b *Binance) GetPriceChangeStats(symbol currency.Pair) (PriceChangeStats, error) { resp := PriceChangeStats{} params := url.Values{} - symbolValue, err := b.FormatSymbol(symbol, asset.Spot) - if err != nil { - return resp, err + rateLimit := spotPriceChangeAllRate + if !symbol.IsEmpty() { + rateLimit = spotDefaultRate + symbolValue, err := b.FormatSymbol(symbol, asset.Spot) + if err != nil { + return resp, err + } + params.Set("symbol", symbolValue) } - params.Set("symbol", symbolValue) - path := priceChange + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, rateLimit, &resp) } // GetTickers returns the ticker data for the last 24 hrs func (b *Binance) GetTickers() ([]PriceChangeStats, error) { var resp []PriceChangeStats - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, priceChange, limitPriceChangeAll, &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, priceChange, spotPriceChangeAllRate, &resp) } // GetLatestSpotPrice returns latest spot price of symbol @@ -437,15 +439,18 @@ func (b *Binance) GetTickers() ([]PriceChangeStats, error) { func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error) { resp := SymbolPrice{} params := url.Values{} - symbolValue, err := b.FormatSymbol(symbol, asset.Spot) - if err != nil { - return resp, err + rateLimit := spotSymbolPriceAllRate + if !symbol.IsEmpty() { + rateLimit = spotDefaultRate + symbolValue, err := b.FormatSymbol(symbol, asset.Spot) + if err != nil { + return resp, err + } + params.Set("symbol", symbolValue) } - params.Set("symbol", symbolValue) - path := symbolPrice + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, symbolPriceLimit(symbolValue), &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, rateLimit, &resp) } // GetBestPrice returns the latest best price for symbol @@ -454,15 +459,18 @@ func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error) func (b *Binance) GetBestPrice(symbol currency.Pair) (BestPrice, error) { resp := BestPrice{} params := url.Values{} - symbolValue, err := b.FormatSymbol(symbol, asset.Spot) - if err != nil { - return resp, err + rateLimit := spotOrderbookTickerAllRate + if !symbol.IsEmpty() { + rateLimit = spotDefaultRate + symbolValue, err := b.FormatSymbol(symbol, asset.Spot) + if err != nil { + return resp, err + } + params.Set("symbol", symbolValue) } - params.Set("symbol", symbolValue) - path := bestPrice + "?" + params.Encode() - return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, bestPriceLimit(symbolValue), &resp) + return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, rateLimit, &resp) } // NewOrder sends a new order to Binance @@ -521,7 +529,7 @@ func (b *Binance) newOrder(api string, o *NewOrderRequest, resp *NewOrderRespons if o.NewOrderRespType != "" { params.Set("newOrderRespType", o.NewOrderRespType) } - return b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, api, params, limitOrder, resp) + return b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, api, params, spotOrderRate, resp) } // CancelExistingOrder sends a cancel order to Binance @@ -542,7 +550,7 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodDelete, orderEndpoint, params, limitOrder, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodDelete, orderEndpoint, params, spotOrderRate, &resp) } // OpenOrders Current open orders. Get all open orders on a symbol. @@ -588,7 +596,7 @@ func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]Quer if limit != "" { params.Set("limit", limit) } - if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, allOrders, params, limitOrdersAll, &resp); err != nil { + if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, allOrders, params, spotOrdersAllRate, &resp); err != nil { return resp, err } @@ -612,7 +620,7 @@ func (b *Binance) QueryOrder(symbol currency.Pair, origClientOrderID string, ord params.Set("orderId", strconv.FormatInt(orderID, 10)) } - if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, orderEndpoint, params, limitOrder, &resp); err != nil { + if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, orderEndpoint, params, spotOrderRate, &resp); err != nil { return resp, err } @@ -632,7 +640,7 @@ func (b *Binance) GetAccount() (*Account, error) { var resp response params := url.Values{} - if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, accountInfo, params, request.Unset, &resp); err != nil { + if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, accountInfo, params, spotAccountInformationRate, &resp); err != nil { return &resp.Account, err } @@ -809,7 +817,7 @@ func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string params.Set("addressTag", addressTag) } - if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, withdrawEndpoint, params, request.Unset, &resp); err != nil { + if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, withdrawEndpoint, params, spotDefaultRate, &resp); err != nil { return "", err } @@ -854,7 +862,7 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT params.Set("endTime", strconv.FormatInt(endTime, 10)) } - if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, withdrawalHistory, params, request.Unset, &response); err != nil { + if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, withdrawalHistory, params, spotDefaultRate, &response); err != nil { return response.WithdrawList, err } @@ -872,9 +880,10 @@ func (b *Binance) GetDepositAddressForCurrency(currency string) (string, error) params := url.Values{} params.Set("asset", currency) params.Set("status", "true") + params.Set("recvWindow", "10000") return resp.Address, - b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, depositAddress, params, request.Unset, &resp) + b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, depositAddress, params, spotDefaultRate, &resp) } // GetWsAuthStreamKey will retrieve a key to use for authorised WS streaming diff --git a/exchanges/binance/binance_cfutures.go b/exchanges/binance/binance_cfutures.go index 8934efb2..63fa6266 100644 --- a/exchanges/binance/binance_cfutures.go +++ b/exchanges/binance/binance_cfutures.go @@ -13,6 +13,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/request" ) const ( @@ -66,7 +67,7 @@ const ( // FuturesExchangeInfo stores CoinMarginedFutures, data func (b *Binance) FuturesExchangeInfo() (CExchangeInfo, error) { var resp CExchangeInfo - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesExchangeInfo, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesExchangeInfo, cFuturesDefaultRate, &resp) } // GetFuturesOrderbook gets orderbook data for CoinMarginedFutures, @@ -74,6 +75,17 @@ func (b *Binance) GetFuturesOrderbook(symbol currency.Pair, limit int64) (OrderB var resp OrderBook var data OrderbookData params := url.Values{} + rateBudget := cFuturesDefaultRate + switch { + case limit == 5, limit == 10, limit == 20, limit == 50: + rateBudget = cFuturesOrderbook50Rate + case limit >= 100 && limit < 500: + rateBudget = cFuturesOrderbook100Rate + case limit >= 500 && limit < 1000: + rateBudget = cFuturesOrderbook500Rate + case limit == 1000: + rateBudget = cFuturesOrderbook1000Rate + } symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -82,7 +94,7 @@ func (b *Binance) GetFuturesOrderbook(symbol currency.Pair, limit int64) (OrderB if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } - err = b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), limitDefault, &data) + err = b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -130,7 +142,7 @@ func (b *Binance) GetFuturesPublicTrades(symbol currency.Pair, limit int64) ([]F if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), cFuturesDefaultRate, &resp) } // GetFuturesHistoricalTrades gets historical public trades for CoinMarginedFutures, @@ -148,7 +160,7 @@ func (b *Binance) GetFuturesHistoricalTrades(symbol currency.Pair, fromID string if limit > 0 && limit < 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesHistoricalTrades, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesHistoricalTrades, params, cFuturesHistoricalTradesRate, &resp) } // GetPastPublicTrades gets past public trades for CoinMarginedFutures, @@ -166,7 +178,7 @@ func (b *Binance) GetPastPublicTrades(symbol currency.Pair, limit, fromID int64) if fromID != 0 { params.Set("fromID", strconv.FormatInt(fromID, 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), cFuturesDefaultRate, &resp) } // GetFuturesAggregatedTradesList gets aggregated trades list for CoinMarginedFutures, @@ -191,7 +203,7 @@ func (b *Binance) GetFuturesAggregatedTradesList(symbol currency.Pair, fromID, l params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesCompressedTrades+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesCompressedTrades+params.Encode(), cFuturesHistoricalTradesRate, &resp) } // GetIndexAndMarkPrice gets index and mark prices for CoinMarginedFutures, @@ -204,7 +216,7 @@ func (b *Binance) GetIndexAndMarkPrice(symbol, pair string) ([]IndexMarkPrice, e if pair != "" { params.Set("pair", pair) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesMarkPrice+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesMarkPrice+params.Encode(), cFuturesIndexMarkPriceRate, &resp) } // GetFuturesKlineData gets futures kline data for CoinMarginedFutures, @@ -212,14 +224,14 @@ func (b *Binance) GetFuturesKlineData(symbol currency.Pair, interval string, lim var data [][10]interface{} var resp []FuturesCandleStick params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } - if limit > 0 && limit <= 1000 { + if limit > 0 && limit <= 1500 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { @@ -233,7 +245,8 @@ func (b *Binance) GetFuturesKlineData(symbol currency.Pair, interval string, lim params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesKlineData+params.Encode(), limitDefault, &data) + rateBudget := getKlineRateBudget(limit) + err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesKlineData+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -335,7 +348,7 @@ func (b *Binance) GetContinuousKlineData(pair, contractType, interval string, li return resp, errors.New("invalid contractType") } params.Set("contractType", contractType) - if limit > 0 && limit <= 1000 { + if limit > 0 && limit <= 1500 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { @@ -349,7 +362,9 @@ func (b *Binance) GetContinuousKlineData(pair, contractType, interval string, li params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesContinuousKline+params.Encode(), limitDefault, &data) + + rateBudget := getKlineRateBudget(limit) + err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesContinuousKline+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -447,7 +462,7 @@ func (b *Binance) GetIndexPriceKlines(pair, interval string, limit int64, startT var resp []FuturesCandleStick params := url.Values{} params.Set("pair", pair) - if limit > 0 && limit <= 1000 { + if limit > 0 && limit <= 1500 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { @@ -461,7 +476,8 @@ func (b *Binance) GetIndexPriceKlines(pair, interval string, limit int64, startT params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesIndexKline+params.Encode(), limitDefault, &data) + rateBudget := getKlineRateBudget(limit) + err := b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesIndexKline+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -563,7 +579,7 @@ func (b *Binance) GetMarkPriceKline(symbol currency.Pair, interval string, limit return resp, err } params.Set("symbol", symbolValue) - if limit > 0 && limit <= 1000 { + if limit > 0 && limit <= 1500 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { @@ -577,7 +593,8 @@ func (b *Binance) GetMarkPriceKline(symbol currency.Pair, interval string, limit params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - err = b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesMarkPriceKline+params.Encode(), limitDefault, &data) + rateBudget := getKlineRateBudget(limit) + err = b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesMarkPriceKline+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -669,11 +686,28 @@ func (b *Binance) GetMarkPriceKline(symbol currency.Pair, interval string, limit return resp, nil } +func getKlineRateBudget(limit int64) request.EndpointLimit { + rateBudget := cFuturesDefaultRate + switch { + case limit > 0 && limit < 100: + rateBudget = cFuturesKline100Rate + case limit >= 100 && limit < 500: + rateBudget = cFuturesKline500Rate + case limit >= 500 && limit < 1000: + rateBudget = cFuturesKline1000Rate + case limit >= 1000: + rateBudget = cFuturesKlineMaxRate + } + return rateBudget +} + // GetFuturesSwapTickerChangeStats gets 24hr ticker change stats for CoinMarginedFutures, func (b *Binance) GetFuturesSwapTickerChangeStats(symbol currency.Pair, pair string) ([]PriceChangeStats, error) { var resp []PriceChangeStats params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := cFuturesTickerPriceHistoryRate + if !symbol.IsEmpty() { + rateLimit = cFuturesDefaultRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -683,14 +717,14 @@ func (b *Binance) GetFuturesSwapTickerChangeStats(symbol currency.Pair, pair str if pair != "" { params.Set("pair", pair) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTickerPriceStats+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTickerPriceStats+params.Encode(), rateLimit, &resp) } // FuturesGetFundingHistory gets funding history for CoinMarginedFutures, func (b *Binance) FuturesGetFundingHistory(symbol currency.Pair, limit int64, startTime, endTime time.Time) ([]FundingRateHistory, error) { var resp []FundingRateHistory params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -707,14 +741,16 @@ func (b *Binance) FuturesGetFundingHistory(symbol currency.Pair, limit int64, st params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesFundingRateHistory+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesFundingRateHistory+params.Encode(), cFuturesDefaultRate, &resp) } // GetFuturesSymbolPriceTicker gets price ticker for symbol func (b *Binance) GetFuturesSymbolPriceTicker(symbol currency.Pair, pair string) ([]SymbolPriceTicker, error) { var resp []SymbolPriceTicker params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := cFuturesOrderbookTickerAllRate + if !symbol.IsEmpty() { + rateLimit = cFuturesDefaultRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -724,14 +760,16 @@ func (b *Binance) GetFuturesSymbolPriceTicker(symbol currency.Pair, pair string) if pair != "" { params.Set("pair", pair) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolPriceTicker+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolPriceTicker+params.Encode(), rateLimit, &resp) } // GetFuturesOrderbookTicker gets orderbook ticker for symbol func (b *Binance) GetFuturesOrderbookTicker(symbol currency.Pair, pair string) ([]SymbolOrderBookTicker, error) { var resp []SymbolOrderBookTicker params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := cFuturesOrderbookTickerAllRate + if !symbol.IsEmpty() { + rateLimit = cFuturesDefaultRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -741,14 +779,16 @@ func (b *Binance) GetFuturesOrderbookTicker(symbol currency.Pair, pair string) ( if pair != "" { params.Set("pair", pair) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolOrderbook+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolOrderbook+params.Encode(), rateLimit, &resp) } -// GetFuturesLiquidationOrders gets orderbook ticker for symbol +// GetFuturesLiquidationOrders gets forced liquidation orders func (b *Binance) GetFuturesLiquidationOrders(symbol currency.Pair, pair string, limit int64, startTime, endTime time.Time) ([]AllLiquidationOrders, error) { var resp []AllLiquidationOrders params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := cFuturesAllForceOrdersRate + if !symbol.IsEmpty() { + rateLimit = cFuturesCurrencyForceOrdersRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -768,7 +808,7 @@ func (b *Binance) GetFuturesLiquidationOrders(symbol currency.Pair, pair string, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesLiquidationOrders+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesLiquidationOrders+params.Encode(), rateLimit, &resp) } // GetOpenInterest gets open interest data for a symbol @@ -780,7 +820,7 @@ func (b *Binance) GetOpenInterest(symbol currency.Pair) (OpenInterestData, error return resp, err } params.Set("symbol", symbolValue) - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOpenInterest+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOpenInterest+params.Encode(), cFuturesDefaultRate, &resp) } // GetOpenInterestStats gets open interest stats for a symbol @@ -808,7 +848,7 @@ func (b *Binance) GetOpenInterestStats(pair, contractType, period string, limit params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOpenInterestStats+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOpenInterestStats+params.Encode(), cFuturesDefaultRate, &resp) } // GetTraderFuturesAccountRatio gets a traders futures account long/short ratio @@ -830,7 +870,7 @@ func (b *Binance) GetTraderFuturesAccountRatio(pair, period string, limit int64, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTopAccountsRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTopAccountsRatio+params.Encode(), cFuturesDefaultRate, &resp) } // GetTraderFuturesPositionsRatio gets a traders futures positions' long/short ratio @@ -852,7 +892,7 @@ func (b *Binance) GetTraderFuturesPositionsRatio(pair, period string, limit int6 params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTopPositionsRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTopPositionsRatio+params.Encode(), cFuturesDefaultRate, &resp) } // GetMarketRatio gets global long/short ratio @@ -874,7 +914,7 @@ func (b *Binance) GetMarketRatio(pair, period string, limit int64, startTime, en params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesLongShortRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesLongShortRatio+params.Encode(), cFuturesDefaultRate, &resp) } // GetFuturesTakerVolume gets futures taker buy/sell volumes @@ -900,7 +940,7 @@ func (b *Binance) GetFuturesTakerVolume(pair, contractType, period string, limit params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesBuySellVolume+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesBuySellVolume+params.Encode(), cFuturesDefaultRate, &resp) } // GetFuturesBasisData gets futures basis data @@ -926,7 +966,7 @@ func (b *Binance) GetFuturesBasisData(pair, contractType, period string, limit i params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesBasis+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesBasis+params.Encode(), cFuturesDefaultRate, &resp) } // FuturesNewOrder sends a new futures order to the exchange @@ -985,7 +1025,7 @@ func (b *Binance) FuturesNewOrder(symbol currency.Pair, side, positionSide, orde if callbackRate != 0 { params.Set("callbackRate", strconv.FormatFloat(callbackRate, 'f', -1, 64)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesOrder, params, cFuturesOrdersDefaultRate, &resp) } // FuturesBatchOrder sends a batch order request @@ -1023,7 +1063,7 @@ func (b *Binance) FuturesBatchOrder(data []PlaceBatchOrderData) ([]FuturesOrderP return resp, err } params.Set("batchOrders", string(jsonData)) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesBatchOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesBatchOrder, params, cFuturesBatchOrdersRate, &resp) } // FuturesBatchCancelOrders sends a batch request to cancel orders @@ -1049,7 +1089,7 @@ func (b *Binance) FuturesBatchCancelOrders(symbol currency.Pair, orderList, orig } params.Set("origClientOrderIdList", string(jsonCliOrdIDList)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesBatchOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesBatchOrder, params, cFuturesOrdersDefaultRate, &resp) } // FuturesGetOrderData gets futures order data @@ -1067,7 +1107,7 @@ func (b *Binance) FuturesGetOrderData(symbol currency.Pair, orderID, origClientO if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOrder, params, cFuturesOrdersDefaultRate, &resp) } // FuturesCancelOrder cancels a futures order @@ -1085,7 +1125,7 @@ func (b *Binance) FuturesCancelOrder(symbol currency.Pair, orderID, origClientOr if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesOrder, params, cFuturesOrdersDefaultRate, &resp) } // FuturesCancelAllOpenOrders cancels a futures order @@ -1097,7 +1137,7 @@ func (b *Binance) FuturesCancelAllOpenOrders(symbol currency.Pair) (GenericAuthR return resp, err } params.Set("symbol", symbolValue) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesCancelAllOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesCancelAllOrders, params, cFuturesOrdersDefaultRate, &resp) } // AutoCancelAllOpenOrders cancels all open futures orders @@ -1111,7 +1151,7 @@ func (b *Binance) AutoCancelAllOpenOrders(symbol currency.Pair, countdownTime in } params.Set("symbol", symbolValue) params.Set("countdownTime", strconv.FormatInt(countdownTime, 10)) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesCountdownCancel, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesCountdownCancel, params, cFuturesCancelAllOrdersRate, &resp) } // FuturesOpenOrderData gets open order data for CoinMarginedFutures, @@ -1129,31 +1169,40 @@ func (b *Binance) FuturesOpenOrderData(symbol currency.Pair, orderID, origClient if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOpenOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOpenOrder, params, cFuturesOrdersDefaultRate, &resp) } // GetFuturesAllOpenOrders gets all open orders data for CoinMarginedFutures, func (b *Binance) GetFuturesAllOpenOrders(symbol currency.Pair, pair string) ([]FuturesOrderData, error) { var resp []FuturesOrderData params := url.Values{} + var p string + var err error + rateLimit := cFuturesGetAllOpenOrdersRate if !symbol.IsEmpty() { - symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) + rateLimit = cFuturesOrdersDefaultRate + p, err = b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } - params.Set("symbol", symbolValue) + params.Set("symbol", p) + } else { + // extend the receive window when all currencies to prevent "recvwindow" error + params.Set("recvWindow", "10000") } if pair != "" { params.Set("pair", pair) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAllOpenOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAllOpenOrders, params, rateLimit, &resp) } // GetAllFuturesOrders gets all orders active cancelled or filled func (b *Binance) GetAllFuturesOrders(symbol currency.Pair, pair string, startTime, endTime time.Time, orderID, limit int64) ([]FuturesOrderData, error) { var resp []FuturesOrderData params := url.Values{} + rateLimit := cFuturesPairOrdersRate if !symbol.IsEmpty() { + rateLimit = cFuturesSymbolOrdersRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -1176,19 +1225,19 @@ func (b *Binance) GetAllFuturesOrders(symbol currency.Pair, pair string, startTi params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAllOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAllOrders, params, rateLimit, &resp) } // GetFuturesAccountBalance gets account balance data for CoinMarginedFutures, account func (b *Binance) GetFuturesAccountBalance() ([]FuturesAccountBalanceData, error) { var resp []FuturesAccountBalanceData - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountBalance, nil, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountBalance, nil, cFuturesDefaultRate, &resp) } // GetFuturesAccountInfo gets account info data for CoinMarginedFutures, account func (b *Binance) GetFuturesAccountInfo() (FuturesAccountInformation, error) { var resp FuturesAccountInformation - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountInfo, nil, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountInfo, nil, cFuturesAccountInformationRate, &resp) } // FuturesChangeInitialLeverage changes initial leverage for the account @@ -1204,7 +1253,7 @@ func (b *Binance) FuturesChangeInitialLeverage(symbol currency.Pair, leverage in return resp, errors.New("invalid leverage") } params.Set("leverage", strconv.FormatInt(leverage, 10)) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesChangeInitialLeverage, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesChangeInitialLeverage, params, cFuturesDefaultRate, &resp) } // FuturesChangeMarginType changes margin type @@ -1220,7 +1269,7 @@ func (b *Binance) FuturesChangeMarginType(symbol currency.Pair, marginType strin return resp, errors.New("invalid marginType") } params.Set("marginType", marginType) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesChangeMarginType, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesChangeMarginType, params, cFuturesDefaultRate, &resp) } // ModifyIsolatedPositionMargin changes margin for an isolated position @@ -1242,7 +1291,7 @@ func (b *Binance) ModifyIsolatedPositionMargin(symbol currency.Pair, positionSid } params.Set("type", strconv.FormatInt(cType, 10)) params.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesModifyMargin, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesModifyMargin, params, cFuturesDefaultRate, &resp) } // FuturesMarginChangeHistory gets past margin changes for positions @@ -1269,7 +1318,7 @@ func (b *Binance) FuturesMarginChangeHistory(symbol currency.Pair, changeType st if limit != 0 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesMarginChangeHistory, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesMarginChangeHistory, params, cFuturesDefaultRate, &resp) } // FuturesPositionsInfo gets futures positions info @@ -1282,14 +1331,16 @@ func (b *Binance) FuturesPositionsInfo(marginAsset, pair string) ([]FuturesPosit if pair != "" { params.Set("pair", pair) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesPositionInfo, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesPositionInfo, params, cFuturesDefaultRate, &resp) } // FuturesTradeHistory gets trade history for CoinMarginedFutures, account func (b *Binance) FuturesTradeHistory(symbol currency.Pair, pair string, startTime, endTime time.Time, limit, fromID int64) ([]FuturesAccountTradeList, error) { var resp []FuturesAccountTradeList params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := cFuturesPairOrdersRate + if !symbol.IsEmpty() { + rateLimit = cFuturesSymbolOrdersRate symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -1312,14 +1363,14 @@ func (b *Binance) FuturesTradeHistory(symbol currency.Pair, pair string, startTi if fromID != 0 { params.Set("fromId", strconv.FormatInt(fromID, 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountTradeList, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountTradeList, params, rateLimit, &resp) } // FuturesIncomeHistory gets income history for CoinMarginedFutures, func (b *Binance) FuturesIncomeHistory(symbol currency.Pair, incomeType string, startTime, endTime time.Time, limit int64) ([]FuturesIncomeHistoryData, error) { var resp []FuturesIncomeHistoryData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -1342,7 +1393,7 @@ func (b *Binance) FuturesIncomeHistory(symbol currency.Pair, incomeType string, if limit != 0 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesIncomeHistory, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesIncomeHistory, params, cFuturesIncomeHistoryRate, &resp) } // FuturesNotionalBracket gets futures notional bracket @@ -1352,14 +1403,14 @@ func (b *Binance) FuturesNotionalBracket(pair string) ([]NotionalBracketData, er if pair != "" { params.Set("pair", pair) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesNotionalBracket, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesNotionalBracket, params, cFuturesDefaultRate, &resp) } // FuturesForceOrders gets futures forced orders func (b *Binance) FuturesForceOrders(symbol currency.Pair, autoCloseType string, startTime, endTime time.Time) ([]ForcedOrdersData, error) { var resp []ForcedOrdersData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -1379,19 +1430,19 @@ func (b *Binance) FuturesForceOrders(symbol currency.Pair, autoCloseType string, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesUsersForceOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesUsersForceOrders, params, cFuturesDefaultRate, &resp) } // FuturesPositionsADLEstimate estimates ADL on positions func (b *Binance) FuturesPositionsADLEstimate(symbol currency.Pair) ([]ADLEstimateData, error) { var resp []ADLEstimateData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } - return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesADLQuantile, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesADLQuantile, params, cFuturesAccountInformationRate, &resp) } diff --git a/exchanges/binance/binance_ufutures.go b/exchanges/binance/binance_ufutures.go index 1e3f2c96..2c155fed 100644 --- a/exchanges/binance/binance_ufutures.go +++ b/exchanges/binance/binance_ufutures.go @@ -64,7 +64,7 @@ const ( // UExchangeInfo stores usdt margined futures data func (b *Binance) UExchangeInfo() (UFuturesExchangeInfo, error) { var resp UFuturesExchangeInfo - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesExchangeInfo, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesExchangeInfo, uFuturesDefaultRate, &resp) } // UFuturesOrderbook gets orderbook data for usdt margined futures @@ -84,7 +84,18 @@ func (b *Binance) UFuturesOrderbook(symbol currency.Pair, limit int64) (OrderBoo } params.Set("limit", strLimit) } - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOrderbook+params.Encode(), limitDefault, &data) + rateBudget := uFuturesDefaultRate + switch { + case limit == 5, limit == 10, limit == 20, limit == 50: + rateBudget = uFuturesOrderbook50Rate + case limit >= 100 && limit < 500: + rateBudget = uFuturesOrderbook100Rate + case limit >= 500 && limit < 1000: + rateBudget = uFuturesOrderbook500Rate + case limit == 1000: + rateBudget = uFuturesOrderbook1000Rate + } + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOrderbook+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -137,7 +148,7 @@ func (b *Binance) URecentTrades(symbol currency.Pair, fromID string, limit int64 if limit > 0 && limit < 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesRecentTrades+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesRecentTrades+params.Encode(), uFuturesDefaultRate, &resp) } // UFuturesHistoricalTrades gets historical public trades for USDTMarginedFutures @@ -155,7 +166,7 @@ func (b *Binance) UFuturesHistoricalTrades(symbol currency.Pair, fromID string, if limit > 0 && limit < 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesHistoricalTrades, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesHistoricalTrades, params, uFuturesHistoricalTradesRate, &resp) } // UCompressedTrades gets compressed public trades for usdt margined futures @@ -180,7 +191,7 @@ func (b *Binance) UCompressedTrades(symbol currency.Pair, fromID string, limit i params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompressedTrades+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompressedTrades+params.Encode(), uFuturesHistoricalTradesRate, &resp) } // UKlineData gets kline data for usdt margined futures @@ -197,7 +208,7 @@ func (b *Binance) UKlineData(symbol currency.Pair, interval string, limit int64, return resp, errors.New("invalid interval") } params.Set("interval", interval) - if limit > 0 && limit < 1000 { + if limit > 0 && limit <= 1500 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { @@ -207,7 +218,18 @@ func (b *Binance) UKlineData(symbol currency.Pair, interval string, limit int64, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesKlineData+params.Encode(), limitDefault, &data) + rateBudget := uFuturesDefaultRate + switch { + case limit > 0 && limit <= 100: + rateBudget = uFuturesKline100Rate + case limit > 100 && limit <= 500: + rateBudget = uFuturesKline500Rate + case limit > 500 && limit <= 1000: + rateBudget = uFuturesKline1000Rate + case limit > 1000: + rateBudget = uFuturesKlineMaxRate + } + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesKlineData+params.Encode(), rateBudget, &data) if err != nil { return resp, err } @@ -302,21 +324,21 @@ func (b *Binance) UKlineData(symbol currency.Pair, interval string, limit int64, // UGetMarkPrice gets mark price data for USDTMarginedFutures func (b *Binance) UGetMarkPrice(symbol currency.Pair) ([]UMarkPrice, error) { params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return nil, err } params.Set("symbol", symbolValue) var tempResp UMarkPrice - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesMarkPrice+params.Encode(), limitDefault, &tempResp) + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesMarkPrice+params.Encode(), uFuturesDefaultRate, &tempResp) if err != nil { return nil, err } return []UMarkPrice{tempResp}, nil } var resp []UMarkPrice - err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesMarkPrice+params.Encode(), limitDefault, &resp) + err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesMarkPrice+params.Encode(), uFuturesDefaultRate, &resp) if err != nil { return nil, err } @@ -327,7 +349,7 @@ func (b *Binance) UGetMarkPrice(symbol currency.Pair) ([]UMarkPrice, error) { func (b *Binance) UGetFundingHistory(symbol currency.Pair, limit int64, startTime, endTime time.Time) ([]FundingRateHistory, error) { var resp []FundingRateHistory params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err @@ -344,69 +366,69 @@ func (b *Binance) UGetFundingHistory(symbol currency.Pair, limit int64, startTim params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesFundingRateHistory+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesFundingRateHistory+params.Encode(), uFuturesDefaultRate, &resp) } // U24HTickerPriceChangeStats gets 24hr ticker price change stats for USDTMarginedFutures func (b *Binance) U24HTickerPriceChangeStats(symbol currency.Pair) ([]U24HrPriceChangeStats, error) { params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return nil, err } params.Set("symbol", symbolValue) var tempResp U24HrPriceChangeStats - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), limitDefault, &tempResp) + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), uFuturesDefaultRate, &tempResp) if err != nil { return nil, err } return []U24HrPriceChangeStats{tempResp}, err } var resp []U24HrPriceChangeStats - err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), limitDefault, &resp) + err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), uFuturesTickerPriceHistoryRate, &resp) return resp, err } // USymbolPriceTicker gets symbol price ticker for USDTMarginedFutures func (b *Binance) USymbolPriceTicker(symbol currency.Pair) ([]USymbolPriceTicker, error) { params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return nil, err } params.Set("symbol", symbolValue) var tempResp USymbolPriceTicker - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolPriceTicker+params.Encode(), limitDefault, &tempResp) + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolPriceTicker+params.Encode(), uFuturesDefaultRate, &tempResp) if err != nil { return nil, err } return []USymbolPriceTicker{tempResp}, err } var resp []USymbolPriceTicker - err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolPriceTicker+params.Encode(), limitDefault, &resp) + err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolPriceTicker+params.Encode(), uFuturesOrderbookTickerAllRate, &resp) return resp, err } // USymbolOrderbookTicker gets symbol orderbook ticker func (b *Binance) USymbolOrderbookTicker(symbol currency.Pair) ([]USymbolOrderbookTicker, error) { params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return nil, err } params.Set("symbol", symbolValue) var tempResp USymbolOrderbookTicker - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolOrderbook+params.Encode(), limitDefault, &tempResp) + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesSymbolOrderbook+params.Encode(), uFuturesDefaultRate, &tempResp) if err != nil { return nil, err } return []USymbolOrderbookTicker{tempResp}, err } var resp []USymbolOrderbookTicker - err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), limitDefault, &resp) + err := b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTickerPriceStats+params.Encode(), uFuturesOrderbookTickerAllRate, &resp) return resp, err } @@ -414,7 +436,9 @@ func (b *Binance) USymbolOrderbookTicker(symbol currency.Pair) ([]USymbolOrderbo func (b *Binance) ULiquidationOrders(symbol currency.Pair, limit int64, startTime, endTime time.Time) ([]ULiquidationOrdersData, error) { var resp []ULiquidationOrdersData params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := uFuturesAllForceOrdersRate + if !symbol.IsEmpty() { + rateLimit = uFuturesCurrencyForceOrdersRate symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err @@ -431,7 +455,7 @@ func (b *Binance) ULiquidationOrders(symbol currency.Pair, limit int64, startTim params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesLiquidationOrders+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesLiquidationOrders+params.Encode(), rateLimit, &resp) } // UOpenInterest gets open interest data for USDTMarginedFutures @@ -443,7 +467,7 @@ func (b *Binance) UOpenInterest(symbol currency.Pair) (UOpenInterestData, error) return resp, err } params.Set("symbol", symbolValue) - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOpenInterest+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOpenInterest+params.Encode(), uFuturesDefaultRate, &resp) } // UOpenInterestStats gets open interest stats for USDTMarginedFutures @@ -469,7 +493,7 @@ func (b *Binance) UOpenInterestStats(symbol currency.Pair, period string, limit params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOpenInterestStats+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesOpenInterestStats+params.Encode(), uFuturesDefaultRate, &resp) } // UTopAcccountsLongShortRatio gets long/short ratio data for top trader accounts in ufutures @@ -495,7 +519,7 @@ func (b *Binance) UTopAcccountsLongShortRatio(symbol currency.Pair, period strin params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTopAccountsRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTopAccountsRatio+params.Encode(), uFuturesDefaultRate, &resp) } // UTopPostionsLongShortRatio gets long/short ratio data for top positions' in ufutures @@ -521,7 +545,7 @@ func (b *Binance) UTopPostionsLongShortRatio(symbol currency.Pair, period string params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTopPositionsRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesTopPositionsRatio+params.Encode(), uFuturesDefaultRate, &resp) } // UGlobalLongShortRatio gets the global long/short ratio data for USDTMarginedFutures @@ -547,7 +571,7 @@ func (b *Binance) UGlobalLongShortRatio(symbol currency.Pair, period string, lim params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesLongShortRatio+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesLongShortRatio+params.Encode(), uFuturesDefaultRate, &resp) } // UTakerBuySellVol gets takers' buy/sell ratio for USDTMarginedFutures @@ -573,27 +597,27 @@ func (b *Binance) UTakerBuySellVol(symbol currency.Pair, period string, limit in params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesBuySellVolume+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesBuySellVolume+params.Encode(), uFuturesDefaultRate, &resp) } // UCompositeIndexInfo stores composite indexs' info for usdt margined futures func (b *Binance) UCompositeIndexInfo(symbol currency.Pair) ([]UCompositeIndexInfoData, error) { params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return nil, err } params.Set("symbol", symbolValue) var tempResp UCompositeIndexInfoData - err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompositeIndexInfo+params.Encode(), limitDefault, &tempResp) + err = b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompositeIndexInfo+params.Encode(), uFuturesDefaultRate, &tempResp) if err != nil { return nil, err } return []UCompositeIndexInfoData{tempResp}, err } var resp []UCompositeIndexInfoData - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompositeIndexInfo+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, ufuturesCompositeIndexInfo+params.Encode(), uFuturesDefaultRate, &resp) } // UFuturesNewOrder sends a new order for USDTMarginedFutures @@ -652,7 +676,7 @@ func (b *Binance) UFuturesNewOrder(symbol currency.Pair, side, positionSide, ord if callbackRate != 0 { params.Set("callbackRate", strconv.FormatFloat(callbackRate, 'f', -1, 64)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesOrder, params, uFuturesOrdersDefaultRate, &resp) } // UPlaceBatchOrders places batch orders @@ -690,7 +714,7 @@ func (b *Binance) UPlaceBatchOrders(data []PlaceBatchOrderData) ([]UOrderData, e return resp, err } params.Set("batchOrders", string(jsonData)) - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesBatchOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesBatchOrder, params, uFuturesBatchOrdersRate, &resp) } // UGetOrderData gets order data for USDTMarginedFutures @@ -708,7 +732,7 @@ func (b *Binance) UGetOrderData(symbol currency.Pair, orderID, cliOrderID string if cliOrderID != "" { params.Set("origClientOrderId", cliOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesOrder, params, uFuturesOrdersDefaultRate, &resp) } // UCancelOrder cancel an order for USDTMarginedFutures @@ -726,7 +750,7 @@ func (b *Binance) UCancelOrder(symbol currency.Pair, orderID, cliOrderID string) if cliOrderID != "" { params.Set("origClientOrderId", cliOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesOrder, params, uFuturesOrdersDefaultRate, &resp) } // UCancelAllOpenOrders cancels all open orders for a symbol ufutures @@ -738,7 +762,7 @@ func (b *Binance) UCancelAllOpenOrders(symbol currency.Pair) (GenericAuthRespons return resp, err } params.Set("symbol", symbolValue) - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesCancelAllOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesCancelAllOrders, params, uFuturesOrdersDefaultRate, &resp) } // UCancelBatchOrders cancel batch order for USDTMarginedFutures @@ -764,7 +788,7 @@ func (b *Binance) UCancelBatchOrders(symbol currency.Pair, orderIDList, origCliO } params.Set("origClientOrderIdList", string(jsonCliOrders)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesBatchOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodDelete, ufuturesBatchOrder, params, uFuturesOrdersDefaultRate, &resp) } // UAutoCancelAllOpenOrders auto cancels all ufutures open orders for a symbol after the set countdown time @@ -777,14 +801,14 @@ func (b *Binance) UAutoCancelAllOpenOrders(symbol currency.Pair, countdownTime i } params.Set("symbol", symbolValue) params.Set("countdownTime", strconv.FormatInt(countdownTime, 10)) - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesCountdownCancel, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesCountdownCancel, params, uFuturesCountdownCancelRate, &resp) } // UFetchOpenOrder sends a request to fetch open order data for USDTMarginedFutures func (b *Binance) UFetchOpenOrder(symbol currency.Pair, orderID, origClientOrderID string) (UOrderData, error) { var resp UOrderData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err @@ -797,34 +821,37 @@ func (b *Binance) UFetchOpenOrder(symbol currency.Pair, orderID, origClientOrder if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesOpenOrder, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesOpenOrder, params, uFuturesOrdersDefaultRate, &resp) } // UAllAccountOpenOrders gets all account's orders for USDTMarginedFutures func (b *Binance) UAllAccountOpenOrders(symbol currency.Pair) ([]UOrderData, error) { var resp []UOrderData params := url.Values{} - if symbol != (currency.Pair{}) { - symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) + rateLimit := uFuturesGetAllOpenOrdersRate + if !symbol.IsEmpty() { + rateLimit = uFuturesOrdersDefaultRate + p, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err } - params.Set("symbol", symbolValue) + params.Set("symbol", p) + } else { + // extend the receive window when all currencies to prevent "recvwindow" error + params.Set("recvWindow", "10000") } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAllOpenOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAllOpenOrders, params, rateLimit, &resp) } // UAllAccountOrders gets all account's orders for USDTMarginedFutures func (b *Binance) UAllAccountOrders(symbol currency.Pair, orderID, limit int64, startTime, endTime time.Time) ([]UFuturesOrderData, error) { var resp []UFuturesOrderData params := url.Values{} - if symbol != (currency.Pair{}) { - symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) - if err != nil { - return resp, err - } - params.Set("symbol", symbolValue) + symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) + if err != nil { + return resp, err } + params.Set("symbol", symbolValue) if orderID != 0 { params.Set("orderId", strconv.FormatInt(orderID, 10)) } @@ -838,19 +865,19 @@ func (b *Binance) UAllAccountOrders(symbol currency.Pair, orderID, limit int64, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAllOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAllOrders, params, uFuturesGetAllOrdersRate, &resp) } // UAccountBalanceV2 gets V2 account balance data func (b *Binance) UAccountBalanceV2() ([]UAccountBalanceV2Data, error) { var resp []UAccountBalanceV2Data - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountBalance, nil, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountBalance, nil, uFuturesOrdersDefaultRate, &resp) } // UAccountInformationV2 gets V2 account balance data func (b *Binance) UAccountInformationV2() (UAccountInformationV2Data, error) { var resp UAccountInformationV2Data - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountInfo, nil, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountInfo, nil, uFuturesAccountInformationRate, &resp) } // UChangeInitialLeverageRequest sends a request to change account's initial leverage @@ -866,7 +893,7 @@ func (b *Binance) UChangeInitialLeverageRequest(symbol currency.Pair, leverage i return resp, errors.New("invalid leverage") } params.Set("leverage", strconv.FormatInt(leverage, 10)) - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesChangeInitialLeverage, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesChangeInitialLeverage, params, uFuturesDefaultRate, &resp) } // UChangeInitialMarginType sends a request to change account's initial margin type @@ -881,7 +908,7 @@ func (b *Binance) UChangeInitialMarginType(symbol currency.Pair, marginType stri return errors.New("invalid marginType") } params.Set("marginType", marginType) - return b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesChangeMarginType, params, limitDefault, nil) + return b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesChangeMarginType, params, uFuturesDefaultRate, nil) } // UModifyIsolatedPositionMarginReq sends a request to modify isolated margin for USDTMarginedFutures @@ -904,7 +931,7 @@ func (b *Binance) UModifyIsolatedPositionMarginReq(symbol currency.Pair, positio } params.Set("type", strconv.FormatInt(cType, 10)) params.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesModifyMargin, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodPost, ufuturesModifyMargin, params, uFuturesDefaultRate, &resp) } // UPositionMarginChangeHistory gets margin change history for USDTMarginedFutures @@ -931,21 +958,21 @@ func (b *Binance) UPositionMarginChangeHistory(symbol currency.Pair, changeType params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesMarginChangeHistory, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesMarginChangeHistory, params, uFuturesDefaultRate, &resp) } // UPositionsInfoV2 gets positions' info for USDTMarginedFutures func (b *Binance) UPositionsInfoV2(symbol currency.Pair) ([]UPositionInformationV2, error) { var resp []UPositionInformationV2 params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesPositionInfo, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesPositionInfo, params, uFuturesDefaultRate, &resp) } // UAccountTradesHistory gets account's trade history data for USDTMarginedFutures @@ -970,7 +997,7 @@ func (b *Binance) UAccountTradesHistory(symbol currency.Pair, fromID string, lim params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountTradeList, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesAccountTradeList, params, uFuturesAccountInformationRate, &resp) } // UAccountIncomeHistory gets account's income history data for USDTMarginedFutures @@ -998,42 +1025,44 @@ func (b *Binance) UAccountIncomeHistory(symbol currency.Pair, incomeType string, params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesIncomeHistory, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesIncomeHistory, params, uFuturesIncomeHistoryRate, &resp) } // UGetNotionalAndLeverageBrackets gets account's notional and leverage brackets for USDTMarginedFutures func (b *Binance) UGetNotionalAndLeverageBrackets(symbol currency.Pair) ([]UNotionalLeverageAndBrakcetsData, error) { var resp []UNotionalLeverageAndBrakcetsData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesNotionalBracket, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesNotionalBracket, params, uFuturesDefaultRate, &resp) } // UPositionsADLEstimate gets estimated ADL data for USDTMarginedFutures positions func (b *Binance) UPositionsADLEstimate(symbol currency.Pair) (UPositionADLEstimationData, error) { var resp UPositionADLEstimationData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesADLQuantile, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesADLQuantile, params, uFuturesAccountInformationRate, &resp) } // UAccountForcedOrders gets account's forced (liquidation) orders for USDTMarginedFutures func (b *Binance) UAccountForcedOrders(symbol currency.Pair, autoCloseType string, limit int64, startTime, endTime time.Time) ([]UForceOrdersData, error) { var resp []UForceOrdersData params := url.Values{} - if symbol != (currency.Pair{}) { + rateLimit := uFuturesAllForceOrdersRate + if !symbol.IsEmpty() { + rateLimit = uFuturesCurrencyForceOrdersRate symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { return resp, err @@ -1056,13 +1085,13 @@ func (b *Binance) UAccountForcedOrders(symbol currency.Pair, autoCloseType strin params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } - return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesUsersForceOrders, params, limitDefault, &resp) + return resp, b.SendAuthHTTPRequest(exchange.RestUSDTMargined, http.MethodGet, ufuturesUsersForceOrders, params, rateLimit, &resp) } // GetPerpMarkets returns exchange information. Check binance_types for more information func (b *Binance) GetPerpMarkets() (PerpsExchangeInfo, error) { var resp PerpsExchangeInfo - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, perpExchangeInfo, limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, perpExchangeInfo, uFuturesDefaultRate, &resp) } // GetFundingRates gets funding rate history for perpetual contracts @@ -1083,5 +1112,5 @@ func (b *Binance) GetFundingRates(symbol currency.Pair, limit string, startTime, if !endTime.IsZero() { params.Set("endTime", strconv.FormatInt(endTime.UnixNano(), 10)) } - return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, fundingRate+params.Encode(), limitDefault, &resp) + return resp, b.SendHTTPRequest(exchange.RestUSDTMargined, fundingRate+params.Encode(), uFuturesDefaultRate, &resp) } diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 536aef1c..f811c1b9 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -10,7 +10,6 @@ import ( "time" "github.com/thrasher-corp/gocryptotrader/common" - "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" @@ -981,23 +980,15 @@ func (b *Binance) GetOrderInfo(orderID string, pair currency.Pair, assetType ass } switch assetType { case asset.Spot: - orderIDInt64, err := convert.Int64FromString(orderID) + resp, err := b.QueryOrder(pair, "", orderIDInt) if err != nil { return respData, err } - - resp, err := b.QueryOrder(pair, "", orderIDInt64) - if err != nil { - return respData, err - } - orderSide := order.Side(resp.Side) - status, err := order.StringToOrderStatus(resp.Status) if err != nil { return respData, err } - orderType := order.Limit if resp.Type == "MARKET" { orderType = order.Market @@ -1019,77 +1010,63 @@ func (b *Binance) GetOrderInfo(orderID string, pair currency.Pair, assetType ass LastUpdated: resp.UpdateTime, }, nil case asset.CoinMarginedFutures: - orderData, err := b.GetAllFuturesOrders(pair, "", time.Time{}, time.Time{}, orderIDInt, 0) - if err != nil { - return respData, err - } - if len(orderData) != 1 { - return respData, fmt.Errorf("no orders received") - } - p, err := currency.NewPairFromString(orderData[0].Pair) + orderData, err := b.FuturesOpenOrderData(pair, orderID, "") if err != nil { return respData, err } var feeBuilder exchange.FeeBuilder - feeBuilder.Amount = orderData[0].ExecutedQty - feeBuilder.PurchasePrice = orderData[0].AvgPrice - feeBuilder.Pair = p + feeBuilder.Amount = orderData.ExecutedQuantity + feeBuilder.PurchasePrice = orderData.AveragePrice + feeBuilder.Pair = pair fee, err := b.GetFee(&feeBuilder) if err != nil { return respData, err } - orderVars := compatibleOrderVars(orderData[0].Side, orderData[0].Status, orderData[0].OrderType) - respData.Amount = orderData[0].OrigQty + orderVars := compatibleOrderVars(orderData.Side, orderData.Status, orderData.OrderType) + respData.Amount = orderData.OriginalQuantity respData.AssetType = assetType - respData.ClientOrderID = orderData[0].ClientOrderID + respData.ClientOrderID = orderData.ClientOrderID respData.Exchange = b.Name - respData.ExecutedAmount = orderData[0].ExecutedQty + respData.ExecutedAmount = orderData.ExecutedQuantity respData.Fee = fee respData.ID = orderID - respData.Pair = p - respData.Price = orderData[0].Price - respData.RemainingAmount = orderData[0].OrigQty - orderData[0].ExecutedQty + respData.Pair = pair + respData.Price = orderData.Price + respData.RemainingAmount = orderData.OriginalQuantity - orderData.ExecutedQuantity respData.Side = orderVars.Side respData.Status = orderVars.Status respData.Type = orderVars.OrderType - respData.Date = orderData[0].Time - respData.LastUpdated = orderData[0].UpdateTime + respData.Date = orderData.Time + respData.LastUpdated = orderData.UpdateTime case asset.USDTMarginedFutures: - orderData, err := b.UAllAccountOrders(currency.Pair{}, 0, 0, time.Time{}, time.Time{}) - if err != nil { - return respData, err - } - if len(orderData) != 1 { - return respData, fmt.Errorf("invalid data received") - } - p, err := currency.NewPairFromString(orderData[0].Symbol) + orderData, err := b.UGetOrderData(pair, orderID, "") if err != nil { return respData, err } var feeBuilder exchange.FeeBuilder - feeBuilder.Amount = orderData[0].ExecutedQty - feeBuilder.PurchasePrice = orderData[0].AvgPrice - feeBuilder.Pair = p + feeBuilder.Amount = orderData.ExecutedQuantity + feeBuilder.PurchasePrice = orderData.AveragePrice + feeBuilder.Pair = pair fee, err := b.GetFee(&feeBuilder) if err != nil { return respData, err } - orderVars := compatibleOrderVars(orderData[0].Side, orderData[0].Status, orderData[0].OrderType) - respData.Amount = orderData[0].OrigQty + orderVars := compatibleOrderVars(orderData.Side, orderData.Status, orderData.OrderType) + respData.Amount = orderData.OriginalQuantity respData.AssetType = assetType - respData.ClientOrderID = orderData[0].ClientOrderID + respData.ClientOrderID = orderData.ClientOrderID respData.Exchange = b.Name - respData.ExecutedAmount = orderData[0].ExecutedQty + respData.ExecutedAmount = orderData.ExecutedQuantity respData.Fee = fee respData.ID = orderID - respData.Pair = p - respData.Price = orderData[0].Price - respData.RemainingAmount = orderData[0].OrigQty - orderData[0].ExecutedQty + respData.Pair = pair + respData.Price = orderData.Price + respData.RemainingAmount = orderData.OriginalQuantity - orderData.ExecutedQuantity respData.Side = orderVars.Side respData.Status = orderVars.Status respData.Type = orderVars.OrderType - respData.Date = orderData[0].Time - respData.LastUpdated = orderData[0].UpdateTime + respData.Date = orderData.Time + respData.LastUpdated = orderData.UpdateTime default: return respData, fmt.Errorf("assetType %s not supported", assetType) } diff --git a/exchanges/binance/cfutures_types.go b/exchanges/binance/cfutures_types.go index d2c6ce36..fc1ca259 100644 --- a/exchanges/binance/cfutures_types.go +++ b/exchanges/binance/cfutures_types.go @@ -234,30 +234,31 @@ type FuturesOrderPlaceData struct { // FuturesOrderGetData stores futures order data for get requests type FuturesOrderGetData struct { - AvgPrice float64 `json:"avgPrice,string"` - ClientOrderID string `json:"clientOrderID"` - CumQty float64 `json:"cumQty,string"` - CumBase float64 `json:"cumBase,string"` - ExecutedQty float64 `json:"executedQty,string"` - OrderID int64 `json:"orderId"` - OrigQty float64 `json:"origQty,string"` - OrigType string `json:"origType"` - Price float64 `json:"price,string"` - ReduceOnly bool `json:"reduceOnly"` - Side string `json:"buy"` - PositionSide string `json:"positionSide"` - Status string `json:"status"` - StopPrice float64 `json:"stopPrice,string"` - ClosePosition bool `json:"closePosition"` - Symbol string `json:"symbol"` - Pair string `json:"pair"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - ActivatePrice float64 `json:"activatePrice,string"` - PriceRate float64 `json:"priceRate,string"` - UpdateTime int64 `json:"updateTime"` - WorkingType string `json:"workingType"` - PriceProtect bool `json:"priceProtect"` + AveragePrice float64 `json:"avgPrice,string"` + ClientOrderID string `json:"clientOrderID"` + CumulativeQuantity float64 `json:"cumQty,string"` + CumulativeBase float64 `json:"cumBase,string"` + ExecutedQuantity float64 `json:"executedQty,string"` + OrderID int64 `json:"orderId"` + OriginalQuantity float64 `json:"origQty,string"` + OriginalType string `json:"origType"` + Price float64 `json:"price,string"` + ReduceOnly bool `json:"reduceOnly"` + Side string `json:"buy"` + PositionSide string `json:"positionSide"` + Status string `json:"status"` + StopPrice float64 `json:"stopPrice,string"` + ClosePosition bool `json:"closePosition"` + Symbol string `json:"symbol"` + Pair string `json:"pair"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + ActivatePrice float64 `json:"activatePrice,string"` + PriceRate float64 `json:"priceRate,string"` + Time time.Time `json:"time"` + UpdateTime time.Time `json:"updateTime"` + WorkingType string `json:"workingType"` + PriceProtect bool `json:"priceProtect"` } // FuturesOrderData stores order data for futures diff --git a/exchanges/binance/ratelimit.go b/exchanges/binance/ratelimit.go index 7ea9366d..6184efbc 100644 --- a/exchanges/binance/ratelimit.go +++ b/exchanges/binance/ratelimit.go @@ -11,34 +11,92 @@ const ( // Binance limit rates // Global dictates the max rate limit for general request items which is // 1200 requests per minute - binanceGlobalInterval = time.Minute - binanceGlobalRequestRate = 1200 + spotInterval = time.Minute + spotRequestRate = 1200 // Order related limits which are segregated from the global rate limits // 100 requests per 10 seconds and max 100000 requests per day. - binanceOrderInterval = 10 * time.Second - binanceOrderRequestRate = 100 - binanceOrderDailyInterval = time.Hour * 24 - binanceOrderDailyMaxRequests = 100000 + spotOrderInterval = 10 * time.Second + spotOrderRequestRate = 100 + cFuturesInterval = time.Minute + cFuturesRequestRate = 6000 + cFuturesOrderInterval = time.Minute + cFuturesOrderRequestRate = 1200 + uFuturesInterval = time.Minute + uFuturesRequestRate = 2400 + uFuturesOrderInterval = time.Minute + uFuturesOrderRequestRate = 1200 ) +// Binance Spot rate limits const ( - limitDefault request.EndpointLimit = iota - limitHistoricalTrades - limitOrderbookDepth500 - limitOrderbookDepth1000 - limitOrderbookDepth5000 - limitOrderbookTickerAll - limitPriceChangeAll - limitSymbolPriceAll - limitOpenOrdersAll - limitOrder - limitOrdersAll + spotDefaultRate request.EndpointLimit = iota + spotHistoricalTradesRate + spotOrderbookDepth500Rate + spotOrderbookDepth1000Rate + spotOrderbookDepth5000Rate + spotOrderbookTickerAllRate + spotPriceChangeAllRate + spotSymbolPriceAllRate + spotOpenOrdersAllRate + spotOrderRate + spotOrdersAllRate + spotAccountInformationRate + uFuturesDefaultRate + uFuturesHistoricalTradesRate + uFuturesSymbolOrdersRate + uFuturesPairOrdersRate + uFuturesCurrencyForceOrdersRate + uFuturesAllForceOrdersRate + uFuturesIncomeHistoryRate + uFuturesOrderbook50Rate + uFuturesOrderbook100Rate + uFuturesOrderbook500Rate + uFuturesOrderbook1000Rate + uFuturesKline100Rate + uFuturesKline500Rate + uFuturesKline1000Rate + uFuturesKlineMaxRate + uFuturesTickerPriceHistoryRate + uFuturesOrdersDefaultRate + uFuturesGetAllOrdersRate + uFuturesAccountInformationRate + uFuturesOrderbookTickerAllRate + uFuturesCountdownCancelRate + uFuturesBatchOrdersRate + uFuturesGetAllOpenOrdersRate + cFuturesDefaultRate + cFuturesHistoricalTradesRate + cFuturesTickerPriceHistoryRate + cFuturesIncomeHistoryRate + cFuturesOrderbook50Rate + cFuturesOrderbook100Rate + cFuturesOrderbook500Rate + cFuturesOrderbook1000Rate + cFuturesKline100Rate + cFuturesKline500Rate + cFuturesKline1000Rate + cFuturesKlineMaxRate + cFuturesIndexMarkPriceRate + cFuturesBatchOrdersRate + cFuturesCancelAllOrdersRate + cFuturesGetAllOpenOrdersRate + cFuturesAllForceOrdersRate + cFuturesCurrencyForceOrdersRate + cFuturesPairOrdersRate + cFuturesSymbolOrdersRate + cFuturesAccountInformationRate + cFuturesOrderbookTickerAllRate + cFuturesOrdersDefaultRate ) // RateLimit implements the request.Limiter interface type RateLimit struct { - GlobalRate *rate.Limiter - Orders *rate.Limiter + SpotRate *rate.Limiter + SpotOrdersRate *rate.Limiter + UFuturesRate *rate.Limiter + UFuturesOrdersRate *rate.Limiter + CFuturesRate *rate.Limiter + CFuturesOrdersRate *rate.Limiter } // Limit executes rate limiting functionality for Binance @@ -46,28 +104,105 @@ func (r *RateLimit) Limit(f request.EndpointLimit) error { var limiter *rate.Limiter var tokens int switch f { - case limitHistoricalTrades: - limiter, tokens = r.GlobalRate, 5 - case limitOrderbookDepth500: - limiter, tokens = r.GlobalRate, 5 - case limitOrderbookDepth1000: - limiter, tokens = r.GlobalRate, 10 - case limitOrderbookDepth5000: - limiter, tokens = r.GlobalRate, 50 - case limitOrderbookTickerAll: - limiter, tokens = r.GlobalRate, 2 - case limitPriceChangeAll: - limiter, tokens = r.GlobalRate, 40 - case limitSymbolPriceAll: - limiter, tokens = r.GlobalRate, 2 - case limitOpenOrdersAll: - limiter, tokens = r.Orders, 40 - case limitOrder: - limiter, tokens = r.Orders, 1 - case limitOrdersAll: - limiter, tokens = r.Orders, 5 + case spotDefaultRate: + limiter, tokens = r.SpotRate, 1 + case spotOrderbookTickerAllRate, + spotSymbolPriceAllRate: + limiter, tokens = r.SpotRate, 2 + case spotHistoricalTradesRate, + spotAccountInformationRate, + spotOrderbookDepth500Rate: + limiter, tokens = r.SpotRate, 5 + case spotOrderbookDepth1000Rate: + limiter, tokens = r.SpotRate, 10 + case spotPriceChangeAllRate: + limiter, tokens = r.SpotRate, 40 + case spotOrderbookDepth5000Rate: + limiter, tokens = r.SpotRate, 50 + case spotOrderRate: + limiter, tokens = r.SpotOrdersRate, 1 + case spotOrdersAllRate: + limiter, tokens = r.SpotOrdersRate, 5 + case spotOpenOrdersAllRate: + limiter, tokens = r.SpotOrdersRate, 40 + case uFuturesDefaultRate, + uFuturesKline100Rate: + limiter, tokens = r.UFuturesRate, 1 + case uFuturesOrderbook50Rate, + uFuturesKline500Rate, + uFuturesOrderbookTickerAllRate: + limiter, tokens = r.UFuturesRate, 2 + case uFuturesOrderbook100Rate, + uFuturesKline1000Rate, + uFuturesAccountInformationRate: + limiter, tokens = r.UFuturesRate, 5 + case uFuturesOrderbook500Rate, + uFuturesKlineMaxRate: + limiter, tokens = r.UFuturesRate, 10 + case uFuturesOrderbook1000Rate, + uFuturesHistoricalTradesRate: + limiter, tokens = r.UFuturesRate, 20 + case uFuturesTickerPriceHistoryRate: + limiter, tokens = r.UFuturesRate, 40 + case uFuturesOrdersDefaultRate: + limiter, tokens = r.UFuturesOrdersRate, 1 + case uFuturesBatchOrdersRate, + uFuturesGetAllOrdersRate: + limiter, tokens = r.UFuturesOrdersRate, 5 + case uFuturesCountdownCancelRate: + limiter, tokens = r.UFuturesOrdersRate, 10 + case uFuturesCurrencyForceOrdersRate, + uFuturesSymbolOrdersRate: + limiter, tokens = r.UFuturesOrdersRate, 20 + case uFuturesIncomeHistoryRate: + limiter, tokens = r.UFuturesOrdersRate, 30 + case uFuturesPairOrdersRate, + uFuturesGetAllOpenOrdersRate: + limiter, tokens = r.UFuturesOrdersRate, 40 + case uFuturesAllForceOrdersRate: + limiter, tokens = r.UFuturesOrdersRate, 50 + case cFuturesKline100Rate: + limiter, tokens = r.CFuturesRate, 1 + case cFuturesKline500Rate, + cFuturesOrderbookTickerAllRate: + limiter, tokens = r.CFuturesRate, 2 + case cFuturesKline1000Rate, + cFuturesAccountInformationRate: + limiter, tokens = r.CFuturesRate, 5 + case cFuturesKlineMaxRate, + cFuturesIndexMarkPriceRate: + limiter, tokens = r.CFuturesRate, 10 + case cFuturesHistoricalTradesRate, + cFuturesCurrencyForceOrdersRate: + limiter, tokens = r.CFuturesRate, 20 + case cFuturesTickerPriceHistoryRate: + limiter, tokens = r.CFuturesRate, 40 + case cFuturesAllForceOrdersRate: + limiter, tokens = r.CFuturesRate, 50 + case cFuturesOrdersDefaultRate: + limiter, tokens = r.CFuturesOrdersRate, 1 + case cFuturesBatchOrdersRate, + cFuturesGetAllOpenOrdersRate: + limiter, tokens = r.CFuturesOrdersRate, 5 + case cFuturesCancelAllOrdersRate: + limiter, tokens = r.CFuturesOrdersRate, 10 + case cFuturesIncomeHistoryRate, + cFuturesSymbolOrdersRate: + limiter, tokens = r.CFuturesOrdersRate, 20 + case cFuturesPairOrdersRate: + limiter, tokens = r.CFuturesOrdersRate, 40 + case cFuturesOrderbook50Rate: + limiter, tokens = r.CFuturesRate, 2 + case cFuturesOrderbook100Rate: + limiter, tokens = r.CFuturesRate, 5 + case cFuturesOrderbook500Rate: + limiter, tokens = r.CFuturesRate, 10 + case cFuturesOrderbook1000Rate: + limiter, tokens = r.CFuturesRate, 20 + case cFuturesDefaultRate: + limiter, tokens = r.CFuturesRate, 1 default: - limiter, tokens = r.GlobalRate, 1 + limiter, tokens = r.SpotRate, 1 } var finalDelay time.Duration @@ -83,44 +218,40 @@ func (r *RateLimit) Limit(f request.EndpointLimit) error { // SetRateLimit returns the rate limit for the exchange func SetRateLimit() *RateLimit { return &RateLimit{ - GlobalRate: request.NewRateLimit(binanceGlobalInterval, binanceGlobalRequestRate), - Orders: request.NewRateLimit(binanceOrderInterval, binanceOrderRequestRate), + SpotRate: request.NewRateLimit(spotInterval, spotRequestRate), + SpotOrdersRate: request.NewRateLimit(spotOrderInterval, spotOrderRequestRate), + UFuturesRate: request.NewRateLimit(uFuturesInterval, uFuturesRequestRate), + UFuturesOrdersRate: request.NewRateLimit(uFuturesOrderInterval, uFuturesOrderRequestRate), + CFuturesRate: request.NewRateLimit(cFuturesInterval, cFuturesRequestRate), + CFuturesOrdersRate: request.NewRateLimit(cFuturesOrderInterval, cFuturesOrderRequestRate), } } func bestPriceLimit(symbol string) request.EndpointLimit { if symbol == "" { - return limitOrderbookTickerAll + return spotOrderbookTickerAllRate } - return limitDefault + return spotDefaultRate } func openOrdersLimit(symbol string) request.EndpointLimit { if symbol == "" { - return limitOpenOrdersAll + return spotOpenOrdersAllRate } - return limitOrder + return spotOrderRate } func orderbookLimit(depth int) request.EndpointLimit { switch { case depth <= 100: - return limitDefault + return spotDefaultRate case depth <= 500: - return limitOrderbookDepth500 + return spotOrderbookDepth500Rate case depth <= 1000: - return limitOrderbookDepth1000 + return spotOrderbookDepth1000Rate } - return limitOrderbookDepth5000 -} - -func symbolPriceLimit(symbol string) request.EndpointLimit { - if symbol == "" { - return limitSymbolPriceAll - } - - return limitDefault + return spotOrderbookDepth5000Rate } diff --git a/exchanges/binance/ratelimit_test.go b/exchanges/binance/ratelimit_test.go index 8a2a2412..94026169 100644 --- a/exchanges/binance/ratelimit_test.go +++ b/exchanges/binance/ratelimit_test.go @@ -13,20 +13,17 @@ func TestRateLimit_Limit(t *testing.T) { Expected request.EndpointLimit Limit request.EndpointLimit }{ - "All Orderbooks Ticker": {Expected: limitOrderbookTickerAll, Limit: bestPriceLimit("")}, - "Orderbook Ticker": {Expected: limitDefault, Limit: bestPriceLimit(symbol)}, - "All Open Orders": {Expected: limitOpenOrdersAll, Limit: openOrdersLimit("")}, - "Open Orders": {Expected: limitOrder, Limit: openOrdersLimit(symbol)}, - "Orderbook Depth 5": {Expected: limitDefault, Limit: orderbookLimit(5)}, - "Orderbook Depth 10": {Expected: limitDefault, Limit: orderbookLimit(10)}, - "Orderbook Depth 20": {Expected: limitDefault, Limit: orderbookLimit(20)}, - "Orderbook Depth 50": {Expected: limitDefault, Limit: orderbookLimit(50)}, - "Orderbook Depth 100": {Expected: limitDefault, Limit: orderbookLimit(100)}, - "Orderbook Depth 500": {Expected: limitOrderbookDepth500, Limit: orderbookLimit(500)}, - "Orderbook Depth 1000": {Expected: limitOrderbookDepth1000, Limit: orderbookLimit(1000)}, - "Orderbook Depth 5000": {Expected: limitOrderbookDepth5000, Limit: orderbookLimit(5000)}, - "All Symbol Prices": {Expected: limitSymbolPriceAll, Limit: symbolPriceLimit("")}, - "Symbol Price": {Expected: limitDefault, Limit: symbolPriceLimit(symbol)}, + "All Orderbooks Ticker": {Expected: spotOrderbookTickerAllRate, Limit: bestPriceLimit("")}, + "Orderbook Ticker": {Expected: spotDefaultRate, Limit: bestPriceLimit(symbol)}, + "Open Orders": {Expected: spotOrderRate, Limit: openOrdersLimit(symbol)}, + "Orderbook Depth 5": {Expected: spotDefaultRate, Limit: orderbookLimit(5)}, + "Orderbook Depth 10": {Expected: spotDefaultRate, Limit: orderbookLimit(10)}, + "Orderbook Depth 20": {Expected: spotDefaultRate, Limit: orderbookLimit(20)}, + "Orderbook Depth 50": {Expected: spotDefaultRate, Limit: orderbookLimit(50)}, + "Orderbook Depth 100": {Expected: spotDefaultRate, Limit: orderbookLimit(100)}, + "Orderbook Depth 500": {Expected: spotOrderbookDepth500Rate, Limit: orderbookLimit(500)}, + "Orderbook Depth 1000": {Expected: spotOrderbookDepth1000Rate, Limit: orderbookLimit(1000)}, + "Orderbook Depth 5000": {Expected: spotOrderbookDepth5000Rate, Limit: orderbookLimit(5000)}, } for name, tt := range testTable { tt := tt @@ -48,10 +45,10 @@ func TestRateLimit_Limit(t *testing.T) { func TestRateLimit_LimitStatic(t *testing.T) { testTable := map[string]request.EndpointLimit{ - "Default": limitDefault, - "Historical Trades": limitHistoricalTrades, - "All Price Changes": limitPriceChangeAll, - "All Orders": limitOrdersAll, + "Default": spotDefaultRate, + "Historical Trades": spotHistoricalTradesRate, + "All Price Changes": spotPriceChangeAllRate, + "All Orders": spotOrdersAllRate, } for name, tt := range testTable { tt := tt diff --git a/exchanges/binance/type_convert.go b/exchanges/binance/type_convert.go index 4fcfafdd..ba255079 100644 --- a/exchanges/binance/type_convert.go +++ b/exchanges/binance/type_convert.go @@ -247,6 +247,24 @@ func (a *UFuturesOrderData) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalJSON deserialises the JSON info, including the timestamp +func (a *FuturesOrderGetData) UnmarshalJSON(data []byte) error { + type Alias FuturesOrderGetData + aux := &struct { + Time binanceTime `json:"time"` + UpdateTime binanceTime `json:"updateTime"` + *Alias + }{ + Alias: (*Alias)(a), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + a.Time = aux.Time.Time() + a.UpdateTime = aux.UpdateTime.Time() + return nil +} + // UnmarshalJSON deserialises the JSON info, including the timestamp func (a *UOrderData) UnmarshalJSON(data []byte) error { type Alias UOrderData diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 1ecfcf1e..924b78c1 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -74,7 +74,7 @@ type HUOBI struct { func (h *HUOBI) GetMarginRates(symbol currency.Pair) (MarginRatesData, error) { var resp MarginRatesData vals := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := h.FormatSymbol(symbol, asset.Spot) if err != nil { return resp, err @@ -699,7 +699,7 @@ func (h *HUOBI) GetMarginAccountBalance(symbol currency.Pair) ([]MarginAccountBa Balances []MarginAccountBalance `json:"data"` }{} vals := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := h.FormatSymbol(symbol, asset.Spot) if err != nil { return resp.Balances, err diff --git a/exchanges/kraken/kraken_futures.go b/exchanges/kraken/kraken_futures.go index 48d5c933..960e42ec 100644 --- a/exchanges/kraken/kraken_futures.go +++ b/exchanges/kraken/kraken_futures.go @@ -186,7 +186,7 @@ func (k *Kraken) FuturesNotifications() (FuturesNotificationData, error) { func (k *Kraken) FuturesCancelAllOrders(symbol currency.Pair) (CancelAllOrdersData, error) { var resp CancelAllOrdersData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := k.FormatSymbol(symbol, asset.Futures) if err != nil { return resp, err @@ -214,7 +214,7 @@ func (k *Kraken) FuturesOpenOrders() (FuturesOpenOrdersData, error) { func (k *Kraken) FuturesRecentOrders(symbol currency.Pair) (FuturesRecentOrdersData, error) { var resp FuturesRecentOrdersData params := url.Values{} - if symbol != (currency.Pair{}) { + if !symbol.IsEmpty() { symbolValue, err := k.FormatSymbol(symbol, asset.Futures) if err != nil { return resp, err diff --git a/testdata/http_mock/binance/binance.json b/testdata/http_mock/binance/binance.json index 711ffe10..1c84dcb1 100644 --- a/testdata/http_mock/binance/binance.json +++ b/testdata/http_mock/binance/binance.json @@ -281710,7 +281710,7 @@ "asset": "BTC", "success": true }, - "queryString": "asset=BTC\u0026recvWindow=5000\u0026signature=3690734a6e2cd2ccd7fb692ec4e5fec67486b80d8a1a5e6159e53602295b1d60\u0026status=true\u0026timestamp=1588749172000", + "queryString": "asset=BTC\u0026recvWindow=10000\u0026signature=3690734a6e2cd2ccd7fb692ec4e5fec67486b80d8a1a5e6159e53602295b1d60\u0026status=true\u0026timestamp=1588749172000", "bodyParams": "", "headers": { "X-Mbx-Apikey": [