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.
 
 

137 lines
3.7 KiB

package trading
import (
"context"
"io"
"sig-pub/api/pb"
"sig-pub/pkg/client"
"sig-pub/pkg/mq"
"sig-pub/pkg/types"
"sig-pub/pkg/utils/collect"
"sig-pub/pkg/zlog"
"time"
"google.golang.org/grpc"
)
type TradingService struct {
marketClientAside *client.TradeInstanceAside
exchangeClient pb.ExchangeServiceClient
klineStore *KlineStore
subscribeKlineIntervals []string
subKlineInsts [3][]string
subKlineStream grpc.BidiStreamingClient[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]
}
func NewTradingService(
marketClientAside *client.TradeInstanceAside,
exchangeClient pb.ExchangeServiceClient,
) *TradingService {
// 订阅实时k线周期列表
subscribeKlineIntervals := collect.Map2Slice(types.SupportedIntervals, func(interval types.Interval, _ types.IntervalAdder) string {
return string(interval)
})
return &TradingService{
marketClientAside: marketClientAside,
exchangeClient: exchangeClient,
subscribeKlineIntervals: subscribeKlineIntervals,
}
}
// 初始化历史k线, 订阅实时k线
func (svr *TradingService) Init() (err error) {
svr.klineStore = NewKlineSeriesStore()
// get instance
exchangeTradeInsts, err := svr.marketClientAside.ListExchangeTradeInstance(context.Background(), pb.ExchangeType_OKX)
if err != nil {
return
}
for _, exInst := range exchangeTradeInsts {
svr.subKlineInsts[exInst.Exchange] = append(svr.subKlineInsts[exInst.Exchange], exInst.InstId)
}
// 拉取已初始化完成交易产品, 初始化k线, 开始订阅k线
// 订阅交易产品初始化完成事件
mq.NatsCreateConsumer("trading", mq.StreamExchange, mq.TopicExchangeTradeInstanceInited, func() *mq.PublishExchangeTradeInstanceInited { return new(mq.PublishExchangeTradeInstanceInited) },
func(msg *mq.PublishExchangeTradeInstanceInited) (err error) {
// 初始化k线, 开始订阅k线
zlog.Infof("trade instance inited: %#v", msg)
return
})
// 订阅k线
go svr.subscribeStreamKlines(false)
return
}
func (svr *TradingService) subscribeKlines() {
}
func (svr *TradingService) subscribeStreamKlines(reconnect bool) {
defer func() {
if svr.subKlineStream != nil {
svr.subKlineStream.CloseSend()
svr.subKlineStream = nil
}
go svr.subscribeStreamKlines(true)
}()
if reconnect {
zlog.Infof("subscribeKlines will reconnect after 5s")
time.Sleep(5 * time.Second)
}
stream, err := svr.exchangeClient.SubscribeKline(context.Background())
if err != nil {
zlog.Error("subscribeKlines reqeust error: ", err)
return
}
svr.subKlineStream = stream
// 发送订阅消息
exchanges := []pb.ExchangeType{pb.ExchangeType_OKX}
for _, exchange := range exchanges {
instIds := svr.subKlineInsts[exchange]
if len(instIds) == 0 {
continue
}
msg := &pb.ReqStreamSubscribeKline{
SubType: pb.SubscribeType_Subscribe,
Exchanges: []pb.ExchangeType{exchange},
InstIds: instIds,
Intervals: svr.subscribeKlineIntervals,
OnlyConfirm: true,
}
zlog.Debugf("send stream subscribe kline msg: %#v", msg)
if err = stream.Send(msg); err != nil {
zlog.Errorf("send stream subscribe kline msg error: %v", msg, err)
return
}
}
// 接收消息的goroutine
for {
msg, err := stream.Recv()
if err == io.EOF {
zlog.Debugf("subscribeKlines connection server closeed")
return
}
if err != nil {
zlog.Error("subscribeKlines recv error: ", err)
return
}
for _, k := range msg.Kline.Klines {
kline := new(types.Kline)
kline.ParsePBKline(msg.Kline.Exchange, k)
zlog.Debugf("recv: streamId=%d, %v, %s, %#v", msg.Kline.StreamId, msg.Kline.Exchange, msg.Kline.InstId, kline)
// kline klineStore -> klineSeries -> strategy -> indicator -> klineSeries.Series
svr.klineStore.Update(msg.Kline.Exchange, msg.Kline.InstId, kline)
}
}
}