mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-22 07:26:50 +00:00
bybit: assortment of updates (#1192)
* bybit: cherry-pickable * bybit: implement fee fetching v5 * bybit: update to use nullable type * bybit: fix some tests * bybit: spell check fix * remove redunant asset dec, and rm output * rm comment code * linter: fixerinos woooo * bybit: constrict rate limit on public spot to v5 * exchanges/bybit/limits: update (CHERRY PICK ME) * glorious: nIIIIIIIIIIIIIIITS * glorious: nits continued * updated comment * update even more * RM LINE! * glorious: nits * Update exchanges/sharedtestvalues/sharedtestvalues.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * fix --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
@@ -10,6 +12,10 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
const jsonStringIdent = `"` // immutable byte sequence
|
||||
|
||||
var errUnhandledType = errors.New("unhandled type")
|
||||
|
||||
// FloatFromString format
|
||||
func FloatFromString(raw interface{}) (float64, error) {
|
||||
str, ok := raw.(string)
|
||||
@@ -187,3 +193,36 @@ func InterfaceToStringOrZeroValue(r interface{}) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringToFloat64 is a float64 that unmarshals from a string. This is useful
|
||||
// for APIs that return numbers as strings and return an empty string instead of
|
||||
// 0.
|
||||
type StringToFloat64 float64
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
// This implementation is slightly more performant than calling json.Unmarshal
|
||||
// again.
|
||||
func (f *StringToFloat64) UnmarshalJSON(data []byte) error {
|
||||
if !bytes.HasPrefix(data, []byte(jsonStringIdent)) {
|
||||
return fmt.Errorf("%w: %s", errUnhandledType, string(data))
|
||||
}
|
||||
|
||||
data = data[1 : len(data)-1] // Remove quotes
|
||||
if len(data) == 0 {
|
||||
*f = StringToFloat64(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
val, err := strconv.ParseFloat(string(data), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*f = StringToFloat64(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64 returns the float64 value of the FloatString.
|
||||
func (f *StringToFloat64) Float64() float64 {
|
||||
return float64(*f)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -315,3 +317,54 @@ func TestInterfaceToStringOrZeroValue(t *testing.T) {
|
||||
t.Errorf("expected meow, got: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToFloat64(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp := struct {
|
||||
Data StringToFloat64 `json:"data"`
|
||||
}{}
|
||||
|
||||
err := json.Unmarshal([]byte(`{"data":"0.00000001"}`), &resp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if resp.Data.Float64() != 1e-8 {
|
||||
t.Fatalf("expected 1e-8, got %v", resp.Data.Float64())
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(`{"data":""}`), &resp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(`{"data":1337.37}`), &resp)
|
||||
if !errors.Is(err, errUnhandledType) {
|
||||
t.Fatalf("received %v but expected %v", err, errUnhandledType)
|
||||
}
|
||||
|
||||
// Demonstrates that a suffix check is not needed.
|
||||
err = json.Unmarshal([]byte(`{"data":"1337.37}`), &resp)
|
||||
if err == nil {
|
||||
t.Fatal("error cannot be nil")
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(`{"data":"MEOW"}`), &resp)
|
||||
if err == nil {
|
||||
t.Fatal("error cannot be nil")
|
||||
}
|
||||
}
|
||||
|
||||
// 2677173 428.9 ns/op 240 B/op 5 allocs/op
|
||||
func BenchmarkStringToFloat64(b *testing.B) {
|
||||
resp := struct {
|
||||
Data StringToFloat64 `json:"data"`
|
||||
}{}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := json.Unmarshal([]byte(`{"data":"0.00000001"}`), &resp)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1214,8 +1214,8 @@ func (b *Binance) FetchSpotExchangeLimits(ctx context.Context) ([]order.MinMaxLe
|
||||
l.MultiplierDown = f.MultiplierDown
|
||||
l.AveragePriceMinutes = f.AvgPriceMinutes
|
||||
case lotSizeFilter:
|
||||
l.MaxAmount = f.MaxQty
|
||||
l.MinAmount = f.MinQty
|
||||
l.MaximumBaseAmount = f.MaxQty
|
||||
l.MinimumBaseAmount = f.MinQty
|
||||
l.AmountStepIncrementSize = f.StepSize
|
||||
case notionalFilter:
|
||||
l.MinNotional = f.MinNotional
|
||||
|
||||
@@ -1474,8 +1474,8 @@ func (b *Binance) FetchCoinMarginExchangeLimits(ctx context.Context) ([]order.Mi
|
||||
MinPrice: coinFutures.Symbols[x].Filters[0].MinPrice,
|
||||
MaxPrice: coinFutures.Symbols[x].Filters[0].MaxPrice,
|
||||
PriceStepIncrementSize: coinFutures.Symbols[x].Filters[0].TickSize,
|
||||
MaxAmount: coinFutures.Symbols[x].Filters[1].MaxQty,
|
||||
MinAmount: coinFutures.Symbols[x].Filters[1].MinQty,
|
||||
MaximumBaseAmount: coinFutures.Symbols[x].Filters[1].MaxQty,
|
||||
MinimumBaseAmount: coinFutures.Symbols[x].Filters[1].MinQty,
|
||||
AmountStepIncrementSize: coinFutures.Symbols[x].Filters[1].StepSize,
|
||||
MarketMinQty: coinFutures.Symbols[x].Filters[2].MinQty,
|
||||
MarketMaxQty: coinFutures.Symbols[x].Filters[2].MaxQty,
|
||||
|
||||
@@ -2771,11 +2771,11 @@ func TestUpdateOrderExecutionLimits(t *testing.T) {
|
||||
if limits.PriceStepIncrementSize == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty PriceStepIncrementSize; Asset: %s, Pair: %s, Got: %v", a, p, limits.PriceStepIncrementSize)
|
||||
}
|
||||
if limits.MinAmount == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty MinAmount; Asset: %s, Pair: %s, Got: %v", a, p, limits.MinAmount)
|
||||
if limits.MinimumBaseAmount == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty MinAmount; Asset: %s, Pair: %s, Got: %v", a, p, limits.MinimumBaseAmount)
|
||||
}
|
||||
if limits.MaxAmount == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty MaxAmount; Asset: %s, Pair: %s, Got: %v", a, p, limits.MaxAmount)
|
||||
if limits.MaximumBaseAmount == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty MaxAmount; Asset: %s, Pair: %s, Got: %v", a, p, limits.MaximumBaseAmount)
|
||||
}
|
||||
if limits.AmountStepIncrementSize == 0 {
|
||||
t.Errorf("Binance UpdateOrderExecutionLimits empty AmountStepIncrementSize; Asset: %s, Pair: %s, Got: %v", a, p, limits.AmountStepIncrementSize)
|
||||
|
||||
@@ -1145,8 +1145,8 @@ func (b *Binance) FetchUSDTMarginExchangeLimits(ctx context.Context) ([]order.Mi
|
||||
MinPrice: usdtFutures.Symbols[x].Filters[0].MinPrice,
|
||||
MaxPrice: usdtFutures.Symbols[x].Filters[0].MaxPrice,
|
||||
PriceStepIncrementSize: usdtFutures.Symbols[x].Filters[0].TickSize,
|
||||
MaxAmount: usdtFutures.Symbols[x].Filters[1].MaxQty,
|
||||
MinAmount: usdtFutures.Symbols[x].Filters[1].MinQty,
|
||||
MaximumBaseAmount: usdtFutures.Symbols[x].Filters[1].MaxQty,
|
||||
MinimumBaseAmount: usdtFutures.Symbols[x].Filters[1].MinQty,
|
||||
AmountStepIncrementSize: usdtFutures.Symbols[x].Filters[1].StepSize,
|
||||
MarketMinQty: usdtFutures.Symbols[x].Filters[2].MinQty,
|
||||
MarketMaxQty: usdtFutures.Symbols[x].Filters[2].MaxQty,
|
||||
|
||||
@@ -696,9 +696,9 @@ func (b *Bithumb) FetchExchangeLimits(ctx context.Context) ([]order.MinMaxLevel,
|
||||
}
|
||||
|
||||
limits = append(limits, order.MinMaxLevel{
|
||||
Pair: cp,
|
||||
Asset: asset.Spot,
|
||||
MinAmount: getAmountMinimum(data.ClosingPrice),
|
||||
Pair: cp,
|
||||
Asset: asset.Spot,
|
||||
MinimumBaseAmount: getAmountMinimum(data.ClosingPrice),
|
||||
})
|
||||
}
|
||||
return limits, nil
|
||||
|
||||
@@ -1125,8 +1125,8 @@ func (b *BTCMarkets) UpdateOrderExecutionLimits(ctx context.Context, a asset.Ite
|
||||
limits[x] = order.MinMaxLevel{
|
||||
Pair: pair,
|
||||
Asset: asset.Spot,
|
||||
MinAmount: markets[x].MinOrderAmount,
|
||||
MaxAmount: markets[x].MaxOrderAmount,
|
||||
MinimumBaseAmount: markets[x].MinOrderAmount,
|
||||
MaximumBaseAmount: markets[x].MaxOrderAmount,
|
||||
AmountStepIncrementSize: math.Pow(10, -markets[x].AmountDecimals),
|
||||
PriceStepIncrementSize: math.Pow(10, -markets[x].PriceDecimals),
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
@@ -42,6 +43,7 @@ const (
|
||||
bybit24HrsChange = "/spot/quote/v1/ticker/24hr"
|
||||
bybitLastTradedPrice = "/spot/quote/v1/ticker/price"
|
||||
bybitBestBidAskPrice = "/spot/quote/v1/ticker/book_ticker"
|
||||
bybitGetTickersV5 = "/v5/market/tickers"
|
||||
|
||||
// Authenticated endpoints
|
||||
bybitSpotOrder = "/spot/v1/order" // create, query, cancel
|
||||
@@ -53,12 +55,18 @@ const (
|
||||
bybitTradeHistory = "/spot/v1/myTrades"
|
||||
bybitWalletBalance = "/spot/v1/account"
|
||||
bybitServerTime = "/spot/v1/time"
|
||||
bybitAccountFee = "/v5/account/fee-rate"
|
||||
|
||||
// Account asset endpoint
|
||||
bybitGetDepositAddress = "/asset/v1/private/deposit/address"
|
||||
bybitWithdrawFund = "/asset/v1/private/withdraw"
|
||||
)
|
||||
|
||||
var (
|
||||
errCategoryNotSet = errors.New("category not set")
|
||||
errBaseNotSet = errors.New("base coin not set when category is option")
|
||||
)
|
||||
|
||||
// GetAllSpotPairs gets all pairs on the exchange
|
||||
func (by *Bybit) GetAllSpotPairs(ctx context.Context) ([]PairData, error) {
|
||||
resp := struct {
|
||||
@@ -153,10 +161,10 @@ func (by *Bybit) GetMergedOrderBook(ctx context.Context, symbol string, scale, d
|
||||
func (by *Bybit) GetTrades(ctx context.Context, symbol string, limit int64) ([]TradeItem, error) {
|
||||
resp := struct {
|
||||
Data []struct {
|
||||
Price float64 `json:"price,string"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
IsBuyerMaker bool `json:"isBuyerMaker"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
Quantity convert.StringToFloat64 `json:"qty"`
|
||||
IsBuyerMaker bool `json:"isBuyerMaker"`
|
||||
} `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
@@ -186,9 +194,9 @@ func (by *Bybit) GetTrades(ctx context.Context, symbol string, limit int64) ([]T
|
||||
|
||||
trades[x] = TradeItem{
|
||||
CurrencyPair: symbol,
|
||||
Price: resp.Data[x].Price,
|
||||
Price: resp.Data[x].Price.Float64(),
|
||||
Side: tradeSide,
|
||||
Volume: resp.Data[x].Quantity,
|
||||
Volume: resp.Data[x].Quantity.Float64(),
|
||||
Time: resp.Data[x].Time.Time(),
|
||||
}
|
||||
}
|
||||
@@ -314,23 +322,9 @@ func (by *Bybit) GetKlines(ctx context.Context, symbol, period string, limit int
|
||||
// Get24HrsChange returns price change statistics for the last 24 hours
|
||||
// If symbol not passed then it will return price change statistics for all pairs
|
||||
func (by *Bybit) Get24HrsChange(ctx context.Context, symbol string) ([]PriceChangeStats, error) {
|
||||
type priceChangeStats struct {
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
Symbol string `json:"symbol"`
|
||||
BestBidPrice float64 `json:"bestBidPrice,string"`
|
||||
BestAskPrice float64 `json:"bestAskPrice,string"`
|
||||
LastPrice float64 `json:"lastPrice,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"`
|
||||
}
|
||||
|
||||
var stats []PriceChangeStats
|
||||
if symbol != "" {
|
||||
resp := struct {
|
||||
Data priceChangeStats `json:"result"`
|
||||
Data PriceChangeStats `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
@@ -341,46 +335,20 @@ func (by *Bybit) Get24HrsChange(ctx context.Context, symbol string) ([]PriceChan
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stats = append(stats, PriceChangeStats{
|
||||
resp.Data.Time.Time(),
|
||||
resp.Data.Symbol,
|
||||
resp.Data.BestAskPrice,
|
||||
resp.Data.BestAskPrice,
|
||||
resp.Data.LastPrice,
|
||||
resp.Data.OpenPrice,
|
||||
resp.Data.HighPrice,
|
||||
resp.Data.LowPrice,
|
||||
resp.Data.Volume,
|
||||
resp.Data.QuoteVolume,
|
||||
})
|
||||
} else {
|
||||
resp := struct {
|
||||
Data []priceChangeStats `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendHTTPRequest(ctx, exchange.RestSpot, bybit24HrsChange, publicSpotRate, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for x := range resp.Data {
|
||||
stats = append(stats, PriceChangeStats{
|
||||
resp.Data[x].Time.Time(),
|
||||
resp.Data[x].Symbol,
|
||||
resp.Data[x].BestAskPrice,
|
||||
resp.Data[x].BestAskPrice,
|
||||
resp.Data[x].LastPrice,
|
||||
resp.Data[x].OpenPrice,
|
||||
resp.Data[x].HighPrice,
|
||||
resp.Data[x].LowPrice,
|
||||
resp.Data[x].Volume,
|
||||
resp.Data[x].QuoteVolume,
|
||||
})
|
||||
}
|
||||
return []PriceChangeStats{resp.Data}, nil
|
||||
}
|
||||
return stats, nil
|
||||
|
||||
resp := struct {
|
||||
Data []PriceChangeStats `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendHTTPRequest(ctx, exchange.RestSpot, bybit24HrsChange, publicSpotRate, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetLastTradedPrice returns last trading price
|
||||
@@ -427,19 +395,9 @@ func (by *Bybit) GetLastTradedPrice(ctx context.Context, symbol string) ([]LastT
|
||||
// GetBestBidAskPrice returns best BID and ASK price
|
||||
// If symbol not passed then it will return best BID and ASK price for all pairs
|
||||
func (by *Bybit) GetBestBidAskPrice(ctx context.Context, symbol string) ([]TickerData, error) {
|
||||
type bestTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice float64 `json:"bidPrice,string"`
|
||||
BidQuantity float64 `json:"bidQty,string"`
|
||||
AskPrice float64 `json:"askPrice,string"`
|
||||
AskQuantity float64 `json:"askQty,string"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
}
|
||||
|
||||
var tickers []TickerData
|
||||
if symbol != "" {
|
||||
resp := struct {
|
||||
Data bestTicker `json:"result"`
|
||||
Data TickerData `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
@@ -450,36 +408,55 @@ func (by *Bybit) GetBestBidAskPrice(ctx context.Context, symbol string) ([]Ticke
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tickers = append(tickers, TickerData{
|
||||
resp.Data.Symbol,
|
||||
resp.Data.BidPrice,
|
||||
resp.Data.BidQuantity,
|
||||
resp.Data.AskPrice,
|
||||
resp.Data.AskQuantity,
|
||||
resp.Data.Time.Time(),
|
||||
})
|
||||
} else {
|
||||
resp := struct {
|
||||
Data []bestTicker `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendHTTPRequest(ctx, exchange.RestSpot, bybitBestBidAskPrice, publicSpotRate, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for x := range resp.Data {
|
||||
tickers = append(tickers, TickerData{
|
||||
resp.Data[x].Symbol,
|
||||
resp.Data[x].BidPrice,
|
||||
resp.Data[x].BidQuantity,
|
||||
resp.Data[x].AskPrice,
|
||||
resp.Data[x].AskQuantity,
|
||||
resp.Data[x].Time.Time(),
|
||||
})
|
||||
}
|
||||
return []TickerData{resp.Data}, nil
|
||||
}
|
||||
return tickers, nil
|
||||
|
||||
resp := struct {
|
||||
Data []TickerData `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendHTTPRequest(ctx, exchange.RestSpot, bybitBestBidAskPrice, publicSpotRate, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetTickersV5 returns tickers for either "spot", "option" or "inverse".
|
||||
// Specific symbol is optional.
|
||||
func (by *Bybit) GetTickersV5(ctx context.Context, category, symbol, baseCoin string) (*ListOfTickers, error) {
|
||||
if category == "" {
|
||||
return nil, errCategoryNotSet
|
||||
}
|
||||
|
||||
if category == "option" && baseCoin == "" {
|
||||
return nil, errBaseNotSet
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("category", category)
|
||||
|
||||
if symbol != "" {
|
||||
val.Set("symbol", symbol)
|
||||
}
|
||||
|
||||
if baseCoin != "" {
|
||||
val.Set("baseCoin", baseCoin)
|
||||
}
|
||||
|
||||
result := struct {
|
||||
Data *ListOfTickers `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendHTTPRequest(ctx, exchange.RestSpot, bybitGetTickersV5+"?"+val.Encode(), publicSpotRate, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
// CreatePostOrder create and post order
|
||||
@@ -789,6 +766,42 @@ func (by *Bybit) WithdrawFund(ctx context.Context, coin, chain, address, tag, am
|
||||
return resp.Data.ID, by.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, bybitWithdrawFund, nil, params, &resp, privateSpotRate)
|
||||
}
|
||||
|
||||
// GetFeeRate returns user account fee
|
||||
// Valid category: "spot", "linear", "inverse", "option"
|
||||
func (by *Bybit) GetFeeRate(ctx context.Context, category, symbol, baseCoin string) (*AccountFee, error) {
|
||||
if category == "" {
|
||||
return nil, errCategoryNotSet
|
||||
}
|
||||
|
||||
if !common.StringDataContains(validCategory, category) {
|
||||
// NOTE: Opted to fail here because if the user passes in an invalid
|
||||
// category the error returned is this
|
||||
// `Bybit raw response: {"retCode":10005,"retMsg":"Permission denied, please check your API key permissions.","result":{},"retExtInfo":{},"time":1683694010783}`
|
||||
return nil, fmt.Errorf("%w, valid category values are %v", errInvalidCategory, validCategory)
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("category", category)
|
||||
if symbol != "" {
|
||||
params.Set("symbol", symbol)
|
||||
}
|
||||
if baseCoin != "" {
|
||||
params.Set("baseCoin", baseCoin)
|
||||
}
|
||||
|
||||
result := struct {
|
||||
Data *AccountFee `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
err := by.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodGet, bybitAccountFee, params, &result, privateFeeRate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (by *Bybit) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result UnmarshalTo) error {
|
||||
endpointPath, err := by.API.Endpoints.GetURL(ePath)
|
||||
@@ -842,8 +855,8 @@ func (by *Bybit) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, me
|
||||
var (
|
||||
payload []byte
|
||||
hmacSignedStr string
|
||||
headers = make(map[string]string)
|
||||
)
|
||||
headers := make(map[string]string)
|
||||
|
||||
if jsonPayload != nil {
|
||||
headers["Content-Type"] = "application/json"
|
||||
@@ -893,19 +906,71 @@ func (by *Bybit) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, me
|
||||
return result.GetError()
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequestV5 sends an authenticated HTTP request
|
||||
func (by *Bybit) SendAuthHTTPRequestV5(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, result UnmarshalTo, f request.EndpointLimit) error {
|
||||
creds, err := by.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
result = &Error{}
|
||||
}
|
||||
|
||||
endpointPath, err := by.API.Endpoints.GetURL(ePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = by.SendPayload(ctx, f, func() (*request.Item, error) {
|
||||
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
headers["X-BAPI-TIMESTAMP"] = timestamp
|
||||
headers["X-BAPI-API-KEY"] = creds.Key
|
||||
headers["X-BAPI-RECV-WINDOW"] = defaultRecvWindow
|
||||
|
||||
var hmacSignedStr string
|
||||
hmacSignedStr, err = getSign(timestamp+creds.Key+defaultRecvWindow+params.Encode(), creds.Secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headers["X-BAPI-SIGN"] = hmacSignedStr
|
||||
return &request.Item{
|
||||
Method: method,
|
||||
Path: endpointPath + common.EncodeURLValues(path, params),
|
||||
Headers: headers,
|
||||
Result: &result,
|
||||
AuthRequest: true,
|
||||
Verbose: by.Verbose,
|
||||
HTTPDebugging: by.HTTPDebugging,
|
||||
HTTPRecording: by.HTTPRecording}, nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return result.GetError()
|
||||
}
|
||||
|
||||
// Error defines all error information for each request
|
||||
type Error struct {
|
||||
ReturnCode int64 `json:"ret_code"`
|
||||
ReturnMsg string `json:"ret_msg"`
|
||||
ExtCode string `json:"ext_code"`
|
||||
ExtMsg string `json:"ext_info"`
|
||||
ReturnCode int64 `json:"ret_code"`
|
||||
ReturnMsg string `json:"ret_msg"`
|
||||
ReturnCodeV5 int64 `json:"retCode"`
|
||||
ReturnMessageV5 string `json:"retMsg"`
|
||||
ExtCode string `json:"ext_code"`
|
||||
ExtMsg string `json:"ext_info"`
|
||||
}
|
||||
|
||||
// GetError checks and returns an error if it is supplied.
|
||||
func (e Error) GetError() error {
|
||||
func (e *Error) GetError() error {
|
||||
if e.ReturnCode != 0 && e.ReturnMsg != "" {
|
||||
return errors.New(e.ReturnMsg)
|
||||
}
|
||||
if e.ReturnCodeV5 != 0 && e.ReturnMessageV5 != "" {
|
||||
return errors.New(e.ReturnMessageV5)
|
||||
}
|
||||
if e.ExtCode != "" && e.ExtMsg != "" {
|
||||
return errors.New(e.ExtMsg)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
@@ -98,12 +99,12 @@ func (by *Bybit) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair)
|
||||
switch data.Result[x].Side {
|
||||
case sideBuy:
|
||||
resp.Bids = append(resp.Bids, orderbook.Item{
|
||||
Price: data.Result[x].Price,
|
||||
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,
|
||||
Price: data.Result[x].Price.Float64(),
|
||||
Amount: data.Result[x].Size,
|
||||
})
|
||||
default:
|
||||
@@ -393,7 +394,7 @@ func (by *Bybit) GetLastFundingRate(ctx context.Context, symbol currency.Pair) (
|
||||
// GetFuturesServerTime returns Bybit server time in seconds
|
||||
func (by *Bybit) GetFuturesServerTime(ctx context.Context) (time.Time, error) {
|
||||
resp := struct {
|
||||
TimeNow float64 `json:"time_now,string"`
|
||||
TimeNow convert.StringToFloat64 `json:"time_now"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
@@ -401,7 +402,7 @@ func (by *Bybit) GetFuturesServerTime(ctx context.Context) (time.Time, error) {
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
sec, dec := math.Modf(resp.TimeNow)
|
||||
sec, dec := math.Modf(resp.TimeNow.Float64())
|
||||
return time.Unix(int64(sec), int64(dec*(1e9))), nil
|
||||
}
|
||||
|
||||
@@ -1085,24 +1086,21 @@ func (by *Bybit) ChangeCoinMargin(ctx context.Context, symbol currency.Pair, buy
|
||||
}
|
||||
|
||||
// GetTradingFeeRate returns trading taker and maker fee rate
|
||||
func (by *Bybit) GetTradingFeeRate(ctx context.Context, symbol currency.Pair) (takerFee, makerFee float64, err error) {
|
||||
func (by *Bybit) GetTradingFeeRate(ctx context.Context, symbol currency.Pair) (*CFuturesTradingFeeRate, error) {
|
||||
params := url.Values{}
|
||||
resp := struct {
|
||||
Result struct {
|
||||
TakerFeeRate float64 `json:"taker_fee_rate,string"`
|
||||
MakerFeeRate float64 `json:"maker_fee_rate,string"`
|
||||
} `json:"result"`
|
||||
Result *CFuturesTradingFeeRate `json:"result"`
|
||||
Error
|
||||
}{}
|
||||
|
||||
symbolValue, err := by.FormatSymbol(symbol, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
return resp.Result.TakerFeeRate, resp.Result.MakerFeeRate, err
|
||||
return nil, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
|
||||
takerFee, makerFee, err = resp.Result.TakerFeeRate, resp.Result.MakerFeeRate, by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetTradingFeeRate, params, nil, &resp, cFuturesGetTradingFeeRate)
|
||||
return
|
||||
return resp.Result,
|
||||
by.SendAuthHTTPRequest(ctx, exchange.RestCoinMargined, http.MethodGet, bybitFuturesAPIVersion+cfuturesGetTradingFeeRate, params, nil, &resp, cFuturesGetTradingFeeRate)
|
||||
}
|
||||
|
||||
// SetCoinRiskLimit sets risk limit
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
|
||||
@@ -60,6 +61,20 @@ func TestMain(m *testing.M) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Turn on all pairs for testing
|
||||
supportedAssets := b.GetAssetTypes(false)
|
||||
for x := range supportedAssets {
|
||||
avail, err := b.GetAvailablePairs(supportedAssets[x])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = b.CurrencyPairs.StorePairs(supportedAssets[x], avail, true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -1055,10 +1070,18 @@ func TestGetTradingFeeRate(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, _, err = b.GetTradingFeeRate(context.Background(), pair)
|
||||
feeRate, err := b.GetTradingFeeRate(context.Background(), pair)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if feeRate.MakerFeeRate == 0 && feeRate.TakerFeeRate == 0 {
|
||||
t.Error("expected fee rate")
|
||||
}
|
||||
|
||||
if feeRate.UserID == 0 {
|
||||
t.Error("expected user id")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetCoinRiskLimit(t *testing.T) {
|
||||
@@ -3309,3 +3332,137 @@ func TestGetUSDCPredictedFundingRate(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTickers(t *testing.T) {
|
||||
t.Parallel()
|
||||
supportedAssets := b.GetAssetTypes(false)
|
||||
ctx := context.Background()
|
||||
for x := range supportedAssets {
|
||||
err := b.UpdateTickers(ctx, supportedAssets[x])
|
||||
if err != nil {
|
||||
t.Fatalf("%v %v\n", supportedAssets[x], err)
|
||||
}
|
||||
|
||||
avail, err := b.GetAvailablePairs(supportedAssets[x])
|
||||
if err != nil {
|
||||
t.Fatalf("%v %v\n", supportedAssets[x], err)
|
||||
}
|
||||
|
||||
for y := range avail {
|
||||
_, err = ticker.GetTicker(b.GetName(), avail[y], supportedAssets[x])
|
||||
if err != nil {
|
||||
t.Fatalf("%v %v %v\n", avail[y], supportedAssets[x], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTickersV5(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetTickersV5(context.Background(), "bruh", "", "")
|
||||
if err != nil && err.Error() != "Illegal category" {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetTickersV5(context.Background(), "option", "", "")
|
||||
if !errors.Is(err, errBaseNotSet) {
|
||||
t.Fatalf("expected: %v, received: %v", errBaseNotSet, err)
|
||||
}
|
||||
|
||||
_, err = b.GetTickersV5(context.Background(), "spot", "", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetTickersV5(context.Background(), "option", "", "BTC")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetTickersV5(context.Background(), "inverse", "", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetTickersV5(context.Background(), "linear", "", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOrderExecutionLimits(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := b.UpdateOrderExecutionLimits(context.Background(), asset.USDCMarginedFutures)
|
||||
if !errors.Is(err, asset.ErrNotSupported) {
|
||||
t.Fatalf("received: %v expected: %v", err, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
err = b.UpdateOrderExecutionLimits(context.Background(), asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("Okx UpdateOrderExecutionLimits() error", err)
|
||||
}
|
||||
|
||||
avail, err := b.GetAvailablePairs(asset.Spot)
|
||||
if err != nil {
|
||||
t.Fatal("Okx GetAvailablePairs() error", err)
|
||||
}
|
||||
|
||||
for x := range avail {
|
||||
limits, err := b.GetOrderExecutionLimits(asset.Spot, avail[x])
|
||||
if err != nil {
|
||||
t.Fatal("Okx GetOrderExecutionLimits() error", err)
|
||||
}
|
||||
if limits == (order.MinMaxLevel{}) {
|
||||
t.Fatal("Okx GetOrderExecutionLimits() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFeeRate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetFeeRate(context.Background(), "", "", "")
|
||||
if !errors.Is(err, errCategoryNotSet) {
|
||||
t.Fatalf("received %v but expected %v", err, errCategoryNotSet)
|
||||
}
|
||||
|
||||
_, err = b.GetFeeRate(context.Background(), "bruh", "", "")
|
||||
if !errors.Is(err, errInvalidCategory) {
|
||||
t.Fatalf("received %v but expected %v", err, errInvalidCategory)
|
||||
}
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
|
||||
_, err = b.GetFeeRate(context.Background(), "spot", "", "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received %v but expected %v", err, nil)
|
||||
}
|
||||
|
||||
_, err = b.GetFeeRate(context.Background(), "linear", "", "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received %v but expected %v", err, nil)
|
||||
}
|
||||
|
||||
_, err = b.GetFeeRate(context.Background(), "inverse", "", "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received %v but expected %v", err, nil)
|
||||
}
|
||||
|
||||
_, err = b.GetFeeRate(context.Background(), "option", "", "ETH")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received %v but expected %v", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForceFileStandard(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := sharedtestvalues.ForceFileStandard(t, sharedtestvalues.EmptyStringPotentialPattern)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if t.Failed() {
|
||||
t.Fatal("Please use convert.StringToFloat64 type instead of `float64` and remove `,string` as strings can be empty in unmarshal process. Then call the Float64() method.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
)
|
||||
|
||||
@@ -44,6 +45,8 @@ var (
|
||||
errExpectedOneOrder = errors.New("expected one order")
|
||||
)
|
||||
|
||||
var validCategory = []string{"spot", "linear", "inverse", "option"}
|
||||
|
||||
// bybitTimeSec provides an internal conversion helper
|
||||
type bybitTimeSec time.Time
|
||||
|
||||
@@ -149,34 +152,6 @@ func (b bybitTimeNanoSec) Time() time.Time {
|
||||
return time.Time(b)
|
||||
}
|
||||
|
||||
// bybitNumericalValue is a type used for when the API returns an empty or
|
||||
// numerical string
|
||||
type bybitNumericalValue float64
|
||||
|
||||
// UnmarshalJSON is custom type json unmarshaller for bybitNumericalValue
|
||||
func (b *bybitNumericalValue) UnmarshalJSON(data []byte) error {
|
||||
var num string
|
||||
err := json.Unmarshal(data, &num)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if num == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
v, err := strconv.ParseFloat(num, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*b = bybitNumericalValue(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64 returns a float64 value for bybitNumericalValue
|
||||
func (b *bybitNumericalValue) Float64() float64 { return float64(*b) }
|
||||
|
||||
// UnmarshalTo acts as interface to exchange API response
|
||||
type UnmarshalTo interface {
|
||||
GetError() error
|
||||
@@ -184,19 +159,19 @@ type UnmarshalTo interface {
|
||||
|
||||
// PairData stores pair data
|
||||
type PairData struct {
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
BaseCurrency string `json:"baseCurrency"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
BasePrecision float64 `json:"basePrecision,string"`
|
||||
QuotePrecision float64 `json:"quotePrecision,string"`
|
||||
MinTradeQuantity float64 `json:"minTradeQuantity,string"`
|
||||
MinTradeAmount float64 `json:"minTradeAmount,string"`
|
||||
MinPricePrecision float64 `json:"minPricePrecision,string"`
|
||||
MaxTradeQuantity float64 `json:"maxTradeQuantity,string"`
|
||||
MaxTradeAmount float64 `json:"maxTradeAmount,string"`
|
||||
Category int64 `json:"category"`
|
||||
ShowStatus bool `json:"showStatus"`
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
BaseCurrency string `json:"baseCurrency"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
BasePrecision convert.StringToFloat64 `json:"basePrecision"`
|
||||
QuotePrecision convert.StringToFloat64 `json:"quotePrecision"`
|
||||
MinTradeQuantity convert.StringToFloat64 `json:"minTradeQuantity"`
|
||||
MinTradeAmount convert.StringToFloat64 `json:"minTradeAmount"`
|
||||
MinPricePrecision convert.StringToFloat64 `json:"minPricePrecision"`
|
||||
MaxTradeQuantity convert.StringToFloat64 `json:"maxTradeQuantity"`
|
||||
MaxTradeAmount convert.StringToFloat64 `json:"maxTradeAmount"`
|
||||
Category int64 `json:"category"`
|
||||
ShowStatus bool `json:"showStatus"`
|
||||
}
|
||||
|
||||
// Orderbook stores the orderbook data
|
||||
@@ -233,32 +208,32 @@ type KlineItem struct {
|
||||
|
||||
// PriceChangeStats contains statistics for the last 24 hours trade
|
||||
type PriceChangeStats struct {
|
||||
Time time.Time
|
||||
Symbol string
|
||||
BestBidPrice float64
|
||||
BestAskPrice float64
|
||||
LastPrice float64
|
||||
OpenPrice float64
|
||||
HighPrice float64
|
||||
LowPrice float64
|
||||
Volume float64
|
||||
QuoteVolume float64
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
Symbol string `json:"symbol"`
|
||||
BestBidPrice convert.StringToFloat64 `json:"bestBidPrice"`
|
||||
BestAskPrice convert.StringToFloat64 `json:"bestAskPrice"`
|
||||
LastPrice convert.StringToFloat64 `json:"lastPrice"`
|
||||
OpenPrice convert.StringToFloat64 `json:"openPrice"`
|
||||
HighPrice convert.StringToFloat64 `json:"highPrice"`
|
||||
LowPrice convert.StringToFloat64 `json:"lowPrice"`
|
||||
Volume convert.StringToFloat64 `json:"volume"`
|
||||
QuoteVolume convert.StringToFloat64 `json:"quoteVolume"`
|
||||
}
|
||||
|
||||
// LastTradePrice contains price for last trade
|
||||
type LastTradePrice struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
}
|
||||
|
||||
// TickerData stores ticker data
|
||||
type TickerData struct {
|
||||
Symbol string
|
||||
BidPrice float64
|
||||
BidQuantity float64
|
||||
AskPrice float64
|
||||
AskQuantity float64
|
||||
Time time.Time
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice convert.StringToFloat64 `json:"bidPrice"`
|
||||
BidQuantity convert.StringToFloat64 `json:"bidQty"`
|
||||
AskPrice convert.StringToFloat64 `json:"askPrice"`
|
||||
AskQuantity convert.StringToFloat64 `json:"askQty"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -296,97 +271,97 @@ type PlaceOrderRequest struct {
|
||||
|
||||
// PlaceOrderResponse store new order response type
|
||||
type PlaceOrderResponse struct {
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time bybitTimeMilliSecStr `json:"transactTime"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"origQty,string"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
AccountID string `json:"accountId"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time bybitTimeMilliSecStr `json:"transactTime"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Quantity convert.StringToFloat64 `json:"origQty"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
AccountID string `json:"accountId"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
ExecutedQty convert.StringToFloat64 `json:"executedQty"`
|
||||
}
|
||||
|
||||
// QueryOrderResponse holds query order data
|
||||
type QueryOrderResponse struct {
|
||||
AccountID string `json:"accountId"`
|
||||
ExchangeID string `json:"exchangeId"`
|
||||
Symbol string `json:"symbol"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
OrderID string `json:"orderId"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
CummulativeQuoteQty float64 `json:"cummulativeQuoteQty,string"`
|
||||
AveragePrice float64 `json:"avgPrice,string"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
IcebergQty float64 `json:"icebergQty,string"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
UpdateTime bybitTimeMilliSecStr `json:"updateTime"`
|
||||
IsWorking bool `json:"isWorking"`
|
||||
AccountID string `json:"accountId"`
|
||||
ExchangeID string `json:"exchangeId"`
|
||||
Symbol string `json:"symbol"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
OrderID string `json:"orderId"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Quantity convert.StringToFloat64 `json:"origQty"`
|
||||
ExecutedQty convert.StringToFloat64 `json:"executedQty"`
|
||||
CummulativeQuoteQty convert.StringToFloat64 `json:"cummulativeQuoteQty"`
|
||||
AveragePrice convert.StringToFloat64 `json:"avgPrice"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
StopPrice convert.StringToFloat64 `json:"stopPrice"`
|
||||
IcebergQty convert.StringToFloat64 `json:"icebergQty"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
UpdateTime bybitTimeMilliSecStr `json:"updateTime"`
|
||||
IsWorking bool `json:"isWorking"`
|
||||
}
|
||||
|
||||
// CancelOrderResponse is the return structured response from the exchange
|
||||
type CancelOrderResponse struct {
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
AccountID string `json:"accountId"`
|
||||
Time bybitTimeMilliSecStr `json:"transactTime"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
AccountID string `json:"accountId"`
|
||||
Time bybitTimeMilliSecStr `json:"transactTime"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Quantity convert.StringToFloat64 `json:"origQty"`
|
||||
ExecutedQty convert.StringToFloat64 `json:"executedQty"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TradeType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
}
|
||||
|
||||
// HistoricalTrade holds recent trade data
|
||||
type HistoricalTrade struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ID string `json:"id"`
|
||||
OrderID string `json:"orderId"`
|
||||
TicketID string `json:"ticketId"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
Commission float64 `json:"commission,string"`
|
||||
CommissionAsset float64 `json:"commissionAsset,string"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
IsBuyer bool `json:"isBuyer"`
|
||||
IsMaker bool `json:"isMaker"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
MatchOrderID string `json:"matchOrderId"`
|
||||
Fee FeeData `json:"fee"`
|
||||
FeeTokenID string `json:"feeTokenId"`
|
||||
FeeAmount float64 `json:"feeAmount,string"`
|
||||
MakerRebate float64 `json:"makerRebate,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
ID string `json:"id"`
|
||||
OrderID string `json:"orderId"`
|
||||
TicketID string `json:"ticketId"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Quantity convert.StringToFloat64 `json:"qty"`
|
||||
Commission convert.StringToFloat64 `json:"commission"`
|
||||
CommissionAsset convert.StringToFloat64 `json:"commissionAsset"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
IsBuyer bool `json:"isBuyer"`
|
||||
IsMaker bool `json:"isMaker"`
|
||||
SymbolName string `json:"symbolName"`
|
||||
MatchOrderID string `json:"matchOrderId"`
|
||||
Fee FeeData `json:"fee"`
|
||||
FeeTokenID string `json:"feeTokenId"`
|
||||
FeeAmount convert.StringToFloat64 `json:"feeAmount"`
|
||||
MakerRebate convert.StringToFloat64 `json:"makerRebate"`
|
||||
}
|
||||
|
||||
// FeeData store fees data
|
||||
type FeeData struct {
|
||||
FeeTokenID int64 `json:"feeTokenId"`
|
||||
FeeTokenName string `json:"feeTokenName"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
FeeTokenID int64 `json:"feeTokenId"`
|
||||
FeeTokenName string `json:"feeTokenName"`
|
||||
Fee convert.StringToFloat64 `json:"fee"`
|
||||
}
|
||||
|
||||
// Balance holds wallet balance
|
||||
type Balance struct {
|
||||
Coin string `json:"coin"`
|
||||
CoinID string `json:"coinId"`
|
||||
CoinName string `json:"coinName"`
|
||||
Total float64 `json:"total,string"`
|
||||
Free float64 `json:"free,string"`
|
||||
Locked float64 `json:"locked,string"`
|
||||
Coin string `json:"coin"`
|
||||
CoinID string `json:"coinId"`
|
||||
CoinName string `json:"coinName"`
|
||||
Total convert.StringToFloat64 `json:"total"`
|
||||
Free convert.StringToFloat64 `json:"free"`
|
||||
Locked convert.StringToFloat64 `json:"locked"`
|
||||
}
|
||||
|
||||
type orderbookResponse struct {
|
||||
@@ -443,12 +418,12 @@ type WsParams struct {
|
||||
|
||||
// WsSpotTickerData stores ws ticker data
|
||||
type WsSpotTickerData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Bid float64 `json:"bidPrice,string"`
|
||||
Ask float64 `json:"askPrice,string"`
|
||||
BidSize float64 `json:"bidQty,string"`
|
||||
AskSize float64 `json:"askQty,string"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
Symbol string `json:"symbol"`
|
||||
Bid convert.StringToFloat64 `json:"bidPrice"`
|
||||
Ask convert.StringToFloat64 `json:"askPrice"`
|
||||
BidSize convert.StringToFloat64 `json:"bidQty"`
|
||||
AskSize convert.StringToFloat64 `json:"askQty"`
|
||||
Time bybitTimeMilliSec `json:"time"`
|
||||
}
|
||||
|
||||
// WsSpotTicker stores ws ticker data
|
||||
@@ -460,13 +435,13 @@ type WsSpotTicker struct {
|
||||
|
||||
// KlineStreamData stores ws kline stream data
|
||||
type KlineStreamData struct {
|
||||
StartTime bybitTimeMilliSec `json:"t"`
|
||||
Symbol string `json:"s"`
|
||||
ClosePrice float64 `json:"c,string"`
|
||||
HighPrice float64 `json:"h,string"`
|
||||
LowPrice float64 `json:"l,string"`
|
||||
OpenPrice float64 `json:"o,string"`
|
||||
Volume float64 `json:"v,string"`
|
||||
StartTime bybitTimeMilliSec `json:"t"`
|
||||
Symbol string `json:"s"`
|
||||
ClosePrice convert.StringToFloat64 `json:"c"`
|
||||
HighPrice convert.StringToFloat64 `json:"h"`
|
||||
LowPrice convert.StringToFloat64 `json:"l"`
|
||||
OpenPrice convert.StringToFloat64 `json:"o"`
|
||||
Volume convert.StringToFloat64 `json:"v"`
|
||||
}
|
||||
|
||||
// KlineStream holds the kline stream data
|
||||
@@ -494,11 +469,11 @@ type WsOrderbook struct {
|
||||
|
||||
// WsTradeData stores ws trade data
|
||||
type WsTradeData struct {
|
||||
Time bybitTimeMilliSec `json:"t"`
|
||||
ID string `json:"v"`
|
||||
Price float64 `json:"p,string"`
|
||||
Size float64 `json:"q,string"`
|
||||
Side bool `json:"m"`
|
||||
Time bybitTimeMilliSec `json:"t"`
|
||||
ID string `json:"v"`
|
||||
Price convert.StringToFloat64 `json:"p"`
|
||||
Size convert.StringToFloat64 `json:"q"`
|
||||
Side bool `json:"m"`
|
||||
}
|
||||
|
||||
// WsTrade stores ws trades data
|
||||
@@ -520,65 +495,65 @@ type wsAccount struct {
|
||||
|
||||
// Currencies stores currencies data
|
||||
type Currencies struct {
|
||||
Asset string `json:"a"`
|
||||
Available float64 `json:"f,string"`
|
||||
Locked float64 `json:"l,string"`
|
||||
Asset string `json:"a"`
|
||||
Available convert.StringToFloat64 `json:"f"`
|
||||
Locked convert.StringToFloat64 `json:"l"`
|
||||
}
|
||||
|
||||
// wsOrderUpdate defines websocket account order update data
|
||||
type wsOrderUpdate struct {
|
||||
EventType string `json:"e"`
|
||||
EventTime string `json:"E"`
|
||||
Symbol string `json:"s"`
|
||||
ClientOrderID string `json:"c"`
|
||||
Side string `json:"S"`
|
||||
OrderType string `json:"o"`
|
||||
TimeInForce string `json:"f"`
|
||||
Quantity float64 `json:"q,string"`
|
||||
Price float64 `json:"p,string"`
|
||||
OrderStatus string `json:"X"`
|
||||
OrderID string `json:"i"`
|
||||
OpponentOrderID string `json:"M"`
|
||||
LastExecutedQuantity float64 `json:"l,string"`
|
||||
CumulativeFilledQuantity float64 `json:"z,string"`
|
||||
LastExecutedPrice float64 `json:"L,string"`
|
||||
Commission float64 `json:"n,string"`
|
||||
CommissionAsset string `json:"N"`
|
||||
IsNormal bool `json:"u"`
|
||||
IsOnOrderBook bool `json:"w"`
|
||||
IsLimitMaker bool `json:"m"`
|
||||
OrderCreationTime bybitTimeMilliSecStr `json:"O"`
|
||||
CumulativeQuoteTransactedQuantity float64 `json:"Z,string"`
|
||||
AccountID string `json:"A"`
|
||||
IsClose bool `json:"C"`
|
||||
Leverage float64 `json:"v,string"`
|
||||
EventType string `json:"e"`
|
||||
EventTime string `json:"E"`
|
||||
Symbol string `json:"s"`
|
||||
ClientOrderID string `json:"c"`
|
||||
Side string `json:"S"`
|
||||
OrderType string `json:"o"`
|
||||
TimeInForce string `json:"f"`
|
||||
Quantity convert.StringToFloat64 `json:"q"`
|
||||
Price convert.StringToFloat64 `json:"p"`
|
||||
OrderStatus string `json:"X"`
|
||||
OrderID string `json:"i"`
|
||||
OpponentOrderID string `json:"M"`
|
||||
LastExecutedQuantity convert.StringToFloat64 `json:"l"`
|
||||
CumulativeFilledQuantity convert.StringToFloat64 `json:"z"`
|
||||
LastExecutedPrice convert.StringToFloat64 `json:"L"`
|
||||
Commission convert.StringToFloat64 `json:"n"`
|
||||
CommissionAsset string `json:"N"`
|
||||
IsNormal bool `json:"u"`
|
||||
IsOnOrderBook bool `json:"w"`
|
||||
IsLimitMaker bool `json:"m"`
|
||||
OrderCreationTime bybitTimeMilliSecStr `json:"O"`
|
||||
CumulativeQuoteTransactedQuantity convert.StringToFloat64 `json:"Z"`
|
||||
AccountID string `json:"A"`
|
||||
IsClose bool `json:"C"`
|
||||
Leverage convert.StringToFloat64 `json:"v"`
|
||||
}
|
||||
|
||||
// wsOrderFilled defines websocket account order filled data
|
||||
type wsOrderFilled struct {
|
||||
EventType string `json:"e"`
|
||||
EventTime string `json:"E"`
|
||||
Symbol string `json:"s"`
|
||||
Quantity float64 `json:"q,string"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"t"`
|
||||
Price float64 `json:"p,string"`
|
||||
TradeID string `json:"T"`
|
||||
OrderID string `json:"o"`
|
||||
UserGenOrderID string `json:"c"`
|
||||
OpponentOrderID string `json:"O"`
|
||||
AccountID string `json:"a"`
|
||||
OpponentAccountID string `json:"A"`
|
||||
IsMaker bool `json:"m"`
|
||||
Side string `json:"S"`
|
||||
EventType string `json:"e"`
|
||||
EventTime string `json:"E"`
|
||||
Symbol string `json:"s"`
|
||||
Quantity convert.StringToFloat64 `json:"q"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"t"`
|
||||
Price convert.StringToFloat64 `json:"p"`
|
||||
TradeID string `json:"T"`
|
||||
OrderID string `json:"o"`
|
||||
UserGenOrderID string `json:"c"`
|
||||
OpponentOrderID string `json:"O"`
|
||||
AccountID string `json:"a"`
|
||||
OpponentAccountID string `json:"A"`
|
||||
IsMaker bool `json:"m"`
|
||||
Side string `json:"S"`
|
||||
}
|
||||
|
||||
// WsFuturesOrderbookData stores ws futures orderbook data
|
||||
type WsFuturesOrderbookData struct {
|
||||
Price float64 `json:"price,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
ID int64 `json:"id"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Symbol string `json:"symbol"`
|
||||
ID int64 `json:"id"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
}
|
||||
|
||||
// WsFuturesOrderbook stores ws futures orderbook
|
||||
@@ -661,32 +636,32 @@ type WsInsurance struct {
|
||||
|
||||
// WsTickerData stores ws ticker data
|
||||
type WsTickerData struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
LastPrice float64 `json:"last_price,string"`
|
||||
BidPrice float64 `json:"bid1_price"`
|
||||
AskPrice float64 `json:"ask1_price"`
|
||||
LastDirection string `json:"last_tick_direction"`
|
||||
PrevPrice24h float64 `json:"prev_price_24h,string"`
|
||||
Price24hPercentChange float64 `json:"price_24h_pcnt_e6"`
|
||||
Price1hPercentChange float64 `json:"price_1h_pcnt_e6"`
|
||||
HighPrice24h float64 `json:"high_price_24h,string"`
|
||||
LowPrice24h float64 `json:"low_price_24h,string"`
|
||||
PrevPrice1h float64 `json:"prev_price_1h,string"`
|
||||
MarkPrice float64 `json:"mark_price,string"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue float64 `json:"open_value_e8"`
|
||||
TotalTurnOver float64 `json:"total_turnover_e8"`
|
||||
TurnOver24h float64 `json:"turnover_24h_e8"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FundingRate int64 `json:"funding_rate_e6"`
|
||||
PredictedFundingRate float64 `json:"predicted_funding_rate_e6"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdateAt time.Time `json:"updated_at"`
|
||||
NextFundingAt time.Time `json:"next_funding_time"`
|
||||
CountDownHour int64 `json:"countdown_hour"`
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
LastPrice convert.StringToFloat64 `json:"last_price"`
|
||||
BidPrice float64 `json:"bid1_price"`
|
||||
AskPrice float64 `json:"ask1_price"`
|
||||
LastDirection string `json:"last_tick_direction"`
|
||||
PrevPrice24h convert.StringToFloat64 `json:"prev_price_24h"`
|
||||
Price24hPercentChange float64 `json:"price_24h_pcnt_e6"`
|
||||
Price1hPercentChange float64 `json:"price_1h_pcnt_e6"`
|
||||
HighPrice24h convert.StringToFloat64 `json:"high_price_24h"`
|
||||
LowPrice24h convert.StringToFloat64 `json:"low_price_24h"`
|
||||
PrevPrice1h convert.StringToFloat64 `json:"prev_price_1h"`
|
||||
MarkPrice convert.StringToFloat64 `json:"mark_price"`
|
||||
IndexPrice convert.StringToFloat64 `json:"index_price"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue float64 `json:"open_value_e8"`
|
||||
TotalTurnOver float64 `json:"total_turnover_e8"`
|
||||
TurnOver24h float64 `json:"turnover_24h_e8"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FundingRate int64 `json:"funding_rate_e6"`
|
||||
PredictedFundingRate float64 `json:"predicted_funding_rate_e6"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdateAt time.Time `json:"updated_at"`
|
||||
NextFundingAt time.Time `json:"next_funding_time"`
|
||||
CountDownHour int64 `json:"countdown_hour"`
|
||||
}
|
||||
|
||||
// WsTicker stores ws ticker
|
||||
@@ -708,45 +683,45 @@ type WsDeltaTicker struct {
|
||||
|
||||
// WsFuturesTickerData stores ws future ticker data
|
||||
type WsFuturesTickerData struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
SymbolName string `json:"symbol_name"`
|
||||
SymbolYear int64 `json:"symbol_year"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Coin string `json:"coin"`
|
||||
QuoteSymbol string `json:"quote_symbol"`
|
||||
Mode string `json:"mode"`
|
||||
IsUpBorrowable int64 `json:"is_up_borrowable"`
|
||||
ImportTime bybitTimeNanoSec `json:"import_time_e9"`
|
||||
StartTradingTime bybitTimeNanoSec `json:"start_trading_time_e9"`
|
||||
TimeToSettle bybitTimeNanoSec `json:"settle_time_e9"`
|
||||
SettleFeeRate int64 `json:"settle_fee_rate_e8"`
|
||||
ContractStatus string `json:"contract_status"`
|
||||
SystemSubsidy int64 `json:"system_subsidy_e8"`
|
||||
LastPrice float64 `json:"last_price,string"`
|
||||
BidPrice float64 `json:"bid1_price"`
|
||||
AskPrice float64 `json:"ask1_price"`
|
||||
LastDirection string `json:"last_tick_direction"`
|
||||
PrevPrice24h float64 `json:"prev_price_24h,string"`
|
||||
Price24hPercentChange float64 `json:"price_24h_pcnt_e6"`
|
||||
Price1hPercentChange float64 `json:"price_1h_pcnt_e6"`
|
||||
HighPrice24h float64 `json:"high_price_24h,string"`
|
||||
LowPrice24h float64 `json:"low_price_24h,string"`
|
||||
PrevPrice1h float64 `json:"prev_price_1h,string"`
|
||||
MarkPrice float64 `json:"mark_price,string"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue float64 `json:"open_value_e8"`
|
||||
TotalTurnOver float64 `json:"total_turnover_e8"`
|
||||
TurnOver24h float64 `json:"turnover_24h_e8"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FairBasis float64 `json:"fair_basis_e8"`
|
||||
FairBasisRate float64 `json:"fair_basis_rate_e8"`
|
||||
BasisInYear float64 `json:"basis_in_year_e8"`
|
||||
ExpectPrice float64 `json:"expect_price,string"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdateAt time.Time `json:"updated_at"`
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
SymbolName string `json:"symbol_name"`
|
||||
SymbolYear int64 `json:"symbol_year"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Coin string `json:"coin"`
|
||||
QuoteSymbol string `json:"quote_symbol"`
|
||||
Mode string `json:"mode"`
|
||||
IsUpBorrowable int64 `json:"is_up_borrowable"`
|
||||
ImportTime bybitTimeNanoSec `json:"import_time_e9"`
|
||||
StartTradingTime bybitTimeNanoSec `json:"start_trading_time_e9"`
|
||||
TimeToSettle bybitTimeNanoSec `json:"settle_time_e9"`
|
||||
SettleFeeRate int64 `json:"settle_fee_rate_e8"`
|
||||
ContractStatus string `json:"contract_status"`
|
||||
SystemSubsidy int64 `json:"system_subsidy_e8"`
|
||||
LastPrice convert.StringToFloat64 `json:"last_price"`
|
||||
BidPrice float64 `json:"bid1_price"`
|
||||
AskPrice float64 `json:"ask1_price"`
|
||||
LastDirection string `json:"last_tick_direction"`
|
||||
PrevPrice24h convert.StringToFloat64 `json:"prev_price_24h"`
|
||||
Price24hPercentChange float64 `json:"price_24h_pcnt_e6"`
|
||||
Price1hPercentChange float64 `json:"price_1h_pcnt_e6"`
|
||||
HighPrice24h convert.StringToFloat64 `json:"high_price_24h"`
|
||||
LowPrice24h convert.StringToFloat64 `json:"low_price_24h"`
|
||||
PrevPrice1h convert.StringToFloat64 `json:"prev_price_1h"`
|
||||
MarkPrice convert.StringToFloat64 `json:"mark_price"`
|
||||
IndexPrice convert.StringToFloat64 `json:"index_price"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue float64 `json:"open_value_e8"`
|
||||
TotalTurnOver float64 `json:"total_turnover_e8"`
|
||||
TurnOver24h float64 `json:"turnover_24h_e8"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FairBasis float64 `json:"fair_basis_e8"`
|
||||
FairBasisRate float64 `json:"fair_basis_rate_e8"`
|
||||
BasisInYear float64 `json:"basis_in_year_e8"`
|
||||
ExpectPrice convert.StringToFloat64 `json:"expect_price"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdateAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// WsFuturesTicker stores ws future ticker
|
||||
@@ -768,11 +743,11 @@ type WsDeltaFuturesTicker struct {
|
||||
|
||||
// WsLiquidationData stores ws liquidation data
|
||||
type WsLiquidationData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty"`
|
||||
Timestamp bybitTimeMilliSec `json:"time"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Qty float64 `json:"qty"`
|
||||
Timestamp bybitTimeMilliSec `json:"time"`
|
||||
}
|
||||
|
||||
// WsFuturesLiquidation stores ws future liquidation
|
||||
@@ -783,36 +758,36 @@ type WsFuturesLiquidation struct {
|
||||
|
||||
// WsFuturesPositionData stores ws future position data
|
||||
type WsFuturesPositionData struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
PositionID int64 `json:"position_idx"` // present in Futures position struct only
|
||||
Mode int64 `json:"mode"` // present in Futures position struct only
|
||||
Isolated bool `json:"isolated"` // present in Futures position struct only
|
||||
PositionValue float64 `json:"position_value,string"`
|
||||
EntryPrice float64 `json:"entry_price,string"`
|
||||
LiquidPrice float64 `json:"liq_price,string"`
|
||||
BustPrice float64 `json:"bust_price,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
OrderMargin float64 `json:"order_margin,string"`
|
||||
PositionMargin float64 `json:"position_margin,string"`
|
||||
AvailableBalance float64 `json:"available_balance,string"`
|
||||
TakeProfit float64 `json:"take_profit,string"`
|
||||
TakeProfitTriggerBy string `json:"tp_trigger_by"`
|
||||
StopLoss float64 `json:"stop_loss,string"`
|
||||
StopLossTriggerBy string `json:"sl_trigger_by"`
|
||||
RealisedPNL float64 `json:"realised_pnl,string"`
|
||||
TrailingStop float64 `json:"trailing_stop,string"`
|
||||
TrailingActive float64 `json:"trailing_active,string"`
|
||||
WalletBalance float64 `json:"wallet_balance,string"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
ClosingFee float64 `json:"occ_closing_fee,string"`
|
||||
FundingFee float64 `json:"occ_funding_fee,string"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
TotalPNL float64 `json:"cum_realised_pnl,string"`
|
||||
Status string `json:"position_status"`
|
||||
Version int64 `json:"position_seq"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
PositionID int64 `json:"position_idx"` // present in Futures position struct only
|
||||
Mode int64 `json:"mode"` // present in Futures position struct only
|
||||
Isolated bool `json:"isolated"` // present in Futures position struct only
|
||||
PositionValue convert.StringToFloat64 `json:"position_value"`
|
||||
EntryPrice convert.StringToFloat64 `json:"entry_price"`
|
||||
LiquidPrice convert.StringToFloat64 `json:"liq_price"`
|
||||
BustPrice convert.StringToFloat64 `json:"bust_price"`
|
||||
Leverage convert.StringToFloat64 `json:"leverage"`
|
||||
OrderMargin convert.StringToFloat64 `json:"order_margin"`
|
||||
PositionMargin convert.StringToFloat64 `json:"position_margin"`
|
||||
AvailableBalance convert.StringToFloat64 `json:"available_balance"`
|
||||
TakeProfit convert.StringToFloat64 `json:"take_profit"`
|
||||
TakeProfitTriggerBy string `json:"tp_trigger_by"`
|
||||
StopLoss convert.StringToFloat64 `json:"stop_loss"`
|
||||
StopLossTriggerBy string `json:"sl_trigger_by"`
|
||||
RealisedPNL convert.StringToFloat64 `json:"realised_pnl"`
|
||||
TrailingStop convert.StringToFloat64 `json:"trailing_stop"`
|
||||
TrailingActive convert.StringToFloat64 `json:"trailing_active"`
|
||||
WalletBalance convert.StringToFloat64 `json:"wallet_balance"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
ClosingFee convert.StringToFloat64 `json:"occ_closing_fee"`
|
||||
FundingFee convert.StringToFloat64 `json:"occ_funding_fee"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
TotalPNL convert.StringToFloat64 `json:"cum_realised_pnl"`
|
||||
Status string `json:"position_status"`
|
||||
Version int64 `json:"position_seq"`
|
||||
}
|
||||
|
||||
// WsFuturesPosition stores ws future position
|
||||
@@ -824,19 +799,19 @@ type WsFuturesPosition struct {
|
||||
|
||||
// WsFuturesExecutionData stores ws future execution data
|
||||
type WsFuturesExecutionData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderID string `json:"order_id"`
|
||||
ExecutionID string `json:"exec_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrderQty float64 `json:"order_qty"`
|
||||
ExecutionType string `json:"exec_type"`
|
||||
ExecutionQty float64 `json:"exec_qty"`
|
||||
ExecutionFee float64 `json:"exec_fee,string"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
IsMaker bool `json:"is_maker"`
|
||||
Time time.Time `json:"trade_time"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderID string `json:"order_id"`
|
||||
ExecutionID string `json:"exec_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
OrderQty float64 `json:"order_qty"`
|
||||
ExecutionType string `json:"exec_type"`
|
||||
ExecutionQty float64 `json:"exec_qty"`
|
||||
ExecutionFee convert.StringToFloat64 `json:"exec_fee"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
IsMaker bool `json:"is_maker"`
|
||||
Time time.Time `json:"trade_time"`
|
||||
}
|
||||
|
||||
// WsFuturesExecution stores ws future execution
|
||||
@@ -847,31 +822,31 @@ type WsFuturesExecution struct {
|
||||
|
||||
// WsOrderData stores ws order data
|
||||
type WsOrderData struct {
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
CreateType string `json:"create_type"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
CummulativeExecQty float64 `json:"cum_exec_qty"`
|
||||
CummulativeExecValue float64 `json:"cum_exec_value,string"`
|
||||
CummulativeExecFee float64 `json:"cum_exec_fee,string"`
|
||||
TakeProfit float64 `json:"take_profit,string"`
|
||||
StopLoss float64 `json:"stop_loss,string"`
|
||||
TrailingStop float64 `json:"trailing_stop,string"`
|
||||
TrailingActive float64 `json:"trailing_active,string"`
|
||||
LastExecPrice float64 `json:"last_exec_price,string"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
Time time.Time `json:"timestamp"` // present in CoinMarginedFutures and Futures only
|
||||
CreateTime time.Time `json:"create_time"` // present in USDTMarginedFutures only
|
||||
UpdateTime time.Time `json:"update_time"` // present in USDTMarginedFutures only
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
CreateType string `json:"create_type"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
CummulativeExecQty float64 `json:"cum_exec_qty"`
|
||||
CummulativeExecValue convert.StringToFloat64 `json:"cum_exec_value"`
|
||||
CummulativeExecFee convert.StringToFloat64 `json:"cum_exec_fee"`
|
||||
TakeProfit convert.StringToFloat64 `json:"take_profit"`
|
||||
StopLoss convert.StringToFloat64 `json:"stop_loss"`
|
||||
TrailingStop convert.StringToFloat64 `json:"trailing_stop"`
|
||||
TrailingActive convert.StringToFloat64 `json:"trailing_active"`
|
||||
LastExecPrice convert.StringToFloat64 `json:"last_exec_price"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
Time time.Time `json:"timestamp"` // present in CoinMarginedFutures and Futures only
|
||||
CreateTime time.Time `json:"create_time"` // present in USDTMarginedFutures only
|
||||
UpdateTime time.Time `json:"update_time"` // present in USDTMarginedFutures only
|
||||
}
|
||||
|
||||
// WsOrder stores ws order
|
||||
@@ -882,23 +857,23 @@ type WsOrder struct {
|
||||
|
||||
// WsStopOrderData stores ws stop order data
|
||||
type WsStopOrderData struct {
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
CreateType string `json:"create_type"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
TriggerPrice float64 `json:"trigger_price,string"`
|
||||
Time time.Time `json:"timestamp"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
CreateType string `json:"create_type"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
TriggerPrice convert.StringToFloat64 `json:"trigger_price"`
|
||||
Time time.Time `json:"timestamp"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
}
|
||||
|
||||
// WsFuturesStopOrder stores ws future stop order
|
||||
@@ -909,23 +884,23 @@ type WsFuturesStopOrder struct {
|
||||
|
||||
// WsUSDTStopOrderData stores ws USDT stop order data
|
||||
type WsUSDTStopOrderData struct {
|
||||
OrderID string `json:"stop_order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
TriggerPrice float64 `json:"trigger_price,string"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
UpdateTime time.Time `json:"update_time"`
|
||||
OrderID string `json:"stop_order_id"`
|
||||
OrderLinkID string `json:"order_link_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"order_type"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
OrderQty float64 `json:"qty"`
|
||||
TimeInForce string `json:"time_in_force"`
|
||||
OrderStatus string `json:"order_status"`
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
TriggerPrice convert.StringToFloat64 `json:"trigger_price"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
CloseOnTrigger bool `json:"close_on_trigger"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
UpdateTime time.Time `json:"update_time"`
|
||||
}
|
||||
|
||||
// WsUSDTFuturesStopOrder stores ws USDT stop order
|
||||
@@ -945,3 +920,68 @@ type WsFuturesWallet struct {
|
||||
Topic string `json:"topic"`
|
||||
Data []WsFuturesWalletData `json:"data"`
|
||||
}
|
||||
|
||||
// Ticker holds ticker information
|
||||
type Ticker struct {
|
||||
// Spot fields
|
||||
Symbol string `json:"symbol"`
|
||||
TopBidPrice convert.StringToFloat64 `json:"bid1Price"`
|
||||
TopBidSize convert.StringToFloat64 `json:"bid1Size"`
|
||||
TopAskPrice convert.StringToFloat64 `json:"ask1Price"`
|
||||
TopAskSize convert.StringToFloat64 `json:"ask1Size"`
|
||||
LastPrice convert.StringToFloat64 `json:"lastPrice"`
|
||||
PreviousPrice24Hr convert.StringToFloat64 `json:"prevPrice24h"`
|
||||
Price24HrPcnt convert.StringToFloat64 `json:"price24hPcnt"`
|
||||
HighPrice24Hr convert.StringToFloat64 `json:"highPrice24h"`
|
||||
LowPrice24Hr convert.StringToFloat64 `json:"lowPrice24h"`
|
||||
Turnover24Hr convert.StringToFloat64 `json:"turnover24h"`
|
||||
Volume24Hr convert.StringToFloat64 `json:"volume24h"`
|
||||
USDIndexPrice convert.StringToFloat64 `json:"usdIndexPrice"`
|
||||
|
||||
// Option fields
|
||||
TopBidImpliedVolatility convert.StringToFloat64 `json:"bid1Iv"`
|
||||
TopAskImpliedVolatility convert.StringToFloat64 `json:"ask1Iv"`
|
||||
MarkPrice convert.StringToFloat64 `json:"markPrice"`
|
||||
IndexPrice convert.StringToFloat64 `json:"indexPrice"`
|
||||
MarkImpliedVolatility convert.StringToFloat64 `json:"markIv"`
|
||||
UnderlyingPrice convert.StringToFloat64 `json:"underlyingPrice"`
|
||||
OpenInterest convert.StringToFloat64 `json:"openInterest"`
|
||||
TotalVolume convert.StringToFloat64 `json:"totalVolume"`
|
||||
TotalTurnover convert.StringToFloat64 `json:"totalTurnover"`
|
||||
Delta convert.StringToFloat64 `json:"delta"`
|
||||
Gamma convert.StringToFloat64 `json:"gamma"`
|
||||
Vega convert.StringToFloat64 `json:"vega"`
|
||||
Theta convert.StringToFloat64 `json:"theta"`
|
||||
PredictedDeliveryPrice convert.StringToFloat64 `json:"predictedDeliveryPrice"`
|
||||
Change24h convert.StringToFloat64 `json:"change24h"`
|
||||
|
||||
// Inverse/linear fields
|
||||
PrevPrice1h convert.StringToFloat64 `json:"prevPrice1h"`
|
||||
OpenInterestValue convert.StringToFloat64 `json:"openInterestValue"`
|
||||
FundingRate convert.StringToFloat64 `json:"fundingRate"`
|
||||
NextFundingTime convert.StringToFloat64 `json:"nextFundingTime"`
|
||||
BasisRate convert.StringToFloat64 `json:"basisRate"`
|
||||
DeliveryFeeRate convert.StringToFloat64 `json:"deliveryFeeRate"`
|
||||
DeliveryTime convert.StringToFloat64 `json:"deliveryTime"`
|
||||
Basis convert.StringToFloat64 `json:"basis"`
|
||||
}
|
||||
|
||||
// Fee holds fee information
|
||||
type Fee struct {
|
||||
BaseCoin string `json:"baseCoin"`
|
||||
Symbol string `json:"symbol"`
|
||||
Taker convert.StringToFloat64 `json:"takerFeeRate"`
|
||||
Maker convert.StringToFloat64 `json:"makerFeeRate"`
|
||||
}
|
||||
|
||||
// AccountFee holds account fee information
|
||||
type AccountFee struct {
|
||||
Category string `json:"category"`
|
||||
List []Fee `json:"list"`
|
||||
}
|
||||
|
||||
// ListOfTickers holds list of tickers
|
||||
type ListOfTickers struct {
|
||||
Category string `json:"category"`
|
||||
List []Ticker `json:"list"`
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -79,13 +80,13 @@ func (by *Bybit) GetUSDCFuturesOrderbook(ctx context.Context, symbol currency.Pa
|
||||
switch data.Result[x].Side {
|
||||
case sideBuy:
|
||||
resp.Bids = append(resp.Bids, orderbook.Item{
|
||||
Price: data.Result[x].Price,
|
||||
Amount: data.Result[x].Size,
|
||||
Price: data.Result[x].Price.Float64(),
|
||||
Amount: data.Result[x].Size.Float64(),
|
||||
})
|
||||
case sideSell:
|
||||
resp.Asks = append(resp.Asks, orderbook.Item{
|
||||
Price: data.Result[x].Price,
|
||||
Amount: data.Result[x].Size,
|
||||
Price: data.Result[x].Price.Float64(),
|
||||
Amount: data.Result[x].Size.Float64(),
|
||||
})
|
||||
default:
|
||||
return nil, errInvalidSide
|
||||
@@ -884,7 +885,7 @@ func (by *Bybit) GetUSDCPosition(ctx context.Context, symbol currency.Pair, cate
|
||||
func (by *Bybit) SetUSDCLeverage(ctx context.Context, symbol currency.Pair, leverage float64) (float64, error) {
|
||||
resp := struct {
|
||||
Result struct {
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
Leverage convert.StringToFloat64 `json:"leverage"`
|
||||
} `json:"result"`
|
||||
USDCError
|
||||
}{}
|
||||
@@ -895,7 +896,7 @@ func (by *Bybit) SetUSDCLeverage(ctx context.Context, symbol currency.Pair, leve
|
||||
}
|
||||
symbolValue, err := by.FormatSymbol(symbol, asset.USDCMarginedFutures)
|
||||
if err != nil {
|
||||
return resp.Result.Leverage, err
|
||||
return 0, err
|
||||
}
|
||||
req["symbol"] = symbolValue
|
||||
|
||||
@@ -904,7 +905,8 @@ func (by *Bybit) SetUSDCLeverage(ctx context.Context, symbol currency.Pair, leve
|
||||
}
|
||||
req["leverage"] = strconv.FormatFloat(leverage, 'f', -1, 64)
|
||||
|
||||
return resp.Result.Leverage, by.SendUSDCAuthHTTPRequest(ctx, exchange.RestUSDCMargined, http.MethodPost, usdcfuturesSetLeverage, req, &resp, usdcSetLeverageRate)
|
||||
return resp.Result.Leverage.Float64(),
|
||||
by.SendUSDCAuthHTTPRequest(ctx, exchange.RestUSDCMargined, http.MethodPost, usdcfuturesSetLeverage, req, &resp, usdcSetLeverageRate)
|
||||
}
|
||||
|
||||
// GetUSDCSettlementHistory gets USDC settlement history with support of last 30 days.
|
||||
@@ -1014,8 +1016,8 @@ func (by *Bybit) GetUSDCLastFundingRate(ctx context.Context, symbol currency.Pai
|
||||
func (by *Bybit) GetUSDCPredictedFundingRate(ctx context.Context, symbol currency.Pair) (predictedFundingRate, predictedFundingFee float64, err error) {
|
||||
resp := struct {
|
||||
Result struct {
|
||||
PredictedFundingRate float64 `json:"predictedFundingRate,string"`
|
||||
PredictedFundingFee float64 `json:"predictedFundingFee,string"`
|
||||
PredictedFundingRate convert.StringToFloat64 `json:"predictedFundingRate"`
|
||||
PredictedFundingFee convert.StringToFloat64 `json:"predictedFundingFee"`
|
||||
} `json:"result"`
|
||||
USDCError
|
||||
}{}
|
||||
@@ -1023,17 +1025,17 @@ func (by *Bybit) GetUSDCPredictedFundingRate(ctx context.Context, symbol currenc
|
||||
req := make(map[string]interface{})
|
||||
var symbolValue string
|
||||
if symbol.IsEmpty() {
|
||||
return resp.Result.PredictedFundingRate, resp.Result.PredictedFundingFee, errSymbolMissing
|
||||
return 0, 0, errSymbolMissing
|
||||
}
|
||||
symbolValue, err = by.FormatSymbol(symbol, asset.USDCMarginedFutures)
|
||||
if err != nil {
|
||||
return resp.Result.PredictedFundingRate, resp.Result.PredictedFundingFee, err
|
||||
return 0, 0, err
|
||||
}
|
||||
req["symbol"] = symbolValue
|
||||
|
||||
err = by.SendUSDCAuthHTTPRequest(ctx, exchange.RestUSDCMargined, http.MethodPost, usdcfuturesGetPredictedFundingRate, req, &resp, usdcGetPredictedFundingRate)
|
||||
predictedFundingRate = resp.Result.PredictedFundingRate
|
||||
predictedFundingFee = resp.Result.PredictedFundingFee
|
||||
predictedFundingRate = resp.Result.PredictedFundingRate.Float64()
|
||||
predictedFundingFee = resp.Result.PredictedFundingFee.Float64()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -301,8 +301,8 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
CurrencyPair: p,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: by.Name,
|
||||
Price: data.TradeData.Price,
|
||||
Amount: data.TradeData.Size,
|
||||
Price: data.TradeData.Price.Float64(),
|
||||
Amount: data.TradeData.Size.Float64(),
|
||||
Side: side,
|
||||
TID: data.TradeData.ID,
|
||||
})
|
||||
@@ -320,8 +320,8 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Bid: data.Ticker.Bid,
|
||||
Ask: data.Ticker.Ask,
|
||||
Bid: data.Ticker.Bid.Float64(),
|
||||
Ask: data.Ticker.Ask.Float64(),
|
||||
LastUpdated: data.Ticker.Time.Time(),
|
||||
AssetType: asset.Spot,
|
||||
Pair: p,
|
||||
@@ -345,11 +345,11 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
Exchange: by.Name,
|
||||
StartTime: data.Kline.StartTime.Time(),
|
||||
Interval: data.Parameters.KlineType,
|
||||
OpenPrice: data.Kline.OpenPrice,
|
||||
ClosePrice: data.Kline.ClosePrice,
|
||||
HighPrice: data.Kline.HighPrice,
|
||||
LowPrice: data.Kline.LowPrice,
|
||||
Volume: data.Kline.Volume,
|
||||
OpenPrice: data.Kline.OpenPrice.Float64(),
|
||||
ClosePrice: data.Kline.ClosePrice.Float64(),
|
||||
HighPrice: data.Kline.HighPrice.Float64(),
|
||||
LowPrice: data.Kline.LowPrice.Float64(),
|
||||
Volume: data.Kline.Volume.Float64(),
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
@@ -431,10 +431,10 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
}
|
||||
|
||||
by.Websocket.DataHandler <- order.Detail{
|
||||
Price: data[j].Price,
|
||||
Amount: data[j].Quantity,
|
||||
ExecutedAmount: data[j].CumulativeFilledQuantity,
|
||||
RemainingAmount: data[j].Quantity - data[j].CumulativeFilledQuantity,
|
||||
Price: data[j].Price.Float64(),
|
||||
Amount: data[j].Quantity.Float64(),
|
||||
ExecutedAmount: data[j].CumulativeFilledQuantity.Float64(),
|
||||
RemainingAmount: data[j].Quantity.Float64() - data[j].CumulativeFilledQuantity.Float64(),
|
||||
Exchange: by.Name,
|
||||
OrderID: data[j].OrderID,
|
||||
Type: oType,
|
||||
@@ -446,8 +446,8 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
ClientOrderID: data[j].ClientOrderID,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: data[j].Price,
|
||||
Amount: data[j].Quantity,
|
||||
Price: data[j].Price.Float64(),
|
||||
Amount: data[j].Quantity.Float64(),
|
||||
Exchange: by.Name,
|
||||
Timestamp: data[j].OrderCreationTime.Time(),
|
||||
},
|
||||
@@ -486,13 +486,13 @@ func (by *Bybit) wsHandleData(respRaw []byte) error {
|
||||
Side: oSide,
|
||||
AssetType: asset.Spot,
|
||||
Pair: p,
|
||||
Price: data[j].Price,
|
||||
Amount: data[j].Quantity,
|
||||
Price: data[j].Price.Float64(),
|
||||
Amount: data[j].Quantity.Float64(),
|
||||
Date: data[j].Timestamp.Time(),
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: data[j].Price,
|
||||
Amount: data[j].Quantity,
|
||||
Price: data[j].Price.Float64(),
|
||||
Amount: data[j].Quantity.Float64(),
|
||||
Exchange: by.Name,
|
||||
Timestamp: data[j].Timestamp.Time(),
|
||||
TID: data[j].TradeID,
|
||||
|
||||
@@ -381,13 +381,16 @@ func (by *Bybit) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs := make([]currency.Pair, len(allPairs))
|
||||
pairs := make([]currency.Pair, 0, len(allPairs))
|
||||
for x := range allPairs {
|
||||
if allPairs[x].Status != "ONLINE" {
|
||||
continue
|
||||
}
|
||||
pair, err = currency.NewPairFromStrings(allPairs[x].BaseCoin, "PERP")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs[x] = pair
|
||||
pairs = append(pairs, pair)
|
||||
}
|
||||
return pairs, nil
|
||||
}
|
||||
@@ -413,58 +416,62 @@ func (by *Bybit) UpdateTradablePairs(ctx context.Context, forceUpdate bool) erro
|
||||
|
||||
// UpdateTickers updates the ticker for all currency pairs of a given asset type
|
||||
func (by *Bybit) UpdateTickers(ctx context.Context, assetType asset.Item) error {
|
||||
allPairs, err := by.GetEnabledPairs(assetType)
|
||||
avail, err := by.GetAvailablePairs(assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled, err := by.GetEnabledPairs(assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch assetType {
|
||||
case asset.Spot:
|
||||
tick, err := by.Get24HrsChange(ctx, "")
|
||||
ticks, err := by.GetTickersV5(ctx, "spot", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for p := range allPairs {
|
||||
formattedPair, err := by.FormatExchangeCurrency(allPairs[p], assetType)
|
||||
|
||||
for x := range ticks.List {
|
||||
pair, err := avail.DeriveFrom(ticks.List[x].Symbol)
|
||||
if err != nil {
|
||||
// These symbols below do not have a spot market but are in fact
|
||||
// perpetuals.
|
||||
if ticks.List[x].Symbol == "ZECUSDT" || ticks.List[x].Symbol == "DASHUSDT" {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for y := range tick {
|
||||
if tick[y].Symbol != formattedPair.String() {
|
||||
continue
|
||||
}
|
||||
if !enabled.Contains(pair, true) {
|
||||
continue
|
||||
}
|
||||
|
||||
cp, err := by.extractCurrencyPair(tick[y].Symbol, assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick[y].LastPrice,
|
||||
High: tick[y].HighPrice,
|
||||
Low: tick[y].LowPrice,
|
||||
Bid: tick[y].BestBidPrice,
|
||||
Ask: tick[y].BestAskPrice,
|
||||
Volume: tick[y].Volume,
|
||||
QuoteVolume: tick[y].QuoteVolume,
|
||||
Open: tick[y].OpenPrice,
|
||||
Pair: cp,
|
||||
LastUpdated: tick[y].Time,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: ticks.List[x].LastPrice.Float64(),
|
||||
High: ticks.List[x].HighPrice24Hr.Float64(),
|
||||
Low: ticks.List[x].LowPrice24Hr.Float64(),
|
||||
Bid: ticks.List[x].TopBidPrice.Float64(),
|
||||
BidSize: ticks.List[x].TopBidSize.Float64(),
|
||||
Ask: ticks.List[x].TopAskPrice.Float64(),
|
||||
AskSize: ticks.List[x].TopAskSize.Float64(),
|
||||
Volume: ticks.List[x].Volume24Hr.Float64(),
|
||||
Pair: pair,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case asset.CoinMarginedFutures, asset.USDTMarginedFutures, asset.Futures:
|
||||
tick, err := by.GetFuturesSymbolPriceTicker(ctx, currency.Pair{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for p := range allPairs {
|
||||
formattedPair, err := by.FormatExchangeCurrency(allPairs[p], assetType)
|
||||
for p := range enabled {
|
||||
formattedPair, err := by.FormatExchangeCurrency(enabled[p], assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -478,11 +485,11 @@ func (by *Bybit) UpdateTickers(ctx context.Context, assetType asset.Item) error
|
||||
return err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick[y].LastPrice,
|
||||
High: tick[y].HighPrice24h,
|
||||
Low: tick[y].LowPrice24h,
|
||||
Bid: tick[y].BidPrice,
|
||||
Ask: tick[y].AskPrice,
|
||||
Last: tick[y].LastPrice.Float64(),
|
||||
High: tick[y].HighPrice24h.Float64(),
|
||||
Low: tick[y].LowPrice24h.Float64(),
|
||||
Bid: tick[y].BidPrice.Float64(),
|
||||
Ask: tick[y].AskPrice.Float64(),
|
||||
Volume: tick[y].Volume24h,
|
||||
Open: tick[y].OpenValue.Float64(),
|
||||
Pair: cp,
|
||||
@@ -493,10 +500,9 @@ func (by *Bybit) UpdateTickers(ctx context.Context, assetType asset.Item) error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case asset.USDCMarginedFutures:
|
||||
for p := range allPairs {
|
||||
formattedPair, err := by.FormatExchangeCurrency(allPairs[p], assetType)
|
||||
for x := range enabled {
|
||||
formattedPair, err := by.FormatExchangeCurrency(enabled[x], assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -511,12 +517,12 @@ func (by *Bybit) UpdateTickers(ctx context.Context, assetType asset.Item) error
|
||||
return err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick.LastPrice,
|
||||
High: tick.High24h,
|
||||
Low: tick.Low24h,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Volume: tick.Volume24h,
|
||||
Last: tick.LastPrice.Float64(),
|
||||
High: tick.High24h.Float64(),
|
||||
Low: tick.Low24h.Float64(),
|
||||
Bid: tick.Bid.Float64(),
|
||||
Ask: tick.Ask.Float64(),
|
||||
Volume: tick.Volume24h.Float64(),
|
||||
Pair: cp,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType})
|
||||
@@ -524,11 +530,9 @@ func (by *Bybit) UpdateTickers(ctx context.Context, assetType asset.Item) error
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("%s %w", assetType, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -552,16 +556,16 @@ func (by *Bybit) UpdateTicker(ctx context.Context, p currency.Pair, assetType as
|
||||
return nil, err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick[y].LastPrice,
|
||||
High: tick[y].HighPrice,
|
||||
Low: tick[y].LowPrice,
|
||||
Bid: tick[y].BestBidPrice,
|
||||
Ask: tick[y].BestAskPrice,
|
||||
Volume: tick[y].Volume,
|
||||
QuoteVolume: tick[y].QuoteVolume,
|
||||
Open: tick[y].OpenPrice,
|
||||
Last: tick[y].LastPrice.Float64(),
|
||||
High: tick[y].HighPrice.Float64(),
|
||||
Low: tick[y].LowPrice.Float64(),
|
||||
Bid: tick[y].BestBidPrice.Float64(),
|
||||
Ask: tick[y].BestAskPrice.Float64(),
|
||||
Volume: tick[y].Volume.Float64(),
|
||||
QuoteVolume: tick[y].QuoteVolume.Float64(),
|
||||
Open: tick[y].OpenPrice.Float64(),
|
||||
Pair: cp,
|
||||
LastUpdated: tick[y].Time,
|
||||
LastUpdated: tick[y].Time.Time(),
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType})
|
||||
if err != nil {
|
||||
@@ -581,11 +585,11 @@ func (by *Bybit) UpdateTicker(ctx context.Context, p currency.Pair, assetType as
|
||||
return nil, err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick[y].LastPrice,
|
||||
High: tick[y].HighPrice24h,
|
||||
Low: tick[y].LowPrice24h,
|
||||
Bid: tick[y].BidPrice,
|
||||
Ask: tick[y].AskPrice,
|
||||
Last: tick[y].LastPrice.Float64(),
|
||||
High: tick[y].HighPrice24h.Float64(),
|
||||
Low: tick[y].LowPrice24h.Float64(),
|
||||
Bid: tick[y].BidPrice.Float64(),
|
||||
Ask: tick[y].AskPrice.Float64(),
|
||||
Volume: tick[y].Volume24h,
|
||||
Open: tick[y].OpenValue.Float64(),
|
||||
Pair: cp,
|
||||
@@ -607,12 +611,12 @@ func (by *Bybit) UpdateTicker(ctx context.Context, p currency.Pair, assetType as
|
||||
return nil, err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tick.LastPrice,
|
||||
High: tick.High24h,
|
||||
Low: tick.Low24h,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Volume: tick.Volume24h,
|
||||
Last: tick.LastPrice.Float64(),
|
||||
High: tick.High24h.Float64(),
|
||||
Low: tick.Low24h.Float64(),
|
||||
Bid: tick.Bid.Float64(),
|
||||
Ask: tick.Ask.Float64(),
|
||||
Volume: tick.Volume24h.Float64(),
|
||||
Pair: cp,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType})
|
||||
@@ -719,9 +723,9 @@ func (by *Bybit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
for i := range balances {
|
||||
currencyBalance[i] = account.Balance{
|
||||
Currency: currency.NewCode(balances[i].CoinName),
|
||||
Total: balances[i].Total,
|
||||
Hold: balances[i].Locked,
|
||||
Free: balances[i].Total - balances[i].Locked,
|
||||
Total: balances[i].Total.Float64(),
|
||||
Hold: balances[i].Locked.Float64(),
|
||||
Free: balances[i].Total.Float64() - balances[i].Locked.Float64(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,9 +760,9 @@ func (by *Bybit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
acc.Currencies = []account.Balance{
|
||||
{
|
||||
Currency: currency.USD,
|
||||
Total: balance.WalletBalance,
|
||||
Hold: balance.WalletBalance - balance.AvailableBalance,
|
||||
Free: balance.AvailableBalance,
|
||||
Total: balance.WalletBalance.Float64(),
|
||||
Hold: balance.WalletBalance.Float64() - balance.AvailableBalance.Float64(),
|
||||
Free: balance.AvailableBalance.Float64(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -813,7 +817,7 @@ func (by *Bybit) GetWithdrawalsHistory(ctx context.Context, c currency.Code, a a
|
||||
Status: w[i].Status,
|
||||
TransferID: strconv.FormatInt(w[i].ID, 10),
|
||||
Currency: w[i].Coin,
|
||||
Amount: w[i].Amount,
|
||||
Amount: w[i].Amount.Float64(),
|
||||
Fee: w[i].Fee,
|
||||
CryptoToAddress: w[i].Address,
|
||||
CryptoTxID: w[i].TxID,
|
||||
@@ -898,8 +902,8 @@ func (by *Bybit) GetRecentTrades(ctx context.Context, p currency.Pair, assetType
|
||||
Exchange: by.Name,
|
||||
CurrencyPair: p,
|
||||
AssetType: assetType,
|
||||
Price: tradeData[i].OrderPrice,
|
||||
Amount: tradeData[i].OrderQty,
|
||||
Price: tradeData[i].OrderPrice.Float64(),
|
||||
Amount: tradeData[i].OrderQty.Float64(),
|
||||
Timestamp: tradeData[i].Timestamp.Time(),
|
||||
})
|
||||
}
|
||||
@@ -1230,18 +1234,18 @@ func (by *Bybit) GetOrderInfo(ctx context.Context, orderID string, pair currency
|
||||
}
|
||||
|
||||
return order.Detail{
|
||||
Amount: resp.Quantity,
|
||||
Amount: resp.Quantity.Float64(),
|
||||
Exchange: by.Name,
|
||||
OrderID: resp.OrderID,
|
||||
ClientOrderID: resp.OrderLinkID,
|
||||
Side: getSide(resp.Side),
|
||||
Type: getTradeType(resp.TradeType),
|
||||
Pair: pair,
|
||||
Cost: resp.CummulativeQuoteQty,
|
||||
Cost: resp.CummulativeQuoteQty.Float64(),
|
||||
AssetType: assetType,
|
||||
Status: getOrderStatus(resp.Status),
|
||||
Price: resp.Price,
|
||||
ExecutedAmount: resp.ExecutedQty,
|
||||
Price: resp.Price.Float64(),
|
||||
ExecutedAmount: resp.ExecutedQty.Float64(),
|
||||
Date: resp.Time.Time(),
|
||||
LastUpdated: resp.UpdateTime.Time(),
|
||||
}, nil
|
||||
@@ -1264,7 +1268,7 @@ func (by *Bybit) GetOrderInfo(ctx context.Context, orderID string, pair currency
|
||||
Side: getSide(resp[0].Side),
|
||||
Type: getTradeType(resp[0].OrderType),
|
||||
Pair: pair,
|
||||
Cost: resp[0].CumulativeQty,
|
||||
Cost: resp[0].CumulativeQty.Float64(),
|
||||
AssetType: assetType,
|
||||
Status: getOrderStatus(resp[0].OrderStatus),
|
||||
Price: resp[0].Price,
|
||||
@@ -1291,7 +1295,7 @@ func (by *Bybit) GetOrderInfo(ctx context.Context, orderID string, pair currency
|
||||
Side: getSide(resp[0].Side),
|
||||
Type: getTradeType(resp[0].OrderType),
|
||||
Pair: pair,
|
||||
Cost: resp[0].CumulativeQty,
|
||||
Cost: resp[0].CumulativeQty.Float64(),
|
||||
AssetType: assetType,
|
||||
Status: getOrderStatus(resp[0].OrderStatus),
|
||||
Price: resp[0].Price,
|
||||
@@ -1318,7 +1322,7 @@ func (by *Bybit) GetOrderInfo(ctx context.Context, orderID string, pair currency
|
||||
Side: getSide(resp[0].Side),
|
||||
Type: getTradeType(resp[0].OrderType),
|
||||
Pair: pair,
|
||||
Cost: resp[0].CumulativeQty,
|
||||
Cost: resp[0].CumulativeQty.Float64(),
|
||||
AssetType: assetType,
|
||||
Status: getOrderStatus(resp[0].OrderStatus),
|
||||
Price: resp[0].Price,
|
||||
@@ -1338,18 +1342,18 @@ func (by *Bybit) GetOrderInfo(ctx context.Context, orderID string, pair currency
|
||||
}
|
||||
|
||||
return order.Detail{
|
||||
Amount: resp[0].Qty,
|
||||
Amount: resp[0].Qty.Float64(),
|
||||
Exchange: by.Name,
|
||||
OrderID: resp[0].ID,
|
||||
ClientOrderID: resp[0].OrderLinkID,
|
||||
Side: getSide(resp[0].Side),
|
||||
Type: getTradeType(resp[0].OrderType),
|
||||
Pair: pair,
|
||||
Cost: resp[0].TotalOrderValue,
|
||||
Cost: resp[0].TotalOrderValue.Float64(),
|
||||
AssetType: assetType,
|
||||
Status: getOrderStatus(resp[0].OrderStatus),
|
||||
Price: resp[0].Price,
|
||||
ExecutedAmount: resp[0].TotalFilledQty,
|
||||
Price: resp[0].Price.Float64(),
|
||||
ExecutedAmount: resp[0].TotalFilledQty.Float64(),
|
||||
Date: resp[0].CreatedAt.Time(),
|
||||
}, nil
|
||||
|
||||
@@ -1453,14 +1457,14 @@ func (by *Bybit) GetActiveOrders(ctx context.Context, req *order.GetOrdersReques
|
||||
for i := range req.Pairs {
|
||||
if req.Pairs[i].String() == openOrders[x].SymbolName {
|
||||
orders = append(orders, order.Detail{
|
||||
Amount: openOrders[x].Quantity,
|
||||
Amount: openOrders[x].Quantity.Float64(),
|
||||
Date: openOrders[x].Time.Time(),
|
||||
Exchange: by.Name,
|
||||
OrderID: openOrders[x].OrderID,
|
||||
ClientOrderID: openOrders[x].OrderLinkID,
|
||||
Side: getSide(openOrders[x].Side),
|
||||
Type: getTradeType(openOrders[x].TradeType),
|
||||
Price: openOrders[x].Price,
|
||||
Price: openOrders[x].Price.Float64(),
|
||||
Status: getOrderStatus(openOrders[x].Status),
|
||||
Pair: req.Pairs[i],
|
||||
AssetType: req.AssetType,
|
||||
@@ -1557,11 +1561,11 @@ func (by *Bybit) GetActiveOrders(ctx context.Context, req *order.GetOrdersReques
|
||||
for i := range req.Pairs {
|
||||
if req.Pairs[i].String() == openOrders[x].Symbol {
|
||||
orders = append(orders, order.Detail{
|
||||
Price: openOrders[x].Price,
|
||||
Amount: openOrders[x].Qty,
|
||||
ExecutedAmount: openOrders[x].TotalFilledQty,
|
||||
RemainingAmount: openOrders[x].Qty - openOrders[x].TotalFilledQty,
|
||||
Fee: openOrders[x].TotalFee,
|
||||
Price: openOrders[x].Price.Float64(),
|
||||
Amount: openOrders[x].Qty.Float64(),
|
||||
ExecutedAmount: openOrders[x].TotalFilledQty.Float64(),
|
||||
RemainingAmount: openOrders[x].Qty.Float64() - openOrders[x].TotalFilledQty.Float64(),
|
||||
Fee: openOrders[x].TotalFee.Float64(),
|
||||
Exchange: by.Name,
|
||||
OrderID: openOrders[x].ID,
|
||||
ClientOrderID: openOrders[x].OrderLinkID,
|
||||
@@ -1610,17 +1614,17 @@ func (by *Bybit) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
|
||||
return nil, err
|
||||
}
|
||||
detail := order.Detail{
|
||||
Amount: resp[i].Quantity,
|
||||
ExecutedAmount: resp[i].ExecutedQty,
|
||||
RemainingAmount: resp[i].Quantity - resp[i].ExecutedQty,
|
||||
Cost: resp[i].CummulativeQuoteQty,
|
||||
Amount: resp[i].Quantity.Float64(),
|
||||
ExecutedAmount: resp[i].ExecutedQty.Float64(),
|
||||
RemainingAmount: resp[i].Quantity.Float64() - resp[i].ExecutedQty.Float64(),
|
||||
Cost: resp[i].CummulativeQuoteQty.Float64(),
|
||||
Date: resp[i].Time.Time(),
|
||||
LastUpdated: resp[i].UpdateTime.Time(),
|
||||
Exchange: by.Name,
|
||||
OrderID: resp[i].OrderID,
|
||||
Side: side,
|
||||
Type: getTradeType(resp[i].TradeType),
|
||||
Price: resp[i].Price,
|
||||
Price: resp[i].Price.Float64(),
|
||||
Pair: pair,
|
||||
Status: getOrderStatus(resp[i].Status),
|
||||
}
|
||||
@@ -1731,16 +1735,16 @@ func (by *Bybit) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
|
||||
return nil, err
|
||||
}
|
||||
detail := order.Detail{
|
||||
Amount: resp[i].Qty,
|
||||
ExecutedAmount: resp[i].TotalFilledQty,
|
||||
RemainingAmount: resp[i].LeavesQty,
|
||||
Amount: resp[i].Qty.Float64(),
|
||||
ExecutedAmount: resp[i].TotalFilledQty.Float64(),
|
||||
RemainingAmount: resp[i].LeavesQty.Float64(),
|
||||
Date: resp[i].CreatedAt.Time(),
|
||||
LastUpdated: resp[i].UpdatedAt.Time(),
|
||||
Exchange: by.Name,
|
||||
OrderID: resp[i].ID,
|
||||
Side: getSide(resp[i].Side),
|
||||
Type: orderType,
|
||||
Price: resp[i].Price,
|
||||
Price: resp[i].Price.Float64(),
|
||||
Pair: pair,
|
||||
Status: orderStatus,
|
||||
}
|
||||
@@ -1879,11 +1883,11 @@ func (by *Bybit) GetHistoricCandles(ctx context.Context, pair currency.Pair, a a
|
||||
for x := range candles {
|
||||
timeSeries[x] = kline.Candle{
|
||||
Time: time.Unix(candles[x].OpenTime, 0),
|
||||
Open: candles[x].Open,
|
||||
High: candles[x].High,
|
||||
Low: candles[x].Low,
|
||||
Close: candles[x].Close,
|
||||
Volume: candles[x].Volume,
|
||||
Open: candles[x].Open.Float64(),
|
||||
High: candles[x].High.Float64(),
|
||||
Low: candles[x].Low.Float64(),
|
||||
Close: candles[x].Close.Float64(),
|
||||
Volume: candles[x].Volume.Float64(),
|
||||
}
|
||||
}
|
||||
case asset.USDTMarginedFutures:
|
||||
@@ -1923,11 +1927,11 @@ func (by *Bybit) GetHistoricCandles(ctx context.Context, pair currency.Pair, a a
|
||||
for x := range candles {
|
||||
timeSeries[x] = kline.Candle{
|
||||
Time: candles[x].OpenTime.Time(),
|
||||
Open: candles[x].Open,
|
||||
High: candles[x].High,
|
||||
Low: candles[x].Low,
|
||||
Close: candles[x].Close,
|
||||
Volume: candles[x].Volume,
|
||||
Open: candles[x].Open.Float64(),
|
||||
High: candles[x].High.Float64(),
|
||||
Low: candles[x].Low.Float64(),
|
||||
Close: candles[x].Close.Float64(),
|
||||
Volume: candles[x].Volume.Float64(),
|
||||
}
|
||||
}
|
||||
default:
|
||||
@@ -1982,11 +1986,11 @@ func (by *Bybit) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
|
||||
for i := range candles {
|
||||
timeSeries = append(timeSeries, kline.Candle{
|
||||
Time: time.Unix(candles[i].OpenTime, 0),
|
||||
Open: candles[i].Open,
|
||||
High: candles[i].High,
|
||||
Low: candles[i].Low,
|
||||
Close: candles[i].Close,
|
||||
Volume: candles[i].Volume,
|
||||
Open: candles[i].Open.Float64(),
|
||||
High: candles[i].High.Float64(),
|
||||
Low: candles[i].Low.Float64(),
|
||||
Close: candles[i].Close.Float64(),
|
||||
Volume: candles[i].Volume.Float64(),
|
||||
})
|
||||
}
|
||||
case asset.USDTMarginedFutures:
|
||||
@@ -2024,11 +2028,11 @@ func (by *Bybit) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
|
||||
for x := range candles {
|
||||
timeSeries = append(timeSeries, kline.Candle{
|
||||
Time: candles[x].OpenTime.Time(),
|
||||
Open: candles[x].Open,
|
||||
High: candles[x].High,
|
||||
Low: candles[x].Low,
|
||||
Close: candles[x].Close,
|
||||
Volume: candles[x].Volume,
|
||||
Open: candles[x].Open.Float64(),
|
||||
High: candles[x].High.Float64(),
|
||||
Low: candles[x].Low.Float64(),
|
||||
Close: candles[x].Close.Float64(),
|
||||
Volume: candles[x].Volume.Float64(),
|
||||
})
|
||||
}
|
||||
default:
|
||||
@@ -2064,3 +2068,46 @@ func (by *Bybit) extractCurrencyPair(symbol string, item asset.Item) (currency.P
|
||||
}
|
||||
return pairs.DeriveFrom(symbol)
|
||||
}
|
||||
|
||||
// UpdateOrderExecutionLimits sets exchange executions for a required asset type
|
||||
func (by *Bybit) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
|
||||
avail, err := by.GetAvailablePairs(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var limits []order.MinMaxLevel
|
||||
switch a {
|
||||
case asset.Spot:
|
||||
var pairsData []PairData
|
||||
pairsData, err = by.GetAllSpotPairs(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
limits = make([]order.MinMaxLevel, 0, len(pairsData))
|
||||
for x := range pairsData {
|
||||
var pair currency.Pair
|
||||
pair, err = avail.DeriveFrom(pairsData[x].Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
limits = append(limits, order.MinMaxLevel{
|
||||
Asset: a,
|
||||
Pair: pair,
|
||||
AmountStepIncrementSize: pairsData[x].BasePrecision.Float64(),
|
||||
QuoteStepIncrementSize: pairsData[x].QuotePrecision.Float64(),
|
||||
MinimumBaseAmount: pairsData[x].MinTradeQuantity.Float64(),
|
||||
MaximumBaseAmount: pairsData[x].MaxTradeQuantity.Float64(),
|
||||
MinimumQuoteAmount: pairsData[x].MinTradeAmount.Float64(),
|
||||
MaximumQuoteAmount: pairsData[x].MaxTradeAmount.Float64(),
|
||||
PriceStepIncrementSize: pairsData[x].MinPricePrecision.Float64(),
|
||||
})
|
||||
}
|
||||
default:
|
||||
// TODO: Add in other assets
|
||||
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
|
||||
}
|
||||
return by.LoadLimits(limits)
|
||||
}
|
||||
|
||||
@@ -389,13 +389,13 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Ticker.LastPrice,
|
||||
High: response.Ticker.HighPrice24h,
|
||||
Low: response.Ticker.LowPrice24h,
|
||||
Last: response.Ticker.LastPrice.Float64(),
|
||||
High: response.Ticker.HighPrice24h.Float64(),
|
||||
Low: response.Ticker.LowPrice24h.Float64(),
|
||||
Bid: response.Ticker.BidPrice,
|
||||
Ask: response.Ticker.AskPrice,
|
||||
Volume: response.Ticker.Volume24h,
|
||||
Close: response.Ticker.PrevPrice24h,
|
||||
Close: response.Ticker.PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Ticker.UpdateAt,
|
||||
AssetType: asset.CoinMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -418,13 +418,13 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Delete[x].LastPrice,
|
||||
High: response.Data.Delete[x].HighPrice24h,
|
||||
Low: response.Data.Delete[x].LowPrice24h,
|
||||
Last: response.Data.Delete[x].LastPrice.Float64(),
|
||||
High: response.Data.Delete[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Delete[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Delete[x].BidPrice,
|
||||
Ask: response.Data.Delete[x].AskPrice,
|
||||
Volume: response.Data.Delete[x].Volume24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Delete[x].UpdateAt,
|
||||
AssetType: asset.CoinMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -442,13 +442,13 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Update[x].LastPrice,
|
||||
High: response.Data.Update[x].HighPrice24h,
|
||||
Low: response.Data.Update[x].LowPrice24h,
|
||||
Last: response.Data.Update[x].LastPrice.Float64(),
|
||||
High: response.Data.Update[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Update[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Update[x].BidPrice,
|
||||
Ask: response.Data.Update[x].AskPrice,
|
||||
Volume: response.Data.Update[x].Volume24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Update[x].UpdateAt,
|
||||
AssetType: asset.CoinMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -466,13 +466,13 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Insert[x].LastPrice,
|
||||
High: response.Data.Insert[x].HighPrice24h,
|
||||
Low: response.Data.Insert[x].LowPrice24h,
|
||||
Last: response.Data.Insert[x].LastPrice.Float64(),
|
||||
High: response.Data.Insert[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Insert[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Insert[x].BidPrice,
|
||||
Ask: response.Data.Insert[x].AskPrice,
|
||||
Volume: response.Data.Insert[x].Volume24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Insert[x].UpdateAt,
|
||||
AssetType: asset.CoinMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -540,13 +540,13 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
OrderID: response.Data[i].OrderID,
|
||||
AssetType: asset.CoinMarginedFutures,
|
||||
Pair: p,
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Side: oSide,
|
||||
Status: oStatus,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -598,7 +598,7 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -610,7 +610,7 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -660,7 +660,7 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -673,7 +673,7 @@ func (by *Bybit) wsCoinHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -709,7 +709,7 @@ func (by *Bybit) processOrderbook(data []WsFuturesOrderbookData, action string,
|
||||
var book orderbook.Base
|
||||
for i := range data {
|
||||
item := orderbook.Item{
|
||||
Price: data[i].Price,
|
||||
Price: data[i].Price.Float64(),
|
||||
Amount: data[i].Size,
|
||||
ID: data[i].ID,
|
||||
}
|
||||
@@ -741,7 +741,7 @@ func (by *Bybit) processOrderbook(data []WsFuturesOrderbookData, action string,
|
||||
var asks, bids []orderbook.Item
|
||||
for i := range data {
|
||||
item := orderbook.Item{
|
||||
Price: data[i].Price,
|
||||
Price: data[i].Price.Float64(),
|
||||
Amount: data[i].Size,
|
||||
ID: data[i].ID,
|
||||
}
|
||||
|
||||
@@ -334,13 +334,13 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Ticker.LastPrice,
|
||||
High: response.Ticker.HighPrice24h,
|
||||
Low: response.Ticker.LowPrice24h,
|
||||
Last: response.Ticker.LastPrice.Float64(),
|
||||
High: response.Ticker.HighPrice24h.Float64(),
|
||||
Low: response.Ticker.LowPrice24h.Float64(),
|
||||
Bid: response.Ticker.BidPrice,
|
||||
Ask: response.Ticker.AskPrice,
|
||||
Volume: response.Ticker.Volume24h,
|
||||
Close: response.Ticker.PrevPrice24h,
|
||||
Close: response.Ticker.PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Ticker.UpdateAt,
|
||||
AssetType: asset.Futures,
|
||||
Pair: p,
|
||||
@@ -363,13 +363,13 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Delete[x].LastPrice,
|
||||
High: response.Data.Delete[x].HighPrice24h,
|
||||
Low: response.Data.Delete[x].LowPrice24h,
|
||||
Last: response.Data.Delete[x].LastPrice.Float64(),
|
||||
High: response.Data.Delete[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Delete[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Delete[x].BidPrice,
|
||||
Ask: response.Data.Delete[x].AskPrice,
|
||||
Volume: response.Data.Delete[x].Volume24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Delete[x].UpdateAt,
|
||||
AssetType: asset.Futures,
|
||||
Pair: p,
|
||||
@@ -387,13 +387,13 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Update[x].LastPrice,
|
||||
High: response.Data.Update[x].HighPrice24h,
|
||||
Low: response.Data.Update[x].LowPrice24h,
|
||||
Last: response.Data.Update[x].LastPrice.Float64(),
|
||||
High: response.Data.Update[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Update[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Update[x].BidPrice,
|
||||
Ask: response.Data.Update[x].AskPrice,
|
||||
Volume: response.Data.Update[x].Volume24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Update[x].UpdateAt,
|
||||
AssetType: asset.Futures,
|
||||
Pair: p,
|
||||
@@ -411,13 +411,13 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Insert[x].LastPrice,
|
||||
High: response.Data.Insert[x].HighPrice24h,
|
||||
Low: response.Data.Insert[x].LowPrice24h,
|
||||
Last: response.Data.Insert[x].LastPrice.Float64(),
|
||||
High: response.Data.Insert[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Insert[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Insert[x].BidPrice,
|
||||
Ask: response.Data.Insert[x].AskPrice,
|
||||
Volume: response.Data.Insert[x].Volume24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Insert[x].UpdateAt,
|
||||
AssetType: asset.Futures,
|
||||
Pair: p,
|
||||
@@ -485,13 +485,13 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
OrderID: response.Data[i].OrderID,
|
||||
AssetType: asset.Futures,
|
||||
Pair: p,
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Side: oSide,
|
||||
Status: oStatus,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -541,7 +541,7 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -553,7 +553,7 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -603,7 +603,7 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -616,7 +616,7 @@ func (by *Bybit) wsFuturesHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
|
||||
@@ -340,13 +340,13 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Ticker.LastPrice,
|
||||
High: response.Ticker.HighPrice24h,
|
||||
Low: response.Ticker.LowPrice24h,
|
||||
Last: response.Ticker.LastPrice.Float64(),
|
||||
High: response.Ticker.HighPrice24h.Float64(),
|
||||
Low: response.Ticker.LowPrice24h.Float64(),
|
||||
Bid: response.Ticker.BidPrice,
|
||||
Ask: response.Ticker.AskPrice,
|
||||
Volume: response.Ticker.Volume24h,
|
||||
Close: response.Ticker.PrevPrice24h,
|
||||
Close: response.Ticker.PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Ticker.UpdateAt,
|
||||
AssetType: asset.USDTMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -369,13 +369,13 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Delete[x].LastPrice,
|
||||
High: response.Data.Delete[x].HighPrice24h,
|
||||
Low: response.Data.Delete[x].LowPrice24h,
|
||||
Last: response.Data.Delete[x].LastPrice.Float64(),
|
||||
High: response.Data.Delete[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Delete[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Delete[x].BidPrice,
|
||||
Ask: response.Data.Delete[x].AskPrice,
|
||||
Volume: response.Data.Delete[x].Volume24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h,
|
||||
Close: response.Data.Delete[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Delete[x].UpdateAt,
|
||||
AssetType: asset.USDTMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -393,13 +393,13 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Update[x].LastPrice,
|
||||
High: response.Data.Update[x].HighPrice24h,
|
||||
Low: response.Data.Update[x].LowPrice24h,
|
||||
Last: response.Data.Update[x].LastPrice.Float64(),
|
||||
High: response.Data.Update[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Update[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Update[x].BidPrice,
|
||||
Ask: response.Data.Update[x].AskPrice,
|
||||
Volume: response.Data.Update[x].Volume24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h,
|
||||
Close: response.Data.Update[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Update[x].UpdateAt,
|
||||
AssetType: asset.USDTMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -417,13 +417,13 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
|
||||
by.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: by.Name,
|
||||
Last: response.Data.Insert[x].LastPrice,
|
||||
High: response.Data.Insert[x].HighPrice24h,
|
||||
Low: response.Data.Insert[x].LowPrice24h,
|
||||
Last: response.Data.Insert[x].LastPrice.Float64(),
|
||||
High: response.Data.Insert[x].HighPrice24h.Float64(),
|
||||
Low: response.Data.Insert[x].LowPrice24h.Float64(),
|
||||
Bid: response.Data.Insert[x].BidPrice,
|
||||
Ask: response.Data.Insert[x].AskPrice,
|
||||
Volume: response.Data.Insert[x].Volume24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h,
|
||||
Close: response.Data.Insert[x].PrevPrice24h.Float64(),
|
||||
LastUpdated: response.Data.Insert[x].UpdateAt,
|
||||
AssetType: asset.USDTMarginedFutures,
|
||||
Pair: p,
|
||||
@@ -493,11 +493,11 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Side: oSide,
|
||||
Status: oStatus,
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[i].Price,
|
||||
Price: response.Data[i].Price.Float64(),
|
||||
Amount: response.Data[i].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -547,7 +547,7 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -559,7 +559,7 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
@@ -609,7 +609,7 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
by.Websocket.DataHandler <- &order.Detail{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
OrderID: response.Data[x].OrderID,
|
||||
@@ -622,7 +622,7 @@ func (by *Bybit) wsUSDTHandleData(respRaw []byte) error {
|
||||
Pair: p,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Price: response.Data[x].Price,
|
||||
Price: response.Data[x].Price.Float64(),
|
||||
Amount: response.Data[x].OrderQty,
|
||||
Exchange: by.Name,
|
||||
Side: oSide,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package bybit
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
)
|
||||
|
||||
var (
|
||||
validFuturesIntervals = []string{
|
||||
@@ -15,10 +19,10 @@ var (
|
||||
|
||||
// OrderbookData stores ob data for cmargined futures
|
||||
type OrderbookData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
Size float64 `json:"size"`
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Size float64 `json:"size"`
|
||||
Side string `json:"side"`
|
||||
}
|
||||
|
||||
// FuturesCandleStick holds kline data
|
||||
@@ -37,46 +41,46 @@ type FuturesCandleStick struct {
|
||||
|
||||
// FuturesCandleStickWithStringParam holds kline data
|
||||
type FuturesCandleStickWithStringParam struct {
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Interval string `json:"interval"`
|
||||
OpenTime int64 `json:"open_time"`
|
||||
Open float64 `json:"open,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
TurnOver float64 `json:"turnover,string"`
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Interval string `json:"interval"`
|
||||
OpenTime int64 `json:"open_time"`
|
||||
Open convert.StringToFloat64 `json:"open"`
|
||||
High convert.StringToFloat64 `json:"high"`
|
||||
Low convert.StringToFloat64 `json:"low"`
|
||||
Close convert.StringToFloat64 `json:"close"`
|
||||
Volume convert.StringToFloat64 `json:"volume"`
|
||||
TurnOver convert.StringToFloat64 `json:"turnover"`
|
||||
}
|
||||
|
||||
// SymbolPriceTicker stores ticker price stats
|
||||
type SymbolPriceTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice float64 `json:"bid_price,string"`
|
||||
AskPrice float64 `json:"ask_price,string"`
|
||||
LastPrice float64 `json:"last_price,string"`
|
||||
LastTickDirection string `json:"last_tick_direction"`
|
||||
Price24hAgo float64 `json:"prev_price_24h,string"`
|
||||
PricePcntChange24h float64 `json:"price_24h_pcnt,string"`
|
||||
HighPrice24h float64 `json:"high_price_24h,string"`
|
||||
LowPrice24h float64 `json:"low_price_24h,string"`
|
||||
Price1hAgo float64 `json:"prev_price_1h,string"`
|
||||
PricePcntChange1h bybitNumericalValue `json:"price_1h_pcnt"`
|
||||
MarkPrice float64 `json:"mark_price,string"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue bybitNumericalValue `json:"open_value"`
|
||||
TotalTurnover bybitNumericalValue `json:"total_turnover"`
|
||||
Turnover24h float64 `json:"turnover_24h,string"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FundingRate float64 `json:"funding_rate,string"`
|
||||
PredictedFundingRate bybitNumericalValue `json:"predicted_funding_rate"`
|
||||
NextFundingTime string `json:"next_funding_time"`
|
||||
CountdownHour int64 `json:"countdown_hour"`
|
||||
DeliveryFeeRate bybitNumericalValue `json:"delivery_fee_rate"`
|
||||
PredictedDeliveryPrice bybitNumericalValue `json:"predicted_delivery_price"`
|
||||
DeliveryTime string `json:"delivery_time"`
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice convert.StringToFloat64 `json:"bid_price"`
|
||||
AskPrice convert.StringToFloat64 `json:"ask_price"`
|
||||
LastPrice convert.StringToFloat64 `json:"last_price"`
|
||||
LastTickDirection string `json:"last_tick_direction"`
|
||||
Price24hAgo convert.StringToFloat64 `json:"prev_price_24h"`
|
||||
PricePcntChange24h convert.StringToFloat64 `json:"price_24h_pcnt"`
|
||||
HighPrice24h convert.StringToFloat64 `json:"high_price_24h"`
|
||||
LowPrice24h convert.StringToFloat64 `json:"low_price_24h"`
|
||||
Price1hAgo convert.StringToFloat64 `json:"prev_price_1h"`
|
||||
PricePcntChange1h convert.StringToFloat64 `json:"price_1h_pcnt"`
|
||||
MarkPrice convert.StringToFloat64 `json:"mark_price"`
|
||||
IndexPrice convert.StringToFloat64 `json:"index_price"`
|
||||
OpenInterest float64 `json:"open_interest"`
|
||||
OpenValue convert.StringToFloat64 `json:"open_value"`
|
||||
TotalTurnover convert.StringToFloat64 `json:"total_turnover"`
|
||||
Turnover24h convert.StringToFloat64 `json:"turnover_24h"`
|
||||
TotalVolume float64 `json:"total_volume"`
|
||||
Volume24h float64 `json:"volume_24h"`
|
||||
FundingRate convert.StringToFloat64 `json:"funding_rate"`
|
||||
PredictedFundingRate convert.StringToFloat64 `json:"predicted_funding_rate"`
|
||||
NextFundingTime string `json:"next_funding_time"`
|
||||
CountdownHour int64 `json:"countdown_hour"`
|
||||
DeliveryFeeRate convert.StringToFloat64 `json:"delivery_fee_rate"`
|
||||
PredictedDeliveryPrice convert.StringToFloat64 `json:"predicted_delivery_price"`
|
||||
DeliveryTime string `json:"delivery_time"`
|
||||
}
|
||||
|
||||
// FuturesPublicTradesData stores recent public trades for futures
|
||||
@@ -101,14 +105,14 @@ type SymbolInfo struct {
|
||||
MakerFee string `json:"maker_fee"`
|
||||
FundingFeeInterval int64 `json:"funding_interval"`
|
||||
LeverageFilter struct {
|
||||
MinLeverage float64 `json:"min_leverage"`
|
||||
MaxLeverage float64 `json:"max_leverage"`
|
||||
LeverageStep float64 `json:"leverage_step,string"`
|
||||
MinLeverage float64 `json:"min_leverage"`
|
||||
MaxLeverage float64 `json:"max_leverage"`
|
||||
LeverageStep convert.StringToFloat64 `json:"leverage_step"`
|
||||
} `json:"leverage_filter"`
|
||||
PriceFilter struct {
|
||||
MinPrice float64 `json:"min_price,string"`
|
||||
MaxPrice float64 `json:"max_price,string"`
|
||||
TickSize float64 `json:"tick_size,string"`
|
||||
MinPrice convert.StringToFloat64 `json:"min_price"`
|
||||
MaxPrice convert.StringToFloat64 `json:"max_price"`
|
||||
TickSize convert.StringToFloat64 `json:"tick_size"`
|
||||
} `json:"price_filter"`
|
||||
LotSizeFilter struct {
|
||||
MinTradeQty float64 `json:"min_trading_qty"`
|
||||
@@ -131,13 +135,13 @@ type MarkPriceKlineData struct {
|
||||
|
||||
// IndexPriceKlineData stores index price kline data
|
||||
type IndexPriceKlineData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Interval string `json:"period"`
|
||||
StartAt int64 `json:"open_time"`
|
||||
Open float64 `json:"open,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Interval string `json:"period"`
|
||||
StartAt int64 `json:"open_time"`
|
||||
Open convert.StringToFloat64 `json:"open"`
|
||||
High convert.StringToFloat64 `json:"high"`
|
||||
Low convert.StringToFloat64 `json:"low"`
|
||||
Close convert.StringToFloat64 `json:"close"`
|
||||
}
|
||||
|
||||
// OpenInterestData stores open interest data
|
||||
@@ -242,35 +246,35 @@ type FuturesRealtimeOrderData struct {
|
||||
// FuturesActiveRealtimeOrder stores future active realtime order
|
||||
type FuturesActiveRealtimeOrder struct {
|
||||
FuturesRealtimeOrderData
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
LastExecutionTime string `json:"last_exec_time"`
|
||||
LastExecutionPrice float64 `json:"last_exec_price"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
LeaveValue float64 `json:"leaves_value,string"`
|
||||
CumulativeQty float64 `json:"cum_exec_qty,string"`
|
||||
CumulativeValue float64 `json:"cum_exec_value,string"`
|
||||
CumulativeFee float64 `json:"cum_exec_fee,string"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
CreatedAt time.Time `json:"create_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
OrderID string `json:"order_id"`
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
LastExecutionTime string `json:"last_exec_time"`
|
||||
LastExecutionPrice float64 `json:"last_exec_price"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
LeaveValue convert.StringToFloat64 `json:"leaves_value"`
|
||||
CumulativeQty convert.StringToFloat64 `json:"cum_exec_qty"`
|
||||
CumulativeValue convert.StringToFloat64 `json:"cum_exec_value"`
|
||||
CumulativeFee convert.StringToFloat64 `json:"cum_exec_fee"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
CreatedAt time.Time `json:"create_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
OrderID string `json:"order_id"`
|
||||
}
|
||||
|
||||
// CoinFuturesConditionalRealtimeOrder stores CMF future coinditional realtime order
|
||||
type CoinFuturesConditionalRealtimeOrder struct {
|
||||
FuturesRealtimeOrderData
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
LeaveValue float64 `json:"leaves_value,string"`
|
||||
CumulativeQty float64 `json:"cum_exec_qty,string"`
|
||||
CumulativeValue float64 `json:"cum_exec_value,string"`
|
||||
CumulativeFee float64 `json:"cum_exec_fee,string"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
CreatedAt string `json:"create_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
OrderID string `json:"order_id"`
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
LeaveValue convert.StringToFloat64 `json:"leaves_value"`
|
||||
CumulativeQty convert.StringToFloat64 `json:"cum_exec_qty"`
|
||||
CumulativeValue convert.StringToFloat64 `json:"cum_exec_value"`
|
||||
CumulativeFee convert.StringToFloat64 `json:"cum_exec_fee"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
CancelType string `json:"cancel_type"`
|
||||
CreatedAt string `json:"create_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
OrderID string `json:"order_id"`
|
||||
}
|
||||
|
||||
// FuturesConditionalRealtimeOrder stores future conditional realtime order
|
||||
@@ -375,10 +379,10 @@ type FuturesCancelOrderData struct {
|
||||
// FuturesCancelOrderResp stores future cancel order response
|
||||
type FuturesCancelOrderResp struct {
|
||||
FuturesCancelOrderData
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
BasePrice float64 `json:"base_price,string"`
|
||||
ExpectedDirection string `json:"expected_direction"`
|
||||
StopOrderType string `json:"stop_order_type"`
|
||||
TriggerBy string `json:"trigger_by"`
|
||||
BasePrice convert.StringToFloat64 `json:"base_price"`
|
||||
ExpectedDirection string `json:"expected_direction"`
|
||||
}
|
||||
|
||||
// RiskInfo stores risk information
|
||||
@@ -397,23 +401,23 @@ type RiskInfo struct {
|
||||
|
||||
// RiskInfoWithStringParam stores risk information where string params
|
||||
type RiskInfoWithStringParam struct {
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Limit int64 `json:"limit"`
|
||||
MaintainMargin float64 `json:"maintain_margin,string"`
|
||||
StartingMargin float64 `json:"starting_margin,string"`
|
||||
Section []string `json:"section"`
|
||||
IsLowestRisk int64 `json:"is_lowest_risk"`
|
||||
CreatedAt string `json:"create_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
MaxLeverage float64 `json:"max_leverage,string"`
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Limit int64 `json:"limit"`
|
||||
MaintainMargin convert.StringToFloat64 `json:"maintain_margin"`
|
||||
StartingMargin convert.StringToFloat64 `json:"starting_margin"`
|
||||
Section []string `json:"section"`
|
||||
IsLowestRisk int64 `json:"is_lowest_risk"`
|
||||
CreatedAt string `json:"create_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
MaxLeverage convert.StringToFloat64 `json:"max_leverage"`
|
||||
}
|
||||
|
||||
// FundingInfo stores funding information
|
||||
type FundingInfo struct {
|
||||
Symbol string `json:"symbol"`
|
||||
FundingRate float64 `json:"funding_rate,string"`
|
||||
FundingRateTimestamp int64 `json:"funding_rate_timestamp"`
|
||||
Symbol string `json:"symbol"`
|
||||
FundingRate convert.StringToFloat64 `json:"funding_rate"`
|
||||
FundingRateTimestamp int64 `json:"funding_rate_timestamp"`
|
||||
}
|
||||
|
||||
// USDTFundingInfo stores USDT funding information
|
||||
@@ -451,19 +455,19 @@ type Position struct {
|
||||
|
||||
// PositionWithStringParam stores position with string params
|
||||
type PositionWithStringParam struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
PositionValue float64 `json:"position_value,string"`
|
||||
EntryPrice float64 `json:"entry_price,string"`
|
||||
LiquidationPrice float64 `json:"liq_price,string"`
|
||||
BankruptcyPrice float64 `json:"bust_price,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
PositionMargin float64 `json:"position_margin,string"`
|
||||
OccupiedClosingFee float64 `json:"occ_closing_fee,string"`
|
||||
RealisedPNL float64 `json:"realised_pnl,string"`
|
||||
AccumulatedRealisedPNL float64 `json:"cum_realised_pnl,string"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Size float64 `json:"size"`
|
||||
PositionValue convert.StringToFloat64 `json:"position_value"`
|
||||
EntryPrice convert.StringToFloat64 `json:"entry_price"`
|
||||
LiquidationPrice convert.StringToFloat64 `json:"liq_price"`
|
||||
BankruptcyPrice convert.StringToFloat64 `json:"bust_price"`
|
||||
Leverage convert.StringToFloat64 `json:"leverage"`
|
||||
PositionMargin convert.StringToFloat64 `json:"position_margin"`
|
||||
OccupiedClosingFee convert.StringToFloat64 `json:"occ_closing_fee"`
|
||||
RealisedPNL convert.StringToFloat64 `json:"realised_pnl"`
|
||||
AccumulatedRealisedPNL convert.StringToFloat64 `json:"cum_realised_pnl"`
|
||||
}
|
||||
|
||||
// PositionData stores position data
|
||||
@@ -482,54 +486,54 @@ type PositionData struct {
|
||||
// PositionDataWithStringParam stores position data with string params
|
||||
type PositionDataWithStringParam struct {
|
||||
PositionWithStringParam
|
||||
IsIsolated bool `json:"is_isolated"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
UnrealisedPNL float64 `json:"unrealised_pnl"`
|
||||
DeleverageIndicator int64 `json:"deleverage_indicator"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
TakeProfit float64 `json:"take_profit,string"`
|
||||
StopLoss float64 `json:"stop_loss,string"`
|
||||
TrailingStop float64 `json:"trailing_stop,string"`
|
||||
IsIsolated bool `json:"is_isolated"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
UnrealisedPNL float64 `json:"unrealised_pnl"`
|
||||
DeleverageIndicator int64 `json:"deleverage_indicator"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
TakeProfit convert.StringToFloat64 `json:"take_profit"`
|
||||
StopLoss convert.StringToFloat64 `json:"stop_loss"`
|
||||
TrailingStop convert.StringToFloat64 `json:"trailing_stop"`
|
||||
}
|
||||
|
||||
// PositionResp stores position response
|
||||
type PositionResp struct {
|
||||
PositionDataWithStringParam
|
||||
PositionID int64 `json:"position_idx"`
|
||||
Mode int64 `json:"mode"`
|
||||
ID int64 `json:"id"`
|
||||
EffectiveLeverage float64 `json:"effective_leverage,string"`
|
||||
OccupiedFundingFee float64 `json:"occ_funding_fee,string"`
|
||||
PositionStatus string `json:"position_status"`
|
||||
CalculatedData string `json:"oc_calc_data"`
|
||||
OrderMargin float64 `json:"order_margin,string"`
|
||||
WalletBalance float64 `json:"wallet_balance,string"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
PositionSequence int64 `json:"position_seq"`
|
||||
TakeProfitStopLossMode string `json:"tp_sl_mode"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
PositionID int64 `json:"position_idx"`
|
||||
Mode int64 `json:"mode"`
|
||||
ID int64 `json:"id"`
|
||||
EffectiveLeverage convert.StringToFloat64 `json:"effective_leverage"`
|
||||
OccupiedFundingFee convert.StringToFloat64 `json:"occ_funding_fee"`
|
||||
PositionStatus string `json:"position_status"`
|
||||
CalculatedData string `json:"oc_calc_data"`
|
||||
OrderMargin convert.StringToFloat64 `json:"order_margin"`
|
||||
WalletBalance convert.StringToFloat64 `json:"wallet_balance"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
PositionSequence int64 `json:"position_seq"`
|
||||
TakeProfitStopLossMode string `json:"tp_sl_mode"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// SetTradingAndStopResp stores set trading and stop response
|
||||
type SetTradingAndStopResp struct {
|
||||
PositionData
|
||||
ID int64 `json:"id"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
OccupiedFundingFee float64 `json:"occ_funding_fee,string"`
|
||||
TakeProfit float64 `json:"take_profit,string"`
|
||||
StopLoss float64 `json:"stop_loss,string"`
|
||||
PositionStatus string `json:"position_status"`
|
||||
DeleverageIndicator int64 `json:"deleverage_indicator"`
|
||||
CalculatedData string `json:"oc_calc_data"`
|
||||
OrderMargin float64 `json:"order_margin,string"`
|
||||
WalletBalance float64 `json:"wallet_balance,string"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
PositionSequence int64 `json:"position_seq"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
ID int64 `json:"id"`
|
||||
RiskID int64 `json:"risk_id"`
|
||||
AutoAddMargin int64 `json:"auto_add_margin"`
|
||||
OccupiedFundingFee convert.StringToFloat64 `json:"occ_funding_fee"`
|
||||
TakeProfit convert.StringToFloat64 `json:"take_profit"`
|
||||
StopLoss convert.StringToFloat64 `json:"stop_loss"`
|
||||
PositionStatus string `json:"position_status"`
|
||||
DeleverageIndicator int64 `json:"deleverage_indicator"`
|
||||
CalculatedData string `json:"oc_calc_data"`
|
||||
OrderMargin convert.StringToFloat64 `json:"order_margin"`
|
||||
WalletBalance convert.StringToFloat64 `json:"wallet_balance"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
PositionSequence int64 `json:"position_seq"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdateAt string `json:"updated_at"`
|
||||
ExtensionField map[string]interface{} `json:"ext_fields"`
|
||||
}
|
||||
|
||||
// USDTPositionResp stores USDT position response
|
||||
@@ -547,24 +551,24 @@ type UpdateMarginResp struct {
|
||||
|
||||
// TradeData stores trade data
|
||||
type TradeData struct {
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkedID string `json:"order_link_id"`
|
||||
OrderSide string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
ExecutionID string `json:"exec_id"`
|
||||
OrderPrice float64 `json:"order_price"`
|
||||
OrderQty float64 `json:"order_qty"`
|
||||
OrderType string `json:"order_type"`
|
||||
FeeRate float64 `json:"fee_rate"`
|
||||
ExecutionFee float64 `json:"exec_fee,string"`
|
||||
ExecutionPrice float64 `json:"exec_price,string"`
|
||||
ExecutionQty float64 `json:"exec_qty"`
|
||||
ExecutionType string `json:"exec_type"`
|
||||
ExecutionValue float64 `json:"exec_value,string"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
ClosedSize float64 `json:"closed_size"`
|
||||
LastLiquidity string `json:"last_liquidity_ind"`
|
||||
TradeTimeMs int64 `json:"trade_time_ms"`
|
||||
OrderID string `json:"order_id"`
|
||||
OrderLinkedID string `json:"order_link_id"`
|
||||
OrderSide string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
ExecutionID string `json:"exec_id"`
|
||||
OrderPrice float64 `json:"order_price"`
|
||||
OrderQty float64 `json:"order_qty"`
|
||||
OrderType string `json:"order_type"`
|
||||
FeeRate float64 `json:"fee_rate"`
|
||||
ExecutionFee convert.StringToFloat64 `json:"exec_fee"`
|
||||
ExecutionPrice convert.StringToFloat64 `json:"exec_price"`
|
||||
ExecutionQty float64 `json:"exec_qty"`
|
||||
ExecutionType string `json:"exec_type"`
|
||||
ExecutionValue convert.StringToFloat64 `json:"exec_value"`
|
||||
LeavesQty float64 `json:"leaves_qty"`
|
||||
ClosedSize float64 `json:"closed_size"`
|
||||
LastLiquidity string `json:"last_liquidity_ind"`
|
||||
TradeTimeMs int64 `json:"trade_time_ms"`
|
||||
}
|
||||
|
||||
// TradeResp stores trade response
|
||||
@@ -650,30 +654,30 @@ type WalletData struct {
|
||||
|
||||
// FundRecord stores funding records
|
||||
type FundRecord struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Coin string `json:"coin"`
|
||||
Type string `json:"type"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
TxID string `json:"tx_id"`
|
||||
Address string `json:"address"`
|
||||
WalletBalance float64 `json:"wallet_balance,string"`
|
||||
ExecutionTime string `json:"exec_time"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Coin string `json:"coin"`
|
||||
Type string `json:"type"`
|
||||
Amount convert.StringToFloat64 `json:"amount"`
|
||||
TxID string `json:"tx_id"`
|
||||
Address string `json:"address"`
|
||||
WalletBalance convert.StringToFloat64 `json:"wallet_balance"`
|
||||
ExecutionTime string `json:"exec_time"`
|
||||
CrossSequence int64 `json:"cross_seq"`
|
||||
}
|
||||
|
||||
// FundWithdrawalRecord stores funding withdrawal records
|
||||
type FundWithdrawalRecord struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Coin string `json:"coin"`
|
||||
Status string `json:"status"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Fee float64 `json:"fee"`
|
||||
Address string `json:"address"`
|
||||
TxID string `json:"tx_id"`
|
||||
SubmittedAt time.Time `json:"submited_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Coin string `json:"coin"`
|
||||
Status string `json:"status"`
|
||||
Amount convert.StringToFloat64 `json:"amount"`
|
||||
Fee float64 `json:"fee"`
|
||||
Address string `json:"address"`
|
||||
TxID string `json:"tx_id"`
|
||||
SubmittedAt time.Time `json:"submited_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// AssetExchangeRecord stores asset exchange records
|
||||
@@ -690,79 +694,79 @@ type AssetExchangeRecord struct {
|
||||
|
||||
// USDCOrderbookData stores orderbook data for USDCMarginedFutures
|
||||
type USDCOrderbookData struct {
|
||||
Price float64 `json:"price,string"`
|
||||
Size float64 `json:"size,string"`
|
||||
Side string `json:"side"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
Size convert.StringToFloat64 `json:"size"`
|
||||
Side string `json:"side"`
|
||||
}
|
||||
|
||||
// USDCContract stores contract data
|
||||
type USDCContract struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
BaseCoin string `json:"baseCoin"`
|
||||
QuoteCoin string `json:"quoteCoin"`
|
||||
TakerFeeRate float64 `json:"takerFeeRate,string"`
|
||||
MakerFeeRate float64 `json:"makerFeeRate,string"`
|
||||
MinLeverage float64 `json:"minLeverage,string"`
|
||||
MaxLeverage float64 `json:"maxLeverage,string"`
|
||||
LeverageStep float64 `json:"leverageStep,string"`
|
||||
MinPrice float64 `json:"minPrice,string"`
|
||||
MaxPrice float64 `json:"maxPrice,string"`
|
||||
TickSize float64 `json:"tickSize,string"`
|
||||
MaxTradingQty float64 `json:"maxTradingQty,string"`
|
||||
MinTradingQty float64 `json:"minTradingQty,string"`
|
||||
QtyStep float64 `json:"qtyStep,string"`
|
||||
DeliveryTime bybitTimeMilliSecStr `json:"deliveryTime"`
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
BaseCoin string `json:"baseCoin"`
|
||||
QuoteCoin string `json:"quoteCoin"`
|
||||
TakerFeeRate convert.StringToFloat64 `json:"takerFeeRate"`
|
||||
MakerFeeRate convert.StringToFloat64 `json:"makerFeeRate"`
|
||||
MinLeverage convert.StringToFloat64 `json:"minLeverage"`
|
||||
MaxLeverage convert.StringToFloat64 `json:"maxLeverage"`
|
||||
LeverageStep convert.StringToFloat64 `json:"leverageStep"`
|
||||
MinPrice convert.StringToFloat64 `json:"minPrice"`
|
||||
MaxPrice convert.StringToFloat64 `json:"maxPrice"`
|
||||
TickSize convert.StringToFloat64 `json:"tickSize"`
|
||||
MaxTradingQty convert.StringToFloat64 `json:"maxTradingQty"`
|
||||
MinTradingQty convert.StringToFloat64 `json:"minTradingQty"`
|
||||
QtyStep convert.StringToFloat64 `json:"qtyStep"`
|
||||
DeliveryTime bybitTimeMilliSecStr `json:"deliveryTime"`
|
||||
}
|
||||
|
||||
// USDCSymbol stores symbol data
|
||||
type USDCSymbol struct {
|
||||
Symbol string `json:"symbol"`
|
||||
NextFundingTime string `json:"nextFundingTime"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
BidSize float64 `json:"bidSize,string"`
|
||||
Ask float64 `json:"ask,string"`
|
||||
AskSize float64 `json:"askSize,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
OpenInterest float64 `json:"openInterest,string"`
|
||||
IndexPrice float64 `json:"indexPrice,string"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
Change24h float64 `json:"change24h,string"`
|
||||
High24h float64 `json:"high24h,string"`
|
||||
Low24h float64 `json:"low24h,string"`
|
||||
Volume24h float64 `json:"volume24h,string"`
|
||||
Turnover24h float64 `json:"turnover24h,string"`
|
||||
TotalVolume float64 `json:"totalVolume,string"`
|
||||
TotalTurnover float64 `json:"totalTurnover,string"`
|
||||
FundingRate float64 `json:"fundingRate,string"`
|
||||
PredictedFundingRate float64 `json:"predictedFundingRate,string"`
|
||||
CountdownHour float64 `json:"countdownHour,string"`
|
||||
UnderlyingPrice string `json:"underlyingPrice"`
|
||||
Symbol string `json:"symbol"`
|
||||
NextFundingTime string `json:"nextFundingTime"`
|
||||
Bid convert.StringToFloat64 `json:"bid"`
|
||||
BidSize convert.StringToFloat64 `json:"bidSize"`
|
||||
Ask convert.StringToFloat64 `json:"ask"`
|
||||
AskSize convert.StringToFloat64 `json:"askSize"`
|
||||
LastPrice convert.StringToFloat64 `json:"lastPrice"`
|
||||
OpenInterest convert.StringToFloat64 `json:"openInterest"`
|
||||
IndexPrice convert.StringToFloat64 `json:"indexPrice"`
|
||||
MarkPrice convert.StringToFloat64 `json:"markPrice"`
|
||||
Change24h convert.StringToFloat64 `json:"change24h"`
|
||||
High24h convert.StringToFloat64 `json:"high24h"`
|
||||
Low24h convert.StringToFloat64 `json:"low24h"`
|
||||
Volume24h convert.StringToFloat64 `json:"volume24h"`
|
||||
Turnover24h convert.StringToFloat64 `json:"turnover24h"`
|
||||
TotalVolume convert.StringToFloat64 `json:"totalVolume"`
|
||||
TotalTurnover convert.StringToFloat64 `json:"totalTurnover"`
|
||||
FundingRate convert.StringToFloat64 `json:"fundingRate"`
|
||||
PredictedFundingRate convert.StringToFloat64 `json:"predictedFundingRate"`
|
||||
CountdownHour convert.StringToFloat64 `json:"countdownHour"`
|
||||
UnderlyingPrice string `json:"underlyingPrice"`
|
||||
}
|
||||
|
||||
// USDCKlineBase stores Kline Base
|
||||
type USDCKlineBase struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Period string `json:"period"`
|
||||
OpenTime bybitTimeSecStr `json:"openTime"`
|
||||
Open float64 `json:"open,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Period string `json:"period"`
|
||||
OpenTime bybitTimeSecStr `json:"openTime"`
|
||||
Open convert.StringToFloat64 `json:"open"`
|
||||
High convert.StringToFloat64 `json:"high"`
|
||||
Low convert.StringToFloat64 `json:"low"`
|
||||
Close convert.StringToFloat64 `json:"close"`
|
||||
}
|
||||
|
||||
// USDCKline stores kline data
|
||||
type USDCKline struct {
|
||||
USDCKlineBase
|
||||
Volume float64 `json:"volume,string"`
|
||||
Turnover float64 `json:"turnover,string"`
|
||||
Volume convert.StringToFloat64 `json:"volume"`
|
||||
Turnover convert.StringToFloat64 `json:"turnover"`
|
||||
}
|
||||
|
||||
// USDCOpenInterest stores open interest data
|
||||
type USDCOpenInterest struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"timestamp"`
|
||||
OpenInterest float64 `json:"openInterest,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"timestamp"`
|
||||
OpenInterest convert.StringToFloat64 `json:"openInterest"`
|
||||
}
|
||||
|
||||
// USDCLargeOrder stores large order data
|
||||
@@ -783,184 +787,191 @@ type USDCAccountRatio struct {
|
||||
|
||||
// USDCTrade stores trade data
|
||||
type USDCTrade struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderPrice float64 `json:"orderPrice,string"`
|
||||
OrderQty float64 `json:"orderQty,string"`
|
||||
Side string `json:"side"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"time"`
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderPrice convert.StringToFloat64 `json:"orderPrice"`
|
||||
OrderQty convert.StringToFloat64 `json:"orderQty"`
|
||||
Side string `json:"side"`
|
||||
Timestamp bybitTimeMilliSecStr `json:"time"`
|
||||
}
|
||||
|
||||
// USDCCreateOrderResp stores create order response
|
||||
type USDCCreateOrderResp struct {
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderPrice float64 `json:"orderPrice,string"`
|
||||
OrderQty float64 `json:"orderQty,string"`
|
||||
OrderType string `json:"orderType"`
|
||||
Side string `json:"side"`
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderPrice convert.StringToFloat64 `json:"orderPrice"`
|
||||
OrderQty convert.StringToFloat64 `json:"orderQty"`
|
||||
OrderType string `json:"orderType"`
|
||||
Side string `json:"side"`
|
||||
}
|
||||
|
||||
// USDCOrder store order data
|
||||
type USDCOrder struct {
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderType string `json:"orderType"`
|
||||
Side string `json:"side"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TotalOrderValue float64 `json:"cumExecValue,string"`
|
||||
TotalFilledQty float64 `json:"cumExecQty,string"`
|
||||
TotalFee float64 `json:"cumExecFee,string"`
|
||||
InitialMargin string `json:"orderIM"`
|
||||
OrderStatus string `json:"orderStatus"`
|
||||
TakeProfit float64 `json:"takeProfit,string"`
|
||||
StopLoss float64 `json:"stopLoss,string"`
|
||||
TPTriggerBy string `json:"tpTriggerBy"`
|
||||
SLTriggerBy string `json:"slTriggerBy"`
|
||||
LastExecPrice float64 `json:"lastExecPrice"`
|
||||
BasePrice string `json:"basePrice"`
|
||||
TriggerPrice float64 `json:"triggerPrice,string"`
|
||||
TriggerBy string `json:"triggerBy"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
StopOrderType string `json:"stopOrderType"`
|
||||
CloseOnTrigger string `json:"closeOnTrigger"`
|
||||
CreatedAt bybitTimeMilliSecStr `json:"createdAt"`
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderType string `json:"orderType"`
|
||||
Side string `json:"side"`
|
||||
Qty convert.StringToFloat64 `json:"qty"`
|
||||
Price convert.StringToFloat64 `json:"price"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
TotalOrderValue convert.StringToFloat64 `json:"cumExecValue"`
|
||||
TotalFilledQty convert.StringToFloat64 `json:"cumExecQty"`
|
||||
TotalFee convert.StringToFloat64 `json:"cumExecFee"`
|
||||
InitialMargin string `json:"orderIM"`
|
||||
OrderStatus string `json:"orderStatus"`
|
||||
TakeProfit convert.StringToFloat64 `json:"takeProfit"`
|
||||
StopLoss convert.StringToFloat64 `json:"stopLoss"`
|
||||
TPTriggerBy string `json:"tpTriggerBy"`
|
||||
SLTriggerBy string `json:"slTriggerBy"`
|
||||
LastExecPrice float64 `json:"lastExecPrice"`
|
||||
BasePrice string `json:"basePrice"`
|
||||
TriggerPrice convert.StringToFloat64 `json:"triggerPrice"`
|
||||
TriggerBy string `json:"triggerBy"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
StopOrderType string `json:"stopOrderType"`
|
||||
CloseOnTrigger string `json:"closeOnTrigger"`
|
||||
CreatedAt bybitTimeMilliSecStr `json:"createdAt"`
|
||||
}
|
||||
|
||||
// USDCOrderHistory stores order history
|
||||
type USDCOrderHistory struct {
|
||||
USDCOrder
|
||||
LeavesQty float64 `json:"leavesQty,string"` // Est. unfilled order qty
|
||||
CashFlow string `json:"cashFlow"`
|
||||
RealisedPnl float64 `json:"realisedPnl,string"`
|
||||
UpdatedAt bybitTimeMilliSecStr `json:"updatedAt"`
|
||||
LeavesQty convert.StringToFloat64 `json:"leavesQty"` // Est. unfilled order qty
|
||||
CashFlow string `json:"cashFlow"`
|
||||
RealisedPnl convert.StringToFloat64 `json:"realisedPnl"`
|
||||
UpdatedAt bybitTimeMilliSecStr `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// USDCTradeHistory stores trade history
|
||||
type USDCTradeHistory struct {
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
TradeID string `json:"tradeId"`
|
||||
ExecPrice float64 `json:"execPrice,string"`
|
||||
ExecQty float64 `json:"execQty,string"`
|
||||
ExecFee float64 `json:"execFee,string"`
|
||||
FeeRate float64 `json:"feeRate,string"`
|
||||
ExecType string `json:"execType"`
|
||||
ExecValue float64 `json:"execValue,string"`
|
||||
TradeTime bybitTimeMilliSecStr `json:"tradeTime"`
|
||||
LastLiquidityInd string `json:"lastLiquidityInd"`
|
||||
ID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
TradeID string `json:"tradeId"`
|
||||
ExecPrice convert.StringToFloat64 `json:"execPrice"`
|
||||
ExecQty convert.StringToFloat64 `json:"execQty"`
|
||||
ExecFee convert.StringToFloat64 `json:"execFee"`
|
||||
FeeRate convert.StringToFloat64 `json:"feeRate"`
|
||||
ExecType string `json:"execType"`
|
||||
ExecValue convert.StringToFloat64 `json:"execValue"`
|
||||
TradeTime bybitTimeMilliSecStr `json:"tradeTime"`
|
||||
LastLiquidityInd string `json:"lastLiquidityInd"`
|
||||
}
|
||||
|
||||
// USDCTxLog stores transaction log data
|
||||
type USDCTxLog struct {
|
||||
TxTime bybitTimeMilliSecStr `json:"transactionTime"`
|
||||
Symbol string `json:"symbol"`
|
||||
Type string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
Size float64 `json:"size,string"`
|
||||
TradePrice float64 `json:"tradePrice,string"`
|
||||
Funding float64 `json:"funding,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
CashFlow string `json:"cashFlow"`
|
||||
Change float64 `json:"change,string"`
|
||||
WalletBalance float64 `json:"walletBalance,string"`
|
||||
FeeRate float64 `json:"feeRate,string"`
|
||||
TradeID string `json:"tradeId"`
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Info string `json:"info"`
|
||||
TxTime bybitTimeMilliSecStr `json:"transactionTime"`
|
||||
Symbol string `json:"symbol"`
|
||||
Type string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Quantity convert.StringToFloat64 `json:"qty"`
|
||||
Size convert.StringToFloat64 `json:"size"`
|
||||
TradePrice convert.StringToFloat64 `json:"tradePrice"`
|
||||
Funding convert.StringToFloat64 `json:"funding"`
|
||||
Fee convert.StringToFloat64 `json:"fee"`
|
||||
CashFlow string `json:"cashFlow"`
|
||||
Change convert.StringToFloat64 `json:"change"`
|
||||
WalletBalance convert.StringToFloat64 `json:"walletBalance"`
|
||||
FeeRate convert.StringToFloat64 `json:"feeRate"`
|
||||
TradeID string `json:"tradeId"`
|
||||
OrderID string `json:"orderId"`
|
||||
OrderLinkID string `json:"orderLinkId"`
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
// USDCWalletBalance store USDC wallet balance
|
||||
type USDCWalletBalance struct {
|
||||
Equity float64 `json:"equity,string"`
|
||||
WalletBalance float64 `json:"walletBalance,string"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
AccountIM float64 `json:"accountIM,string"`
|
||||
AccountMM float64 `json:"accountMM,string"`
|
||||
TotalRPL float64 `json:"totalRPL,string"`
|
||||
TotalSessionUPL float64 `json:"totalSessionUPL,string"`
|
||||
TotalSessionRPL float64 `json:"totalSessionRPL,string"`
|
||||
Equity convert.StringToFloat64 `json:"equity"`
|
||||
WalletBalance convert.StringToFloat64 `json:"walletBalance"`
|
||||
AvailableBalance convert.StringToFloat64 `json:"availableBalance"`
|
||||
AccountIM convert.StringToFloat64 `json:"accountIM"`
|
||||
AccountMM convert.StringToFloat64 `json:"accountMM"`
|
||||
TotalRPL convert.StringToFloat64 `json:"totalRPL"`
|
||||
TotalSessionUPL convert.StringToFloat64 `json:"totalSessionUPL"`
|
||||
TotalSessionRPL convert.StringToFloat64 `json:"totalSessionRPL"`
|
||||
}
|
||||
|
||||
// USDCAssetInfo stores USDC asset data
|
||||
type USDCAssetInfo struct {
|
||||
BaseCoin string `json:"baseCoin"`
|
||||
TotalDelta float64 `json:"totalDelta,string"`
|
||||
TotalGamma float64 `json:"totalGamma,string"`
|
||||
TotalVega float64 `json:"totalVega,string"`
|
||||
TotalTheta float64 `json:"totalTheta,string"`
|
||||
TotalRPL float64 `json:"totalRPL,string"`
|
||||
SessionUPL float64 `json:"sessionUPL,string"`
|
||||
SessionRPL float64 `json:"sessionRPL,string"`
|
||||
IM float64 `json:"im,string"`
|
||||
MM float64 `json:"mm,string"`
|
||||
BaseCoin string `json:"baseCoin"`
|
||||
TotalDelta convert.StringToFloat64 `json:"totalDelta"`
|
||||
TotalGamma convert.StringToFloat64 `json:"totalGamma"`
|
||||
TotalVega convert.StringToFloat64 `json:"totalVega"`
|
||||
TotalTheta convert.StringToFloat64 `json:"totalTheta"`
|
||||
TotalRPL convert.StringToFloat64 `json:"totalRPL"`
|
||||
SessionUPL convert.StringToFloat64 `json:"sessionUPL"`
|
||||
SessionRPL convert.StringToFloat64 `json:"sessionRPL"`
|
||||
IM convert.StringToFloat64 `json:"im"`
|
||||
MM convert.StringToFloat64 `json:"mm"`
|
||||
}
|
||||
|
||||
// USDCPosition store USDC position data
|
||||
type USDCPosition struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
ClosingFee float64 `json:"occClosingFee,string"`
|
||||
LiquidPrice string `json:"liqPrice"`
|
||||
Position float64 `json:"positionValue"`
|
||||
TakeProfit float64 `json:"takeProfit,string"`
|
||||
RiskID string `json:"riskId"`
|
||||
TrailingStop float64 `json:"trailingStop,string"`
|
||||
UnrealisedPnl float64 `json:"unrealisedPnl,string"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
CumRealisedPnl float64 `json:"cumRealisedPnl,string"`
|
||||
PositionMM float64 `json:"positionMM,string"`
|
||||
PositionIM float64 `json:"positionIM,string"`
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
Size float64 `json:"size,string"`
|
||||
SessionRPL float64 `json:"sessionRPL,string"`
|
||||
SessionUPL float64 `json:"sessionUPL,string"`
|
||||
StopLoss float64 `json:"stopLoss,string"`
|
||||
OrderMargin float64 `json:"orderMargin,string"`
|
||||
SessionAvgPrice float64 `json:"sessionAvgPrice,string"`
|
||||
CreatedAt bybitTimeMilliSecStr `json:"createdAt"`
|
||||
UpdatedAt bybitTimeMilliSecStr `json:"updatedAt"`
|
||||
TpSLMode string `json:"tpSLMode"`
|
||||
Side string `json:"side"`
|
||||
BustPrice string `json:"bustPrice"`
|
||||
PositionStatus string `json:"positionStatus"`
|
||||
DeleverageIndicator int64 `json:"deleverageIndicator"`
|
||||
Symbol string `json:"symbol"`
|
||||
Leverage convert.StringToFloat64 `json:"leverage"`
|
||||
ClosingFee convert.StringToFloat64 `json:"occClosingFee"`
|
||||
LiquidPrice string `json:"liqPrice"`
|
||||
Position float64 `json:"positionValue"`
|
||||
TakeProfit convert.StringToFloat64 `json:"takeProfit"`
|
||||
RiskID string `json:"riskId"`
|
||||
TrailingStop convert.StringToFloat64 `json:"trailingStop"`
|
||||
UnrealisedPnl convert.StringToFloat64 `json:"unrealisedPnl"`
|
||||
MarkPrice convert.StringToFloat64 `json:"markPrice"`
|
||||
CumRealisedPnl convert.StringToFloat64 `json:"cumRealisedPnl"`
|
||||
PositionMM convert.StringToFloat64 `json:"positionMM"`
|
||||
PositionIM convert.StringToFloat64 `json:"positionIM"`
|
||||
EntryPrice convert.StringToFloat64 `json:"entryPrice"`
|
||||
Size convert.StringToFloat64 `json:"size"`
|
||||
SessionRPL convert.StringToFloat64 `json:"sessionRPL"`
|
||||
SessionUPL convert.StringToFloat64 `json:"sessionUPL"`
|
||||
StopLoss convert.StringToFloat64 `json:"stopLoss"`
|
||||
OrderMargin convert.StringToFloat64 `json:"orderMargin"`
|
||||
SessionAvgPrice convert.StringToFloat64 `json:"sessionAvgPrice"`
|
||||
CreatedAt bybitTimeMilliSecStr `json:"createdAt"`
|
||||
UpdatedAt bybitTimeMilliSecStr `json:"updatedAt"`
|
||||
TpSLMode string `json:"tpSLMode"`
|
||||
Side string `json:"side"`
|
||||
BustPrice string `json:"bustPrice"`
|
||||
PositionStatus string `json:"positionStatus"`
|
||||
DeleverageIndicator int64 `json:"deleverageIndicator"`
|
||||
}
|
||||
|
||||
// USDCSettlementHistory store USDC settlement history data
|
||||
type USDCSettlementHistory struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
Size float64 `json:"size,string"`
|
||||
SessionAvgPrice float64 `json:"sessionAvgPrice,string"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
SessionRpl float64 `json:"sessionRpl,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Time bybitTimeMilliSecStr `json:"time"`
|
||||
Size convert.StringToFloat64 `json:"size"`
|
||||
SessionAvgPrice convert.StringToFloat64 `json:"sessionAvgPrice"`
|
||||
MarkPrice convert.StringToFloat64 `json:"markPrice"`
|
||||
SessionRpl convert.StringToFloat64 `json:"sessionRpl"`
|
||||
}
|
||||
|
||||
// USDCRiskLimit store USDC risk limit data
|
||||
type USDCRiskLimit struct {
|
||||
RiskID string `json:"riskId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Limit string `json:"limit"`
|
||||
Section []string `json:"section"`
|
||||
StartingMargin float64 `json:"startingMargin,string"`
|
||||
MaintainMargin float64 `json:"maintainMargin,string"`
|
||||
IsLowestRisk bool `json:"isLowestRisk"`
|
||||
MaxLeverage float64 `json:"maxLeverage,string"`
|
||||
RiskID string `json:"riskId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Limit string `json:"limit"`
|
||||
Section []string `json:"section"`
|
||||
StartingMargin convert.StringToFloat64 `json:"startingMargin"`
|
||||
MaintainMargin convert.StringToFloat64 `json:"maintainMargin"`
|
||||
IsLowestRisk bool `json:"isLowestRisk"`
|
||||
MaxLeverage convert.StringToFloat64 `json:"maxLeverage"`
|
||||
}
|
||||
|
||||
// USDCFundingInfo store USDC funding data
|
||||
type USDCFundingInfo struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Time bybitTimeMilliSecStr `json:"fundingRateTimestamp"`
|
||||
Rate float64 `json:"fundingRate,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time bybitTimeMilliSecStr `json:"fundingRateTimestamp"`
|
||||
Rate convert.StringToFloat64 `json:"fundingRate"`
|
||||
}
|
||||
|
||||
// CFuturesTradingFeeRate stores trading fee rate
|
||||
type CFuturesTradingFeeRate struct {
|
||||
TakerFeeRate convert.StringToFloat64 `json:"taker_fee_rate"`
|
||||
MakerFeeRate convert.StringToFloat64 `json:"maker_fee_rate"`
|
||||
UserID int64 `json:"user_id"`
|
||||
}
|
||||
|
||||
@@ -10,22 +10,26 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
spotInterval = time.Second
|
||||
spotRequestRate = 70
|
||||
// See: https://bybit-exchange.github.io/docs/v5/rate-limit
|
||||
spotInterval = time.Second * 5
|
||||
spotRequestRate = 120
|
||||
|
||||
futuresPublicInterval = time.Second
|
||||
futuresRequestRate = 50
|
||||
|
||||
spotPrivateRequestRate = 20
|
||||
futuresInterval = time.Minute
|
||||
futuresDefaultRateCount = 100
|
||||
futuresOrderRate = 100
|
||||
futuresOrderListRate = 600
|
||||
futuresExecutionRate = 120
|
||||
futuresPositionRateCount = 75
|
||||
futuresPositionListRate = 120
|
||||
futuresFundingRate = 120
|
||||
futuresWalletRate = 120
|
||||
futuresAccountRate = 600
|
||||
spotPrivateInterval = time.Second
|
||||
spotPrivateRequestRate = 20
|
||||
spotPrivateFeeRequestRate = 10
|
||||
futuresInterval = time.Minute
|
||||
futuresDefaultRateCount = 100
|
||||
futuresOrderRate = 100
|
||||
futuresOrderListRate = 600
|
||||
futuresExecutionRate = 120
|
||||
futuresPositionRateCount = 75
|
||||
futuresPositionListRate = 120
|
||||
futuresFundingRate = 120
|
||||
futuresWalletRate = 120
|
||||
futuresAccountRate = 600
|
||||
|
||||
usdcPerpetualPublicRate = 50
|
||||
usdcPerpetualCancelAllRate = 1
|
||||
@@ -37,7 +41,7 @@ const (
|
||||
publicSpotRate request.EndpointLimit = iota
|
||||
publicFuturesRate
|
||||
privateSpotRate
|
||||
|
||||
privateFeeRate
|
||||
cFuturesDefaultRate
|
||||
|
||||
cFuturesCancelActiveOrderRate
|
||||
@@ -153,6 +157,7 @@ type RateLimit struct {
|
||||
SpotRate *rate.Limiter
|
||||
FuturesRate *rate.Limiter
|
||||
PrivateSpotRate *rate.Limiter
|
||||
PrivateFeeRate *rate.Limiter
|
||||
CMFuturesDefaultRate *rate.Limiter
|
||||
CMFuturesOrderRate *rate.Limiter
|
||||
CMFuturesOrderListRate *rate.Limiter
|
||||
@@ -202,131 +207,92 @@ func (r *RateLimit) Limit(ctx context.Context, f request.EndpointLimit) error {
|
||||
limiter, tokens = r.SpotRate, 1
|
||||
case privateSpotRate:
|
||||
limiter, tokens = r.PrivateSpotRate, 1
|
||||
|
||||
case privateFeeRate:
|
||||
limiter, tokens = r.PrivateFeeRate, 1
|
||||
case cFuturesDefaultRate:
|
||||
limiter, tokens = r.CMFuturesDefaultRate, 1
|
||||
|
||||
case cFuturesCancelActiveOrderRate, cFuturesCreateConditionalOrderRate, cFuturesCancelConditionalOrderRate, cFuturesReplaceActiveOrderRate,
|
||||
cFuturesReplaceConditionalOrderRate, cFuturesCreateOrderRate:
|
||||
limiter, tokens = r.CMFuturesOrderRate, 1
|
||||
case cFuturesCancelAllActiveOrderRate, cFuturesCancelAllConditionalOrderRate:
|
||||
limiter, tokens = r.CMFuturesOrderRate, 10
|
||||
|
||||
case cFuturesGetActiveOrderRate, cFuturesGetConditionalOrderRate, cFuturesGetRealtimeOrderRate:
|
||||
limiter, tokens = r.CMFuturesOrderListRate, 1
|
||||
|
||||
case cFuturesTradeRate:
|
||||
limiter, tokens = r.CMFuturesExecutionRate, 1
|
||||
|
||||
case cFuturesSetLeverageRate, cFuturesUpdateMarginRate, cFuturesSetTradingRate, cFuturesSwitchPositionRate, cFuturesGetTradingFeeRate:
|
||||
limiter, tokens = r.CMFuturesPositionRate, 1
|
||||
|
||||
case cFuturesPositionRate, cFuturesWalletBalanceRate:
|
||||
limiter, tokens = r.CMFuturesPositionListRate, 1
|
||||
|
||||
case cFuturesLastFundingFeeRate, cFuturesPredictFundingRate:
|
||||
limiter, tokens = r.CMFuturesFundingRate, 1
|
||||
|
||||
case cFuturesWalletFundRecordRate, cFuturesWalletWithdrawalRate:
|
||||
limiter, tokens = r.CMFuturesWalletRate, 1
|
||||
|
||||
case cFuturesAPIKeyInfoRate:
|
||||
limiter, tokens = r.CMFuturesAccountRate, 1
|
||||
|
||||
case uFuturesDefaultRate:
|
||||
limiter, tokens = r.UFuturesDefaultRate, 1
|
||||
|
||||
case uFuturesCreateOrderRate, uFuturesCancelOrderRate, uFuturesCreateConditionalOrderRate, uFuturesCancelConditionalOrderRate:
|
||||
limiter, tokens = r.UFuturesOrderRate, 1
|
||||
|
||||
case uFuturesCancelAllOrderRate, uFuturesCancelAllConditionalOrderRate:
|
||||
limiter, tokens = r.UFuturesOrderRate, 10
|
||||
|
||||
case uFuturesSetLeverageRate, uFuturesSwitchMargin, uFuturesSwitchPosition, uFuturesSetMarginRate, uFuturesSetTradingStopRate, uFuturesUpdateMarginRate:
|
||||
limiter, tokens = r.UFuturesPositionRate, 1
|
||||
|
||||
case uFuturesPositionRate, uFuturesGetClosedTradesRate, uFuturesGetTradesRate:
|
||||
limiter, tokens = r.UFuturesPositionListRate, 1
|
||||
|
||||
case uFuturesGetActiveOrderRate, uFuturesGetActiveRealtimeOrderRate, uFuturesGetConditionalOrderRate, uFuturesGetConditionalRealtimeOrderRate:
|
||||
limiter, tokens = r.UFuturesOrderListRate, 1
|
||||
|
||||
case uFuturesGetMyLastFundingFeeRate, uFuturesPredictFundingRate:
|
||||
limiter, tokens = r.UFuturesFundingRate, 1
|
||||
|
||||
case futuresDefaultRate:
|
||||
limiter, tokens = r.FuturesDefaultRate, 1
|
||||
|
||||
case futuresCancelOrderRate, futuresCreateOrderRate, futuresReplaceOrderRate, futuresReplaceConditionalOrderRate, futuresCancelConditionalOrderRate,
|
||||
futuresCreateConditionalOrderRate:
|
||||
limiter, tokens = r.FuturesOrderRate, 1
|
||||
|
||||
case futuresCancelAllOrderRate, futuresCancelAllConditionalOrderRate:
|
||||
limiter, tokens = r.FuturesOrderRate, 10
|
||||
|
||||
case futuresGetActiveOrderRate, futuresGetConditionalOrderRate, futuresGetActiveRealtimeOrderRate, futuresGetConditionalRealtimeOrderRate:
|
||||
limiter, tokens = r.FuturesOrderListRate, 1
|
||||
|
||||
case futuresGetTradeRate:
|
||||
limiter, tokens = r.FuturesExecutionRate, 1
|
||||
|
||||
case futuresSetLeverageRate, futuresUpdateMarginRate, futuresSetTradingStopRate, futuresSwitchPositionModeRate, futuresSwitchMarginRate, futuresSwitchPositionRate:
|
||||
limiter, tokens = r.FuturesPositionRate, 1
|
||||
|
||||
case futuresPositionRate:
|
||||
limiter, tokens = r.FuturesPositionListRate, 1
|
||||
|
||||
case usdcPublicRate:
|
||||
limiter, tokens = r.USDCPublic, 1
|
||||
|
||||
case usdcCancelAllOrderRate:
|
||||
limiter, tokens = r.USDCCancelAllOrderRate, 1
|
||||
|
||||
case usdcPlaceOrderRate:
|
||||
limiter, tokens = r.USDCPlaceOrderRate, 1
|
||||
|
||||
case usdcModifyOrderRate:
|
||||
limiter, tokens = r.USDCModifyOrderRate, 1
|
||||
|
||||
case usdcCancelOrderRate:
|
||||
limiter, tokens = r.USDCCancelOrderRate, 1
|
||||
|
||||
case usdcGetOrderRate:
|
||||
limiter, tokens = r.USDCGetOrderRate, 1
|
||||
|
||||
case usdcGetOrderHistoryRate:
|
||||
limiter, tokens = r.USDCGetOrderHistoryRate, 1
|
||||
|
||||
case usdcGetTradeHistoryRate:
|
||||
limiter, tokens = r.USDCGetTradeHistoryRate, 1
|
||||
|
||||
case usdcGetTransactionRate:
|
||||
limiter, tokens = r.USDCGetTransactionRate, 1
|
||||
|
||||
case usdcGetWalletRate:
|
||||
limiter, tokens = r.USDCGetWalletRate, 1
|
||||
|
||||
case usdcGetAssetRate:
|
||||
limiter, tokens = r.USDCGetAssetRate, 1
|
||||
|
||||
case usdcGetMarginRate:
|
||||
limiter, tokens = r.USDCGetMarginRate, 1
|
||||
|
||||
case usdcGetPositionRate:
|
||||
limiter, tokens = r.USDCGetPositionRate, 1
|
||||
|
||||
case usdcSetLeverageRate:
|
||||
limiter, tokens = r.USDCSetLeverageRate, 1
|
||||
|
||||
case usdcGetSettlementRate:
|
||||
limiter, tokens = r.USDCGetSettlementRate, 1
|
||||
|
||||
case usdcSetRiskRate:
|
||||
limiter, tokens = r.USDCSetRiskRate, 1
|
||||
|
||||
case usdcGetPredictedFundingRate:
|
||||
limiter, tokens = r.USDCGetPredictedFundingRate, 1
|
||||
|
||||
default:
|
||||
limiter, tokens = r.SpotRate, 1
|
||||
}
|
||||
@@ -360,7 +326,8 @@ func SetRateLimit() *RateLimit {
|
||||
return &RateLimit{
|
||||
SpotRate: request.NewRateLimit(spotInterval, spotRequestRate),
|
||||
FuturesRate: request.NewRateLimit(futuresPublicInterval, futuresRequestRate),
|
||||
PrivateSpotRate: request.NewRateLimit(spotInterval, spotPrivateRequestRate),
|
||||
PrivateSpotRate: request.NewRateLimit(spotPrivateInterval, spotPrivateRequestRate),
|
||||
PrivateFeeRate: request.NewRateLimit(spotPrivateInterval, spotPrivateFeeRequestRate),
|
||||
CMFuturesDefaultRate: request.NewRateLimit(futuresInterval, futuresDefaultRateCount),
|
||||
CMFuturesOrderRate: request.NewRateLimit(futuresInterval, futuresOrderRate),
|
||||
CMFuturesOrderListRate: request.NewRateLimit(futuresInterval, futuresOrderListRate),
|
||||
|
||||
@@ -1907,7 +1907,7 @@ func TestUpdateOrderExecutionLimits(t *testing.T) {
|
||||
t.Errorf("Okx UpdateOrderExecutionLimits wrong PriceStepIncrementSize; Asset: %s Pair: %s Expected: %v Got: %v", a, tt.pair, tt.step, got)
|
||||
}
|
||||
|
||||
if got := limits.MinAmount; got != tt.min {
|
||||
if got := limits.MinimumBaseAmount; got != tt.min {
|
||||
t.Errorf("Okx UpdateOrderExecutionLimits wrong MinAmount; Pair: %s Expected: %v Got: %v", tt.pair, tt.min, got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ func (ok *Okx) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) err
|
||||
Pair: pair,
|
||||
Asset: a,
|
||||
PriceStepIncrementSize: insts[x].TickSize,
|
||||
MinAmount: insts[x].MinimumOrderSize,
|
||||
MinimumBaseAmount: insts[x].MinimumOrderSize,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ var (
|
||||
errCannotLoadLimit = errors.New("cannot load limit, levels not supplied")
|
||||
errInvalidPriceLevels = errors.New("invalid price levels, cannot load limits")
|
||||
errInvalidAmountLevels = errors.New("invalid amount levels, cannot load limits")
|
||||
errInvalidQuoteLevels = errors.New("invalid quote levels, cannot load limits")
|
||||
)
|
||||
|
||||
// ExecutionLimits defines minimum and maximum values in relation to
|
||||
@@ -74,9 +75,12 @@ type MinMaxLevel struct {
|
||||
MultiplierDown float64
|
||||
MultiplierDecimal float64
|
||||
AveragePriceMinutes int64
|
||||
MinAmount float64
|
||||
MaxAmount float64
|
||||
MinimumBaseAmount float64
|
||||
MaximumBaseAmount float64
|
||||
MinimumQuoteAmount float64
|
||||
MaximumQuoteAmount float64
|
||||
AmountStepIncrementSize float64
|
||||
QuoteStepIncrementSize float64
|
||||
MinNotional float64
|
||||
MaxIcebergParts int64
|
||||
MarketMinQty float64
|
||||
@@ -130,15 +134,26 @@ func (e *ExecutionLimits) LoadLimits(levels []MinMaxLevel) error {
|
||||
levels[x].MaxPrice)
|
||||
}
|
||||
|
||||
if levels[x].MinAmount > 0 &&
|
||||
levels[x].MaxAmount > 0 &&
|
||||
levels[x].MinAmount > levels[x].MaxAmount {
|
||||
if levels[x].MinimumBaseAmount > 0 &&
|
||||
levels[x].MaximumBaseAmount > 0 &&
|
||||
levels[x].MinimumBaseAmount > levels[x].MaximumBaseAmount {
|
||||
return fmt.Errorf("%w for %s %s supplied min: %f max: %f",
|
||||
errInvalidAmountLevels,
|
||||
levels[x].Asset,
|
||||
levels[x].Pair,
|
||||
levels[x].MinAmount,
|
||||
levels[x].MaxAmount)
|
||||
levels[x].MinimumBaseAmount,
|
||||
levels[x].MaximumBaseAmount)
|
||||
}
|
||||
|
||||
if levels[x].MinimumQuoteAmount > 0 &&
|
||||
levels[x].MaximumQuoteAmount > 0 &&
|
||||
levels[x].MinimumQuoteAmount > levels[x].MaximumQuoteAmount {
|
||||
return fmt.Errorf("%w for %s %s supplied min: %f max: %f",
|
||||
errInvalidQuoteLevels,
|
||||
levels[x].Asset,
|
||||
levels[x].Pair,
|
||||
levels[x].MinimumQuoteAmount,
|
||||
levels[x].MaximumQuoteAmount)
|
||||
}
|
||||
|
||||
m2[levels[x].Pair.Quote.Item] = levels[x]
|
||||
@@ -209,25 +224,26 @@ func (e *ExecutionLimits) CheckOrderExecutionLimits(a asset.Item, cp currency.Pa
|
||||
|
||||
// Conforms checks outbound parameters
|
||||
func (m *MinMaxLevel) Conforms(price, amount float64, orderType Type) error {
|
||||
// TODO: Update to take in account Quote amounts as well as Base amounts.
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.MinAmount != 0 && amount < m.MinAmount {
|
||||
if m.MinimumBaseAmount != 0 && amount < m.MinimumBaseAmount {
|
||||
return fmt.Errorf("%w min: %.8f supplied %.8f",
|
||||
ErrAmountBelowMin,
|
||||
m.MinAmount,
|
||||
m.MinimumBaseAmount,
|
||||
amount)
|
||||
}
|
||||
if m.MaxAmount != 0 && amount > m.MaxAmount {
|
||||
if m.MaximumBaseAmount != 0 && amount > m.MaximumBaseAmount {
|
||||
return fmt.Errorf("%w min: %.8f supplied %.8f",
|
||||
ErrAmountExceedsMax,
|
||||
m.MaxAmount,
|
||||
m.MaximumBaseAmount,
|
||||
amount)
|
||||
}
|
||||
if m.AmountStepIncrementSize != 0 {
|
||||
dAmount := decimal.NewFromFloat(amount)
|
||||
dMinAmount := decimal.NewFromFloat(m.MinAmount)
|
||||
dMinAmount := decimal.NewFromFloat(m.MaximumBaseAmount)
|
||||
dStep := decimal.NewFromFloat(m.AmountStepIncrementSize)
|
||||
if !dAmount.Sub(dMinAmount).Mod(dStep).IsZero() {
|
||||
return fmt.Errorf("%w stepSize: %.8f supplied %.8f",
|
||||
@@ -288,7 +304,7 @@ func (m *MinMaxLevel) Conforms(price, amount float64, orderType Type) error {
|
||||
}
|
||||
|
||||
if m.MarketMinQty != 0 &&
|
||||
m.MinAmount < m.MarketMinQty &&
|
||||
m.MinimumBaseAmount < m.MarketMinQty &&
|
||||
amount < m.MarketMinQty {
|
||||
return fmt.Errorf("%w min: %.8f supplied %.8f",
|
||||
ErrMarketAmountBelowMin,
|
||||
@@ -296,7 +312,7 @@ func (m *MinMaxLevel) Conforms(price, amount float64, orderType Type) error {
|
||||
amount)
|
||||
}
|
||||
if m.MarketMaxQty != 0 &&
|
||||
m.MaxAmount > m.MarketMaxQty &&
|
||||
m.MaximumBaseAmount > m.MarketMaxQty &&
|
||||
amount > m.MarketMaxQty {
|
||||
return fmt.Errorf("%w max: %.8f supplied %.8f",
|
||||
ErrMarketAmountExceedsMax,
|
||||
|
||||
@@ -25,11 +25,11 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
invalidAsset := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Pair: btcusd,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
err = e.LoadLimits(invalidAsset)
|
||||
@@ -41,11 +41,11 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
invalidPairLoading := []MinMaxLevel{
|
||||
{
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
newLimits := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
badLimit := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 2,
|
||||
MaxPrice: 1,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 2,
|
||||
MaxPrice: 1,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -88,12 +88,12 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
badLimit = []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 1,
|
||||
MaxPrice: 2,
|
||||
MinAmount: 10,
|
||||
MaxAmount: 9,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 1,
|
||||
MaxPrice: 2,
|
||||
MinimumBaseAmount: 10,
|
||||
MaximumBaseAmount: 9,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -116,9 +116,9 @@ func TestLoadLimits(t *testing.T) {
|
||||
|
||||
noCompare := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinAmount: 10,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinimumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -151,12 +151,12 @@ func TestGetOrderExecutionLimits(t *testing.T) {
|
||||
|
||||
newLimits := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -185,8 +185,8 @@ func TestGetOrderExecutionLimits(t *testing.T) {
|
||||
t.Fatalf("expected error %v but received %v", nil, err)
|
||||
}
|
||||
|
||||
if tt.MaxAmount != newLimits[0].MaxAmount ||
|
||||
tt.MinAmount != newLimits[0].MinAmount ||
|
||||
if tt.MaximumBaseAmount != newLimits[0].MaximumBaseAmount ||
|
||||
tt.MinimumBaseAmount != newLimits[0].MinimumBaseAmount ||
|
||||
tt.MaxPrice != newLimits[0].MaxPrice ||
|
||||
tt.MinPrice != newLimits[0].MinPrice {
|
||||
t.Fatal("unexpected values")
|
||||
@@ -203,12 +203,12 @@ func TestCheckLimit(t *testing.T) {
|
||||
|
||||
newLimits := []MinMaxLevel{
|
||||
{
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinAmount: 1,
|
||||
MaxAmount: 10,
|
||||
Pair: btcusd,
|
||||
Asset: asset.Spot,
|
||||
MinPrice: 100000,
|
||||
MaxPrice: 1000000,
|
||||
MinimumBaseAmount: 1,
|
||||
MaximumBaseAmount: 10,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -305,8 +305,8 @@ func TestConforms(t *testing.T) {
|
||||
t.Fatalf("expected error %v but received %v", nil, err)
|
||||
}
|
||||
|
||||
tt.MinAmount = 1
|
||||
tt.MaxAmount = 10
|
||||
tt.MinimumBaseAmount = 1
|
||||
tt.MaximumBaseAmount = 10
|
||||
tt.MarketMinQty = 1.1
|
||||
tt.MarketMaxQty = 9.9
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package sharedtestvalues
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -103,3 +108,42 @@ func SkipTestIfCannotManipulateOrders(t *testing.T, exch exchange.IBotExchange,
|
||||
func AreAPICredentialsSet(exch exchange.IBotExchange) bool {
|
||||
return exch.VerifyAPICredentials(exch.GetDefaultCredentials()) == nil
|
||||
}
|
||||
|
||||
// EmptyStringPotentialPattern is a regular expression pattern for a potential
|
||||
// empty string into float64
|
||||
var EmptyStringPotentialPattern = `.*float64.*json:"[^"]*,string".*`
|
||||
|
||||
// ForceFileStandard will check all files in the current directory for a regular
|
||||
// expression pattern. If the pattern is found the test will fail.
|
||||
func ForceFileStandard(t *testing.T, pattern string) error {
|
||||
t.Helper()
|
||||
|
||||
r := regexp.MustCompile(pattern)
|
||||
|
||||
root := "." // Specify the root directory to start walking from
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".go") {
|
||||
fileContents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read file: %v", err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(fileContents, []byte("\n"))
|
||||
for x, line := range lines {
|
||||
if r.Match(line) {
|
||||
t.Errorf("File: %s line contains pattern [%s] match with [%s] at line %d", path, pattern, string(line), x+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to walk directory: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ var (
|
||||
errInvalidTicker = errors.New("invalid ticker")
|
||||
errTickerNotFound = errors.New("ticker not found")
|
||||
errExchangeNameIsEmpty = errors.New("exchange name is empty")
|
||||
errBidEqualsAsk = errors.New("bid equals ask this is a crossed or locked market")
|
||||
errBidGreaterThanAsk = errors.New("bid greater than ask this is a crossed or locked market")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -129,6 +131,27 @@ func ProcessTicker(p *Price) error {
|
||||
return fmt.Errorf("%s %s", p.ExchangeName, errPairNotSet)
|
||||
}
|
||||
|
||||
if p.Bid != 0 && p.Ask != 0 {
|
||||
switch {
|
||||
case p.ExchangeName == "Bitfinex" && p.AssetType == asset.MarginFunding:
|
||||
// Margin funding books can be crossed see Bitfinex.
|
||||
default:
|
||||
if p.Bid == p.Ask {
|
||||
return fmt.Errorf("%s %s %w",
|
||||
p.ExchangeName,
|
||||
p.Pair,
|
||||
errBidEqualsAsk)
|
||||
}
|
||||
|
||||
if p.Bid > p.Ask {
|
||||
return fmt.Errorf("%s %s %w",
|
||||
p.ExchangeName,
|
||||
p.Pair,
|
||||
errBidGreaterThanAsk)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.AssetType == asset.Empty {
|
||||
return fmt.Errorf("%s %s %s",
|
||||
p.ExchangeName,
|
||||
|
||||
@@ -281,6 +281,39 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
|
||||
t.Fatal("TestProcessTicker pair mismatch")
|
||||
}
|
||||
|
||||
err = ProcessTicker(&Price{
|
||||
ExchangeName: "Bitfinex",
|
||||
Pair: currency.NewPair(currency.BTC, currency.USD),
|
||||
AssetType: asset.Margin,
|
||||
Bid: 1337,
|
||||
Ask: 1337,
|
||||
})
|
||||
if !errors.Is(err, errBidEqualsAsk) {
|
||||
t.Errorf("received: %v but expected: %v", err, errBidEqualsAsk)
|
||||
}
|
||||
|
||||
err = ProcessTicker(&Price{
|
||||
ExchangeName: "Bitfinex",
|
||||
Pair: currency.NewPair(currency.BTC, currency.USD),
|
||||
AssetType: asset.Margin,
|
||||
Bid: 1338,
|
||||
Ask: 1336,
|
||||
})
|
||||
if !errors.Is(err, errBidGreaterThanAsk) {
|
||||
t.Errorf("received: %v but expected: %v", err, errBidGreaterThanAsk)
|
||||
}
|
||||
|
||||
err = ProcessTicker(&Price{
|
||||
ExchangeName: "Bitfinex",
|
||||
Pair: currency.NewPair(currency.BTC, currency.USD),
|
||||
AssetType: asset.MarginFunding,
|
||||
Bid: 1338,
|
||||
Ask: 1336,
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received: %v but expected: %v", err, nil)
|
||||
}
|
||||
|
||||
// now test for processing a pair with a different quote currency
|
||||
newPair, err = currency.NewPairFromStrings("BTC", "AUD")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user