pkg/exchange: upgrade kline ws to v2

This commit is contained in:
edwin 2024-08-12 23:07:32 +08:00
parent 4925d8bfd9
commit b02be2cf70
4 changed files with 62 additions and 50 deletions

View File

@ -8,6 +8,7 @@ import (
const ( const (
PrivateWebSocketURL = "wss://ws.bitget.com/v2/ws/private" PrivateWebSocketURL = "wss://ws.bitget.com/v2/ws/private"
PublicWebSocketURL = "wss://ws.bitget.com/v2/ws/public"
) )
type APIResponse = bitgetapi.APIResponse type APIResponse = bitgetapi.APIResponse

View File

@ -120,7 +120,7 @@ func (s *Stream) Unsubscribe() {
func (s *Stream) createEndpoint(_ context.Context) (string, error) { func (s *Stream) createEndpoint(_ context.Context) (string, error) {
var url string var url string
if s.PublicOnly { if s.PublicOnly {
url = bitgetapi.PublicWebSocketURL url = v2.PublicWebSocketURL
} else { } else {
url = v2.PrivateWebSocketURL url = v2.PrivateWebSocketURL
} }
@ -245,7 +245,7 @@ func (s *Stream) ping(conn *websocket.Conn) error {
func convertSubscription(sub types.Subscription) (WsArg, error) { func convertSubscription(sub types.Subscription) (WsArg, error) {
arg := WsArg{ arg := WsArg{
// support spot only // support spot only
InstType: instSp, InstType: instSpV2,
Channel: "", Channel: "",
InstId: sub.Symbol, InstId: sub.Symbol,
} }

View File

@ -179,7 +179,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
input := `{ input := `{
"event":"subscribe", "event":"subscribe",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"books5", "channel":"books5",
"instId":"BTCUSDT" "instId":"BTCUSDT"
} }
@ -191,7 +191,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
assert.Equal(t, WsEvent{ assert.Equal(t, WsEvent{
Event: WsEventSubscribe, Event: WsEventSubscribe,
Arg: WsArg{ Arg: WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook5, Channel: ChannelOrderBook5,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, },
@ -204,7 +204,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
input := `{ input := `{
"event":"unsubscribe", "event":"unsubscribe",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"books5", "channel":"books5",
"instId":"BTCUSDT" "instId":"BTCUSDT"
} }
@ -216,7 +216,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
assert.Equal(t, WsEvent{ assert.Equal(t, WsEvent{
Event: WsEventUnsubscribe, Event: WsEventUnsubscribe,
Arg: WsArg{ Arg: WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook5, Channel: ChannelOrderBook5,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, },
@ -227,7 +227,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
input := `{ input := `{
"event":"error", "event":"error",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"books5", "channel":"books5",
"instId":"BTCUSDT-" "instId":"BTCUSDT-"
}, },
@ -245,7 +245,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
Msg: "instType:sp,channel:books5,instId:BTCUSDT- doesn't exist", Msg: "instType:sp,channel:books5,instId:BTCUSDT- doesn't exist",
Op: "subscribe", Op: "subscribe",
Arg: WsArg{ Arg: WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook5, Channel: ChannelOrderBook5,
InstId: "BTCUSDT-", InstId: "BTCUSDT-",
}, },
@ -256,7 +256,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"books5", "channel":"books5",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -349,7 +349,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"trade", "channel":"trade",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -434,7 +434,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"trade", "channel":"trade",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -456,7 +456,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"trade", "channel":"trade",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -478,7 +478,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"trade", "channel":"trade",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -500,7 +500,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"trade", "channel":"trade",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
@ -524,12 +524,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631"] ["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -549,6 +549,7 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
LowestPrice: fixedpoint.NewFromFloat(34355.53), LowestPrice: fixedpoint.NewFromFloat(34355.53),
ClosePrice: fixedpoint.NewFromFloat(34416.41), ClosePrice: fixedpoint.NewFromFloat(34416.41),
Volume: fixedpoint.NewFromFloat(99.6631), Volume: fixedpoint.NewFromFloat(99.6631),
QuoteVolume: fixedpoint.NewFromFloat(123456),
}, },
}, },
actionType: actionType, actionType: actionType,
@ -571,12 +572,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.45","34458.98","34355.53","34416.41","99.6631", "123456"] ["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -588,12 +589,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["timestamp","34361.49","34458.98","34355.53","34416.41","99.6631"] ["timestamp","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -605,12 +606,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","1p","34458.98","34355.53","34416.41","99.6631"] ["1698744600000","1p","34458.98","34355.53","34416.41","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -622,12 +623,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.45","3p","34355.53","34416.41","99.6631"] ["1698744600000","34361.49","3p","34355.53","34416.41","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -639,12 +640,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.45","34458.98","1p","34416.41","99.6631"] ["1698744600000","34361.49","34458.98","1p","34416.41","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -656,12 +657,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.45","34458.98","34355.53","1c","99.6631"] ["1698744600000","34361.49","34458.98","34355.53","1c","99.6631", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -673,12 +674,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) {
input := `{ input := `{
"action":"%s", "action":"%s",
"arg":{ "arg":{
"instType":"sp", "instType":"SPOT",
"channel":"candle5m", "channel":"candle5m",
"instId":"BTCUSDT" "instId":"BTCUSDT"
}, },
"data":[ "data":[
["1698744600000","34361.45","34458.98","34355.53","34416.41", "1v"] ["1698744600000","34361.49","34458.98","34355.53","34416.41","1v", "123456", "123"]
], ],
"ts":1697697791670 "ts":1697697791670
}` }`
@ -698,7 +699,7 @@ func Test_convertSubscription(t *testing.T) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, WsArg{ assert.Equal(t, WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook5, Channel: ChannelOrderBook5,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, res) }, res)
@ -713,7 +714,7 @@ func Test_convertSubscription(t *testing.T) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, WsArg{ assert.Equal(t, WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook15, Channel: ChannelOrderBook15,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, res) }, res)
@ -728,7 +729,7 @@ func Test_convertSubscription(t *testing.T) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, WsArg{ assert.Equal(t, WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelOrderBook, Channel: ChannelOrderBook,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, res) }, res)
@ -741,7 +742,7 @@ func Test_convertSubscription(t *testing.T) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, WsArg{ assert.Equal(t, WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelTrade, Channel: ChannelTrade,
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, res) }, res)
@ -757,7 +758,7 @@ func Test_convertSubscription(t *testing.T) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, WsArg{ assert.Equal(t, WsArg{
InstType: instSp, InstType: instSpV2,
Channel: ChannelType(localInterval), Channel: ChannelType(localInterval),
InstId: "BTCUSDT", InstId: "BTCUSDT",
}, res) }, res)

View File

@ -14,7 +14,6 @@ import (
type InstType string type InstType string
const ( const (
instSp InstType = "sp"
instSpV2 InstType = "SPOT" instSpV2 InstType = "SPOT"
) )
@ -285,9 +284,12 @@ var (
types.Interval30m: "candle30m", types.Interval30m: "candle30m",
types.Interval1h: "candle1H", types.Interval1h: "candle1H",
types.Interval4h: "candle4H", types.Interval4h: "candle4H",
types.Interval12h: "candle12H", types.Interval6h: "candle6Hutc",
types.Interval1d: "candle1D", types.Interval12h: "candle12Hutc",
types.Interval1w: "candle1W", types.Interval1d: "candle1Dutc",
types.Interval3d: "candle3Dutc",
types.Interval1w: "candle1Wutc",
types.Interval1mo: "candle1Mutc",
} }
toGlobalInterval = map[string]types.Interval{ toGlobalInterval = map[string]types.Interval{
@ -297,9 +299,12 @@ var (
"candle30m": types.Interval30m, "candle30m": types.Interval30m,
"candle1H": types.Interval1h, "candle1H": types.Interval1h,
"candle4H": types.Interval4h, "candle4H": types.Interval4h,
"candle12H": types.Interval12h, "candle6Hutc": types.Interval6h,
"candle1D": types.Interval1d, "candle12Hutc": types.Interval12h,
"candle1W": types.Interval1w, "candle1Dutc": types.Interval1d,
"candle3Dutc": types.Interval3d,
"candle1Wutc": types.Interval1w,
"candle1Mutc": types.Interval1mo,
} }
// we align utc time zone // we align utc time zone
@ -345,6 +350,7 @@ type KLine struct {
LowestPrice fixedpoint.Value LowestPrice fixedpoint.Value
ClosePrice fixedpoint.Value ClosePrice fixedpoint.Value
Volume fixedpoint.Value Volume fixedpoint.Value
QuoteVolume fixedpoint.Value
} }
func (k KLine) ToGlobal(interval types.Interval, symbol string) types.KLine { func (k KLine) ToGlobal(interval types.Interval, symbol string) types.KLine {
@ -361,7 +367,7 @@ func (k KLine) ToGlobal(interval types.Interval, symbol string) types.KLine {
High: k.HighestPrice, High: k.HighestPrice,
Low: k.LowestPrice, Low: k.LowestPrice,
Volume: k.Volume, Volume: k.Volume,
QuoteVolume: fixedpoint.Zero, // not supported QuoteVolume: k.QuoteVolume,
TakerBuyBaseAssetVolume: fixedpoint.Zero, // not supported TakerBuyBaseAssetVolume: fixedpoint.Zero, // not supported
TakerBuyQuoteAssetVolume: fixedpoint.Zero, // not supported TakerBuyQuoteAssetVolume: fixedpoint.Zero, // not supported
LastTradeID: 0, // not supported LastTradeID: 0, // not supported
@ -400,9 +406,10 @@ func parseKLineSliceJSON(in []byte) (slice KLineSlice, err error) {
} }
for _, raw := range rawKLines { for _, raw := range rawKLines {
if len(raw) != 6 { if len(raw) != 8 {
return nil, fmt.Errorf("unexpected kline length: %d, data: %q", len(raw), raw) return nil, fmt.Errorf("unexpected kline length: %d, data: %q", len(raw), raw)
} }
// even though it supports 8 fields, we only parse the ones we need.
var kline KLine var kline KLine
if err = json.Unmarshal(raw[0], &kline.StartTime); err != nil { if err = json.Unmarshal(raw[0], &kline.StartTime); err != nil {
return nil, fmt.Errorf("failed to unmarshal into timestamp: %q", raw[0]) return nil, fmt.Errorf("failed to unmarshal into timestamp: %q", raw[0])
@ -422,6 +429,9 @@ func parseKLineSliceJSON(in []byte) (slice KLineSlice, err error) {
if err = json.Unmarshal(raw[5], &kline.Volume); err != nil { if err = json.Unmarshal(raw[5], &kline.Volume); err != nil {
return nil, fmt.Errorf("failed to unmarshal into volume: %q", raw[5]) return nil, fmt.Errorf("failed to unmarshal into volume: %q", raw[5])
} }
if err = json.Unmarshal(raw[6], &kline.QuoteVolume); err != nil {
return nil, fmt.Errorf("failed to unmarshal into quote volume: %q", raw[6])
}
slice = append(slice, kline) slice = append(slice, kline)
} }