|
|
|
|
@ -733,7 +733,7 @@ func (svc *ExchangeService) CalcSeriesRange(arg *pb.SeriesRange) (after, before,
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// HistoryKline 获取交易产品历史k线 (before < klines... < after)
|
|
|
|
|
func (svc *ExchangeService) HistoryKline(ctx context.Context, arg *pb.SeriesRange) (live bool, klines []*types.Kline, err error) { |
|
|
|
|
func (svc *ExchangeService) HistoryKline(arg *pb.SeriesRange, recvBranch int, recvKline func(klines []*pb.Kline) error) (live bool, err error) { |
|
|
|
|
// 交易产品参数检查
|
|
|
|
|
exchange := svc.exchanges.Get(arg.Exchange) |
|
|
|
|
exchangeInstId, ok := exchange.TradeInstIds.Load(arg.InstId) |
|
|
|
|
@ -748,89 +748,61 @@ func (svc *ExchangeService) HistoryKline(ctx context.Context, arg *pb.SeriesRang
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// todo 交易产品初始化完成检查
|
|
|
|
|
exchangeInst, ok := exchange.ExchangeInsts.Load(exchangeInstId) |
|
|
|
|
if !ok { |
|
|
|
|
err = fmt.Errorf("trade instance not support for exchange: %s for %s", arg.InstId, arg.Exchange) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
// 交易产品初始化完成检查
|
|
|
|
|
if status := exchangeInst.Status.Load(); status != int32(data.StatusOk) { |
|
|
|
|
err = fmt.Errorf("trade instance not ready: %s(%s) for %d", arg.InstId, arg.Exchange, status) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
// 限制最大时间范围
|
|
|
|
|
afterTs, beforeTs, total, err := svc.CalcSeriesRange(arg) |
|
|
|
|
if err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if total > MaxHistoryKlines { |
|
|
|
|
err = fmt.Errorf("time range too large max %d", MaxHistoryKlines) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
// if total > MaxHistoryKlines {
|
|
|
|
|
// err = fmt.Errorf("time range too large max %d", MaxHistoryKlines)
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
if arg.Limit > 0 && total > int64(arg.Limit) { |
|
|
|
|
err = fmt.Errorf("time range %d out of limit %d", total, arg.Limit) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 时间分段查询: 升降序, live, open
|
|
|
|
|
branch := int64(10) |
|
|
|
|
// 分批查询
|
|
|
|
|
branch := int64(2000) |
|
|
|
|
before, after := beforeTs, afterTs |
|
|
|
|
recvBuffer := make([]*pb.Kline, 0, recvBranch) |
|
|
|
|
for range 10000 { |
|
|
|
|
if arg.Desc { |
|
|
|
|
before = intervalAdder(after, -branch) |
|
|
|
|
if before > afterTs { // int64 越界
|
|
|
|
|
before = beforeTs |
|
|
|
|
} |
|
|
|
|
before = max(before, beforeTs) |
|
|
|
|
before = max(intervalAdder(after, -branch+1), beforeTs) |
|
|
|
|
} else { |
|
|
|
|
after = intervalAdder(before, branch) |
|
|
|
|
if after < beforeTs { // int64 越界
|
|
|
|
|
after = afterTs |
|
|
|
|
} |
|
|
|
|
after = min(after, afterTs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for { |
|
|
|
|
klines, err = svc.exchangeDataPersist.ListKline(*exchangeInst.Inst, interval, before, after) |
|
|
|
|
if err != nil { |
|
|
|
|
zlog.Error("list vmtsdb kline error: ", err) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if len(klines) == 0 { |
|
|
|
|
break |
|
|
|
|
after = min(intervalAdder(before, branch-1), afterTs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if arg.Desc { |
|
|
|
|
after = intervalAdder(klines[0].Ts, -1) |
|
|
|
|
before = max(intervalAdder(after, -branch), beforeTs) |
|
|
|
|
if after < KlineBefore0 || before > after { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
before = intervalAdder(klines[0].Ts, 1) |
|
|
|
|
after = min(intervalAdder(before, 1000), afterTs) |
|
|
|
|
if before > time.Now().UnixMilli() || before > after { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if arg.Desc { |
|
|
|
|
collect.Reverse(klines) |
|
|
|
|
} |
|
|
|
|
tss := collect.Mapping(klines, func(_ int, k *types.Kline) int64 { return k.Ts }) |
|
|
|
|
zlog.Info(tss) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
klines, err = svc.exchangeDataPersist.ListKline(*exchangeInst.Inst, interval, beforeTs, afterTs) |
|
|
|
|
if err != nil { |
|
|
|
|
klines, errK := svc.exchangeDataPersist.ListKline(*exchangeInst.Inst, interval, before, after) |
|
|
|
|
if errK != nil { |
|
|
|
|
err = errK |
|
|
|
|
zlog.Error("list vmtsdb kline error: ", err) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if len(klines) == 0 { |
|
|
|
|
return |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 检查k线是否连续进行补齐
|
|
|
|
|
if err = svc.paddingKlinesIfNotSeries(exchange, arg.InstId, interval, klines); err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
lastK := klines[len(klines)-1] |
|
|
|
|
// vmtsdb 数据刷盘30s延迟, 使用内存数据替代第一根k线
|
|
|
|
|
if after == afterTs && lastK.Ts != afterTs { |
|
|
|
|
// vmtsdb 数据落盘30s延迟, 使用内存数据替代最新的一根k线
|
|
|
|
|
lastConfirmK := exchangeInst.LastKline.Get(interval) |
|
|
|
|
if lastConfirmK.Ts == lastK.Ts { |
|
|
|
|
lastK = &lastConfirmK |
|
|
|
|
@ -840,62 +812,43 @@ func (svc *ExchangeService) HistoryKline(ctx context.Context, arg *pb.SeriesRang
|
|
|
|
|
lastK = &lastConfirmK |
|
|
|
|
klines = append(klines, &lastConfirmK) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 降序排序
|
|
|
|
|
if arg.Desc { |
|
|
|
|
collect.Reverse(klines) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 实时k线
|
|
|
|
|
if arg.Live && len(klines) > 0 { |
|
|
|
|
if !live && arg.Live && lastK.Ts == afterTs { |
|
|
|
|
liveK := exchangeInst.LiveKline.Get(interval) |
|
|
|
|
if latest := intervalAdder(lastK.Ts, 1) == liveK.Ts; latest { |
|
|
|
|
if arg.Desc { |
|
|
|
|
klines = append([]*types.Kline{&liveK}, klines...) |
|
|
|
|
} else { |
|
|
|
|
klines = append(klines, &liveK) |
|
|
|
|
} |
|
|
|
|
live = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 查询历史k线(按时间升序流式返回)
|
|
|
|
|
func (svc *ExchangeService) HistoryKlineStream(arg *pb.SeriesRange, stream grpc.ServerStreamingServer[pb.RspHistoryKlineStream]) (err error) { |
|
|
|
|
ctx := context.Background() |
|
|
|
|
_, klines, err := svc.HistoryKline(ctx, arg) |
|
|
|
|
if err != nil { |
|
|
|
|
return |
|
|
|
|
// next loop
|
|
|
|
|
if arg.Desc { |
|
|
|
|
after = intervalAdder(klines[0].Ts, -1) |
|
|
|
|
} else { |
|
|
|
|
before = intervalAdder(klines[len(klines)-1].Ts, 1) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 交易产品参数检查
|
|
|
|
|
if !svc.exchanges.IsSupport(arg.Exchange) { |
|
|
|
|
err = fmt.Errorf("exchange not support: %s", arg.Exchange) |
|
|
|
|
return |
|
|
|
|
// 降序排序
|
|
|
|
|
if arg.Desc { |
|
|
|
|
collect.Reverse(klines) |
|
|
|
|
} |
|
|
|
|
exchange := svc.exchanges.Get(arg.Exchange) |
|
|
|
|
interval := types.Interval(arg.Interval) |
|
|
|
|
|
|
|
|
|
// 检查k线是否连续进行补齐
|
|
|
|
|
if err = svc.paddingKlinesIfNotSeries(exchange, arg.InstId, interval, klines); err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
zlog.Infof("krange: %s, total=%d, %d~%d", arg.InstId, len(klines), klines[0].Ts, klines[len(klines)-1].Ts) |
|
|
|
|
|
|
|
|
|
branch := 100 |
|
|
|
|
// 分成小批量recv
|
|
|
|
|
length := len(klines) |
|
|
|
|
kBuffer := make([]*pb.Kline, 0, branch) |
|
|
|
|
for i, kline := range klines { |
|
|
|
|
kBuffer = append(kBuffer, kline.ToPBKline()) |
|
|
|
|
if len(kBuffer) < branch && i < length-1 { |
|
|
|
|
recvBuffer = append(recvBuffer, kline.ToPBKline()) |
|
|
|
|
if len(recvBuffer) < recvBranch && i < length-1 { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
rsp := &pb.RspHistoryKlineStream{Klines: kBuffer} |
|
|
|
|
if sendErr := stream.Send(rsp); sendErr != nil { |
|
|
|
|
err = sendErr |
|
|
|
|
return |
|
|
|
|
if err = recvKline(recvBuffer); err != nil { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
recvBuffer = recvBuffer[:0] |
|
|
|
|
} |
|
|
|
|
kBuffer = kBuffer[:0] |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|