You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

162 lines
4.3 KiB

package okx
import (
"fmt"
"sig-pub/pkg/types"
"strconv"
"github.com/govalues/decimal"
)
// WS/K线频道
// 获取K线数据,推送频率最快是间隔1秒推送一次数据。
type CandleData [][]string
var (
// k线类型
// 如 [1s/1m/3m/5m/15m/30m/1H/2H/4H]
// 香港时间开盘价k线:[6H/12H/1D/2D/3D/1W/1M/3M]
// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/2Dutc/3Dutc/1Wutc/1Mutc/3Mutc]
// "candle1s" candle3Mutc candle1Mutc candle1Wutc candle1Dutc candle2Dutc candle3Dutc candle5Dutc candle12Hutc candle6Hutc
// candles = []string{"candle3M", "candle1M", "candle1W", "candle1D", "candle2D", "candle3D", "candle5D", "candle12H", "candle6H", "candle4H", "candle2H", "candle1H", "candle30m", "candle15m", "candle5m", "candle3m", "candle1m"}
subCandles = []string{
// "candle3M", "candle1M",
"candle1W", "candle1D", "candle2D", "candle3D", "candle5D",
"candle12H", "candle6H", "candle4H", "candle2H", "candle1H",
"candle30m", "candle15m", "candle5m", "candle3m", "candle1m",
"candle1s",
}
)
// ChannelCandle k线订阅频道
type ChannelCandle struct {
cfg wsChannelConfig[*CandleData, *types.ChannelKline]
wsChannel *wsChannel[*CandleData, *types.ChannelKline]
}
func NewChannelCandle(
traceId string,
httpProxy string,
) *ChannelCandle {
cfg := wsChannelConfig[*CandleData, *types.ChannelKline]{
channelId: traceId,
httpProxy: httpProxy,
wsUrl: "/ws/v5/business",
subscribeChannels: subCandles,
dataInstanceFunc: func() *CandleData {
var d CandleData
return &d
},
dataMappingFunc: candleData2Klines,
}
return &ChannelCandle{cfg: cfg}
}
func (c *ChannelCandle) Init() (err error) {
c.wsChannel = newWsChannel(c.cfg)
return c.wsChannel.Init()
}
func (c *ChannelCandle) Consumer() <-chan *types.ChannelKline {
return c.wsChannel.Consumer()
}
func (c *ChannelCandle) Subscribe(instIds ...string) (err error) {
return c.wsChannel.Subscribe(instIds...)
}
func (c *ChannelCandle) Unsubscribe(instIds ...string) (err error) {
return c.wsChannel.Unsubscribe(instIds...)
}
func (c *ChannelCandle) IsSubscribe(instId string) bool {
return c.wsChannel.IsSubscribed(instId)
}
func (c *ChannelCandle) GetSubscribes() (instIds []string) {
return c.wsChannel.GetSubscribes()
}
// func candleData2Klines() (klines []*types.Kline) {
func candleData2Klines(channelData *ChannelData[*CandleData]) (r *types.ChannelKline, err error) {
r = &types.ChannelKline{
InstId: channelData.InstId,
Exchange: types.ExchangeOKX,
}
for _, data := range *channelData.Data {
ts, e := strconv.ParseInt(data[0], 10, 64)
if e != nil {
err = e
return
}
kline := &types.Kline{
Ts: ts,
Confirm: data[8] == "1",
}
switch channelData.Channel {
default:
err = fmt.Errorf("unsupport candle: %s", channelData.Channel)
continue
case "candle1s":
kline.Interval = types.Interval1s
// case "candle5s":
// kline.Interval = types.Interval5s
case "candle1m":
kline.Interval = types.Interval1m
case "candle3m":
kline.Interval = types.Interval3m
case "candle5m":
kline.Interval = types.Interval5m
case "candle15m":
kline.Interval = types.Interval15m
case "candle30m":
kline.Interval = types.Interval30m
case "candle1H":
kline.Interval = types.Interval1h
case "candle2H":
kline.Interval = types.Interval2h
case "candle4H":
kline.Interval = types.Interval4h
case "candle6H":
kline.Interval = types.Interval6h
case "candle12H":
kline.Interval = types.Interval12h
case "candle1D":
kline.Interval = types.Interval1d
case "candle2D":
kline.Interval = types.Interval2d
case "candle3D":
kline.Interval = types.Interval3d
case "candle5D":
kline.Interval = types.Interval5d
case "candle1W":
kline.Interval = types.Interval1w
// case "candle1M":
// kline.Interval = types.Interval1mo
// case "candle3M":
// kline.Interval = types.Interval3mo
}
var kinds = []*decimal.Decimal{&kline.Open, &kline.High, &kline.Low, &kline.Close, &kline.Vol, nil, &kline.VolQuote}
for i := 1; i <= 7; i++ {
if kinds[i-1] == nil {
continue
}
*kinds[i-1], err = decimal.Parse(data[i])
if err != nil {
return
}
}
// ims, ok := kline.Interval.Milliseconds()
// if !ok {
// err = fmt.Errorf("unsupport interval: %v", kline.Interval)
// continue
// }
// kline.Tid = ts / ims
r.Klines = append(r.Klines, kline)
}
return
}