Files
gocryptotrader/exchanges/bybit/bybit_cfutures.go
Gareth Kirwan f05f24da8b Types: Switch convert.StringToFloat64 to types.Number (#1415)
* Types: Add Number type

* Types: Switch StringToFloat64 for Number

This change mostly just renames the type.
convert package and StringToFloat64 represent actions, not types,
and make it misleading to use outside of the API context,
especially when using it for a Float64ToString operation.

* Common: Remove StringToFloat64

Replaced by types.Number

* fixup! Types: Switch StringToFloat64 for Number

Second pass at Okx

* Spellcheck: Fix whitespace handling for okx line
2023-12-20 13:01:27 +11:00

1312 lines
44 KiB
Go

package bybit
import (
"context"
"math"
"net/http"
"net/url"
"strconv"
"strings"
"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"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/types"
)
const (
bybitFuturesAPIVersion = "/v2"
// public endpoint
cfuturesOrderbook = "/public/orderBook/L2"
cfuturesKline = "/public/kline/list"
cfuturesSymbolPriceTicker = "/public/tickers"
cfuturesRecentTrades = "/public/trading-records"
cfuturesSymbolInfo = "/public/symbols"
cfuturesMarkPriceKline = "/public/mark-price-kline"
cfuturesIndexKline = "/public/index-price-kline"
cfuturesIndexPremiumKline = "/public/premium-index-kline"
cfuturesOpenInterest = "/public/open-interest"
cfuturesBigDeal = "/public/big-deal"
cfuturesAccountRatio = "/public/account-ratio"
cfuturesGetRiskLimit = "/public/risk-limit/list"
cfuturesGetLastFundingRate = "/public/funding/prev-funding-rate"
cfuturesGetServerTime = "/public/time"
cfuturesGetAnnouncement = "/public/announcement"
// auth endpoint
cfuturesCreateOrder = "/private/order/create"
cfuturesGetActiveOrders = "/private/order/list"
cfuturesCancelActiveOrder = "/private/order/cancel"
cfuturesCancelAllActiveOrders = "/private/order/cancelAll"
cfuturesReplaceActiveOrder = "/private/order/replace"
cfuturesGetActiveRealtimeOrders = "/private/order"
cfuturesCreateConditionalOrder = "/private/stop-order/create"
cfuturesGetConditionalOrders = "/private/stop-order/list"
cfuturesCancelConditionalOrder = "/private/stop-order/cancel"
cfuturesCancelAllConditionalOrders = "/private/stop-order/cancelAll"
cfuturesReplaceConditionalOrder = "/private/stop-order/replace"
cfuturesGetConditionalRealtimeOrders = "/private/stop-order"
cfuturesPosition = "/private/position/list"
cfuturesUpdateMargin = "/private/position/change-position-margin"
cfuturesSetTrading = "/private/position/trading-stop"
cfuturesSetLeverage = "/private/position/leverage/save"
cfuturesGetTrades = "/private/execution/list"
cfuturesGetClosedTrades = "/private/trade/closed-pnl/list"
cfuturesSwitchPosition = "/private/tpsl/switch-mode"
cfuturesSwitchMargin = "/private/position/switch-isolated"
cfuturesGetTradingFeeRate = "/private/position/fee-rate"
cfuturesSetRiskLimit = "/private/position/risk-limit"
cfuturesGetMyLastFundingFee = "/private/funding/prev-funding"
cfuturesPredictFundingRate = "/private/funding/predicted-funding"
cfuturesGetAPIKeyInfo = "/private/account/api-key"
cfuturesGetLiquidityContributionPoints = "/private/account/lcp"
cfuturesGetWalletBalance = "/private/wallet/balance"
cfuturesGetWalletFundRecords = "/private/wallet/fund/records"
cfuturesGetWalletWithdrawalRecords = "/private/wallet/withdraw/list"
cfuturesGetAssetExchangeRecords = "/private/exchange-order/list"
)
// GetFuturesOrderbook gets orderbook data for CoinMarginedFutures.
func (by *Bybit) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair) (*Orderbook, error) {
var resp Orderbook
data := struct {
Result []OrderbookData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return nil, err
}
params.Set("symbol", symbolValue)
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesOrderbook, params)
err = by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &data)
if err != nil {
return nil, err
}
for x := range data.Result {
switch data.Result[x].Side {
case sideBuy:
resp.Bids = append(resp.Bids, orderbook.Item{
Price: data.Result[x].Price.Float64(),
Amount: data.Result[x].Size,
})
case sideSell:
resp.Asks = append(resp.Asks, orderbook.Item{
Price: data.Result[x].Price.Float64(),
Amount: data.Result[x].Size,
})
default:
return nil, errInvalidSide
}
}
return &resp, nil
}
// GetFuturesKlineData gets futures kline data for CoinMarginedFutures.
func (by *Bybit) GetFuturesKlineData(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime time.Time) ([]FuturesCandleStickWithStringParam, error) {
resp := struct {
Data []FuturesCandleStickWithStringParam `json:"result"`
Error
}{}
params := url.Values{}
if symbol.IsEmpty() {
return resp.Data, errSymbolMissing
}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesIntervals, interval) {
return resp.Data, errInvalidInterval
}
if startTime.IsZero() {
return nil, errInvalidStartTime
}
params.Set("interval", interval)
params.Set("from", strconv.FormatInt(startTime.Unix(), 10))
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesKline, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetFuturesSymbolPriceTicker gets price ticker for symbol.
func (by *Bybit) GetFuturesSymbolPriceTicker(ctx context.Context, symbol currency.Pair) ([]SymbolPriceTicker, error) {
resp := struct {
Data []SymbolPriceTicker `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesSymbolPriceTicker, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetPublicTrades gets past public trades for CoinMarginedFutures.
func (by *Bybit) GetPublicTrades(ctx context.Context, symbol currency.Pair, limit int64) ([]FuturesPublicTradesData, error) {
resp := struct {
Data []FuturesPublicTradesData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesRecentTrades, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetSymbolsInfo gets all symbol pair information for CoinMarginedFutures.
func (by *Bybit) GetSymbolsInfo(ctx context.Context) ([]SymbolInfo, error) {
resp := struct {
Data []SymbolInfo `json:"result"`
Error
}{}
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, bybitFuturesAPIVersion+cfuturesSymbolInfo, publicFuturesRate, &resp)
}
// GetMarkPriceKline gets mark price kline data
func (by *Bybit) GetMarkPriceKline(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime time.Time) ([]MarkPriceKlineData, error) {
resp := struct {
Data []MarkPriceKlineData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesIntervals, interval) {
return resp.Data, errInvalidInterval
}
params.Set("interval", interval)
if startTime.IsZero() {
return resp.Data, errInvalidStartTime
}
params.Set("from", strconv.FormatInt(startTime.Unix(), 10))
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesMarkPriceKline, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetIndexPriceKline gets index price kline data
func (by *Bybit) GetIndexPriceKline(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime time.Time) ([]IndexPriceKlineData, error) {
resp := struct {
Data []IndexPriceKlineData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesIntervals, interval) {
return resp.Data, errInvalidInterval
}
params.Set("interval", interval)
if startTime.IsZero() {
return resp.Data, errInvalidStartTime
}
params.Set("from", strconv.FormatInt(startTime.Unix(), 10))
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesIndexKline, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetPremiumIndexPriceKline gets premium index price kline data
func (by *Bybit) GetPremiumIndexPriceKline(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime time.Time) ([]IndexPriceKlineData, error) {
resp := struct {
Data []IndexPriceKlineData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesIntervals, interval) {
return resp.Data, errInvalidInterval
}
params.Set("interval", interval)
if startTime.IsZero() {
return resp.Data, errInvalidStartTime
}
params.Set("from", strconv.FormatInt(startTime.Unix(), 10))
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesIndexPremiumKline, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetOpenInterest gets open interest data for a symbol.
func (by *Bybit) GetOpenInterest(ctx context.Context, symbol currency.Pair, period string, limit int64) ([]OpenInterestData, error) {
resp := struct {
Data []OpenInterestData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesPeriods, period) {
return resp.Data, errInvalidPeriod
}
params.Set("period", period)
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesOpenInterest, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetLatestBigDeal gets filled orders worth more than 500,000 USD within the last 24h for symbol.
func (by *Bybit) GetLatestBigDeal(ctx context.Context, symbol currency.Pair, limit int64) ([]BigDealData, error) {
resp := struct {
Data []BigDealData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesBigDeal, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetAccountRatio gets user accounts long-short ratio.
func (by *Bybit) GetAccountRatio(ctx context.Context, symbol currency.Pair, period string, limit int64) ([]AccountRatioData, error) {
resp := struct {
Data []AccountRatioData `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if !common.StringDataCompare(validFuturesPeriods, period) {
return resp.Data, errInvalidPeriod
}
params.Set("period", period)
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesAccountRatio, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetRiskLimit returns risk limit
func (by *Bybit) GetRiskLimit(ctx context.Context, symbol currency.Pair) ([]RiskInfoWithStringParam, error) {
resp := struct {
Data []RiskInfoWithStringParam `json:"result"`
Error
}{}
params := url.Values{}
if !symbol.IsEmpty() {
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
}
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesGetRiskLimit, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetLastFundingRate returns latest generated funding fee
func (by *Bybit) GetLastFundingRate(ctx context.Context, symbol currency.Pair) (FundingInfo, error) {
resp := struct {
Data FundingInfo `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
path := common.EncodeURLValues(bybitFuturesAPIVersion+cfuturesGetLastFundingRate, params)
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, path, publicFuturesRate, &resp)
}
// GetFuturesServerTime returns Bybit server time in seconds
func (by *Bybit) GetFuturesServerTime(ctx context.Context) (time.Time, error) {
resp := struct {
TimeNow types.Number `json:"time_now"`
Error
}{}
err := by.SendHTTPRequest(ctx, exchange.RestCoinMargined, bybitFuturesAPIVersion+cfuturesGetServerTime, publicFuturesRate, &resp)
if err != nil {
return time.Time{}, err
}
sec, dec := math.Modf(resp.TimeNow.Float64())
return time.Unix(int64(sec), int64(dec*(1e9))), nil
}
// GetAnnouncement returns announcements in the last 30 days in reverse order
func (by *Bybit) GetAnnouncement(ctx context.Context) ([]AnnouncementInfo, error) {
resp := struct {
Data []AnnouncementInfo `json:"result"`
Error
}{}
return resp.Data, by.SendHTTPRequest(ctx, exchange.RestCoinMargined, bybitFuturesAPIVersion+cfuturesGetAnnouncement, publicFuturesRate, &resp)
}
// CreateCoinFuturesOrder sends a new futures order to the exchange
func (by *Bybit) CreateCoinFuturesOrder(ctx context.Context, symbol currency.Pair, side, orderType, timeInForce,
orderLinkID, takeProfitTriggerBy, stopLossTriggerBy string,
quantity, price, takeProfit, stopLoss float64, closeOnTrigger, reduceOnly bool) (FuturesOrderDataResp, error) {
resp := struct {
Data FuturesOrderDataResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
params.Set("side", side)
params.Set("order_type", orderType)
if quantity <= 0 {
return resp.Data, errInvalidQuantity
}
params.Set("qty", strconv.FormatFloat(quantity, 'f', -1, 64))
if price != 0 {
params.Set("price", strconv.FormatFloat(price, 'f', -1, 64))
}
if timeInForce == "" {
return resp.Data, errInvalidTimeInForce
}
params.Set("time_in_force", timeInForce)
if closeOnTrigger {
params.Set("close_on_trigger", "true")
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if takeProfit != 0 {
params.Set("take_profit", strconv.FormatFloat(takeProfit, 'f', -1, 64))
}
if stopLoss != 0 {
params.Set("stop_loss", strconv.FormatFloat(stopLoss, 'f', -1, 64))
}
if takeProfitTriggerBy != "" {
params.Set("tp_trigger_by", takeProfitTriggerBy)
}
if stopLossTriggerBy != "" {
params.Set("sl_trigger_by", stopLossTriggerBy)
}
if reduceOnly {
params.Set("reduce_only", "true")
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCreateOrder, params, nil, &resp, cFuturesCreateOrderRate)
}
// GetActiveCoinFuturesOrders gets list of futures active orders
func (by *Bybit) GetActiveCoinFuturesOrders(ctx context.Context, symbol currency.Pair, orderStatus, direction, cursor string, limit int64) ([]FuturesActiveOrderResp, error) {
resp := struct {
Result struct {
Data []FuturesActiveOrderResp `json:"data"`
Cursor string `json:"cursor"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Result.Data, err
}
params.Set("symbol", symbolValue)
if orderStatus != "" {
params.Set("order_status", orderStatus)
}
if direction != "" {
params.Set("direction", direction)
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if cursor != "" {
params.Set("cursor", cursor)
}
return resp.Result.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetActiveOrders, params, nil, &resp, cFuturesGetActiveOrderRate)
}
// CancelActiveCoinFuturesOrders cancels futures unfilled or partially filled orders
func (by *Bybit) CancelActiveCoinFuturesOrders(ctx context.Context, symbol currency.Pair, orderID, orderLinkID string) (FuturesOrderDataResp, error) {
resp := struct {
Data FuturesOrderDataResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if orderID == "" && orderLinkID == "" {
return resp.Data, errOrderOrOrderLinkIDMissing
}
if orderID != "" {
params.Set("order_id", orderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCancelActiveOrder, params, nil, &resp, cFuturesCancelActiveOrderRate)
}
// CancelAllActiveCoinFuturesOrders cancels all futures unfilled or partially filled orders
func (by *Bybit) CancelAllActiveCoinFuturesOrders(ctx context.Context, symbol currency.Pair) ([]FuturesOrderDataResp, error) {
resp := struct {
Data []FuturesOrderDataResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCancelAllActiveOrders, params, nil, &resp, cFuturesCancelAllActiveOrderRate)
}
// ReplaceActiveCoinFuturesOrders modify unfilled or partially filled orders
func (by *Bybit) ReplaceActiveCoinFuturesOrders(ctx context.Context, symbol currency.Pair, orderID, orderLinkID, takeProfitTriggerBy, stopLossTriggerBy string,
updatedQty int64, updatedPrice, takeProfitPrice, stopLossPrice float64) (string, error) {
resp := struct {
Data struct {
OrderID string `json:"order_id"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return "", err
}
params.Set("symbol", symbolValue)
if orderID == "" && orderLinkID == "" {
return "", errOrderOrOrderLinkIDMissing
}
if orderID != "" {
params.Set("order_id", orderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if updatedQty != 0 {
params.Set("p_r_qty", strconv.FormatInt(updatedQty, 10))
}
if updatedPrice != 0 {
params.Set("p_r_price", strconv.FormatFloat(updatedPrice, 'f', -1, 64))
}
if takeProfitPrice != 0 {
params.Set("take_profit", strconv.FormatFloat(takeProfitPrice, 'f', -1, 64))
}
if stopLossPrice != 0 {
params.Set("stop_loss", strconv.FormatFloat(stopLossPrice, 'f', -1, 64))
}
if takeProfitTriggerBy != "" {
params.Set("tp_trigger_by", takeProfitTriggerBy)
}
if stopLossTriggerBy != "" {
params.Set("sl_trigger_by", stopLossTriggerBy)
}
return resp.Data.OrderID, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesReplaceActiveOrder, params, nil, &resp, cFuturesReplaceActiveOrderRate)
}
// GetActiveRealtimeCoinOrders query real time order data
func (by *Bybit) GetActiveRealtimeCoinOrders(ctx context.Context, symbol currency.Pair, orderID, orderLinkID string) ([]FuturesActiveRealtimeOrder, error) {
var data []FuturesActiveRealtimeOrder
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return data, err
}
params.Set("symbol", symbolValue)
if orderID != "" {
params.Set("order_id", orderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if orderID == "" && orderLinkID == "" {
resp := struct {
Data []FuturesActiveRealtimeOrder `json:"result"`
Error
}{}
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetActiveRealtimeOrders, params, nil, &resp, cFuturesGetRealtimeOrderRate)
if err != nil {
return data, err
}
data = append(data, resp.Data...)
} else {
resp := struct {
Data FuturesActiveRealtimeOrder `json:"result"`
Error
}{}
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetActiveRealtimeOrders, params, nil, &resp, cFuturesGetRealtimeOrderRate)
if err != nil {
return data, err
}
data = append(data, resp.Data)
}
return data, nil
}
// CreateConditionalCoinFuturesOrder sends a new conditional futures order to the exchange
func (by *Bybit) CreateConditionalCoinFuturesOrder(ctx context.Context, symbol currency.Pair, side, orderType, timeInForce,
orderLinkID, takeProfitTriggerBy, stopLossTriggerBy, triggerBy string,
quantity, price, takeProfit, stopLoss, basePrice, stopPrice float64, closeOnTrigger bool) (FuturesConditionalOrderResp, error) {
resp := struct {
Data FuturesConditionalOrderResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
params.Set("side", side)
params.Set("order_type", orderType)
if quantity <= 0 {
return resp.Data, errInvalidQuantity
}
params.Set("qty", strconv.FormatFloat(quantity, 'f', -1, 64))
if price != 0 {
params.Set("price", strconv.FormatFloat(price, 'f', -1, 64))
}
if basePrice <= 0 {
return resp.Data, errInvalidBasePrice
}
params.Set("base_price", strconv.FormatFloat(basePrice, 'f', -1, 64))
if stopPrice <= 0 {
return resp.Data, errInvalidStopPrice
}
params.Set("stop_px", strconv.FormatFloat(stopPrice, 'f', -1, 64))
if timeInForce == "" {
return resp.Data, errInvalidTimeInForce
}
params.Set("time_in_force", timeInForce)
if triggerBy != "" {
params.Set("trigger_by", triggerBy)
}
if closeOnTrigger {
params.Set("close_on_trigger", "true")
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if takeProfit != 0 {
params.Set("take_profit", strconv.FormatFloat(takeProfit, 'f', -1, 64))
}
if stopLoss != 0 {
params.Set("stop_loss", strconv.FormatFloat(stopLoss, 'f', -1, 64))
}
if takeProfitTriggerBy != "" {
params.Set("tp_trigger_by", takeProfitTriggerBy)
}
if stopLossTriggerBy != "" {
params.Set("sl_trigger_by", stopLossTriggerBy)
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCreateConditionalOrder, params, nil, &resp, cFuturesCreateConditionalOrderRate)
}
// GetConditionalCoinFuturesOrders gets list of futures conditional orders
func (by *Bybit) GetConditionalCoinFuturesOrders(ctx context.Context, symbol currency.Pair, stopOrderStatus, direction, cursor string, limit int64) ([]CoinFuturesConditionalOrders, error) {
resp := struct {
Result struct {
Data []CoinFuturesConditionalOrders `json:"data"`
Cursor string `json:"cursor"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Result.Data, err
}
params.Set("symbol", symbolValue)
if stopOrderStatus != "" {
params.Set("stop_order_status", stopOrderStatus)
}
if direction != "" {
params.Set("direction", direction)
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if cursor != "" {
params.Set("cursor", cursor)
}
return resp.Result.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetConditionalOrders, params, nil, &resp, cFuturesGetConditionalOrderRate)
}
// CancelConditionalCoinFuturesOrders cancels untriggered conditional orders
func (by *Bybit) CancelConditionalCoinFuturesOrders(ctx context.Context, symbol currency.Pair, stopOrderID, orderLinkID string) (string, error) {
resp := struct {
Data struct {
StopOrderID string `json:"stop_order_id"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return "", err
}
params.Set("symbol", symbolValue)
if stopOrderID == "" && orderLinkID == "" {
return "", errStopOrderOrOrderLinkIDMissing
}
if stopOrderID != "" {
params.Set("stop_order_id", stopOrderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
return resp.Data.StopOrderID, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCancelConditionalOrder, params, nil, &resp, cFuturesCancelConditionalOrderRate)
}
// CancelAllConditionalCoinFuturesOrders cancels all untriggered conditional orders
func (by *Bybit) CancelAllConditionalCoinFuturesOrders(ctx context.Context, symbol currency.Pair) ([]FuturesCancelOrderResp, error) {
resp := struct {
Data []FuturesCancelOrderResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesCancelAllConditionalOrders, params, nil, &resp, cFuturesCancelAllConditionalOrderRate)
}
// ReplaceConditionalCoinFuturesOrders modify unfilled or partially filled conditional orders
func (by *Bybit) ReplaceConditionalCoinFuturesOrders(ctx context.Context, symbol currency.Pair, stopOrderID, orderLinkID, takeProfitTriggerBy, stopLossTriggerBy string,
updatedQty, updatedPrice, takeProfitPrice, stopLossPrice, orderTriggerPrice float64) (string, error) {
resp := struct {
Data struct {
OrderID string `json:"stop_order_id"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return "", err
}
params.Set("symbol", symbolValue)
if stopOrderID == "" && orderLinkID == "" {
return "", errStopOrderOrOrderLinkIDMissing
}
if stopOrderID != "" {
params.Set("stop_order_id", stopOrderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if updatedQty != 0 {
params.Set("p_r_qty", strconv.FormatFloat(updatedQty, 'f', -1, 64))
}
if updatedPrice != 0 {
params.Set("p_r_price", strconv.FormatFloat(updatedPrice, 'f', -1, 64))
}
if orderTriggerPrice != 0 {
params.Set("p_r_trigger_price", strconv.FormatFloat(orderTriggerPrice, 'f', -1, 64))
}
if takeProfitPrice != 0 {
params.Set("take_profit", strconv.FormatFloat(takeProfitPrice, 'f', -1, 64))
}
if stopLossPrice != 0 {
params.Set("stop_loss", strconv.FormatFloat(stopLossPrice, 'f', -1, 64))
}
if takeProfitTriggerBy != "" {
params.Set("tp_trigger_by", takeProfitTriggerBy)
}
if stopLossTriggerBy != "" {
params.Set("sl_trigger_by", stopLossTriggerBy)
}
return resp.Data.OrderID, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesReplaceConditionalOrder, params, nil, &resp, cFuturesReplaceConditionalOrderRate)
}
// GetConditionalRealtimeCoinOrders query real time conditional order data
func (by *Bybit) GetConditionalRealtimeCoinOrders(ctx context.Context, symbol currency.Pair, stopOrderID, orderLinkID string) ([]CoinFuturesConditionalRealtimeOrder, error) {
var data []CoinFuturesConditionalRealtimeOrder
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return data, err
}
params.Set("symbol", symbolValue)
if stopOrderID != "" {
params.Set("stop_order_id", stopOrderID)
}
if orderLinkID != "" {
params.Set("order_link_id", orderLinkID)
}
if stopOrderID == "" && orderLinkID == "" {
resp := struct {
Data []CoinFuturesConditionalRealtimeOrder `json:"result"`
Error
}{}
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetConditionalRealtimeOrders, params, nil, &resp, cFuturesDefaultRate)
if err != nil {
return data, err
}
data = append(data, resp.Data...)
} else {
resp := struct {
Data CoinFuturesConditionalRealtimeOrder `json:"result"`
Error
}{}
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetConditionalRealtimeOrders, params, nil, &resp, cFuturesDefaultRate)
if err != nil {
return data, err
}
data = append(data, resp.Data)
}
return data, nil
}
// GetCoinPositions returns list of user positions
func (by *Bybit) GetCoinPositions(ctx context.Context, symbol currency.Pair) ([]PositionResp, error) {
var data []PositionResp
params := url.Values{}
if !symbol.IsEmpty() {
resp := struct {
Data PositionResp `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return data, err
}
params.Set("symbol", symbolValue)
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesPosition, params, nil, &resp, cFuturesPositionRate)
if err != nil {
return data, err
}
data = append(data, resp.Data)
} else {
resp := struct {
Data []PositionResp `json:"result"`
Error
}{}
err := by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesPosition, params, nil, &resp, cFuturesPositionRate)
if err != nil {
return data, err
}
data = append(data, resp.Data...)
}
return data, nil
}
// SetCoinMargin updates margin
func (by *Bybit) SetCoinMargin(ctx context.Context, symbol currency.Pair, margin string) (float64, error) {
resp := struct {
Data float64 `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if margin == "" {
return resp.Data, errInvalidMargin
}
params.Set("margin", margin)
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesUpdateMargin, params, nil, &resp, cFuturesUpdateMarginRate)
}
// SetCoinTradingAndStop sets take profit, stop loss, and trailing stop for your open position
func (by *Bybit) SetCoinTradingAndStop(ctx context.Context, symbol currency.Pair, takeProfit, stopLoss, trailingStop, newTrailingActive, stopLossQty, takeProfitQty float64, takeProfitTriggerBy, stopLossTriggerBy string) (SetTradingAndStopResp, error) {
resp := struct {
Data SetTradingAndStopResp `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if takeProfit >= 0 {
params.Set("take_profit", strconv.FormatFloat(takeProfit, 'f', -1, 64))
}
if stopLoss >= 0 {
params.Set("stop_loss", strconv.FormatFloat(stopLoss, 'f', -1, 64))
}
if trailingStop >= 0 {
params.Set("trailing_stop", strconv.FormatFloat(trailingStop, 'f', -1, 64))
}
if newTrailingActive != 0 {
params.Set("new_trailing_active", strconv.FormatFloat(newTrailingActive, 'f', -1, 64))
}
if stopLossQty != 0 {
params.Set("sl_size", strconv.FormatFloat(stopLossQty, 'f', -1, 64))
}
if takeProfitQty != 0 {
params.Set("tp_size", strconv.FormatFloat(takeProfitQty, 'f', -1, 64))
}
if takeProfitTriggerBy != "" {
params.Set("tp_trigger_by", takeProfitTriggerBy)
}
if stopLossTriggerBy != "" {
params.Set("sl_trigger_by", stopLossTriggerBy)
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesSetTrading, params, nil, &resp, cFuturesDefaultRate)
}
// SetCoinLeverage sets leverage
func (by *Bybit) SetCoinLeverage(ctx context.Context, symbol currency.Pair, leverage float64, leverageOnly bool) (float64, error) {
resp := struct {
Data float64 `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
if leverage <= 0 {
return resp.Data, errInvalidLeverage
}
params.Set("leverage", strconv.FormatFloat(leverage, 'f', -1, 64))
if leverageOnly {
params.Set("leverage_only", "true")
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesSetLeverage, params, nil, &resp, cFuturesSetLeverageRate)
}
// GetCoinTradeRecords returns list of user trades
func (by *Bybit) GetCoinTradeRecords(ctx context.Context, symbol currency.Pair, orderID, order string, startTime, page, limit int64) ([]TradeResp, error) {
params := url.Values{}
resp := struct {
Data struct {
OrderID string `json:"order_id"`
Trades []TradeResp `json:"trade_list"`
} `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.Trades, err
}
params.Set("symbol", symbolValue)
if orderID != "" {
params.Set("order_id", orderID)
}
if order != "" {
params.Set("order", order)
}
if startTime != 0 {
params.Set("start_time", strconv.FormatInt(startTime, 10))
}
if page != 0 {
params.Set("page", strconv.FormatInt(page, 10))
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
return resp.Data.Trades, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetTrades, params, nil, &resp, cFuturesTradeRate)
}
// GetClosedCoinTrades returns closed profit and loss records
func (by *Bybit) GetClosedCoinTrades(ctx context.Context, symbol currency.Pair, executionType string, startTime, endTime time.Time, page, limit int64) ([]ClosedTrades, error) {
params := url.Values{}
resp := struct {
Data struct {
CurrentPage int64 `json:"current_page"`
Trades []ClosedTrades `json:"data"`
} `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.Trades, err
}
params.Set("symbol", symbolValue)
if executionType != "" {
params.Set("execution_type", executionType)
}
if !startTime.IsZero() {
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
}
if !endTime.IsZero() {
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
}
if page > 0 && page <= 50 {
params.Set("page", strconv.FormatInt(page, 10))
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
return resp.Data.Trades, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetClosedTrades, params, nil, &resp, cFuturesDefaultRate)
}
// ChangeCoinMode switches mode between full or partial position
func (by *Bybit) ChangeCoinMode(ctx context.Context, symbol currency.Pair, takeProfitStopLoss string) (string, error) {
resp := struct {
Data struct {
Mode string `json:"tp_sl_mode"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.Mode, err
}
params.Set("symbol", symbolValue)
if takeProfitStopLoss == "" {
return resp.Data.Mode, errInvalidTakeProfitStopLoss
}
params.Set("tp_sl_mode", takeProfitStopLoss)
return resp.Data.Mode, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesSwitchPosition, params, nil, &resp, cFuturesSwitchPositionRate)
}
// ChangeCoinMargin switches margin between cross or isolated
func (by *Bybit) ChangeCoinMargin(ctx context.Context, symbol currency.Pair, buyLeverage, sellLeverage float64, isIsolated bool) error {
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return err
}
params.Set("symbol", symbolValue)
params.Set("buy_leverage", strconv.FormatFloat(buyLeverage, 'f', -1, 64))
params.Set("sell_leverage", strconv.FormatFloat(sellLeverage, 'f', -1, 64))
if isIsolated {
params.Set("is_isolated", "true")
} else {
params.Set("is_isolated", "false")
}
return by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesSwitchMargin, params, nil, nil, cFuturesDefaultRate)
}
// GetTradingFeeRate returns trading taker and maker fee rate
func (by *Bybit) GetTradingFeeRate(ctx context.Context, symbol currency.Pair) (*CFuturesTradingFeeRate, error) {
params := url.Values{}
resp := struct {
Result *CFuturesTradingFeeRate `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return nil, err
}
params.Set("symbol", symbolValue)
return resp.Result,
by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetTradingFeeRate, params, nil, &resp, cFuturesGetTradingFeeRate)
}
// SetCoinRiskLimit sets risk limit
func (by *Bybit) SetCoinRiskLimit(ctx context.Context, symbol currency.Pair, riskID int64) (int64, error) {
resp := struct {
Data struct {
RiskID int64 `json:"risk_id"`
} `json:"result"`
Error
}{}
params := url.Values{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.RiskID, err
}
params.Set("symbol", symbolValue)
if riskID <= 0 {
return resp.Data.RiskID, errInvalidRiskID
}
params.Set("risk_id", strconv.FormatInt(riskID, 10))
return resp.Data.RiskID, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodPost, bybitFuturesAPIVersion+cfuturesSetRiskLimit, params, nil, &resp, cFuturesDefaultRate)
}
// GetCoinLastFundingFee returns last funding fees
func (by *Bybit) GetCoinLastFundingFee(ctx context.Context, symbol currency.Pair) (FundingFee, error) {
params := url.Values{}
resp := struct {
Data FundingFee `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data, err
}
params.Set("symbol", symbolValue)
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetMyLastFundingFee, params, nil, &resp, cFuturesLastFundingFeeRate)
}
// GetCoinPredictedFundingRate returns predicted funding rates and fees
func (by *Bybit) GetCoinPredictedFundingRate(ctx context.Context, symbol currency.Pair) (fundingRate, fundingFee float64, err error) {
params := url.Values{}
resp := struct {
Data struct {
PredictedFundingRate float64 `json:"predicted_funding_rate"`
PredictedFundingFee float64 `json:"predicted_funding_fee"`
} `json:"result"`
Error
}{}
var symbolValue string
symbolValue, err = by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.PredictedFundingRate, resp.Data.PredictedFundingFee, err
}
params.Set("symbol", symbolValue)
err = by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesPredictFundingRate, params, nil, &resp, cFuturesPredictFundingRate)
fundingRate = resp.Data.PredictedFundingRate
fundingFee = resp.Data.PredictedFundingFee
return
}
// GetAPIKeyInfo returns user API Key information
func (by *Bybit) GetAPIKeyInfo(ctx context.Context) ([]APIKeyData, error) {
params := url.Values{}
resp := struct {
Data []APIKeyData `json:"result"`
Error
}{}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetAPIKeyInfo, params, nil, &resp, cFuturesAPIKeyInfoRate)
}
// GetLiquidityContributionPointsInfo returns latest LCP information
func (by *Bybit) GetLiquidityContributionPointsInfo(ctx context.Context, symbol currency.Pair) ([]LCPData, error) {
params := url.Values{}
resp := struct {
Data struct {
LCPList []LCPData `json:"lcp_list"`
} `json:"result"`
Error
}{}
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp.Data.LCPList, err
}
params.Set("symbol", symbolValue)
return resp.Data.LCPList, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetLiquidityContributionPoints, params, nil, &resp, cFuturesDefaultRate)
}
// GetFutureWalletBalance returns wallet balance
func (by *Bybit) GetFutureWalletBalance(ctx context.Context, coin string) (map[string]WalletData, error) {
params := url.Values{}
resp := struct {
Wallets map[string]WalletData `json:"result"`
Error
}{}
if coin != "" {
params.Set("coin", coin)
}
return resp.Wallets, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetWalletBalance, params, nil, &resp, cFuturesWalletBalanceRate)
}
// GetWalletFundRecords returns wallet fund records
func (by *Bybit) GetWalletFundRecords(ctx context.Context, startDate, endDate, currency, coin, walletFundType string, page, limit int64) ([]FundRecord, error) {
params := url.Values{}
resp := struct {
Data struct {
Records []FundRecord `json:"data"`
} `json:"result"`
Error
}{}
if startDate != "" {
params.Set("start_date", startDate)
}
if endDate != "" {
params.Set("end_date", endDate)
}
if currency != "" {
params.Set("currency", currency)
}
if coin != "" {
params.Set("coin", coin)
}
if walletFundType != "" {
params.Set("wallet_fund_type", walletFundType)
}
if page != 0 {
params.Set("page", strconv.FormatInt(page, 10))
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
return resp.Data.Records, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetWalletFundRecords, params, nil, &resp, cFuturesWalletFundRecordRate)
}
// GetWalletWithdrawalRecords returns wallet withdrawal records
func (by *Bybit) GetWalletWithdrawalRecords(ctx context.Context, startDate, endDate, status string, coin currency.Code, page, limit int64) ([]FundWithdrawalRecord, error) {
params := url.Values{}
resp := struct {
Data struct {
Records []FundWithdrawalRecord `json:"data"`
} `json:"result"`
Error
}{}
if startDate != "" {
params.Set("start_date", startDate)
}
if endDate != "" {
params.Set("end_date", endDate)
}
if !coin.IsEmpty() {
params.Set("coin", strings.ToUpper(coin.String()))
}
if status != "" {
params.Set("status", status)
}
if page != 0 {
params.Set("page", strconv.FormatInt(page, 10))
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
return resp.Data.Records, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetWalletWithdrawalRecords, params, nil, &resp, cFuturesWalletWithdrawalRate)
}
// GetAssetExchangeRecords returns wallet asset exchange records
func (by *Bybit) GetAssetExchangeRecords(ctx context.Context, direction string, from, limit int64) ([]AssetExchangeRecord, error) {
params := url.Values{}
resp := struct {
Data []AssetExchangeRecord `json:"result"`
Error
}{}
if direction != "" {
params.Set("direction", direction)
}
if from != 0 {
params.Set("from", strconv.FormatInt(from, 10))
}
if limit > 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
return resp.Data, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetAssetExchangeRecords, params, nil, &resp, cFuturesDefaultRate)
}