From d371aca7679009b76ff09ae13cea1f8e575f8b2e Mon Sep 17 00:00:00 2001 From: Natercio Moniz Date: Sat, 16 May 2026 11:58:35 +0100 Subject: [PATCH] apply selectors only on sells for performance --- internal/report.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/internal/report.go b/internal/report.go index f296652..24483e3 100644 --- a/internal/report.go +++ b/internal/report.go @@ -55,8 +55,8 @@ type ReportWriter interface { type Selector func(Record) bool // BuildReport reads records from a RecordReader and, if the record passes the Selector, it is -// processed into the report -func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, s Selector) error { +// processed into the ReportWriter. +func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, sel Selector) error { buys := make(map[string]*FillerQueue) var buysCount, sellsCount int64 @@ -83,14 +83,6 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, return err } - if !s(rec) { - slog.Debug("Report: skipping record", - slog.String("symbol", rec.Symbol()), - slog.String("side", rec.Side().String()), - ) - continue - } - if rec.Side().IsBuy() { buysCount++ } else { @@ -105,7 +97,7 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, buys[rec.Symbol()] = buyQueue } - err = processRecord(ctx, buyQueue, rec, writer) + err = processRecord(ctx, buyQueue, rec, sel, writer) if err != nil { return fmt.Errorf("processing record: %w", err) } @@ -114,7 +106,11 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, } } -func processRecord(ctx context.Context, q *FillerQueue, rec Record, writer ReportWriter) error { +// processRecord either adds buys to the queue or consumes buys from the queue when processing a +// sell record. +// Selectors are only applied for sells for performance reasons. It's much cheaper to just accumulate +// buys and only actually inspect a record once a sell happens +func processRecord(ctx context.Context, q *FillerQueue, rec Record, sel Selector, writer ReportWriter) error { slog.Debug("Report: processing record", slog.String("symbol", rec.Symbol()), slog.String("side", rec.Side().String()), @@ -125,6 +121,14 @@ func processRecord(ctx context.Context, q *FillerQueue, rec Record, writer Repor q.Push(NewFiller(rec)) case SideSell: + if !sel(rec) { + slog.Debug("Report: skipping record", + slog.String("symbol", rec.Symbol()), + slog.String("side", rec.Side().String()), + ) + return nil + } + unmatchedQty := rec.Quantity() for unmatchedQty.IsPositive() {