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
This commit is contained in:
Adam
2021-02-12 16:19:18 +11:00
committed by GitHub
parent e9bd2ad4d8
commit 504c2fad6d
169 changed files with 227754 additions and 31776 deletions

View File

@@ -17,18 +17,30 @@ import (
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/log"
)
// Binance is the overarching type across the Binance package
type Binance struct {
exchange.Base
// Valid string list that is required by the exchange
validLimits []int
obm *orderbookManager
}
const (
apiURL = "https://api.binance.com"
apiURL = "https://api.binance.com"
spotAPIURL = "https://sapi.binance.com"
cfuturesAPIURL = "https://dapi.binance.com"
ufuturesAPIURL = "https://fapi.binance.com"
// Public endpoints
exchangeInfo = "/api/v3/exchangeInfo"
orderBookDepth = "/api/v3/depth"
recentTrades = "/api/v3/trades"
historicalTrades = "/api/v3/historicalTrades"
aggregatedTrades = "/api/v3/aggTrades"
candleStick = "/api/v3/klines"
averagePrice = "/api/v3/avgPrice"
@@ -37,45 +49,57 @@ const (
bestPrice = "/api/v3/ticker/bookTicker"
accountInfo = "/api/v3/account"
userAccountStream = "/api/v3/userDataStream"
perpExchangeInfo = "/fapi/v1/exchangeInfo"
// Authenticated endpoints
newOrderTest = "/api/v3/order/test"
newOrder = "/api/v3/order"
cancelOrder = "/api/v3/order"
queryOrder = "/api/v3/order"
openOrders = "/api/v3/openOrders"
allOrders = "/api/v3/allOrders"
myTrades = "/api/v3/myTrades"
newOrderTest = "/api/v3/order/test"
orderEndpoint = "/api/v3/order"
openOrders = "/api/v3/openOrders"
allOrders = "/api/v3/allOrders"
// Withdraw API endpoints
withdrawEndpoint = "/wapi/v3/withdraw.html"
depositHistory = "/wapi/v3/depositHistory.html"
withdrawalHistory = "/wapi/v3/withdrawHistory.html"
depositAddress = "/wapi/v3/depositAddress.html"
accountStatus = "/wapi/v3/accountStatus.html"
systemStatus = "/wapi/v3/systemStatus.html"
dustLog = "/wapi/v3/userAssetDribbletLog.html"
tradeFee = "/wapi/v3/tradeFee.html"
assetDetail = "/wapi/v3/assetDetail.html"
withdrawEndpoint = "/wapi/v3/withdraw.html"
depositHistory = "/wapi/v3/depositHistory.html"
withdrawalHistory = "/wapi/v3/withdrawHistory.html"
depositAddress = "/wapi/v3/depositAddress.html"
accountStatus = "/wapi/v3/accountStatus.html"
systemStatus = "/wapi/v3/systemStatus.html"
dustLog = "/wapi/v3/userAssetDribbletLog.html"
tradeFee = "/wapi/v3/tradeFee.html"
assetDetail = "/wapi/v3/assetDetail.html"
undocumentedInterestHistory = "/gateway-api/v1/public/isolated-margin/pair/vip-level"
undocumentedCrossMarginInterestHistory = "/gateway-api/v1/friendly/margin/vip/spec/list-all"
)
// Binance is the overarching type across the Bithumb package
type Binance struct {
exchange.Base
// GetInterestHistory gets interest history for currency/currencies provided
func (b *Binance) GetInterestHistory() (MarginInfoData, error) {
var resp MarginInfoData
if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedInterestHistory, limitDefault, &resp); err != nil {
return resp, err
}
return resp, nil
}
// Valid string list that is required by the exchange
validLimits []int
// GetCrossMarginInterestHistory gets cross-margin interest history for currency/currencies provided
func (b *Binance) GetCrossMarginInterestHistory() (CrossMarginInterestData, error) {
var resp CrossMarginInterestData
if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedCrossMarginInterestHistory, limitDefault, &resp); err != nil {
return resp, err
}
return resp, nil
}
obm *orderbookManager
// GetMarginMarkets returns exchange information. Check binance_types for more information
func (b *Binance) GetMarginMarkets() (PerpsExchangeInfo, error) {
var resp PerpsExchangeInfo
return resp, b.SendHTTPRequest(exchange.RestSpot, perpExchangeInfo, limitDefault, &resp)
}
// GetExchangeInfo returns exchange information. Check binance_types for more
// information
func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) {
var resp ExchangeInfo
path := b.API.Endpoints.URL + exchangeInfo
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, exchangeInfo, limitDefault, &resp)
}
// GetOrderBook returns full orderbook information
@@ -90,7 +114,7 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error
}
params := url.Values{}
symbol, err := b.formatSymbol(obd.Symbol)
symbol, err := b.FormatSymbol(obd.Symbol, asset.Spot)
if err != nil {
return orderbook, err
}
@@ -98,8 +122,7 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error
params.Set("limit", fmt.Sprintf("%d", obd.Limit))
var resp OrderBookData
path := common.EncodeURLValues(b.API.Endpoints.URL+orderBookDepth, params)
if err := b.SendHTTPRequest(path, orderbookLimit(obd.Limit), &resp); err != nil {
if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, orderBookDepth+"?"+params.Encode(), orderbookLimit(obd.Limit), &resp); err != nil {
return orderbook, err
}
@@ -147,16 +170,16 @@ func (b *Binance) GetMostRecentTrades(rtr RecentTradeRequestParams) ([]RecentTra
var resp []RecentTrade
params := url.Values{}
symbol, err := b.formatSymbol(rtr.Symbol)
symbol, err := b.FormatSymbol(rtr.Symbol, asset.Spot)
if err != nil {
return nil, err
}
params.Set("symbol", symbol)
params.Set("limit", fmt.Sprintf("%d", rtr.Limit))
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, recentTrades, params.Encode())
path := recentTrades + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
}
// GetHistoricalTrades returns historical trade activity
@@ -177,7 +200,7 @@ func (b *Binance) GetHistoricalTrades(symbol string, limit int, fromID int64) ([
// https://binance-docs.github.io/apidocs/spot/en/#compressed-aggregate-trades-list
func (b *Binance) GetAggregatedTrades(arg *AggregatedTradeRequestParams) ([]AggregatedTrade, error) {
params := url.Values{}
symbol, err := b.formatSymbol(arg.Symbol)
symbol, err := b.FormatSymbol(arg.Symbol, asset.Spot)
if err != nil {
return nil, err
}
@@ -218,10 +241,9 @@ func (b *Binance) GetAggregatedTrades(arg *AggregatedTradeRequestParams) ([]Aggr
// We would receive {"code":-1128,"msg":"Combination of optional parameters invalid."}
return nil, errors.New("please set StartTime or FromId, but not both")
}
var resp []AggregatedTrade
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
path := aggregatedTrades + "?" + params.Encode()
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
}
// batchAggregateTrades fetches trades in multiple requests
@@ -246,8 +268,8 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params
}
params.Set("startTime", timeString(start))
params.Set("endTime", timeString(start.Add(time.Hour)))
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
err := b.SendHTTPRequest(path, limitDefault, &resp)
path := aggregatedTrades + "?" + params.Encode()
err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
if err != nil {
log.Warn(log.ExchangeSys, err.Error())
return resp, err
@@ -263,9 +285,9 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params
for ; arg.Limit == 0 || len(resp) < arg.Limit; fromID = resp[len(resp)-1].ATradeID {
// Keep requesting new data after last retrieved trade
params.Set("fromId", strconv.FormatInt(fromID, 10))
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
path := aggregatedTrades + "?" + params.Encode()
var additionalTrades []AggregatedTrade
err := b.SendHTTPRequest(path, limitDefault, &additionalTrades)
err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &additionalTrades)
if err != nil {
return resp, err
}
@@ -304,7 +326,7 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
var klineData []CandleStick
params := url.Values{}
symbol, err := b.formatSymbol(arg.Symbol)
symbol, err := b.FormatSymbol(arg.Symbol, asset.Spot)
if err != nil {
return nil, err
}
@@ -320,9 +342,9 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
params.Set("endTime", timeString(arg.EndTime))
}
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, candleStick, params.Encode())
path := candleStick + "?" + params.Encode()
if err := b.SendHTTPRequest(path, limitDefault, &resp); err != nil {
if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp); err != nil {
return klineData, err
}
@@ -375,15 +397,15 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) {
resp := AveragePrice{}
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
params.Set("symbol", symbolValue)
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, averagePrice, params.Encode())
path := averagePrice + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
}
// GetPriceChangeStats returns price change statistics for the last 24 hours
@@ -392,22 +414,21 @@ func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) {
func (b *Binance) GetPriceChangeStats(symbol currency.Pair) (PriceChangeStats, error) {
resp := PriceChangeStats{}
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
params.Set("symbol", symbolValue)
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, priceChange, params.Encode())
path := priceChange + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
}
// GetTickers returns the ticker data for the last 24 hrs
func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
var resp []PriceChangeStats
path := b.API.Endpoints.URL + priceChange
return resp, b.SendHTTPRequest(path, limitPriceChangeAll, &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, priceChange, limitPriceChangeAll, &resp)
}
// GetLatestSpotPrice returns latest spot price of symbol
@@ -416,15 +437,15 @@ func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error) {
resp := SymbolPrice{}
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
params.Set("symbol", symbolValue)
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, symbolPrice, params.Encode())
path := symbolPrice + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, symbolPriceLimit(symbolValue), &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, symbolPriceLimit(symbolValue), &resp)
}
// GetBestPrice returns the latest best price for symbol
@@ -433,21 +454,21 @@ func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error)
func (b *Binance) GetBestPrice(symbol currency.Pair) (BestPrice, error) {
resp := BestPrice{}
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
params.Set("symbol", symbolValue)
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, bestPrice, params.Encode())
path := bestPrice + "?" + params.Encode()
return resp, b.SendHTTPRequest(path, bestPriceLimit(symbolValue), &resp)
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, bestPriceLimit(symbolValue), &resp)
}
// NewOrder sends a new order to Binance
func (b *Binance) NewOrder(o *NewOrderRequest) (NewOrderResponse, error) {
var resp NewOrderResponse
if err := b.newOrder(newOrder, o, &resp); err != nil {
if err := b.newOrder(orderEndpoint, o, &resp); err != nil {
return resp, err
}
@@ -465,10 +486,8 @@ func (b *Binance) NewOrderTest(o *NewOrderRequest) error {
}
func (b *Binance) newOrder(api string, o *NewOrderRequest, resp *NewOrderResponse) error {
path := b.API.Endpoints.URL + api
params := url.Values{}
symbol, err := b.formatSymbol(o.Symbol)
symbol, err := b.FormatSymbol(o.Symbol, asset.Spot)
if err != nil {
return err
}
@@ -502,16 +521,14 @@ func (b *Binance) newOrder(api string, o *NewOrderRequest, resp *NewOrderRespons
if o.NewOrderRespType != "" {
params.Set("newOrderRespType", o.NewOrderRespType)
}
return b.SendAuthHTTPRequest(http.MethodPost, path, params, limitOrder, resp)
return b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, api, params, limitOrder, resp)
}
// CancelExistingOrder sends a cancel order to Binance
func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origClientOrderID string) (CancelOrderResponse, error) {
var resp CancelOrderResponse
path := b.API.Endpoints.URL + cancelOrder
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
@@ -525,8 +542,7 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC
if origClientOrderID != "" {
params.Set("origClientOrderId", origClientOrderID)
}
return resp, b.SendAuthHTTPRequest(http.MethodDelete, path, params, limitOrder, &resp)
return resp, b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodDelete, orderEndpoint, params, limitOrder, &resp)
}
// OpenOrders Current open orders. Get all open orders on a symbol.
@@ -535,14 +551,12 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC
func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
var resp []QueryOrderData
path := b.API.Endpoints.URL + openOrders
params := url.Values{}
var symbol string
if pair != nil {
var err error
symbol, err = b.formatSymbol(*pair)
symbol, err = b.FormatSymbol(*pair, asset.Spot)
if err != nil {
return resp, err
}
@@ -551,7 +565,7 @@ func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
params.Set("symbol", symbol)
}
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, openOrdersLimit(symbol), &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, openOrders, params, openOrdersLimit(symbol), &resp); err != nil {
return resp, err
}
@@ -564,10 +578,8 @@ func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]QueryOrderData, error) {
var resp []QueryOrderData
path := b.API.Endpoints.URL + allOrders
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
@@ -578,7 +590,7 @@ func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]Quer
if limit != "" {
params.Set("limit", limit)
}
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, limitOrdersAll, &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, allOrders, params, limitOrdersAll, &resp); err != nil {
return resp, err
}
@@ -589,10 +601,8 @@ func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]Quer
func (b *Binance) QueryOrder(symbol currency.Pair, origClientOrderID string, orderID int64) (QueryOrderData, error) {
var resp QueryOrderData
path := b.API.Endpoints.URL + queryOrder
params := url.Values{}
symbolValue, err := b.formatSymbol(symbol)
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
if err != nil {
return resp, err
}
@@ -604,7 +614,7 @@ func (b *Binance) QueryOrder(symbol currency.Pair, origClientOrderID string, ord
params.Set("orderId", strconv.FormatInt(orderID, 10))
}
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, limitOrder, &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, orderEndpoint, params, limitOrder, &resp); err != nil {
return resp, err
}
@@ -622,11 +632,9 @@ func (b *Binance) GetAccount() (*Account, error) {
}
var resp response
path := b.API.Endpoints.URL + accountInfo
params := url.Values{}
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, accountInfo, params, request.Unset, &resp); err != nil {
return &resp.Account, err
}
@@ -638,10 +646,14 @@ func (b *Binance) GetAccount() (*Account, error) {
}
// SendHTTPRequest sends an unauthenticated request
func (b *Binance) SendHTTPRequest(path string, f request.EndpointLimit, result interface{}) error {
func (b *Binance) SendHTTPRequest(ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error {
endpointPath, err := b.API.Endpoints.GetURL(ePath)
if err != nil {
return err
}
return b.SendPayload(context.Background(), &request.Item{
Method: http.MethodGet,
Path: path,
Path: endpointPath + path,
Result: result,
Verbose: b.Verbose,
HTTPDebugging: b.HTTPDebugging,
@@ -650,42 +662,41 @@ func (b *Binance) SendHTTPRequest(path string, f request.EndpointLimit, result i
}
// SendAuthHTTPRequest sends an authenticated HTTP request
func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, f request.EndpointLimit, result interface{}) error {
func (b *Binance) SendAuthHTTPRequest(ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result interface{}) error {
if !b.AllowAuthenticatedRequest() {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
}
endpointPath, err := b.API.Endpoints.GetURL(ePath)
if err != nil {
return err
}
path = endpointPath + path
if params == nil {
params = url.Values{}
}
recvWindow := 5 * time.Second
params.Set("recvWindow", strconv.FormatInt(convert.RecvWindow(recvWindow), 10))
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
signature := params.Encode()
hmacSigned := crypto.GetHMAC(crypto.HashSHA256, []byte(signature), []byte(b.API.Credentials.Secret))
hmacSignedStr := crypto.HexEncodeToString(hmacSigned)
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = b.API.Credentials.Key
if b.Verbose {
log.Debugf(log.ExchangeSys, "sent path: %s", path)
}
path = common.EncodeURLValues(path, params)
path += "&signature=" + hmacSignedStr
interim := json.RawMessage{}
errCap := struct {
Success bool `json:"success"`
Message string `json:"msg"`
Code int64 `json:"code"`
}{}
ctx, cancel := context.WithTimeout(context.Background(), recvWindow)
defer cancel()
err := b.SendPayload(ctx, &request.Item{
err = b.SendPayload(ctx, &request.Item{
Method: method,
Path: path,
Headers: headers,
@@ -699,13 +710,11 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, f
if err != nil {
return err
}
if err := json.Unmarshal(interim, &errCap); err == nil {
if !errCap.Success && errCap.Message != "" {
if !errCap.Success && errCap.Message != "" && errCap.Code != 200 {
return errors.New(errCap.Message)
}
}
return json.Unmarshal(interim, result)
}
@@ -779,7 +788,6 @@ func getCryptocurrencyWithdrawalFee(c currency.Code) float64 {
// WithdrawCrypto sends cryptocurrency to the address of your choosing
func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string) (string, error) {
var resp WithdrawResponse
path := b.API.Endpoints.URL + withdrawEndpoint
params := url.Values{}
params.Set("asset", asset)
@@ -792,7 +800,7 @@ func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string
params.Set("addressTag", addressTag)
}
if err := b.SendAuthHTTPRequest(http.MethodPost, path, params, request.Unset, &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, withdrawEndpoint, params, request.Unset, &resp); err != nil {
return "", err
}
@@ -811,7 +819,6 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
WithdrawList []WithdrawStatusResponse `json:"withdrawList"`
}
path := b.API.Endpoints.URL + withdrawalHistory
params := url.Values{}
params.Set("asset", c.String())
@@ -838,7 +845,7 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
params.Set("endTime", strconv.FormatInt(endTime, 10))
}
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &response); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, withdrawalHistory, params, request.Unset, &response); err != nil {
return response.WithdrawList, err
}
@@ -847,8 +854,6 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
// GetDepositAddressForCurrency retrieves the wallet address for a given currency
func (b *Binance) GetDepositAddressForCurrency(currency string) (string, error) {
path := b.API.Endpoints.URL + depositAddress
resp := struct {
Address string `json:"address"`
Success bool `json:"success"`
@@ -860,16 +865,20 @@ func (b *Binance) GetDepositAddressForCurrency(currency string) (string, error)
params.Set("status", "true")
return resp.Address,
b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &resp)
b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, depositAddress, params, request.Unset, &resp)
}
// GetWsAuthStreamKey will retrieve a key to use for authorised WS streaming
func (b *Binance) GetWsAuthStreamKey() (string, error) {
endpointPath, err := b.API.Endpoints.GetURL(exchange.RestSpotSupplementary)
if err != nil {
return "", err
}
var resp UserAccountStream
path := b.API.Endpoints.URL + userAccountStream
path := endpointPath + userAccountStream
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = b.API.Credentials.Key
err := b.SendPayload(context.Background(), &request.Item{
err = b.SendPayload(context.Background(), &request.Item{
Method: http.MethodPost,
Path: path,
Headers: headers,
@@ -888,12 +897,15 @@ func (b *Binance) GetWsAuthStreamKey() (string, error) {
// MaintainWsAuthStreamKey will keep the key alive
func (b *Binance) MaintainWsAuthStreamKey() error {
var err error
endpointPath, err := b.API.Endpoints.GetURL(exchange.RestSpotSupplementary)
if err != nil {
return err
}
if listenKey == "" {
listenKey, err = b.GetWsAuthStreamKey()
return err
}
path := b.API.Endpoints.URL + userAccountStream
path := endpointPath + userAccountStream
params := url.Values{}
params.Set("listenKey", listenKey)
path = common.EncodeURLValues(path, params)

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,6 @@ func TestMain(m *testing.M) {
}
b.setupOrderbookManager()
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
log.Printf(sharedtestvalues.LiveTesting, b.Name, b.API.Endpoints.URL)
log.Printf(sharedtestvalues.LiveTesting, b.Name)
os.Exit(m.Run())
}

View File

@@ -45,9 +45,14 @@ func TestMain(m *testing.M) {
if err != nil {
log.Fatalf("Mock server error %s", err)
}
b.HTTPClient = newClient
b.API.Endpoints.URL = serverDetails
log.Printf(sharedtestvalues.MockTesting, b.Name, b.API.Endpoints.URL)
endpointMap := b.API.Endpoints.GetURLMap()
for k := range endpointMap {
err = b.API.Endpoints.SetRunning(k, serverDetails)
if err != nil {
log.Fatal(err)
}
}
log.Printf(sharedtestvalues.MockTesting, b.Name)
os.Exit(m.Run())
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,12 +19,6 @@ const (
Completed
)
// Response holds basic binance api response data
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
// ExchangeInfo holds the full exchange information type
type ExchangeInfo struct {
Code int `json:"code"`
@@ -93,6 +87,7 @@ type OrderBookData struct {
// OrderBook actual structured data that can be used for orderbook
type OrderBook struct {
Symbol string
LastUpdateID int64
Code int
Msg string
@@ -237,6 +232,18 @@ type AggregatedTrade struct {
BestMatchPrice bool `json:"M"`
}
// IndexMarkPrice stores data for index and mark prices
type IndexMarkPrice struct {
Symbol string `json:"symbol"`
Pair string `json:"pair"`
MarkPrice float64 `json:"markPrice,string"`
IndexPrice float64 `json:"indexPrice,string"`
EstimatedSettlePrice float64 `json:"estimatedSettlePrice,string"`
LastFundingRate string `json:"lastFundingRate"`
NextFundingTime int64 `json:"nextFundingTime"`
Time int64 `json:"time"`
}
// CandleStick holds kline data
type CandleStick struct {
OpenTime time.Time
@@ -749,6 +756,22 @@ type WsPayload struct {
ID int64 `json:"id"`
}
// CrossMarginInterestData stores cross margin data for borrowing
type CrossMarginInterestData struct {
Code int64 `json:"code,string"`
Message string `json:"message"`
MessageDetail string `json:"messageDetail"`
Data []struct {
AssetName string `json:"assetName"`
Specs []struct {
VipLevel string `json:"vipLevel"`
DailyInterestRate string `json:"dailyInterestRate"`
BorrowLimit string `json:"borrowLimit"`
} `json:"specs"`
} `json:"data"`
Success bool `json:"success"`
}
// orderbookManager defines a way of managing and maintaining synchronisation
// across connections and assets.
type orderbookManager struct {

File diff suppressed because it is too large Load Diff

View File

@@ -525,20 +525,22 @@ func (b *Binance) GenerateSubscriptions() ([]stream.ChannelSubscription, error)
var subscriptions []stream.ChannelSubscription
assets := b.GetAssetTypes()
for x := range assets {
pairs, err := b.GetEnabledPairs(assets[x])
if err != nil {
return nil, err
}
if assets[x] == asset.Spot {
pairs, err := b.GetEnabledPairs(assets[x])
if err != nil {
return nil, err
}
for y := range pairs {
for z := range channels {
lp := pairs[y].Lower()
lp.Delimiter = ""
subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: lp.String() + channels[z],
Currency: pairs[y],
Asset: assets[x],
})
for y := range pairs {
for z := range channels {
lp := pairs[y].Lower()
lp.Delimiter = ""
subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: lp.String() + channels[z],
Currency: pairs[y],
Asset: assets[x],
})
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,608 @@
package binance
import (
"time"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
// Response holds basic binance api response data
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
// FuturesPublicTradesData stores recent public trades for futures
type FuturesPublicTradesData struct {
ID int64 `json:"id"`
Price float64 `json:"price,string"`
Qty float64 `json:"qty,string"`
QuoteQty float64 `json:"quoteQty,string"`
Time int64 `json:"time"`
IsBuyerMaker bool `json:"isBuyerMaker"`
}
// CompressedTradesData stores futures trades data in a compressed format
type CompressedTradesData struct {
TradeID int64 `json:"a"`
Price float64 `json:"p"`
Quantity float64 `json:"q"`
FirstTradeID int64 `json:"f"`
LastTradeID int64 `json:"l"`
Timestamp int64 `json:"t"`
BuyerMaker bool `json:"b"`
}
// MarkPriceData stores mark price data for futures
type MarkPriceData struct {
Symbol string `json:"symbol"`
MarkPrice float64 `json:"markPrice"`
LastFundingRate float64 `json:"lastFundingRate"`
NextFundingTime int64 `json:"nextFundingTime"`
Time int64 `json:"time"`
}
// SymbolPriceTicker stores ticker price stats
type SymbolPriceTicker struct {
Symbol string `json:"symbol"`
Price float64 `json:"price,string"`
Time int64 `json:"time"`
}
// SymbolOrderBookTicker stores orderbook ticker data
type SymbolOrderBookTicker struct {
Symbol string `json:"symbol"`
BidPrice float64 `json:"bidPrice,string"`
AskPrice float64 `json:"askPrice,string"`
BidQty float64 `json:"bidQty,string"`
AskQty float64 `json:"askQty,string"`
Time int64 `json:"time"`
}
// FuturesCandleStick holds kline data
type FuturesCandleStick struct {
OpenTime time.Time
Open float64
High float64
Low float64
Close float64
Volume float64
CloseTime time.Time
BaseAssetVolume float64
NumberOfTrades int64
TakerBuyVolume float64
TakerBuyBaseAssetVolume float64
}
// AllLiquidationOrders gets all liquidation orders
type AllLiquidationOrders struct {
Symbol string `json:"symbol"`
Price float64 `json:"price,string"`
OrigQty float64 `json:"origQty,string"`
ExecutedQty float64 `json:"executedQty,string"`
AveragePrice float64 `json:"averagePrice,string"`
Status string `json:"status"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
Side string `json:"side"`
Time int64 `json:"time"`
}
// OpenInterestData stores open interest data
type OpenInterestData struct {
Symbol string `json:"symbol"`
Pair string `json:"pair"`
OpenInterest float64 `json:"openInterest,string"`
ContractType string `json:"contractType"`
Time int64 `json:"time"`
}
// OpenInterestStats stores stats for open interest data
type OpenInterestStats struct {
Pair string `json:"pair"`
ContractType string `json:"contractType"`
SumOpenInterest float64 `json:"sumOpenInterest,string"`
SumOpenInterestValue float64 `json:"sumOpenInterestValue,string"`
Timestamp int64 `json:"timestamp"`
}
// TopTraderAccountRatio stores account ratio data for top traders
type TopTraderAccountRatio struct {
Pair string `json:"pair"`
LongShortRatio float64 `json:"longShortRatio,string"`
LongAccount float64 `json:"longAccount,string"`
ShortAccount float64 `json:"shortAccount,string"`
Timestamp int64 `json:"timestamp"`
}
// TopTraderPositionRatio stores position ratio for top trader accounts
type TopTraderPositionRatio struct {
Pair string `json:"pair"`
LongShortRatio float64 `json:"longShortRatio,string"`
LongPosition float64 `json:"longPosition,string"`
ShortPosition float64 `json:"shortPosition,string"`
Timestamp int64 `json:"timestamp"`
}
// GlobalLongShortRatio stores ratio data of all longs vs shorts
type GlobalLongShortRatio struct {
Symbol string `json:"symbol"`
LongShortRatio float64 `json:"longShortRatio"`
LongAccount float64 `json:"longAccount"`
ShortAccount float64 `json:"shortAccount"`
Timestamp string `json:"timestamp"`
}
// TakerBuySellVolume stores taker buy sell volume
type TakerBuySellVolume struct {
Pair string `json:"pair"`
ContractType string `json:"contractType"`
TakerBuyVolume float64 `json:"takerBuyVol,string"`
BuySellRatio float64 `json:"takerSellVol,string"`
BuyVol float64 `json:"takerBuyVolValue,string"`
SellVol float64 `json:"takerSellVolValue,string"`
Timestamp int64 `json:"timestamp"`
}
// FuturesBasisData gets futures basis data
type FuturesBasisData struct {
Pair string `json:"pair"`
ContractType string `json:"contractType"`
FuturesPrice float64 `json:"futuresPrice,string"`
IndexPrice float64 `json:"indexPrice,string"`
Basis float64 `json:"basis,string"`
BasisRate float64 `json:"basisRate,string"`
Timestamp int64 `json:"timestamp"`
}
// PlaceBatchOrderData stores batch order data for placing
type PlaceBatchOrderData struct {
Symbol string `json:"symbol"`
Side string `json:"side"`
PositionSide string `json:"positionSide,omitempty"`
OrderType string `json:"type"`
TimeInForce string `json:"timeInForce,omitempty"`
Quantity float64 `json:"quantity"`
ReduceOnly string `json:"reduceOnly,omitempty"`
Price float64 `json:"price"`
NewClientOrderID string `json:"newClientOrderId,omitempty"`
StopPrice float64 `json:"stopPrice,omitempty"`
ActivationPrice float64 `json:"activationPrice,omitempty"`
CallbackRate float64 `json:"callbackRate,omitempty"`
WorkingType string `json:"workingType,omitempty"`
PriceProtect string `json:"priceProtect,omitempty"`
NewOrderRespType string `json:"newOrderRespType,omitempty"`
}
// BatchCancelOrderData stores batch cancel order data
type BatchCancelOrderData struct {
ClientOrderID string `json:"clientOrderID"`
CumQty float64 `json:"cumQty,string"`
CumBase float64 `json:"cumBase,string"`
ExecuteQty float64 `json:"executeQty,string"`
OrderID int64 `json:"orderID,string"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice int64 `json:"stopPrice"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
TimeInForce string `json:"TimeInForce"`
OrderType string `json:"type"`
OrigType string `json:"origType"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
Code int64 `json:"code"`
Msg string `json:"msg"`
}
// FuturesOrderPlaceData stores futures order data
type FuturesOrderPlaceData struct {
ClientOrderID string `json:"clientOrderID"`
CumQty float64 `json:"cumQty,string"`
CumBase float64 `json:"cumBase,string"`
ExecuteQty float64 `json:"executeQty,string"`
OrderID int64 `json:"orderID,string"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice int64 `json:"stopPrice"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
TimeInForce string `json:"TimeInForce"`
OrderType string `json:"type"`
OrigType string `json:"origType"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
}
// FuturesOrderGetData stores futures order data for get requests
type FuturesOrderGetData struct {
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderID"`
CumQty float64 `json:"cumQty,string"`
CumBase float64 `json:"cumBase,string"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"buy"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
}
// FuturesOrderData stores order data for futures
type FuturesOrderData struct {
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumBase string `json:"cumBase"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
Time int64 `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
}
// OrderVars stores side, status and type for any order/trade
type OrderVars struct {
Side order.Side
Status order.Status
OrderType order.Type
Fee float64
}
// AutoCancelAllOrdersData gives data of auto cancelling all open orders
type AutoCancelAllOrdersData struct {
Symbol string `json:"symbol"`
CountdownTime int64 `json:"countdownTime,string"`
}
// LevelDetail stores level detail data
type LevelDetail struct {
Level string `json:"level"`
MaxBorrowable float64 `json:"maxBorrowable,string"`
InterestRate float64 `json:"interestRate,string"`
}
// MarginInfoData stores margin info data
type MarginInfoData struct {
Data []struct {
MarginRatio string `json:"marginRatio"`
Base struct {
AssetName string `json:"assetName"`
LevelDetails []LevelDetail `json:"levelDetails"`
} `json:"base"`
Quote struct {
AssetName string `json:"assetName"`
LevelDetails []LevelDetail `json:"levelDetails"`
} `json:"quote"`
} `json:"data"`
}
// FuturesAccountBalanceData stores account balance data for futures
type FuturesAccountBalanceData struct {
AccountAlias string `json:"accountAlias"`
Asset string `json:"asset"`
Balance float64 `json:"balance,string"`
WithdrawAvailable float64 `json:"withdrawAvailable,string"`
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
CrossUnPNL float64 `json:"crossUnPNL,string"`
AvailableBalance float64 `json:"availableBalance,string"`
UpdateTime int64 `json:"updateTime"`
}
// FuturesAccountInformation stores account information for futures account
type FuturesAccountInformation struct {
Assets []struct {
Asset string `json:"asset"`
WalletBalance float64 `json:"walletBalance,string"`
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
MarginBalance float64 `json:"marginBalance,string"`
MaintMargin float64 `json:"maintMargin,string"`
InitialMargin float64 `json:"initialMargin,string"`
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
Leverage float64 `json:"leverage,string"`
Isolated bool `json:"isolated"`
PositionSide string `json:"positionSide"`
EntryPrice float64 `json:"entryPrice,string"`
MaxQty float64 `json:"maxQty,string"`
} `json:"assets"`
Positions []struct {
Symbol string `json:"symbol"`
InitialMargin float64 `json:"initialMargin,string"`
MaintMargin float64 `json:"maintMargin,string"`
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
Leverage float64 `json:"leverage,string"`
Isolated bool `json:"isolated"`
PositionSide string `json:"positionSide"`
EntryPrice float64 `json:"entryPrice,string"`
MaxQty float64 `json:"maxQty,string"`
} `json:"positions"`
CanDeposit bool `json:"canDeposit"`
CanTrade bool `json:"canTrade"`
CanWithdraw bool `json:"canWithdraw"`
FeeTier int64 `json:"feeTier"`
UpdateTime int64 `json:"updateTime"`
}
// GenericAuthResponse is a general data response for a post auth request
type GenericAuthResponse struct {
Code int64 `json:"code"`
Msg string `json:"msg"`
}
// FuturesLeverageData stores leverage data for futures
type FuturesLeverageData struct {
Leverage int64 `json:"leverage"`
MaxQty float64 `json:"maxQty,string"`
Symbol string `json:"symbol"`
}
// ModifyIsolatedMarginData stores margin modification data
type ModifyIsolatedMarginData struct {
Amount float64 `json:"amount"`
Code int64 `json:"code"`
Msg string `json:"msg"`
ModType string `json:"modType"`
}
// GetPositionMarginChangeHistoryData gets margin change history for positions
type GetPositionMarginChangeHistoryData struct {
Amount float64 `json:"amount"`
Asset string `json:"asset"`
Symbol string `json:"symbol"`
Timestamp int64 `json:"time"`
MarginChangeType int64 `json:"type"`
PositionSide string `json:"positionSide"`
}
// FuturesPositionInformation stores futures position info
type FuturesPositionInformation struct {
Symbol string `json:"symbol"`
PositionAmount float64 `json:"positionAmt,string"`
EntryPrice float64 `json:"entryPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
UnrealizedProfit float64 `json:"unRealizedProfit,string"`
LiquidationPrice float64 `json:"liquidation,string"`
Leverage int64 `json:"leverage"`
MaxQty float64 `json:"maxQty"`
MarginType string `json:"marginType"`
IsolatedMargin float64 `json:"isolatedMargin,string"`
IsAutoAddMargin bool `json:"isAutoAddMargin"`
PositionSide string `json:"positionSide"`
}
// FuturesAccountTradeList stores account trade list data
type FuturesAccountTradeList struct {
Symbol string `json:"symbol"`
ID int64 `json:"id"`
OrderID int64 `json:"orderID"`
Pair string `json:"pair"`
Side string `json:"side"`
Price string `json:"price"`
Qty float64 `json:"qty"`
RealizedPNL float64 `json:"realizedPNL"`
MarginAsset string `json:"marginAsset"`
BaseQty float64 `json:"baseQty"`
Commission float64 `json:"commission"`
CommissionAsset string `json:"commissionAsset"`
Timestamp int64 `json:"timestamp"`
PositionSide string `json:"positionSide"`
Buyer bool `json:"buyer"`
Maker bool `json:"maker"`
}
// FuturesIncomeHistoryData stores futures income history data
type FuturesIncomeHistoryData struct {
Symbol string `json:"symbol"`
IncomeType string `json:"incomeType"`
Income float64 `json:"income,string"`
Asset string `json:"asset"`
Info string `json:"info"`
Timestamp int64 `json:"time"`
}
// NotionalBracketData stores notional bracket data
type NotionalBracketData struct {
Pair string `json:"pair"`
Brackets []struct {
Bracket int64 `json:"bracket"`
InitialLeverage float64 `json:"initialLeverage"`
QtyCap float64 `json:"qtyCap"`
QtylFloor float64 `json:"qtyFloor"`
MaintMarginRatio float64 `json:"maintMarginRatio"`
}
}
// ForcedOrdersData stores forced orders data
type ForcedOrdersData struct {
OrderID int64 `json:"orderId"`
Symbol string `json:"symbol"`
Status string `json:"status"`
ClientOrderID string `json:"clientOrderId"`
Price float64 `json:"price,string"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
ExecutedQty float64 `json:"executedQty,string"`
CumQuote float64 `json:"cumQuote,string"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"orderType"`
ReduceOnly bool `json:"reduceOnly"`
ClosePosition bool `json:"closePosition"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
StopPrice float64 `json:"stopPrice,string"`
WorkingType string `json:"workingType"`
PriceProtect float64 `json:"priceProtect,string"`
OrigType string `json:"origType"`
Time int64 `json:"time"`
UpdateTime int64 `json:"updateTime"`
}
// ADLEstimateData stores data for ADL estimates
type ADLEstimateData struct {
Symbol string `json:"symbol"`
ADLQuantile struct {
Long float64 `json:"LONG"`
Short float64 `json:"SHORT"`
Hedge float64 `json:"HEDGE"`
} `json:"adlQuantile"`
}
// InterestHistoryData gets interest history data
type InterestHistoryData struct {
Asset string `json:"asset"`
Interest float64 `json:"interest"`
LendingType string `json:"lendingType"`
ProductName string `json:"productName"`
Time string `json:"time"`
}
// FundingRateData stores funding rates data
type FundingRateData struct {
Symbol string `json:"symbol"`
FundingRate float64 `json:"fundingRate,string"`
FundingTime int64 `json:"fundingTime"`
}
// SymbolsData stores perp futures' symbols
type SymbolsData struct {
Symbol string `json:"symbol"`
}
// PerpsExchangeInfo stores data for perps
type PerpsExchangeInfo struct {
Symbols []SymbolsData `json:"symbols"`
}
// UFuturesExchangeInfo stores exchange info for ufutures
type UFuturesExchangeInfo struct {
RateLimits []struct {
Interval string `json:"interval"`
IntervalNum int64 `json:"intervalNum"`
Limit int64 `json:"limit"`
RateLimitType string `json:"rateLimitType"`
} `json:"rateLimits"`
ServerTime int64 `json:"serverTime"`
Symbols []struct {
Symbol string `json:"symbol"`
Status string `json:"status"`
MaintenanceMarginPercent float64 `json:"maintMarginPercent,string"`
RequiredMarginPercent float64 `json:"requiredMarginPercent,string"`
BaseAsset string `json:"baseAsset"`
QuoteAsset string `json:"quoteAsset"`
PricePrecision int64 `json:"pricePrecision"`
QuantityPrecision int64 `json:"quantityPrecision"`
BaseAssetPrecision int64 `json:"baseAssetPrecision"`
QuotePrecision int64 `json:"quotePrecision"`
Filters []struct {
MinPrice float64 `json:"minPrice,string"`
MaxPrice float64 `json:"maxPrice,string"`
FilterType string `json:"filterType"`
TickSize float64 `json:"tickSize,string"`
StepSize float64 `json:"stepSize,string"`
MaxQty float64 `json:"maxQty,string"`
MinQty float64 `json:"minQty,string"`
Limit int64 `json:"limit"`
MultiplierDown float64 `json:"multiplierDown,string"`
MultiplierUp float64 `json:"multiplierUp,string"`
MultiplierDecimal float64 `json:"multiplierDecimal,string"`
} `json:"filters"`
OrderTypes []string `json:"orderTypes"`
TimeInForce []string `json:"timeInForce"`
} `json:"symbols"`
Timezone string `json:"timezone"`
}
// CExchangeInfo stores exchange info for cfutures
type CExchangeInfo struct {
ExchangeFilters []interface{} `json:"exchangeFilters"`
RateLimits []struct {
Interval string `json:"interval"`
IntervalNum int64 `json:"intervalNul"`
Limit int64 `json:"limit"`
RateLimitType string `json:"rateLimitType"`
} `json:"rateLimits"`
ServerTime int64 `json:"serverTime"`
Symbols []struct {
Filters []struct {
FilterType string `json:"filterType"`
MinPrice float64 `json:"minPrice,string"`
MaxPrice float64 `json:"maxPrice,string"`
StepSize float64 `json:"stepSize,string"`
MaxQty float64 `json:"maxQty,string"`
MinQty float64 `json:"minQty,string"`
Limit int64 `json:"limit"`
MultiplierDown float64 `json:"multiplierDown,string"`
MultiplierUp float64 `json:"multiplierUp,string"`
MultiplierDecimal float64 `json:"multiplierDecimal,string"`
} `json:"filters"`
OrderTypes []string `json:"orderType"`
TimeInForce []string `json:"timeInForce"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
ContractType string `json:"contractType"`
DeliveryDate int64 `json:"deliveryDate"`
OnboardDate int64 `json:"onboardDate"`
ContractStatus string `json:"contractStatus"`
ContractSize int64 `json:"contractSize"`
QuoteAsset string `json:"quoteAsset"`
BaseAsset string `json:"baseAsset"`
MarginAsset string `json:"marginAsset"`
PricePrecision int64 `json:"pricePrecision"`
QuantityPrecision int64 `json:"quantityPrecision"`
BaseAssetPrecision int64 `json:"baseAssetPrecision"`
QuotePrecision int64 `json:"quotePrecision"`
MaintMarginPercent float64 `json:"maintMarginPercent,string"`
RequiredMarginPercent float64 `json:"requiredMarginPercent,string"`
} `json:"symbols"`
Timezone string `json:"timezone"`
}

View File

@@ -6,8 +6,6 @@ import (
"time"
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)
// binanceTime provides an internal conversion helper
@@ -346,13 +344,3 @@ func (a *wsListStatus) UnmarshalJSON(data []byte) error {
a.Data.TransactionTime = aux.Data.TransactionTime.Time()
return nil
}
// formatSymbol formats the given pair to a string suitable for exchange API requests
// currently applicable to Spot and Margin assets
func (b *Binance) formatSymbol(pair currency.Pair) (string, error) {
pairFmt, err := b.GetPairFormat(asset.Spot, true)
if err != nil {
return pair.String(), err
}
return pairFmt.Format(pair), nil
}

View File

@@ -0,0 +1,411 @@
package binance
var (
validFuturesIntervals = []string{
"1m", "3m", "5m", "15m", "30m",
"1h", "2h", "4h", "6h", "8h",
"12h", "1d", "3d", "1w", "1M",
}
validContractType = []string{
"ALL", "CURRENT_QUARTER", "NEXT_QUARTER",
}
validOrderType = []string{
"LIMIT", "MARKET", "STOP", "TAKE_PROFIT",
"STOP_MARKET", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET",
}
validNewOrderRespType = []string{"ACK", "RESULT"}
validWorkingType = []string{"MARK_PRICE", "CONTRACT_TYPE"}
validPositionSide = []string{"BOTH", "LONG", "SHORT"}
validMarginType = []string{"ISOLATED", "CROSSED"}
validIncomeType = []string{"TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", "COMMISSION", "INSURANCE_CLEAR"}
validAutoCloseTypes = []string{"LIQUIDATION", "ADL"}
validMarginChange = map[string]int64{
"add": 1,
"reduce": 2,
}
uValidOBLimits = []string{"5", "10", "20", "50", "100", "500", "1000"}
uValidPeriods = []string{"5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"}
)
// USDT Margined Futures
// OrderbookData stores ob data for umargined and cmargined futures
type OrderbookData struct {
LastUpdateID int64 `json:"lastUpdateID"`
Timestamp int64 `json:"T"`
Bids [][2]string `json:"bids"`
Asks [][2]string `json:"asks"`
}
// UPublicTradesData stores trade data
type UPublicTradesData struct {
ID int64 `json:"id"`
Price float64 `json:"price,string"`
Qty float64 `json:"qty,string"`
QuoteQty float64 `json:"quoteQty,string"`
Time int64 `json:"time"`
IsBuyerMaker bool `json:"isBuyerMaker"`
}
// UCompressedTradeData stores compressed trade data
type UCompressedTradeData struct {
AggregateTradeID int64 `json:"a"`
Price float64 `json:"p,string"`
Quantity float64 `json:"q,string"`
FirstTradeID int64 `json:"f"`
LastTradeID int64 `json:"l"`
Timestamp int64 `json:"t"`
IsBuyerMaker bool `json:"m"`
}
// UMarkPrice stores mark price data
type UMarkPrice struct {
Symbol string `json:"symbol"`
MarkPrice float64 `json:"markPrice,string"`
IndexPrice float64 `json:"indexPrice,string"`
LastFundingRate float64 `json:"lastFundingRate,string"`
NextFundingTime int64 `json:"nextFundingTime"`
Time int64 `json:"time"`
}
// FundingRateHistory stores funding rate history
type FundingRateHistory struct {
Symbol string `json:"symbol"`
FundingRate float64 `json:"fundingRate,string"`
FundingTime int64 `json:"fundingTime"`
}
// U24HrPriceChangeStats stores price change stats data
type U24HrPriceChangeStats struct {
Symbol string `json:"symbol"`
PriceChange float64 `json:"priceChange,string"`
PriceChangePercent float64 `json:"priceChangePercent,string"`
WeightedAvgPrice float64 `json:"weightedAvgPrice,string"`
PrevClosePrice float64 `json:"prevClosePrice,string"`
LastPrice float64 `json:"lastPrice,string"`
LastQty float64 `json:"lastQty,string"`
OpenPrice float64 `json:"openPrice,string"`
HighPrice float64 `json:"highPrice,string"`
LowPrice float64 `json:"lowPrice,string"`
Volume float64 `json:"volume,string"`
QuoteVolume float64 `json:"quoteVolume,string"`
OpenTime int64 `json:"openTime"`
CloseTime int64 `json:"closeTime"`
FirstID int64 `json:"firstId"`
LastID int64 `json:"lastId"`
Count int64 `json:"count"`
}
// USymbolPriceTicker stores symbol price ticker data
type USymbolPriceTicker struct {
Symbol string `json:"symbol"`
Price float64 `json:"price,string"`
Time int64 `json:"time"`
}
// USymbolOrderbookTicker stores symbol orderbook ticker data
type USymbolOrderbookTicker struct {
Symbol string `json:"symbol"`
BidPrice float64 `json:"bidPrice,string"`
BidQty float64 `json:"bidQty,string"`
AskPrice float64 `json:"askPrice,string"`
AskQty float64 `json:"askQty,string"`
Time int64 `json:"time"`
}
// ULiquidationOrdersData stores liquidation orders data
type ULiquidationOrdersData struct {
Symbol string `json:"symbol"`
Price float64 `json:"price,string"`
OrigQty float64 `json:"origQty,string"`
ExecutedQty float64 `json:"executedQty,string"`
AveragePrice float64 `json:"averagePrice,string"`
Status string `json:"status"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
Side string `json:"side"`
Time int64 `json:"time"`
}
// UOpenInterestData stores open interest data
type UOpenInterestData struct {
OpenInterest float64 `json:"openInterest,string"`
Symbol string `json:"symbol"`
Time int64 `json:"time"`
}
// UOpenInterestStats stores open interest stats data
type UOpenInterestStats struct {
Symbol string `json:"symbol"`
SumOpenInterest float64 `json:"sumOpenInterest,string"`
SumOpenInterestValue float64 `json:"sumOpenInterestValue,string"`
Timestamp int64 `json:"timestamp"`
}
// ULongShortRatio stores top trader accounts' or positions' or global long/short ratio data
type ULongShortRatio struct {
Symbol string `json:"symbol"`
LongShortRatio float64 `json:"longShortRatio,string"`
LongAccount float64 `json:"longAccount,string"`
ShortAccount float64 `json:"shortAccount,string"`
Timestamp int64 `json:"timestamp"`
}
// UTakerVolumeData stores volume data on buy/sell side from takers
type UTakerVolumeData struct {
BuySellRatio float64 `json:"buySellRatio,string"`
BuyVol float64 `json:"buyVol,string"`
SellVol float64 `json:"sellVol,string"`
Timestamp int64 `json:"timestamp"`
}
// UCompositeIndexInfoData stores composite index data for usdt margined futures
type UCompositeIndexInfoData struct {
Symbol string `json:"symbol"`
Time int64 `json:"time"`
BaseAssetList []struct {
BaseAsset string `json:"baseAsset"`
WeightInQuantity float64 `json:"weightInQuantity,string"`
WeightInPercentage float64 `json:"weightInPercentage,string"`
} `json:"baseAssetList"`
}
// UOrderData stores order data
type UOrderData struct {
ClientOrderID string `json:"clientOrderId"`
CumQty float64 `json:"cumQty,string"`
CumQuote float64 `json:"cumQuote,string"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
OrigType string `json:"origType"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
Code int64 `json:"code"`
Msg string `json:"msg"`
}
// UFuturesOrderData stores order data for ufutures
type UFuturesOrderData struct {
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumQuote string `json:"cumQuote"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Time int64 `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
}
// UAccountBalanceV2Data stores account balance data for ufutures
type UAccountBalanceV2Data struct {
AccountAlias string `json:"accountAlias"`
Asset string `json:"asset"`
Balance float64 `json:"balance,string"`
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
CrossUnrealizedPNL float64 `json:"crossUnPnl,string"`
AvailableBalance float64 `json:"availableBalance,string"`
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
}
// UAccountInformationV2Data stores account info for ufutures
type UAccountInformationV2Data struct {
FeeTier int64 `json:"feeTier"`
CanTrade bool `json:"canTrade"`
CanDeposit bool `json:"canDeposit"`
CanWithdraw bool `json:"canWithdraw"`
UpdateTime int64 `json:"updateTime"`
TotalInitialMargin float64 `json:"totalInitialMargin,string"`
TotalMaintenance float64 `json:"totalMaintMargin,string"`
TotalWalletBalance float64 `json:"totalWalletBalance,string"`
TotalUnrealizedProfit float64 `json:"totalUnrealizedProfit,string"`
TotalMarginBalance float64 `json:"totalMarginBalance,string"`
TotalPositionInitialMargin float64 `json:"totalPositionInitialMargin,string"`
TotalOpenOrderInitialMargin float64 `json:"totalOpenOrderInitialMargin,string"`
TotalCrossWalletBalance float64 `json:"totalCrossWalletBalance,string"`
TotalCrossUnrealizedPNL float64 `json:"totalCrossUnPnl,string"`
AvailableBalance float64 `json:"availableBalance,string"`
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
Assets []struct {
Asset string `json:"asset"`
WalletBalance float64 `json:"walletBalance,string"`
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
MarginBalance float64 `json:"marginBalance,string"`
MaintMargin float64 `json:"maintMargin,string"`
InitialMargin float64 `json:"initialMargin,string"`
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
CrossUnPnl float64 `json:"crossUnPnl,string"`
AvailableBalance float64 `json:"availableBalance,string"`
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
} `json:"assets"`
Positions []struct {
Symbol string `json:"symbol"`
InitialMargin float64 `json:"initialMargin,string"`
MaintenanceMargin float64 `json:"maintMargin,string"`
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
Leverage float64 `json:"leverage,string"`
Isolated bool `json:"isolated"`
EntryPrice float64 `json:"entryPrice,string"`
MaxNotional float64 `json:"maxNotional,string"`
PositionSide string `json:"positionSide"`
} `json:"positions"`
}
// UChangeInitialLeverage stores leverage change data
type UChangeInitialLeverage struct {
Leverage int64 `json:"leverage"`
MaxNotionalValue float64 `json:"maxNotionalValue,string"`
Symbol string `json:"symbol"`
}
// UModifyIsolatedPosMargin stores modified isolated margin positions' data
type UModifyIsolatedPosMargin struct {
Amount float64 `json:"amount,string"`
MarginType int64 `json:"type"`
}
// UPositionMarginChangeHistoryData gets position margin change history data
type UPositionMarginChangeHistoryData struct {
Amount float64 `json:"amount,string"`
Asset string `json:"asset"`
Symbol string `json:"symbol"`
Time int64 `json:"time"`
MarginType int64 `json:"type"`
PositionSide string `json:"positionSide"`
}
// UPositionInformationV2 stores positions data
type UPositionInformationV2 struct {
EntryPrice float64 `json:"entryPrice,string"`
MarginType string `json:"marginType"`
AutoAddMarginEnabled bool `json:"isAutoAddMargin,string"`
IsolatedMargin float64 `json:"isolatedMargin,string"`
Leverage float64 `json:"leverage,string"`
LiquidationPrice float64 `json:"liquidationPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
MaxNotionalValue float64 `json:"maxNotionalValue,string"`
PositionAmount float64 `json:"positionAmt,string"`
Symbol string `json:"symbol"`
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
PositionSide string `json:"positionSide"`
}
// UAccountTradeHistory stores trade data for the users account
type UAccountTradeHistory struct {
Buyer bool `json:"buyer"`
Commission float64 `json:"commission,string"`
CommissionAsset string `json:"commissionAsset"`
ID int64 `json:"id"`
Maker bool `json:"maker"`
OrderID int64 `json:"orderId"`
Price float64 `json:"price,string"`
Qty float64 `json:"qty,string"`
QuoteQty float64 `json:"quoteQty"`
RealizedPNL float64 `json:"realizedPnl,string"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Symbol string `json:"symbol"`
Time int64 `json:"time"`
}
// UAccountIncomeHistory stores income history data
type UAccountIncomeHistory struct {
Symbol string `json:"symbol"`
IncomeType string `json:"incomeType"`
Income float64 `json:"income,string"`
Asset string `json:"asset"`
Info string `json:"info"`
Time int64 `json:"time"`
TranID int64 `json:"tranId"`
TradeID string `json:"tradeId"`
}
// UNotionalLeverageAndBrakcetsData stores notional and leverage brackets data for the account
type UNotionalLeverageAndBrakcetsData struct {
Symbol string `json:"symbol"`
Brackets []struct {
Bracket int64 `json:"bracket"`
InitialLeverage float64 `json:"initialLeverage"`
NotionalCap float64 `json:"notionalCap"`
NotionalFloor float64 `json:"notionalFloor"`
MaintenanceMarginRatio float64 `json:"maintMarginRatio"`
Cumulative float64 `json:"cum"`
} `json:"brackets"`
}
// UPositionADLEstimationData stores ADL estimation data for a position
type UPositionADLEstimationData struct {
Symbol string `json:"symbol"`
ADLQuantile struct {
Long int64 `json:"LONG"`
Short int64 `json:"SHORT"`
Hedge int64 `json:"HEDGE"`
} `json:"adlQuantile"`
}
// UForceOrdersData stores liquidation orders data for the account
type UForceOrdersData struct {
OrderID int64 `json:"orderId"`
Symbol string `json:"symbol"`
Status string `json:"status"`
ClientOrderID string `json:"clientOrderId"`
Price float64 `json:"price,string"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
ExecutedQty float64 `json:"executedQty,string"`
CumQuote float64 `json:"cumQuote,string"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ReduceOnly bool `json:"reduceOnly"`
ClosePosition bool `json:"closePosition"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
StopPrice float64 `json:"stopPrice,string"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect,string"`
OrigType string `json:"origType"`
Time int64 `json:"time"`
UpdateTime int64 `json:"updateTime"`
}