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.
127 lines
3.4 KiB
127 lines
3.4 KiB
package trading |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"io" |
|
"sig-pub/api/pb" |
|
"sig-pub/pkg/indicator" |
|
"sig-pub/pkg/types" |
|
"sig-pub/pkg/types/series" |
|
"sig-pub/pkg/zlog" |
|
|
|
"google.golang.org/grpc" |
|
) |
|
|
|
type IOffsetIndicatorContext interface { |
|
indicator.IIndicatorContext |
|
SetOffset(offset int16) |
|
AddOffset(offset int16) |
|
} |
|
|
|
// IndicatorContext 指标上下文, 提供k线序列给指标计算使用 |
|
type IndicatorContext struct { |
|
IOffsetIndicatorContext |
|
kSeries *KlineSeries |
|
offset int16 |
|
} |
|
|
|
func NewIndicatorContext(kSeries *KlineSeries) *IndicatorContext { |
|
return &IndicatorContext{ |
|
kSeries: kSeries, |
|
} |
|
} |
|
|
|
func (c *IndicatorContext) SetOffset(offset int16) { |
|
c.offset = offset |
|
} |
|
|
|
func (c *IndicatorContext) AddOffset(offset int16) { |
|
c.offset += offset |
|
} |
|
|
|
func (c *IndicatorContext) Get(offset int16) (kline types.Kline) { |
|
offset += c.offset |
|
k, ok := c.kSeries.Get(offset) |
|
if !ok { |
|
lastTs := c.kSeries.LastTs() |
|
zlog.Warningf("get kline series offset out of range: offset=%d, lastTs=%d", offset, lastTs) |
|
panic(fmt.Errorf("get kline series offset out of range: offset=%d", offset)) |
|
} |
|
return k |
|
} |
|
|
|
func (c *IndicatorContext) Series(offset, count int16) (klines series.Klines) { |
|
offset += c.offset |
|
ks, ok := c.kSeries.Series(offset, count) |
|
if !ok { |
|
zlog.Warningf("get kline series offset out of range: offset=%d, count=%d, lastTs=%d", offset, count, c.kSeries.LastTs()) |
|
panic(fmt.Errorf("get kline series offset out of range: offset=%d, count=%d", offset, count)) |
|
} |
|
return ks |
|
} |
|
|
|
type HistoryIndicatorContext struct { |
|
IOffsetIndicatorContext |
|
exchangeClient pb.ExchangeServiceClient |
|
context *IndicatorContext |
|
} |
|
|
|
func NewHistoryIndicatorContext(exchangeClient pb.ExchangeServiceClient) *HistoryIndicatorContext { |
|
return &HistoryIndicatorContext{ |
|
exchangeClient: exchangeClient, |
|
} |
|
} |
|
func (c *HistoryIndicatorContext) Init(exchange pb.ExchangeType, instId string, interval types.Interval, before, after int64) (totalK int, err error) { |
|
// fetch history series |
|
req := &pb.ReqHistoryKlineStream{ |
|
Exchange: exchange, |
|
InstId: instId, |
|
Interval: string(interval), |
|
Count: 0, |
|
Before: before, |
|
After: after, |
|
} |
|
stream, err := c.exchangeClient.HistoryKlineStream(context.Background(), req, grpc.UseCompressor("snappy")) |
|
if err != nil { |
|
zlog.Errorf("fetch history kline stream error: instId=%s(%s), interval=%s, %#v, err=%v", instId, exchange, interval, req, err) |
|
return |
|
} |
|
|
|
klineSeries := NewKlineSeries(exchange, instId, interval) |
|
for { |
|
msg, err0 := stream.Recv() |
|
if err0 == io.EOF { |
|
break |
|
} |
|
if err0 != nil { |
|
err = err0 |
|
zlog.Error("fetch kline stream recv error: ", err0) |
|
return |
|
} |
|
// zlog.Debugf("recv: %s(%s), %s, branch=%d, ts=%d~%d", instId, exchange, interval, len(msg.Klines), msg.Klines[0].Ts, msg.Klines[len(msg.Klines)-1].Ts) |
|
totalK += len(msg.Klines) |
|
for _, k := range msg.Klines { |
|
kline := new(types.Kline) |
|
kline.ParsePBKline(exchange, k) |
|
if lastTs, ok := klineSeries.Update(kline); !ok { |
|
err = fmt.Errorf("history stream kline not series: last=%d", lastTs) |
|
return |
|
} |
|
} |
|
} |
|
c.context = NewIndicatorContext(klineSeries) |
|
return |
|
} |
|
|
|
func (c *HistoryIndicatorContext) SetOffset(offset int16) { |
|
c.context.SetOffset(offset) |
|
} |
|
|
|
func (c *HistoryIndicatorContext) Get(offset int16) (kline types.Kline) { |
|
return c.context.Get(offset) |
|
} |
|
|
|
func (c *HistoryIndicatorContext) Series(offset, count int16) (klines series.Klines) { |
|
return c.context.Series(offset, count) |
|
}
|
|
|