mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Bybit: Fix WS ticker processing (#1538)
* Bybit: Fix WS ticker processing * Bybit: Refactor SetDefaults
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
@@ -2950,34 +2952,22 @@ func TestGetWithdrawalsHistory(t *testing.T) {
|
||||
|
||||
func TestGetRecentTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetRecentTrades(context.Background(), spotTradablePair, asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = b.GetRecentTrades(context.Background(), inverseTradablePair, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = b.GetRecentTrades(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = b.GetRecentTrades(context.Background(), usdcMarginedTradablePair, asset.USDCMarginedFutures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = b.GetRecentTrades(context.Background(), spotTradablePair, asset.Futures)
|
||||
if !errors.Is(err, asset.ErrNotSupported) {
|
||||
t.Error(err)
|
||||
}
|
||||
cp, err := b.ExtractCurrencyPair("BTC-29DEC23-80000-C", asset.Options, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = b.GetRecentTrades(context.Background(), cp, asset.Options)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
for _, tt := range []struct {
|
||||
a asset.Item
|
||||
p currency.Pair
|
||||
}{
|
||||
{asset.Spot, spotTradablePair},
|
||||
{asset.Options, optionsTradablePair},
|
||||
{asset.CoinMarginedFutures, inverseTradablePair},
|
||||
{asset.USDTMarginedFutures, usdtMarginedTradablePair},
|
||||
{asset.USDCMarginedFutures, usdcMarginedTradablePair},
|
||||
} {
|
||||
_, err := b.GetRecentTrades(context.Background(), tt.p, tt.a)
|
||||
assert.NoErrorf(t, err, "GetRecentTrades should not error for %s asset", tt.a)
|
||||
}
|
||||
|
||||
_, err := b.GetRecentTrades(context.Background(), spotTradablePair, asset.Futures)
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
func TestGetBybitServerTime(t *testing.T) {
|
||||
@@ -3096,9 +3086,6 @@ var pushDataMap = map[string]string{
|
||||
"Orderbook Snapshot": `{"topic":"orderbook.50.BTCUSDT","ts":1690719970602,"type":"snapshot","data":{"s":"BTCUSDT","b":[["29328.25","3.911681"],["29328.21","0.117584"],["29328.19","0.511493"],["29328.16","0.013639"],["29328","0.1646"],["29327.99","1"],["29327.98","0.681309"],["29327.53","0.001"],["29327.46","0.000048"],["29327","0.046517"],["29326.99","0.077528"],["29326.55","0.026808"],["29326.48","0.03"],["29326","0.1646"],["29325.99","0.00075"],["29325.93","0.409862"],["29325.92","0.745"],["29325.87","0.511533"],["29325.85","0.00018"],["29325.42","0.001023"],["29325.41","0.68199"],["29325.36","0.006309"],["29325.35","0.0153"],["29324.97","0.903728"],["29324.96","1.506212"],["29324.49","0.016966"],["29324.38","0.0341"],["29324.17","1.4535"],["29324","0.1646"],["29323.99","0.00075"],["29323.92","0.050492"],["29323.77","1.023141"],["29323.72","0.12"],["29323.48","0.0153"],["29323.26","0.001362"],["29322.78","0.464948"],["29322.77","0.745"],["29322.76","0.0153"],["29322.73","0.013633"],["29322.67","0.53"],["29322.62","0.01"],["29322.04","0.97036"],["29322","0.1656"],["29321.99","0.00075"],["29321.56","0.0341"],["29321.52","0.613945"],["29321.51","0.13"],["29321.4","0.002"],["29321.18","0.196788"],["29321.13","0.34104"]],"a":[["29328.26","1.256884"],["29328.36","0.013639"],["29328.97","0.51148"],["29329","0.002046"],["29329.2","0.035597"],["29329.27","0.001"],["29329.44","0.03523"],["29329.99","0.791676"],["29330","0.546264"],["29330.28","0.001"],["29330.35","0.767184"],["29330.5","0.002725"],["29330.51","0.0341"],["29330.79","0.03"],["29330.81","0.158412"],["29330.93","0.68199"],["29330.95","0.282036"],["29331","0.041"],["29331.13","0.0003"],["29331.19","0.01"],["29331.53","0.050164"],["29331.54","0.008573"],["29331.99","0.26305"],["29332.11","0.008124"],["29332.21","0.8721"],["29332.22","1.4535"],["29332.41","0.157"],["29332.58","0.001023"],["29332.59","0.0153"],["29332.84","0.679527"],["29332.85","1.022812"],["29332.98","0.200071"],["29333.01","1.13254"],["29333.24","0.0153"],["29333.25","0.001362"],["29333.35","0.625"],["29333.37","0.01"],["29333.56","0.0341"],["29333.68","0.21795"],["29333.85","0.182562"],["29333.98","0.0003"],["29333.99","0.00105"],["29334.16","0.009132"],["29334.29","0.0003"],["29334.48","0.029675"],["29334.7","0.00086"],["29334.99","0.006838"],["29335","0.002177"],["29335.18","0.013622"],["29335.32","0.034099"]],"u":51668654,"seq":10194901787}}`,
|
||||
"Orderbook Update": `{"topic":"orderbook.50.ACAUSDT","ts":1690719548494,"type":"snapshot","data":{"s":"ACAUSDT","b":[["0.0657","5363.66"],["0.0646","7910.21"],["0.0645","1435.73"],["0.0644","1552.8"],["0.0642","6904.01"],["0.064","3232.64"],["0.0639","106"],["0.0637","100"],["0.0636","25.62"],["0.0635","209.43"],["0.0631","237.47"],["0.063","258.13"],["0.0627","318.97"],["0.0625","10066.99"],["0.0624","16.1"],["0.0623","41.72"],["0.0622","1624.59"],["0.0621","402.57"],["0.0616","10.65"],["0.0613","652"],["0.061","1081.97"],["0.0604","413.91"],["0.06","1471.82"],["0.0597","15000"],["0.0595","15000"],["0.0593","608.77"],["0.0591","430.79"],["0.059","444"],["0.0586","4536.97"],["0.0584","1533.58"],["0.0583","3764.43"],["0.0581","3072.34"],["0.058","2654.9"],["0.0579","1022.23"],["0.0576","1931.71"],["0.0574","2545.88"],["0.0573","821.27"],["0.0571","2957"],["0.0568","1483.57"],["0.0561","392.24"],["0.0555","900.9"],["0.055","322.15"],["0.0549","182"],["0.0545","30"],["0.0536","24.24"],["0.0535","1869.15"],["0.053","40"],["0.0529","189"],["0.0525","701.66"],["0.0521","1122.64"]],"a":[["0.0661","3320.27"],["0.0662","8667.02"],["0.0663","6087.91"],["0.0664","6060.61"],["0.0684","591.31"],["0.0689","155.77"],["0.069","1148.02"],["0.0694","2421.86"],["0.0699","155.77"],["0.07","445.87"],["0.0701","142.65"],["0.071","2131.4"],["0.0718","1447.83"],["0.072","420.62"],["0.0743","1399.15"],["0.0745","1481.62"],["0.0747","32.97"],["0.0748","900.38"],["0.0749","209.44"],["0.075","124.49"],["0.0757","41.9"],["0.0762","657.43"],["0.077","48.77"],["0.0779","96.26"],["0.078","12305.94"],["0.079","29.77"],["0.0797","512.26"],["0.0799","743.29"],["0.08","5050.7"],["0.0814","11.71"],["0.0815","75.93"],["0.0817","403"],["0.082","817.43"],["0.0825","768.47"],["0.0828","388.77"],["0.083","150.53"],["0.0835","18"],["0.084","10776.95"],["0.0841","1465.17"],["0.0848","15000"],["0.085","16976.73"],["0.0853","798.45"],["0.0856","5239.19"],["0.0857","5134.18"],["0.0858","3885.13"],["0.0859","3691.71"],["0.086","16847.35"],["0.0862","898.68"],["0.0863","994.24"],["0.0865","1251.56"]],"u":4694899,"seq":12206894097}}`,
|
||||
"Public Trade": `{"topic":"publicTrade.ATOM2SUSDT","ts":1690720953113,"type":"snapshot","data":[{"i":"2200000000067341890","T":1690720953111,"p":"3.6279","v":"1.3637","S":"Sell","s":"ATOM2SUSDT","BT":false}]}`,
|
||||
"Public Linear Ticker": `{ "topic": "tickers.BTCUSDT", "type": "snapshot", "data": { "symbol": "BTCUSDT", "tickDirection": "PlusTick", "price24hPcnt": "0.017103", "lastPrice": "17216.00", "prevPrice24h": "16926.50", "highPrice24h": "17281.50", "lowPrice24h": "16915.00", "prevPrice1h": "17238.00", "markPrice": "17217.33", "indexPrice": "17227.36", "openInterest": "68744.761", "openInterestValue": "1183601235.91", "turnover24h": "1570383121.943499", "volume24h": "91705.276", "nextFundingTime": "1673280000000", "fundingRate": "-0.000212", "bid1Price": "17215.50", "bid1Size": "84.489", "ask1Price": "17216.00", "ask1Size": "83.020" }, "cs": 24987956059, "ts": 1673272861686 }`,
|
||||
"Public Option Ticker": `{ "id": "tickers.BTC-6JAN23-17500-C-2480334983-1672917511074", "topic": "tickers.BTC-6JAN23-17500-C", "ts": 1672917511074, "data": { "symbol": "BTC-6JAN23-17500-C", "bidPrice": "0", "bidSize": "0", "bidIv": "0", "askPrice": "10", "askSize": "5.1", "askIv": "0.514", "lastPrice": "10", "highPrice24h": "25", "lowPrice24h": "5", "markPrice": "7.86976724", "indexPrice": "16823.73", "markPriceIv": "0.4896", "underlyingPrice": "16815.1", "openInterest": "49.85", "turnover24h": "446802.8473", "volume24h": "26.55", "totalVolume": "86", "totalTurnover": "1437431", "delta": "0.047831", "gamma": "0.00021453", "vega": "0.81351067", "theta": "-19.9115368", "predictedDeliveryPrice": "0", "change24h": "-0.33333334" }, "type": "snapshot" }`,
|
||||
"Public Ticker": `{"topic":"tickers.APTUSDC","ts":1690724804979,"type":"snapshot","cs":11505608330,"data":{"symbol":"APTUSDC","lastPrice":"7.0884","highPrice24h":"7.19","lowPrice24h":"7.0666","prevPrice24h":"7.0767","volume24h":"642.45","turnover24h":"4568.920448","price24hPcnt":"0.0017","usdIndexPrice":"7.07930012"}}`,
|
||||
"Public Kline": `{ "topic": "kline.5.BTCUSDT", "data": [ { "start": 1672324800000, "end": 1672325099999, "interval": "5", "open": "16649.5", "close": "16677", "high": "16677", "low": "16608", "volume": "2.081", "turnover": "34666.4005", "confirm": false, "timestamp": 1672324988882 } ], "ts": 1672324988882,"type": "snapshot"}`,
|
||||
"Public Liquidiation": `{ "data": { "price": "0.03803", "side": "Buy", "size": "1637", "symbol": "GALAUSDT", "updatedTime": 1673251091822 }, "topic": "liquidation.GALAUSDT", "ts": 1673251091822, "type": "snapshot" }`,
|
||||
"Public LT Kline": `{ "type": "snapshot", "topic": "kline_lt.5.EOS3LUSDT", "data": [ { "start": 1672325100000, "end": 1672325399999, "interval": "5", "open": "0.416039541212402799", "close": "0.41477848043290448", "high": "0.416039541212402799", "low": "0.409734237314911206", "confirm": false, "timestamp": 1672325322393 } ], "ts": 1672325322393 }`,
|
||||
@@ -3121,6 +3108,157 @@ func TestPushData(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWsTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := new(Bybit) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
assetRouting := []asset.Item{
|
||||
asset.Spot, asset.Options, asset.USDTMarginedFutures, asset.USDTMarginedFutures,
|
||||
asset.USDCMarginedFutures, asset.USDCMarginedFutures, asset.CoinMarginedFutures, asset.CoinMarginedFutures,
|
||||
}
|
||||
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsTicker.json", func(r []byte) error {
|
||||
defer slices.Delete(assetRouting, 0, 1)
|
||||
return b.wsHandleData(assetRouting[0], r)
|
||||
})
|
||||
close(b.Websocket.DataHandler)
|
||||
expected := 8
|
||||
require.Len(t, b.Websocket.DataHandler, expected, "Should see correct number of tickers")
|
||||
for resp := range b.Websocket.DataHandler {
|
||||
switch v := resp.(type) {
|
||||
case *ticker.Price:
|
||||
assert.Equal(t, b.Name, v.ExchangeName, "ExchangeName should be correct")
|
||||
switch expected - len(b.Websocket.DataHandler) {
|
||||
case 1: // Spot
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 21109.77, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 21426.99, v.High, "High should be correct")
|
||||
assert.Equal(t, 20575.00, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 6780.866843, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, "BTC_USDT", v.Pair.String(), "Pair should be correct")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(233366401000), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 2: // Option
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, 3565.00, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 3715.00, v.High, "High should be correct")
|
||||
assert.Equal(t, 3555.00, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 1.62, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 3475.00, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 10.14, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 3520.00, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 2.5, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 3502.0715721, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61912.8, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 29.35, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, "BTC-28JUN24-60000-P", v.Pair.String(), "Pair should be correct")
|
||||
assert.Equal(t, asset.Options, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715742949283), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 3: // USDTMargined snapshot
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61874.00, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62752.90, v.High, "High should be correct")
|
||||
assert.Equal(t, 61000.10, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 98430.1050, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61873.9, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 3.783, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61874.00, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 16.278, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61875.25, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61903.73, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 58117.022, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.USDTMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715748762463), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 4: // USDTMargined partial
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61874.00, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62752.90, v.High, "High should be correct")
|
||||
assert.Equal(t, 61000.10, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 98430.1050, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61873.90, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 3.543, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61874.00, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 16.278, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61875.06, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61903.59, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 58117.022, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.USDTMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715748763063), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 5: // USDCMargined snapshot
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.PERP, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61945.70, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62242.2, v.High, "High should be correct")
|
||||
assert.Equal(t, 61059.1, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 427.375, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61909.2, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 0.035, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61909.60, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 0.082, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61943.58, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61942.85, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 526.806, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.USDCMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715756612118), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 6: // USDCMargined partial
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.PERP, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61945.70, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62242.2, v.High, "High should be correct")
|
||||
assert.Equal(t, 61059.1, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 427.375, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61909.5, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 0.035, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61909.60, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 0.082, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61943.58, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61942.85, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 526.806, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.USDCMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(171575661221), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 7: // CoinMargined snapshot
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.USD, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61894.0, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62265.5, v.High, "High should be correct")
|
||||
assert.Equal(t, 61029.5, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 391976479.0, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61891.5, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 12667.0, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61892.0, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 60953.0, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61894.0, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61923.36, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 931760496.0, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.CoinMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715757637952), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
case 8: // CoinMargined partial
|
||||
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
|
||||
assert.Equal(t, currency.USD, v.Pair.Quote, "Pair quote should be correct")
|
||||
assert.Equal(t, 61894.0, v.Last, "Last should be correct")
|
||||
assert.Equal(t, 62265.5, v.High, "High should be correct")
|
||||
assert.Equal(t, 61029.5, v.Low, "Low should be correct")
|
||||
assert.Equal(t, 391976479.0, v.Volume, "Volume should be correct")
|
||||
assert.Equal(t, 61891.5, v.Bid, "Bid should be correct")
|
||||
assert.Equal(t, 27634.0, v.BidSize, "BidSize should be correct")
|
||||
assert.Equal(t, 61892.0, v.Ask, "Ask should be correct")
|
||||
assert.Equal(t, 60953.0, v.AskSize, "AskSize should be correct")
|
||||
assert.Equal(t, 61894.0, v.MarkPrice, "MarkPrice should be correct")
|
||||
assert.Equal(t, 61923.36, v.IndexPrice, "IndexPrice should be correct")
|
||||
assert.Equal(t, 931760496.0, v.OpenInterest, "OpenInterest should be correct")
|
||||
assert.Equal(t, asset.CoinMarginedFutures, v.AssetType, "AssetType should be correct")
|
||||
assert.Equal(t, int64(1715757638152), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Unexpected type in DataHandler: %T (%s)", v, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
var feeBuilder = &exchange.FeeBuilder{
|
||||
@@ -3274,17 +3412,6 @@ func TestGetLongShortRatio(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractCurrencyPair(t *testing.T) {
|
||||
t.Parallel()
|
||||
dogeUSDT := currency.Pair{Base: currency.DOGE, Quote: currency.USDT}
|
||||
pair, err := b.ExtractCurrencyPair("DOGEUSDT", asset.Spot, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !pair.Equal(dogeUSDT) {
|
||||
t.Fatalf("expecting %v, got %v", dogeUSDT, pair)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToOrderStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
input := []struct {
|
||||
@@ -3397,84 +3524,6 @@ func TestConstructOrderDetails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractCurrencyPair extracts the currency pair equivalent of provided pair string.
|
||||
func (by *Bybit) ExtractCurrencyPair(symbol string, assetType asset.Item, request bool) (currency.Pair, error) {
|
||||
format, err := by.GetPairFormat(assetType, request)
|
||||
if err != nil {
|
||||
return currency.EMPTYPAIR, err
|
||||
}
|
||||
var pair currency.Pair
|
||||
pair, err = by.MatchSymbolWithAvailablePairs(symbol, assetType, true)
|
||||
if err != nil {
|
||||
return currency.EMPTYPAIR, err
|
||||
}
|
||||
return pair.Format(format), nil
|
||||
}
|
||||
|
||||
func TestUpdateOptionsTickerInformation(t *testing.T) {
|
||||
t.Parallel()
|
||||
snapshots := map[asset.Item]string{
|
||||
asset.Spot: `{ "topic": "tickers.BTC-USDT", "ts": 1673853746003, "type": "snapshot", "cs": 2588407389, "data": { "symbol": "BTCUSDT", "lastPrice": "21109.77", "highPrice24h": "21426.99", "lowPrice24h": "20575", "prevPrice24h": "20704.93", "volume24h": "6780.866843", "turnover24h": "141946527.22907118", "price24hPcnt": "0.0196", "usdIndexPrice": "21120.2400136" } }`,
|
||||
asset.USDTMarginedFutures: `{ "topic": "tickers.BTC_USDT", "type": "snapshot", "data": { "symbol": "BTCUSDT", "tickDirection": "PlusTick", "price24hPcnt": "0.017103", "lastPrice": "17216.00", "prevPrice24h": "16926.50", "highPrice24h": "17281.50", "lowPrice24h": "16915.00", "prevPrice1h": "17238.00", "markPrice": "17217.33", "indexPrice": "17227.36", "openInterest": "68744.761", "openInterestValue": "1183601235.91", "turnover24h": "1570383121.943499", "volume24h": "91705.276", "nextFundingTime": "1673280000000", "fundingRate": "-0.000212", "bid1Price": "17215.50", "bid1Size": "84.489", "ask1Price": "17216.00", "ask1Size": "83.020" }, "cs": 24987956059, "ts": 1673272861686 }`,
|
||||
asset.Options: `{ "id": "tickers.BTC-6JAN23-17500-C-2480334983-1672917511074", "topic": "tickers.BTC-6JAN23-17500-C", "ts": 1672917511074, "data": { "symbol": "BTC-USD-220930-28000-P", "bidPrice": "0", "bidSize": "0", "bidIv": "0", "askPrice": "10", "askSize": "5.1", "askIv": "0.514", "lastPrice": "10", "highPrice24h": "25", "lowPrice24h": "5", "markPrice": "7.86976724", "indexPrice": "16823.73", "markPriceIv": "0.4896", "underlyingPrice": "16815.1", "openInterest": "49.85", "turnover24h": "446802.8473", "volume24h": "26.55", "totalVolume": "86", "totalTurnover": "1437431", "delta": "0.047831", "gamma": "0.00021453", "vega": "0.81351067", "theta": "-19.9115368", "predictedDeliveryPrice": "0", "change24h": "-0.33333334" }, "type": "snapshot" }`,
|
||||
}
|
||||
var err error
|
||||
for x := range snapshots {
|
||||
err = b.wsHandleData(x, []byte(snapshots[x]))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Spot update processing
|
||||
data := `{ "symbol": "BTC-USDT", "lastPrice": "21109.77", "highPrice24h": "21426.99", "lowPrice24h": "20575", "prevPrice24h": "20704.93", "volume24h": "6780.866843", "turnover24h": "141946527.22907118", "price24hPcnt": "0.0196", "usdIndexPrice": "21120.2400136" }`
|
||||
var result WsSpotTicker
|
||||
err = json.Unmarshal([]byte(data), &result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp, err := b.ExtractCurrencyPair(result.Symbol, asset.Spot, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = b.updateSpotTickerInformation(&result, cp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Linear update processing
|
||||
data = `{ "symbol": "BTC_USDT", "tickDirection": "PlusTick", "price24hPcnt": "0.017103", "lastPrice": "17216.00", "prevPrice24h": "16926.50", "highPrice24h": "17281.50", "lowPrice24h": "16915.00", "prevPrice1h": "17238.00", "markPrice": "17217.33", "indexPrice": "17227.36", "openInterest": "68744.761", "openInterestValue": "1183601235.91", "turnover24h": "1570383121.943499", "volume24h": "91705.276", "nextFundingTime": "1673280000000", "fundingRate": "-0.000212", "bid1Price": "17215.50", "bid1Size": "84.489", "ask1Price": "17216.00", "ask1Size": "83.020" }`
|
||||
var resultLinear WsLinearTicker
|
||||
err = json.Unmarshal([]byte(data), &resultLinear)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp, err = b.ExtractCurrencyPair(resultLinear.Symbol, asset.USDTMarginedFutures, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = b.updateTickerInformation(&resultLinear, cp, asset.USDTMarginedFutures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Options update processing
|
||||
data = `{"symbol": "BTC-USD-220930-28000-P", "bidPrice": "0", "bidSize": "0", "bidIv": "0", "askPrice": "10", "askSize": "5.1", "askIv": "0.514", "lastPrice": "10", "highPrice24h": "25", "lowPrice24h": "5", "markPrice": "7.86976724", "indexPrice": "16823.73", "markPriceIv": "0.4896", "underlyingPrice": "16815.1", "openInterest": "49.85", "turnover24h": "446802.8473", "volume24h": "26.55", "totalVolume": "86", "totalTurnover": "1437431", "delta": "0.047831", "gamma": "0.00021453", "vega": "0.81351067", "theta": "-19.9115368", "predictedDeliveryPrice": "0", "change24h": "-0.33333334" }`
|
||||
var resultOptions WsOptionTicker
|
||||
err = json.Unmarshal([]byte(data), &resultOptions)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp, err = currency.NewPairFromString(resultOptions.Symbol)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = b.updateOptionsTickerInformation(&resultOptions, cp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOpenInterest(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetOpenInterest(context.Background(), key.PairAsset{
|
||||
|
||||
@@ -164,9 +164,10 @@ type TickerData struct {
|
||||
List []TickerItem `json:"list"`
|
||||
}
|
||||
|
||||
// TickerItem represents a ticker item detail.
|
||||
// TickerItem represents a ticker item detail
|
||||
type TickerItem struct {
|
||||
Symbol string `json:"symbol"`
|
||||
TickDirection string `json:"tickDirection"`
|
||||
LastPrice types.Number `json:"lastPrice"`
|
||||
IndexPrice types.Number `json:"indexPrice"`
|
||||
MarkPrice types.Number `json:"markPrice"`
|
||||
@@ -193,6 +194,7 @@ type TickerItem struct {
|
||||
Bid1Iv types.Number `json:"bid1Iv"`
|
||||
Ask1Iv types.Number `json:"ask1Iv"`
|
||||
MarkIv types.Number `json:"markIv"`
|
||||
MarkPriceIv types.Number `json:"markPriceIv"`
|
||||
UnderlyingPrice types.Number `json:"underlyingPrice"`
|
||||
TotalVolume types.Number `json:"totalVolume"`
|
||||
TotalTurnover types.Number `json:"totalTurnover"`
|
||||
@@ -201,6 +203,13 @@ type TickerItem struct {
|
||||
Vega types.Number `json:"vega"`
|
||||
Theta types.Number `json:"theta"`
|
||||
Change24Hour types.Number `json:"change24h"`
|
||||
UsdIndexPrice types.Number `json:"usdIndexPrice"`
|
||||
BidPrice types.Number `json:"bidPrice"`
|
||||
BidSize types.Number `json:"bidSize"`
|
||||
BidIv types.Number `json:"bidIv"`
|
||||
AskPrice types.Number `json:"askPrice"`
|
||||
AskSize types.Number `json:"askSize"`
|
||||
AskIv types.Number `json:"askIv"`
|
||||
}
|
||||
|
||||
// FundingRateHistory represents a funding rate history for a category.
|
||||
@@ -1786,72 +1795,6 @@ type WebsocketPublicTrades []struct {
|
||||
BlockTrade bool `json:"BT"`
|
||||
}
|
||||
|
||||
// WsLinearTicker represents a linear ticker information.
|
||||
type WsLinearTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
TickDirection string `json:"tickDirection"`
|
||||
Price24HPcnt types.Number `json:"price24hPcnt"`
|
||||
LastPrice types.Number `json:"lastPrice"`
|
||||
PrevPrice24H types.Number `json:"prevPrice24h"`
|
||||
HighPrice24H types.Number `json:"highPrice24h"`
|
||||
LowPrice24H types.Number `json:"lowPrice24h"`
|
||||
PrevPrice1H types.Number `json:"prevPrice1h"`
|
||||
MarkPrice types.Number `json:"markPrice"`
|
||||
IndexPrice types.Number `json:"indexPrice"`
|
||||
OpenInterest types.Number `json:"openInterest"`
|
||||
OpenInterestValue types.Number `json:"openInterestValue"`
|
||||
Turnover24H types.Number `json:"turnover24h"`
|
||||
Volume24H types.Number `json:"volume24h"`
|
||||
NextFundingTime convert.ExchangeTime `json:"nextFundingTime"`
|
||||
FundingRate types.Number `json:"fundingRate"`
|
||||
Bid1Price types.Number `json:"bid1Price"`
|
||||
Bid1Size types.Number `json:"bid1Size"`
|
||||
Ask1Price types.Number `json:"ask1Price"`
|
||||
Ask1Size types.Number `json:"ask1Size"`
|
||||
}
|
||||
|
||||
// WsOptionTicker represents options public ticker data.
|
||||
type WsOptionTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice types.Number `json:"bidPrice"`
|
||||
BidSize types.Number `json:"bidSize"`
|
||||
BidIv types.Number `json:"bidIv"`
|
||||
AskPrice types.Number `json:"askPrice"`
|
||||
AskSize types.Number `json:"askSize"`
|
||||
AskIv types.Number `json:"askIv"`
|
||||
LastPrice types.Number `json:"lastPrice"`
|
||||
HighPrice24H types.Number `json:"highPrice24h"`
|
||||
LowPrice24H types.Number `json:"lowPrice24h"`
|
||||
MarkPrice types.Number `json:"markPrice"`
|
||||
IndexPrice types.Number `json:"indexPrice"`
|
||||
MarkPriceIv types.Number `json:"markPriceIv"`
|
||||
UnderlyingPrice types.Number `json:"underlyingPrice"`
|
||||
OpenInterest types.Number `json:"openInterest"`
|
||||
Turnover24H types.Number `json:"turnover24h"`
|
||||
Volume24H types.Number `json:"volume24h"`
|
||||
TotalVolume types.Number `json:"totalVolume"`
|
||||
TotalTurnover types.Number `json:"totalTurnover"`
|
||||
Delta types.Number `json:"delta"`
|
||||
Gamma types.Number `json:"gamma"`
|
||||
Vega types.Number `json:"vega"`
|
||||
Theta types.Number `json:"theta"`
|
||||
PredictedDeliveryPrice types.Number `json:"predictedDeliveryPrice"`
|
||||
Change24H types.Number `json:"change24h"`
|
||||
}
|
||||
|
||||
// WsSpotTicker represents a spot public ticker information.
|
||||
type WsSpotTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
LastPrice types.Number `json:"lastPrice"`
|
||||
HighPrice24H types.Number `json:"highPrice24h"`
|
||||
LowPrice24H types.Number `json:"lowPrice24h"`
|
||||
PrevPrice24H types.Number `json:"prevPrice24h"`
|
||||
Volume24H types.Number `json:"volume24h"`
|
||||
Turnover24H types.Number `json:"turnover24h"`
|
||||
Price24HPcnt types.Number `json:"price24hPcnt"`
|
||||
UsdIndexPrice types.Number `json:"usdIndexPrice"`
|
||||
}
|
||||
|
||||
// WsKlines represents a list of Kline data.
|
||||
type WsKlines []struct {
|
||||
Confirm bool `json:"confirm"`
|
||||
@@ -1889,16 +1832,6 @@ type LTKlines []struct {
|
||||
Timestamp convert.ExchangeTime `json:"timestamp"`
|
||||
}
|
||||
|
||||
// LTTicker represents a leverage token ticker.
|
||||
type LTTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
LastPrice types.Number `json:"lastPrice"`
|
||||
HighPrice24H types.Number `json:"highPrice24h"`
|
||||
LowPrice24H types.Number `json:"lowPrice24h"`
|
||||
PrevPrice24H types.Number `json:"prevPrice24h"`
|
||||
Price24HPercentage types.Number `json:"price24hPcnt"`
|
||||
}
|
||||
|
||||
// LTNav represents leveraged token nav stream.
|
||||
type LTNav struct {
|
||||
Symbol string `json:"symbol"`
|
||||
|
||||
@@ -495,7 +495,7 @@ func (by *Bybit) wsLeverageTokenNav(resp *WebsocketResponse) error {
|
||||
}
|
||||
|
||||
func (by *Bybit) wsProcessLeverageTokenTicker(assetType asset.Item, resp *WebsocketResponse) error {
|
||||
var result LTTicker
|
||||
var result TickerItem
|
||||
err := json.Unmarshal(resp.Data, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -596,197 +596,104 @@ func (by *Bybit) wsProcessKline(assetType asset.Item, resp *WebsocketResponse, t
|
||||
}
|
||||
|
||||
func (by *Bybit) wsProcessPublicTicker(assetType asset.Item, resp *WebsocketResponse) error {
|
||||
format, err := by.GetPairFormat(assetType, false)
|
||||
tickResp := new(TickerItem)
|
||||
if err := json.Unmarshal(resp.Data, tickResp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := by.MatchSymbolWithAvailablePairs(tickResp.Symbol, assetType, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch assetType {
|
||||
case asset.Spot:
|
||||
var result WsSpotTicker
|
||||
err := json.Unmarshal(resp.Data, &result)
|
||||
pFmt, err := by.GetPairFormat(assetType, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p = p.Format(pFmt)
|
||||
|
||||
var tick *ticker.Price
|
||||
if resp.Type == "snapshot" {
|
||||
tick = &ticker.Price{
|
||||
Pair: p,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType,
|
||||
}
|
||||
} else {
|
||||
// ticker updates may be partial, so we need to update the current ticker
|
||||
tick, err = ticker.GetTicker(by.Name, p, assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp, err := currency.NewPairFromString(result.Symbol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp = cp.Format(format)
|
||||
if resp.Type == "snapshot" {
|
||||
return ticker.ProcessTicker(&ticker.Price{
|
||||
Last: result.LastPrice.Float64(),
|
||||
High: result.HighPrice24H.Float64(),
|
||||
Low: result.LowPrice24H.Float64(),
|
||||
Volume: result.Volume24H.Float64(),
|
||||
Pair: cp,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType,
|
||||
LastUpdated: resp.Timestamp.Time(),
|
||||
})
|
||||
}
|
||||
var tickerData *ticker.Price
|
||||
tickerData, err = by.updateSpotTickerInformation(&result, cp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tickerData.LastUpdated = resp.Timestamp.Time()
|
||||
return nil
|
||||
case asset.USDCMarginedFutures, asset.USDTMarginedFutures, asset.CoinMarginedFutures:
|
||||
var result WsLinearTicker
|
||||
err := json.Unmarshal(resp.Data, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp, err := currency.NewPairFromString(result.Symbol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp = cp.Format(format)
|
||||
if resp.Type == "snapshot" {
|
||||
return ticker.ProcessTicker(&ticker.Price{
|
||||
Last: result.LastPrice.Float64(),
|
||||
High: result.HighPrice24H.Float64(),
|
||||
Low: result.LowPrice24H.Float64(),
|
||||
Bid: result.Bid1Price.Float64(),
|
||||
BidSize: result.Bid1Size.Float64(),
|
||||
Ask: result.Ask1Price.Float64(),
|
||||
AskSize: result.Ask1Size.Float64(),
|
||||
Volume: result.Volume24H.Float64(),
|
||||
Pair: cp,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType,
|
||||
})
|
||||
}
|
||||
var tickerData *ticker.Price
|
||||
tickerData, err = by.updateTickerInformation(&result, cp, assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tickerData.LastUpdated = resp.Timestamp.Time()
|
||||
by.Websocket.DataHandler <- tickerData
|
||||
return nil
|
||||
}
|
||||
|
||||
updateTicker(tick, tickResp)
|
||||
tick.LastUpdated = resp.Timestamp.Time()
|
||||
|
||||
if err = ticker.ProcessTicker(tick); err == nil {
|
||||
by.Websocket.DataHandler <- tick
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func updateTicker(tick *ticker.Price, resp *TickerItem) {
|
||||
if resp.LastPrice.Float64() != 0 {
|
||||
tick.Last = resp.LastPrice.Float64()
|
||||
}
|
||||
if resp.HighPrice24H.Float64() != 0 {
|
||||
tick.High = resp.HighPrice24H.Float64()
|
||||
}
|
||||
if resp.LowPrice24H.Float64() != 0 {
|
||||
tick.Low = resp.LowPrice24H.Float64()
|
||||
}
|
||||
if resp.Volume24H.Float64() != 0 {
|
||||
tick.Volume = resp.Volume24H.Float64()
|
||||
}
|
||||
|
||||
if tick.AssetType == asset.Spot {
|
||||
return
|
||||
}
|
||||
|
||||
if resp.MarkPrice.Float64() != 0 {
|
||||
tick.MarkPrice = resp.MarkPrice.Float64()
|
||||
}
|
||||
if resp.IndexPrice.Float64() != 0 {
|
||||
tick.IndexPrice = resp.IndexPrice.Float64()
|
||||
}
|
||||
if resp.OpenInterest.Float64() != 0 {
|
||||
tick.OpenInterest = resp.OpenInterest.Float64()
|
||||
}
|
||||
|
||||
switch tick.AssetType {
|
||||
case asset.Options:
|
||||
var result WsOptionTicker
|
||||
err := json.Unmarshal(resp.Data, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
if resp.BidPrice.Float64() != 0 {
|
||||
tick.Bid = resp.BidPrice.Float64()
|
||||
}
|
||||
cp, err := currency.NewPairFromString(result.Symbol)
|
||||
if err != nil {
|
||||
return err
|
||||
if resp.BidSize.Float64() != 0 {
|
||||
tick.BidSize = resp.BidSize.Float64()
|
||||
}
|
||||
cp = cp.Format(format)
|
||||
if resp.Type == "snapshot" {
|
||||
return ticker.ProcessTicker(&ticker.Price{
|
||||
Last: result.LastPrice.Float64(),
|
||||
High: result.HighPrice24H.Float64(),
|
||||
Low: result.LastPrice.Float64(),
|
||||
Bid: result.BidPrice.Float64(),
|
||||
BidSize: result.BidSize.Float64(),
|
||||
Ask: result.AskPrice.Float64(),
|
||||
AskSize: result.AskSize.Float64(),
|
||||
Volume: result.Volume24H.Float64(),
|
||||
Pair: cp,
|
||||
ExchangeName: by.Name,
|
||||
AssetType: assetType,
|
||||
})
|
||||
if resp.AskPrice.Float64() != 0 {
|
||||
tick.Ask = resp.AskPrice.Float64()
|
||||
}
|
||||
tickerData, err := by.updateOptionsTickerInformation(&result, cp)
|
||||
if err != nil {
|
||||
return err
|
||||
if resp.AskSize.Float64() != 0 {
|
||||
tick.AskSize = resp.AskSize.Float64()
|
||||
}
|
||||
case asset.USDCMarginedFutures, asset.USDTMarginedFutures, asset.CoinMarginedFutures:
|
||||
if resp.Bid1Price.Float64() != 0 {
|
||||
tick.Bid = resp.Bid1Price.Float64()
|
||||
}
|
||||
if resp.Bid1Size.Float64() != 0 {
|
||||
tick.BidSize = resp.Bid1Size.Float64()
|
||||
}
|
||||
if resp.Ask1Price.Float64() != 0 {
|
||||
tick.Ask = resp.Ask1Price.Float64()
|
||||
}
|
||||
if resp.Ask1Size.Float64() != 0 {
|
||||
tick.AskSize = resp.Ask1Size.Float64()
|
||||
}
|
||||
tickerData.LastUpdated = resp.Timestamp.Time()
|
||||
by.Websocket.DataHandler <- tickerData
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("ticker data unsupported for asset type %v", assetType)
|
||||
}
|
||||
}
|
||||
|
||||
func (by *Bybit) updateSpotTickerInformation(result *WsSpotTicker, cp currency.Pair) (*ticker.Price, error) {
|
||||
tickerData, err := ticker.GetTicker(by.Name, cp, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.LastPrice.Float64() != 0 {
|
||||
tickerData.Last = result.LastPrice.Float64()
|
||||
}
|
||||
if result.HighPrice24H.Float64() != 0 {
|
||||
tickerData.High = result.HighPrice24H.Float64()
|
||||
}
|
||||
if result.LowPrice24H.Float64() != 0 {
|
||||
tickerData.Low = result.LowPrice24H.Float64()
|
||||
}
|
||||
if result.Volume24H.Float64() != 0 {
|
||||
tickerData.Volume = result.Volume24H.Float64()
|
||||
}
|
||||
return tickerData, nil
|
||||
}
|
||||
|
||||
func (by *Bybit) updateTickerInformation(result *WsLinearTicker, cp currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tickerData, err := ticker.GetTicker(by.Name, cp, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.LastPrice.Float64() != 0 {
|
||||
tickerData.Last = result.LastPrice.Float64()
|
||||
}
|
||||
if result.HighPrice24H.Float64() != 0 {
|
||||
tickerData.High = result.HighPrice24H.Float64()
|
||||
}
|
||||
if result.Volume24H.Float64() != 0 {
|
||||
tickerData.Volume = result.Volume24H.Float64()
|
||||
}
|
||||
if result.LowPrice24H.Float64() != 0 {
|
||||
tickerData.Low = result.LowPrice24H.Float64()
|
||||
}
|
||||
if result.Bid1Price.Float64() != 0 {
|
||||
tickerData.Bid = result.Bid1Price.Float64()
|
||||
}
|
||||
if result.Bid1Size.Float64() != 0 {
|
||||
tickerData.BidSize = result.Bid1Size.Float64()
|
||||
}
|
||||
if result.Ask1Price.Float64() != 0 {
|
||||
tickerData.Ask = result.Ask1Price.Float64()
|
||||
}
|
||||
if result.Ask1Size.Float64() != 0 {
|
||||
tickerData.AskSize = result.Ask1Size.Float64()
|
||||
}
|
||||
return tickerData, nil
|
||||
}
|
||||
|
||||
func (by *Bybit) updateOptionsTickerInformation(result *WsOptionTicker, cp currency.Pair) (*ticker.Price, error) {
|
||||
tickerData, err := ticker.GetTicker(by.Name, cp, asset.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.LastPrice.Float64() != 0 {
|
||||
tickerData.Last = result.LastPrice.Float64()
|
||||
}
|
||||
if result.HighPrice24H.Float64() != 0 {
|
||||
tickerData.High = result.HighPrice24H.Float64()
|
||||
}
|
||||
if result.Volume24H.Float64() != 0 {
|
||||
tickerData.Volume = result.Volume24H.Float64()
|
||||
}
|
||||
if result.LowPrice24H.Float64() != 0 {
|
||||
tickerData.Low = result.LowPrice24H.Float64()
|
||||
}
|
||||
if result.BidPrice.Float64() != 0 {
|
||||
tickerData.Bid = result.BidPrice.Float64()
|
||||
}
|
||||
if result.BidSize.Float64() != 0 {
|
||||
tickerData.BidSize = result.BidSize.Float64()
|
||||
}
|
||||
if result.AskPrice.Float64() != 0 {
|
||||
tickerData.Ask = result.AskPrice.Float64()
|
||||
}
|
||||
if result.AskSize.Float64() != 0 {
|
||||
tickerData.AskSize = result.AskSize.Float64()
|
||||
}
|
||||
return tickerData, nil
|
||||
}
|
||||
|
||||
func (by *Bybit) wsProcessPublicTrade(assetType asset.Item, resp *WebsocketResponse) error {
|
||||
var result WebsocketPublicTrades
|
||||
err := json.Unmarshal(resp.Data, &result)
|
||||
|
||||
@@ -33,6 +33,25 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
|
||||
type assetPairFmt struct {
|
||||
asset asset.Item
|
||||
cfgFmt *currency.PairFormat
|
||||
reqFmt *currency.PairFormat
|
||||
}
|
||||
|
||||
var (
|
||||
underscoreFmt = ¤cy.PairFormat{Uppercase: true, Delimiter: "_"}
|
||||
dashFmt = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
|
||||
plainFmt = ¤cy.PairFormat{Uppercase: true}
|
||||
assetPairFmts = []assetPairFmt{
|
||||
{asset.Spot, underscoreFmt, plainFmt},
|
||||
{asset.USDTMarginedFutures, underscoreFmt, plainFmt},
|
||||
{asset.CoinMarginedFutures, underscoreFmt, plainFmt},
|
||||
{asset.USDCMarginedFutures, dashFmt, plainFmt},
|
||||
{asset.Options, dashFmt, dashFmt},
|
||||
}
|
||||
)
|
||||
|
||||
// SetDefaults sets the basic defaults for Bybit
|
||||
func (by *Bybit) SetDefaults() {
|
||||
by.Name = "Bybit"
|
||||
@@ -41,55 +60,19 @@ func (by *Bybit) SetDefaults() {
|
||||
by.API.CredentialsValidator.RequiresKey = true
|
||||
by.API.CredentialsValidator.RequiresSecret = true
|
||||
|
||||
configFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: "_"}
|
||||
requestFormat := ¤cy.PairFormat{Uppercase: true}
|
||||
spotPairStore := currency.PairStore{RequestFormat: requestFormat, ConfigFormat: configFmt}
|
||||
err := by.StoreAssetPairFormat(asset.Spot, spotPairStore)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", asset.Spot, err)
|
||||
}
|
||||
usdtMarginedFuturesPairStore := currency.PairStore{RequestFormat: requestFormat, ConfigFormat: configFmt}
|
||||
err = by.StoreAssetPairFormat(asset.USDTMarginedFutures, usdtMarginedFuturesPairStore)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", asset.USDTMarginedFutures, err)
|
||||
}
|
||||
usdcMarginedFutures := currency.PairStore{RequestFormat: requestFormat,
|
||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}}
|
||||
err = by.StoreAssetPairFormat(asset.USDCMarginedFutures, usdcMarginedFutures)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", asset.USDCMarginedFutures, err)
|
||||
}
|
||||
coinMarginedFutures := currency.PairStore{RequestFormat: requestFormat, ConfigFormat: configFmt}
|
||||
err = by.StoreAssetPairFormat(asset.CoinMarginedFutures, coinMarginedFutures)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", asset.CoinMarginedFutures, err)
|
||||
}
|
||||
optionPairStore := currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||
}
|
||||
err = by.StoreAssetPairFormat(asset.Options, optionPairStore)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", asset.Options, err)
|
||||
for _, n := range assetPairFmts {
|
||||
ps := currency.PairStore{RequestFormat: n.reqFmt, ConfigFormat: n.cfgFmt}
|
||||
if err := by.StoreAssetPairFormat(n.asset, ps); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v %v", n.asset, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = by.DisableAssetWebsocketSupport(asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
err = by.DisableAssetWebsocketSupport(asset.USDTMarginedFutures)
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
err = by.DisableAssetWebsocketSupport(asset.USDCMarginedFutures)
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
for _, a := range []asset.Item{asset.CoinMarginedFutures, asset.USDTMarginedFutures, asset.USDCMarginedFutures, asset.Options} {
|
||||
if err := by.DisableAssetWebsocketSupport(a); err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = by.DisableAssetWebsocketSupport(asset.Options)
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
by.Features = exchange.Features{
|
||||
Supports: exchange.FeaturesSupported{
|
||||
REST: true,
|
||||
@@ -176,14 +159,8 @@ func (by *Bybit) SetDefaults() {
|
||||
},
|
||||
}
|
||||
|
||||
by.Requester, err = request.New(by.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(GetRateLimit()))
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
by.API.Endpoints = by.NewEndpoints()
|
||||
err = by.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
err := by.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bybitAPIURL,
|
||||
exchange.RestCoinMargined: bybitAPIURL,
|
||||
exchange.RestUSDTMargined: bybitAPIURL,
|
||||
@@ -195,6 +172,13 @@ func (by *Bybit) SetDefaults() {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
|
||||
if by.Requester, err = request.New(by.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(GetRateLimit()),
|
||||
); err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
|
||||
by.Websocket = stream.NewWebsocket()
|
||||
by.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
by.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
|
||||
8
exchanges/bybit/testdata/wsTicker.json
vendored
Normal file
8
exchanges/bybit/testdata/wsTicker.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{"topic":"tickers.BTC-USDT","type":"snapshot","ts":233366401000,"cs":2588407389,"data":{"symbol":"BTCUSDT","lastPrice":"21109.77","highPrice24h":"21426.99","lowPrice24h":"20575","prevPrice24h":"20704.93","volume24h":"6780.866843","turnover24h":"141946527.22907118","price24hPcnt":"0.0196","usdIndexPrice":"21120.2400136"}}
|
||||
{"topic":"tickers.BTC-28JUN24-60000-P","ts":1715742949283,"type":"snapshot","id":"tickers.BTC-28JUN24-60000-P-6222585724-1715742949283","data":{"symbol":"BTC-28JUN24-60000-P","bidPrice":"3475","bidSize":"10.14","bidIv":"0.5479","askPrice":"3520","askSize":"2.5","askIv":"0.5534","lastPrice":"3565","highPrice24h":"3715","lowPrice24h":"3555","markPrice":"3502.0715721","indexPrice":"61912.8","markPriceIv":"0.5513","underlyingPrice":"62588.50709846","openInterest":"29.35","turnover24h":"101005.6875725","volume24h":"1.62","totalVolume":"45","totalTurnover":"2911557","delta":"-0.37596534","gamma":"0.00003161","vega":"82.65324199","theta":"-51.54651685","predictedDeliveryPrice":"0","change24h":"0.02148998"}}
|
||||
{"topic":"tickers.BTCUSDT","type":"snapshot","data":{"symbol":"BTCUSDT","tickDirection":"ZeroPlusTick","price24hPcnt":"-0.009772","lastPrice":"61874.00","prevPrice24h":"62484.60","highPrice24h":"62752.90","lowPrice24h":"61000.10","prevPrice1h":"61901.80","markPrice":"61875.25","indexPrice":"61903.73","openInterest":"58117.022","openInterestValue":"3596005265.51","turnover24h":"6073739017.8331","volume24h":"98430.1050","nextFundingTime":"1715760000000","fundingRate":"0.00008055","bid1Price":"61873.90","bid1Size":"3.783","ask1Price":"61874.00","ask1Size":"16.278"},"cs":176530003895,"ts":1715748762463}
|
||||
{"topic":"tickers.BTCUSDT","type":"delta","data":{"symbol":"BTCUSDT","markPrice":"61875.06","indexPrice":"61903.59","openInterestValue":"3595994223.27","bid1Price":"61873.90","bid1Size":"3.543"},"cs":176530004279,"ts":1715748763063}
|
||||
{"topic":"tickers.BTCPERP","type":"snapshot","data":{"symbol":"BTCPERP","tickDirection":"ZeroMinusTick","price24hPcnt":"-0.000733","lastPrice":"61945.70","prevPrice24h":"61991.20","highPrice24h":"62242.20","lowPrice24h":"61059.10","prevPrice1h":"61868.30","markPrice":"61943.58","indexPrice":"61942.85","openInterest":"526.806","openInterestValue":"32632249.61","turnover24h":"26364945.7684","volume24h":"427.3750","nextFundingTime":"1715760000000","fundingRate":"0.00004979","bid1Price":"61909.20","bid1Size":"0.035","ask1Price":"61909.60","ask1Size":"0.082"},"cs":17493207242,"ts":1715756612118}
|
||||
{"topic":"tickers.BTCPERP","type":"delta","data":{"symbol":"BTCPERP","bid1Price":"61909.50","bid1Size":"0.035"},"cs":17493207267,"ts":171575661221}
|
||||
{"topic":"tickers.BTCUSD","type":"snapshot","data":{"symbol":"BTCUSD","tickDirection":"ZeroMinusTick","price24hPcnt":"-0.000096","lastPrice":"61894.00","prevPrice24h":"61900.00","highPrice24h":"62265.50","lowPrice24h":"61029.50","prevPrice1h":"61917.50","markPrice":"61894.00","indexPrice":"61923.36","openInterest":"931760496","openInterestValue":"15054.13","turnover24h":"6363.5775","volume24h":"391976479.0000","nextFundingTime":"1715760000000","fundingRate":"0.0001","bid1Price":"61891.50","bid1Size":"12667","ask1Price":"61892.00","ask1Size":"60953"},"cs":42159594212,"ts":1715757637952}
|
||||
{"topic":"tickers.BTCUSD","type":"delta","data":{"symbol":"BTCUSD","bid1Price":"61891.50","bid1Size":"27634"},"cs":42159594251,"ts":1715757638152}
|
||||
@@ -141,8 +141,7 @@ func FindLast(p currency.Pair, a asset.Item) (float64, error) {
|
||||
return 0, fmt.Errorf("%w %s %s", errTickerNotFound, p, a)
|
||||
}
|
||||
|
||||
// ProcessTicker processes incoming tickers, creating or updating the Tickers
|
||||
// list
|
||||
// ProcessTicker processes incoming tickers, creating or updating the Tickers list
|
||||
func ProcessTicker(p *Price) error {
|
||||
if p == nil {
|
||||
return errors.New(errTickerPriceIsNil)
|
||||
|
||||
@@ -37,7 +37,9 @@ type Price struct {
|
||||
High float64 `json:"High"`
|
||||
Low float64 `json:"Low"`
|
||||
Bid float64 `json:"Bid"`
|
||||
BidSize float64 `json:"BidSize"`
|
||||
Ask float64 `json:"Ask"`
|
||||
AskSize float64 `json:"AskSize"`
|
||||
Volume float64 `json:"Volume"`
|
||||
QuoteVolume float64 `json:"QuoteVolume"`
|
||||
PriceATH float64 `json:"PriceATH"`
|
||||
@@ -54,9 +56,7 @@ type Price struct {
|
||||
// Funding rate field variables
|
||||
FlashReturnRate float64
|
||||
BidPeriod float64
|
||||
BidSize float64
|
||||
AskPeriod float64
|
||||
AskSize float64
|
||||
FlashReturnRateAmount float64
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user