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.
167 lines
4.5 KiB
167 lines
4.5 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 { |
|
var candles []string |
|
for _, interval := range subscribeCandles { |
|
candles = append(candles, "candle"+interval) |
|
} |
|
cfg := wsChannelConfig[*CandleData, *types.ChannelKline]{ |
|
channelId: traceId, |
|
httpProxy: httpProxy, |
|
wsUrl: "/ws/v5/business", |
|
subscribeChannels: candles, |
|
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 |
|
}
|
|
|