package trading import ( "sig-pub/api/pb" vmts "sig-pub/pkg/storage/tsdb/victoria_metrics" "sig-pub/pkg/types" "sig-pub/pkg/utils/collect" ) type KlineStore struct { vmdb vmts.VictoriaMetricsTSDB store [3]*collect.ConcurrentMap[string, *KlineStoreInstance] // K线列表: []exchange } func NewKlineSeriesStore() (kss *KlineStore) { kss = &KlineStore{} kss.store[pb.ExchangeType_OKX] = collect.NewConcurrentMap[string, *KlineStoreInstance](64, func(s string) string { return s }) // kss.klines[pb.ExchangeType_BINANCE] = return } func (s *KlineStore) Update(exchange pb.ExchangeType, instId string, kline *types.Kline) (k types.Kline) { storeInst := s.store[exchange].ComputeIfAbsent(instId, func(k string) *KlineStoreInstance { return NewKlineStoreInstance(exchange, k) }) storeInst.Update(kline) return } // KlineStoreInstance 单个交易产品所有周期k线 type KlineStoreInstance struct { Exchange pb.ExchangeType InstId string IntervalKlines *collect.SyncMap[types.Interval, *KlineSeries] } func NewKlineStoreInstance(exchange pb.ExchangeType, instId string) *KlineStoreInstance { si := &KlineStoreInstance{ Exchange: exchange, InstId: instId, IntervalKlines: collect.NewSyncMap[types.Interval, *KlineSeries](), } for interval := range types.SupportedIntervals { si.IntervalKlines.Store(interval, NewKlineSeries(exchange, instId, interval)) } return si } // Update 更新k线 // kline klineStore -> klineSeries -> strategy -> indicator -> klineSeries.Series func (si *KlineStoreInstance) Update(kline *types.Kline) (ok bool) { ks, ok := si.IntervalKlines.Load(kline.Interval) if !ok { return } if lastTs, serial := ks.Update(kline); !serial { // k线不完整 // 拉取k线 start := lastTs end := kline.Ts _, _ = start, end } ok = true // emit kline event return }