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.
125 lines
3.3 KiB
125 lines
3.3 KiB
package trading |
|
|
|
import ( |
|
"context" |
|
"io" |
|
"sig-pub/api/pb" |
|
"sig-pub/pkg/client" |
|
"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, |
|
klineStore: NewKlineSeriesStore(exchangeClient), |
|
subscribeKlineIntervals: subscribeKlineIntervals, |
|
} |
|
} |
|
|
|
// 初始化历史k线, 订阅实时k线 |
|
func (svr *TradingService) Init() (err error) { |
|
if err = svr.klineStore.Init(); err != nil { |
|
return |
|
} |
|
|
|
// 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线 |
|
go svr.subscribeStreamKlines(false) |
|
return |
|
} |
|
|
|
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) |
|
} |
|
} |
|
}
|
|
|