package backtest import ( "context" "fmt" "sort" "time" "git.toki-labs.com/toki/alt/packages/domain/market" "git.toki-labs.com/toki/alt/services/worker/internal/storage" ) // StorageBarSource adapts worker market-data storage ports to the backtest // engine's market/timeframe/date-range input boundary. type StorageBarSource struct { instruments storage.InstrumentStore bars storage.BarStore } func NewStorageBarSource(instruments storage.InstrumentStore, bars storage.BarStore) *StorageBarSource { return &StorageBarSource{instruments: instruments, bars: bars} } func (s *StorageBarSource) GetBars(ctx context.Context, mkt market.Market, timeframe market.Timeframe, from, to time.Time) ([]market.Bar, error) { if s == nil || s.instruments == nil || s.bars == nil { return nil, fmt.Errorf("backtest storage bar source: storage is not configured") } instruments, err := s.instruments.ListInstruments(ctx) if err != nil { return nil, fmt.Errorf("backtest storage bar source: list instruments: %w", err) } var out []market.Bar for _, inst := range instruments { if inst.Market != mkt { continue } bars, err := s.bars.GetBars(ctx, inst.ID, timeframe, from, to) if err != nil { return nil, fmt.Errorf("backtest storage bar source: get bars for %q: %w", inst.ID, err) } out = append(out, bars...) } sort.Slice(out, func(i, j int) bool { if out[i].Timestamp.Equal(out[j].Timestamp) { return out[i].InstrumentID < out[j].InstrumentID } return out[i].Timestamp.Before(out[j].Timestamp) }) return out, nil }