package binance import ( "encoding/json" "errors" "fmt" "net/http" "net/url" "strconv" "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" ) const ( // Unauth cfuturesExchangeInfo = "/dapi/v1/exchangeInfo?" cfuturesOrderbook = "/dapi/v1/depth?" cfuturesRecentTrades = "/dapi/v1/trades?" cfuturesHistoricalTrades = "/dapi/v1/historicalTrades" cfuturesCompressedTrades = "/dapi/v1/aggTrades?" cfuturesKlineData = "/dapi/v1/klines?" cfuturesContinuousKline = "/dapi/v1/continuousKlines?" cfuturesIndexKline = "/dapi/v1/indexPriceKlines?" cfuturesMarkPriceKline = "/dapi/v1/markPriceKlines?" cfuturesMarkPrice = "/dapi/v1/premiumIndex?" cfuturesFundingRateHistory = "/dapi/v1/fundingRate?" cfuturesTickerPriceStats = "/dapi/v1/ticker/24hr?" cfuturesSymbolPriceTicker = "/dapi/v1/ticker/price?" cfuturesSymbolOrderbook = "/dapi/v1/ticker/bookTicker?" cfuturesLiquidationOrders = "/dapi/v1/allForceOrders?" cfuturesOpenInterest = "/dapi/v1/openInterest?" cfuturesOpenInterestStats = "/futures/data/openInterestHist?" cfuturesTopAccountsRatio = "/futures/data/topLongShortAccountRatio?" cfuturesTopPositionsRatio = "/futures/data/topLongShortPositionRatio?" cfuturesLongShortRatio = "/futures/data/globalLongShortAccountRatio?" cfuturesBuySellVolume = "/futures/data/takerBuySellVol?" cfuturesBasis = "/futures/data/basis?" // Auth cfuturesOrder = "/dapi/v1/order" cfuturesBatchOrder = "/dapi/v1/batchOrders" cfuturesCancelAllOrders = "/dapi/v1/allOpenOrders" cfuturesCountdownCancel = "/dapi/v1/countdownCancelAll" cfuturesOpenOrder = "/dapi/v1/openOrder" cfuturesAllOpenOrders = "/dapi/v1/openOrders" cfuturesAllOrders = "/dapi/v1/allOrders" cfuturesAccountBalance = "/dapi/v1/balance" cfuturesAccountInfo = "/dapi/v1/account" cfuturesChangeInitialLeverage = "/dapi/v1/leverage" cfuturesChangeMarginType = "/dapi/v1/marginType" cfuturesModifyMargin = "/dapi/v1/positionMargin" cfuturesMarginChangeHistory = "/dapi/v1/positionMargin/history" cfuturesPositionInfo = "/dapi/v1/positionRisk" cfuturesAccountTradeList = "/dapi/v1/userTrades" cfuturesIncomeHistory = "/dapi/v1/income" cfuturesNotionalBracket = "/dapi/v1/leverageBracket" cfuturesUsersForceOrders = "/dapi/v1/forceOrders" cfuturesADLQuantile = "/dapi/v1/adlQuantile" ) // FuturesExchangeInfo stores CoinMarginedFutures, data func (b *Binance) FuturesExchangeInfo() (CExchangeInfo, error) { var resp CExchangeInfo return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesExchangeInfo, limitDefault, &resp) } // GetFuturesOrderbook gets orderbook data for CoinMarginedFutures, func (b *Binance) GetFuturesOrderbook(symbol currency.Pair, limit int64) (OrderBook, error) { var resp OrderBook var data OrderbookData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } err = b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), limitDefault, &data) if err != nil { return resp, err } var price, quantity float64 for x := range data.Asks { price, err = strconv.ParseFloat(data.Asks[x][0], 64) if err != nil { return resp, err } quantity, err = strconv.ParseFloat(data.Asks[x][1], 64) if err != nil { return resp, err } resp.Asks = append(resp.Asks, OrderbookItem{ Price: price, Quantity: quantity, }) } for y := range data.Bids { price, err = strconv.ParseFloat(data.Bids[y][0], 64) if err != nil { return resp, err } quantity, err = strconv.ParseFloat(data.Bids[y][1], 64) if err != nil { return resp, err } resp.Bids = append(resp.Bids, OrderbookItem{ Price: price, Quantity: quantity, }) } return resp, nil } // GetFuturesPublicTrades gets recent public trades for CoinMarginedFutures, func (b *Binance) GetFuturesPublicTrades(symbol currency.Pair, limit int64) ([]FuturesPublicTradesData, error) { var resp []FuturesPublicTradesData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), limitDefault, &resp) } // GetFuturesHistoricalTrades gets historical public trades for CoinMarginedFutures, func (b *Binance) GetFuturesHistoricalTrades(symbol currency.Pair, fromID string, limit int64) ([]UPublicTradesData, error) { var resp []UPublicTradesData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if fromID != "" { params.Set("fromID", fromID) } if limit > 0 && limit < 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesHistoricalTrades, params, limitDefault, &resp) } // GetPastPublicTrades gets past public trades for CoinMarginedFutures, func (b *Binance) GetPastPublicTrades(symbol currency.Pair, limit, fromID int64) ([]FuturesPublicTradesData, error) { var resp []FuturesPublicTradesData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if fromID != 0 { params.Set("fromID", strconv.FormatInt(fromID, 10)) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesRecentTrades+params.Encode(), limitDefault, &resp) } // GetFuturesAggregatedTradesList gets aggregated trades list for CoinMarginedFutures, func (b *Binance) GetFuturesAggregatedTradesList(symbol currency.Pair, fromID, limit int64, startTime, endTime time.Time) ([]AggregatedTrade, error) { var resp []AggregatedTrade params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if fromID != 0 { params.Set("fromID", strconv.FormatInt(fromID, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetIndexAndMarkPrice gets index and mark prices for CoinMarginedFutures, func (b *Binance) GetIndexAndMarkPrice(symbol, pair string) ([]IndexMarkPrice, error) { var resp []IndexMarkPrice params := url.Values{} if symbol != "" { params.Set("symbol", symbol) } if pair != "" { params.Set("pair", pair) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesMarkPrice+params.Encode(), limitDefault, &resp) } // GetFuturesKlineData gets futures kline data for CoinMarginedFutures, func (b *Binance) GetFuturesKlineData(symbol currency.Pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) { var data [][10]interface{} var resp []FuturesCandleStick params := url.Values{} if symbol != (currency.Pair{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { return resp, errors.New("invalid interval parsed") } params.Set("interval", interval) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) if err != nil { return resp, err } var floatData float64 var strData string var ok bool var tempData FuturesCandleStick for x := range data { floatData, ok = data[x][0].(float64) if !ok { return resp, errors.New("type assertion failed for open time") } tempData.OpenTime = time.Unix(int64(floatData), 0) strData, ok = data[x][1].(string) if !ok { return resp, errors.New("type assertion failed for open") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Open = floatData strData, ok = data[x][2].(string) if !ok { return resp, errors.New("type assertion failed for high") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.High = floatData strData, ok = data[x][3].(string) if !ok { return resp, errors.New("type assertion failed for low") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Low = floatData strData, ok = data[x][4].(string) if !ok { return resp, errors.New("type assertion failed for close") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Close = floatData strData, ok = data[x][5].(string) if !ok { return resp, errors.New("type assertion failed for volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Volume = floatData floatData, ok = data[x][6].(float64) if !ok { return resp, errors.New("type assertion failed for close time") } tempData.CloseTime = time.Unix(int64(floatData), 0) strData, ok = data[x][7].(string) if !ok { return resp, errors.New("type assertion failed for base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.BaseAssetVolume = floatData floatData, ok = data[x][8].(float64) if !ok { return resp, errors.New("type assertion failed for taker buy volume") } tempData.TakerBuyVolume = floatData strData, ok = data[x][9].(string) if !ok { return resp, errors.New("type assertion failed for taker buy base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.TakerBuyBaseAssetVolume = floatData resp = append(resp, tempData) } return resp, nil } // GetContinuousKlineData gets continuous kline data func (b *Binance) GetContinuousKlineData(pair, contractType, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) { var data [][10]interface{} var resp []FuturesCandleStick params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validContractType, contractType) { return resp, errors.New("invalid contractType") } params.Set("contractType", contractType) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { return resp, errors.New("invalid interval parsed") } params.Set("interval", interval) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) if err != nil { return resp, err } var floatData float64 var strData string var ok bool var tempData FuturesCandleStick for x := range data { floatData, ok = data[x][0].(float64) if !ok { return resp, errors.New("type assertion failed for open time") } tempData.OpenTime = time.Unix(int64(floatData), 0) strData, ok = data[x][1].(string) if !ok { return resp, errors.New("type assertion failed for open") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Open = floatData strData, ok = data[x][2].(string) if !ok { return resp, errors.New("type assertion failed for high") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.High = floatData strData, ok = data[x][3].(string) if !ok { return resp, errors.New("type assertion failed for low") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Low = floatData strData, ok = data[x][4].(string) if !ok { return resp, errors.New("type assertion failed for close") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Close = floatData strData, ok = data[x][5].(string) if !ok { return resp, errors.New("type assertion failed for volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Volume = floatData floatData, ok = data[x][6].(float64) if !ok { return resp, errors.New("type assertion failed for close time") } tempData.CloseTime = time.Unix(int64(floatData), 0) strData, ok = data[x][7].(string) if !ok { return resp, errors.New("type assertion failed for base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.BaseAssetVolume = floatData floatData, ok = data[x][8].(float64) if !ok { return resp, errors.New("type assertion failed for taker buy volume") } tempData.TakerBuyVolume = floatData strData, ok = data[x][9].(string) if !ok { return resp, errors.New("type assertion failed for taker buy base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.TakerBuyBaseAssetVolume = floatData resp = append(resp, tempData) } return resp, nil } // GetIndexPriceKlines gets continuous kline data func (b *Binance) GetIndexPriceKlines(pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) { var data [][10]interface{} var resp []FuturesCandleStick params := url.Values{} params.Set("pair", pair) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { return resp, errors.New("invalid interval parsed") } params.Set("interval", interval) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) if err != nil { return resp, err } var floatData float64 var strData string var ok bool var tempData FuturesCandleStick for x := range data { floatData, ok = data[x][0].(float64) if !ok { return resp, errors.New("type assertion failed for open time") } tempData.OpenTime = time.Unix(int64(floatData), 0) strData, ok = data[x][1].(string) if !ok { return resp, errors.New("type assertion failed for open") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Open = floatData strData, ok = data[x][2].(string) if !ok { return resp, errors.New("type assertion failed for high") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.High = floatData strData, ok = data[x][3].(string) if !ok { return resp, errors.New("type assertion failed for low") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Low = floatData strData, ok = data[x][4].(string) if !ok { return resp, errors.New("type assertion failed for close") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Close = floatData strData, ok = data[x][5].(string) if !ok { return resp, errors.New("type assertion failed for volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Volume = floatData floatData, ok = data[x][6].(float64) if !ok { return resp, errors.New("type assertion failed for close time") } tempData.CloseTime = time.Unix(int64(floatData), 0) strData, ok = data[x][7].(string) if !ok { return resp, errors.New("type assertion failed for base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.BaseAssetVolume = floatData floatData, ok = data[x][8].(float64) if !ok { return resp, errors.New("type assertion failed for taker buy volume") } tempData.TakerBuyVolume = floatData strData, ok = data[x][9].(string) if !ok { return resp, errors.New("type assertion failed for taker buy base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.TakerBuyBaseAssetVolume = floatData resp = append(resp, tempData) } return resp, nil } // GetMarkPriceKline gets mark price kline data func (b *Binance) GetMarkPriceKline(symbol currency.Pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) { var data [][10]interface{} var resp []FuturesCandleStick params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, interval) { return resp, errors.New("invalid interval parsed") } params.Set("interval", interval) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) if err != nil { return resp, err } var floatData float64 var strData string var ok bool var tempData FuturesCandleStick for x := range data { floatData, ok = data[x][0].(float64) if !ok { return resp, errors.New("type assertion failed for open time") } tempData.OpenTime = time.Unix(int64(floatData), 0) strData, ok = data[x][1].(string) if !ok { return resp, errors.New("type assertion failed for open") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Open = floatData strData, ok = data[x][2].(string) if !ok { return resp, errors.New("type assertion failed for high") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.High = floatData strData, ok = data[x][3].(string) if !ok { return resp, errors.New("type assertion failed for low") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Low = floatData strData, ok = data[x][4].(string) if !ok { return resp, errors.New("type assertion failed for close") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Close = floatData strData, ok = data[x][5].(string) if !ok { return resp, errors.New("type assertion failed for volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.Volume = floatData floatData, ok = data[x][6].(float64) if !ok { return resp, errors.New("type assertion failed for close time") } tempData.CloseTime = time.Unix(int64(floatData), 0) strData, ok = data[x][7].(string) if !ok { return resp, errors.New("type assertion failed for base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.BaseAssetVolume = floatData floatData, ok = data[x][8].(float64) if !ok { return resp, errors.New("type assertion failed for taker buy volume") } tempData.TakerBuyVolume = floatData strData, ok = data[x][9].(string) if !ok { return resp, errors.New("type assertion failed for taker buy base asset volume") } floatData, err = strconv.ParseFloat(strData, 64) if err != nil { return resp, err } tempData.TakerBuyBaseAssetVolume = floatData resp = append(resp, tempData) } return resp, nil } // 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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesTickerPriceStats+params.Encode(), limitDefault, &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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if limit > 0 && limit < 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // 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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolPriceTicker+params.Encode(), limitDefault, &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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesSymbolOrderbook+params.Encode(), limitDefault, &resp) } // GetFuturesLiquidationOrders gets orderbook ticker for symbol 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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetOpenInterest gets open interest data for a symbol func (b *Binance) GetOpenInterest(symbol currency.Pair) (OpenInterestData, error) { var resp OpenInterestData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) return resp, b.SendHTTPRequest(exchange.RestCoinMargined, cfuturesOpenInterest+params.Encode(), limitDefault, &resp) } // GetOpenInterestStats gets open interest stats for a symbol func (b *Binance) GetOpenInterestStats(pair, contractType, period string, limit int64, startTime, endTime time.Time) ([]OpenInterestStats, error) { var resp []OpenInterestStats params := url.Values{} if pair != "" { params.Set("pair", pair) } if !common.StringDataCompare(validContractType, contractType) { return resp, errors.New("invalid contractType") } params.Set("contractType", contractType) if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period") } params.Set("period", period) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetTraderFuturesAccountRatio gets a traders futures account long/short ratio func (b *Binance) GetTraderFuturesAccountRatio(pair, period string, limit int64, startTime, endTime time.Time) ([]TopTraderAccountRatio, error) { var resp []TopTraderAccountRatio params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period") } params.Set("period", period) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetTraderFuturesPositionsRatio gets a traders futures positions' long/short ratio func (b *Binance) GetTraderFuturesPositionsRatio(pair, period string, limit int64, startTime, endTime time.Time) ([]TopTraderPositionRatio, error) { var resp []TopTraderPositionRatio params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period") } params.Set("period", period) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetMarketRatio gets global long/short ratio func (b *Binance) GetMarketRatio(pair, period string, limit int64, startTime, endTime time.Time) ([]TopTraderPositionRatio, error) { var resp []TopTraderPositionRatio params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period") } params.Set("period", period) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetFuturesTakerVolume gets futures taker buy/sell volumes func (b *Binance) GetFuturesTakerVolume(pair, contractType, period string, limit int64, startTime, endTime time.Time) ([]TakerBuySellVolume, error) { var resp []TakerBuySellVolume params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validContractType, contractType) { return resp, errors.New("invalid contractType") } params.Set("contractType", contractType) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period parsed") } params.Set("period", period) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // GetFuturesBasisData gets futures basis data func (b *Binance) GetFuturesBasisData(pair, contractType, period string, limit int64, startTime, endTime time.Time) ([]FuturesBasisData, error) { var resp []FuturesBasisData params := url.Values{} params.Set("pair", pair) if !common.StringDataCompare(validContractType, contractType) { return resp, errors.New("invalid contractType") } params.Set("contractType", contractType) if limit > 0 && limit <= 1000 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !common.StringDataCompare(validFuturesIntervals, period) { return resp, errors.New("invalid period parsed") } params.Set("period", period) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // FuturesNewOrder sends a new futures order to the exchange func (b *Binance) FuturesNewOrder(symbol currency.Pair, side, positionSide, orderType, timeInForce, newClientOrderID, closePosition, workingType, newOrderRespType string, quantity, price, stopPrice, activationPrice, callbackRate float64, reduceOnly bool) (FuturesOrderPlaceData, error) { var resp FuturesOrderPlaceData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) params.Set("side", side) if positionSide != "" { if !common.StringDataCompare(validPositionSide, positionSide) { return resp, errors.New("invalid positionSide") } params.Set("positionSide", positionSide) } params.Set("type", orderType) params.Set("timeInForce", timeInForce) if reduceOnly { params.Set("reduceOnly", "true") } if newClientOrderID != "" { params.Set("newClientOrderID", newClientOrderID) } if closePosition != "" { params.Set("closePosition", closePosition) } if workingType != "" { if !common.StringDataCompare(validWorkingType, workingType) { return resp, errors.New("invalid workingType") } params.Set("workingType", workingType) } if newOrderRespType != "" { if !common.StringDataCompare(validNewOrderRespType, newOrderRespType) { return resp, errors.New("invalid newOrderRespType") } params.Set("newOrderRespType", newOrderRespType) } if quantity != 0 { params.Set("quantity", strconv.FormatFloat(quantity, 'f', -1, 64)) } if price != 0 { params.Set("price", strconv.FormatFloat(price, 'f', -1, 64)) } if stopPrice != 0 { params.Set("stopPrice", strconv.FormatFloat(stopPrice, 'f', -1, 64)) } if activationPrice != 0 { params.Set("activationPrice", strconv.FormatFloat(activationPrice, 'f', -1, 64)) } if callbackRate != 0 { params.Set("callbackRate", strconv.FormatFloat(callbackRate, 'f', -1, 64)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesOrder, params, limitDefault, &resp) } // FuturesBatchOrder sends a batch order request func (b *Binance) FuturesBatchOrder(data []PlaceBatchOrderData) ([]FuturesOrderPlaceData, error) { var resp []FuturesOrderPlaceData params := url.Values{} for x := range data { unformattedPair, err := currency.NewPairFromString(data[x].Symbol) if err != nil { return resp, err } formattedPair, err := b.FormatExchangeCurrency(unformattedPair, asset.CoinMarginedFutures) if err != nil { return resp, err } data[x].Symbol = formattedPair.String() if data[x].PositionSide != "" { if !common.StringDataCompare(validPositionSide, data[x].PositionSide) { return resp, errors.New("invalid positionSide") } } if data[x].WorkingType != "" { if !common.StringDataCompare(validWorkingType, data[x].WorkingType) { return resp, errors.New("invalid workingType") } } if data[x].NewOrderRespType != "" { if !common.StringDataCompare(validNewOrderRespType, data[x].NewOrderRespType) { return resp, errors.New("invalid newOrderRespType") } } } jsonData, err := json.Marshal(data) if err != nil { return resp, err } params.Set("batchOrders", string(jsonData)) return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesBatchOrder, params, limitDefault, &resp) } // FuturesBatchCancelOrders sends a batch request to cancel orders func (b *Binance) FuturesBatchCancelOrders(symbol currency.Pair, orderList, origClientOrderIDList []string) ([]BatchCancelOrderData, error) { var resp []BatchCancelOrderData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if len(orderList) != 0 { jsonOrderList, err := json.Marshal(orderList) if err != nil { return resp, err } params.Set("orderIdList", string(jsonOrderList)) } if len(origClientOrderIDList) != 0 { jsonCliOrdIDList, err := json.Marshal(origClientOrderIDList) if err != nil { return resp, err } params.Set("origClientOrderIdList", string(jsonCliOrdIDList)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesBatchOrder, params, limitDefault, &resp) } // FuturesGetOrderData gets futures order data func (b *Binance) FuturesGetOrderData(symbol currency.Pair, orderID, origClientOrderID string) (FuturesOrderGetData, error) { var resp FuturesOrderGetData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if orderID != "" { params.Set("orderId", orderID) } if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOrder, params, limitDefault, &resp) } // FuturesCancelOrder cancels a futures order func (b *Binance) FuturesCancelOrder(symbol currency.Pair, orderID, origClientOrderID string) (FuturesOrderGetData, error) { var resp FuturesOrderGetData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if orderID != "" { params.Set("orderId", orderID) } if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesOrder, params, limitDefault, &resp) } // FuturesCancelAllOpenOrders cancels a futures order func (b *Binance) FuturesCancelAllOpenOrders(symbol currency.Pair) (GenericAuthResponse, error) { var resp GenericAuthResponse params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodDelete, cfuturesCancelAllOrders, params, limitDefault, &resp) } // AutoCancelAllOpenOrders cancels all open futures orders // countdownTime 1000 = 1s, example - to cancel all orders after 30s (countdownTime: 30000) func (b *Binance) AutoCancelAllOpenOrders(symbol currency.Pair, countdownTime int64) (AutoCancelAllOrdersData, error) { var resp AutoCancelAllOrdersData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) params.Set("countdownTime", strconv.FormatInt(countdownTime, 10)) return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesCountdownCancel, params, limitDefault, &resp) } // FuturesOpenOrderData gets open order data for CoinMarginedFutures, func (b *Binance) FuturesOpenOrderData(symbol currency.Pair, orderID, origClientOrderID string) (FuturesOrderGetData, error) { var resp FuturesOrderGetData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if orderID != "" { params.Set("orderId", orderID) } if origClientOrderID != "" { params.Set("origClientOrderId", origClientOrderID) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesOpenOrder, params, limitDefault, &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{} if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAllOpenOrders, params, limitDefault, &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{} if !symbol.IsEmpty() { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } if orderID != 0 { params.Set("orderID", strconv.FormatInt(orderID, 10)) } if limit > 0 && limit <= 100 { params.Set("limit", strconv.FormatInt(limit, 10)) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // 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) } // 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) } // FuturesChangeInitialLeverage changes initial leverage for the account func (b *Binance) FuturesChangeInitialLeverage(symbol currency.Pair, leverage int64) (FuturesLeverageData, error) { var resp FuturesLeverageData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if leverage < 1 || leverage > 125 { 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) } // FuturesChangeMarginType changes margin type func (b *Binance) FuturesChangeMarginType(symbol currency.Pair, marginType string) (GenericAuthResponse, error) { var resp GenericAuthResponse params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if !common.StringDataCompare(validMarginType, marginType) { return resp, errors.New("invalid marginType") } params.Set("marginType", marginType) return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodPost, cfuturesChangeMarginType, params, limitDefault, &resp) } // ModifyIsolatedPositionMargin changes margin for an isolated position func (b *Binance) ModifyIsolatedPositionMargin(symbol currency.Pair, positionSide, changeType string, amount float64) (GenericAuthResponse, error) { var resp GenericAuthResponse params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) if !common.StringDataCompare(validPositionSide, positionSide) { return resp, errors.New("invalid positionSide") } params.Set("positionSide", positionSide) cType, ok := validMarginChange[changeType] if !ok { return resp, errors.New("invalid changeType") } 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) } // FuturesMarginChangeHistory gets past margin changes for positions func (b *Binance) FuturesMarginChangeHistory(symbol currency.Pair, changeType string, startTime, endTime time.Time, limit int64) ([]GetPositionMarginChangeHistoryData, error) { var resp []GetPositionMarginChangeHistoryData params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) cType, ok := validMarginChange[changeType] if !ok { return resp, errors.New("invalid changeType") } params.Set("type", strconv.FormatInt(cType, 10)) if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } if limit != 0 { params.Set("limit", strconv.FormatInt(limit, 10)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesMarginChangeHistory, params, limitDefault, &resp) } // FuturesPositionsInfo gets futures positions info func (b *Binance) FuturesPositionsInfo(marginAsset, pair string) ([]FuturesPositionInformation, error) { var resp []FuturesPositionInformation params := url.Values{} if marginAsset != "" { params.Set("marginAsset", marginAsset) } if pair != "" { params.Set("pair", pair) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesPositionInfo, params, limitDefault, &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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if pair != "" { params.Set("pair", pair) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } if limit != 0 { params.Set("limit", strconv.FormatInt(limit, 10)) } if fromID != 0 { params.Set("fromId", strconv.FormatInt(fromID, 10)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesAccountTradeList, params, limitDefault, &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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if incomeType != "" { if !common.StringDataCompare(validIncomeType, incomeType) { return resp, fmt.Errorf("invalid incomeType: %v", incomeType) } params.Set("incomeType", incomeType) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } if limit != 0 { params.Set("limit", strconv.FormatInt(limit, 10)) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesIncomeHistory, params, limitDefault, &resp) } // FuturesNotionalBracket gets futures notional bracket func (b *Binance) FuturesNotionalBracket(pair string) ([]NotionalBracketData, error) { var resp []NotionalBracketData params := url.Values{} if pair != "" { params.Set("pair", pair) } return resp, b.SendAuthHTTPRequest(exchange.RestCoinMargined, http.MethodGet, cfuturesNotionalBracket, params, limitDefault, &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{}) { symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures) if err != nil { return resp, err } params.Set("symbol", symbolValue) } if autoCloseType != "" { if !common.StringDataCompare(validAutoCloseTypes, autoCloseType) { return resp, errors.New("invalid autoCloseType") } params.Set("autoCloseType", autoCloseType) } if !startTime.IsZero() && !endTime.IsZero() { if startTime.After(endTime) { return resp, errors.New("startTime cannot be after endTime") } 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) } // FuturesPositionsADLEstimate estimates ADL on positions func (b *Binance) FuturesPositionsADLEstimate(symbol currency.Pair) ([]ADLEstimateData, error) { var resp []ADLEstimateData params := url.Values{} if symbol != (currency.Pair{}) { 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) }