Files
gocryptotrader/exchanges/binance/binance_cfutures.go
Scott 50bbdabf43 BugFix: RPCServer cannot retrieve open orders/getOrder due to unset asset type (#634)
* Fixes issue where getorders could not work due to unset asset type in rpcserver.go. Adds test. Also adds start and end date to the cli.

* A few fixes

* lint

* fixes oopsie that affected doopsie

* Ensures dates are set for all open order implementations. Adds new filter to ensure orders without dates are returned rather than filtered. Fixes up Binance OpenOrders implementation. Adds some extra typeconverts for binance

* Add updated time to Binance GetActiveOrders. Update rpcserver.go to only set the time if its not empty. Also addressed bad expected value

* Actually fixes things this time

* Improves recvWindow to process openOrders

* Adds asset type to getOrder as well

* Fixes tests

* Adds missing date fields

* Fixes default time, updates default errors

* Default start to last month, instead of last year
2021-02-25 17:13:21 +11:00

1398 lines
48 KiB
Go

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)
}