Files
gocryptotrader/exchanges/binance/binance_cfutures.go
Adam 504c2fad6d Feature: Implement funding rates, futures and coin margin (exchange API coverage) (#530)
* ALMOST THERE

* more api wips

* more api thingz

* testing n more api wipz

* more apiz

* more wips

* what is goin on

* more wips

* whip n testing

* testing

* testing

no keys

* remove log

* kraken is broken

ugh

* still broken

* fixing auth funcs + usdtm api docs

* wip

* api stuffs

* whip

* more wips

* whip

* more wip

* api wip n testing

* wip

* wip

* unsaved

* wip n testing

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* whip

* wrapper authenticated functions

* adding asset type and fixing dependencies

* wip

* binance auth wrapper start

* wrapper functionality

* wip

* wip

* wip

* wrapper cancel functions

* order submission for wrappers

* wip

* more error fixing and nits

* websocket beginning n error fix

* wip

* WOW

* glorious n shazzy nits

* useless nits

* wip

* fixing things

* merge stuffs

* crapveyor

* crapveyor rebuild

* probably broke more things than he fixed

* rm lns n other thangs

* hope

* please

* stop it

* done

* ofcourse

* rm vb

* fix lbank

* appveyor please

* float lev

* DONT ASK RYAN FOR HELP EVER

* wip

* wip

* endpoint upgrades continued

* path upgrade

* NeeeNeeeNeeeNeeeNING

* fix stuffs

* fixing time issue

* fixing broken funcs

* glorious nits

* shaz changes

* fixing errors for fundmon

* more error fixing for fundmon

* test running past 30s

* basic changes

* THX AGAIN SHAZBERT

* path system upgrade

* config upgrade

* unsaved stuffs

* broken wip config upgrade

* path system upgrade contd.

* path system upgrade contd

* path upgrade ready for review

* testing verbose removed

* linter stuffs

* appveyor stuffs

* appveyor stuff

* fixed?

* bugfix

* wip

* broken stuff

* fix test

* wierd hack fix

* appveyor pls stop

* error found

* more useless nits

* bitmex err

* broken wip

* broken wip path upgrade change to uint32

* changed url lookups to uint

* WOW

* ready4review

* config fixed HOPEFULLY

* config fix and glorious changes

* efficient way of getting orders and open orders

* binance wrapper logic fixing

* testing, adding tests and fixing lot of errrrrs

* merge master

* appveyor stuffs

* appveyor stuffs

* fmt

* test

* octalLiteral issue fix?

* octalLiteral fix?

* rm vb

* prnt ln to restart

* adding testz

* test fixzzz

* READY FOR REVIEW

* Actually ready now

* FORMATTING

* addressing shazzy n glorious nits

* crapveyor

* rm vb

* small change

* fixing err

* shazbert nits

* review changes

* requested changes

* more requested changes

* noo

* last nit fixes

* restart appveyor

* improving test cov

* Update .golangci.yml

* shazbert changes

* moving pair formatting

* format pair update wip

* path upgrade complete

* error fix

* appveyor linters

* more linters

* remove testexch

* more formatting changes

* changes

* shazbert changes

* checking older requested changes to ensure completion

* wip

* fixing broken code

* error fix

* all fixed

* additional changes

* more changes

* remove commented code

* ftx margin api

* appveyor fixes

* more appveyor issues + test addition

* more appveyor issues + test addition

* remove unnecessary

* testing

* testing, fixing okex api, error fix

* git merge fix

* go sum

* glorious changes and error fix

* rm vb

* more glorious changes and go mod tidy

* fixed now

* okex testing upgrade

* old config migration and batch fetching fix

* added test

* glorious requested changes WIP

* tested and fixed

* go fmted

* go fmt and test fix

* additional funcs and tests for fundingRates

* OKEX tested and fixed

* appveyor fixes

* ineff assign

* 1 glorious change

* error fix

* typo

* shazbert changes

* glorious code changes and path fixing huobi WIP

* adding assetType to accountinfo functions

* fixing panic

* panic fix and updating account info wrappers WIP

* updateaccountinfo updated

* testing WIP binance USDT n Coin Margined and Kraken Futures

* auth functions tested and fixed

* added test

* config reverted

* shazbert and glorious changes

* shazbert and glorious changes

* latest changes and portfolio update

* go fmt change:

* remove commented codes

* improved error checking

* index out of range fix

* rm ln

* critical nit

* glorious latest changes

* appveyor changes

* shazbert change

* easier readability

* latest glorious changes

* shadow dec

* assetstore updated

* last change

* another last change

* merge changes

* go mod tidy

* thrasher requested changes wip

* improving struct layouts

* appveyor go fmt

* remove unnecessary code

* shazbert changes

* small change

* oopsie

* tidy

* configtest reverted

* error fix

* oopsie

* for what

* test patch fix

* insecurities

* fixing tests

* fix config
2021-02-12 16:19:18 +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 != (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.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 != (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 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)
}