During a backtest,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-redis-mongo-docker/llms.txt
Use this file to discover all available pages before exploring further.
backtest-kit can invoke readXData() thousands of times per second — once per candle, per signal, per active strategy instance. Each call must resolve a domain-specific context key (e.g. symbol + strategyName + exchangeName) to the live document in MongoDB. A raw MongoDB B-tree scan is O(log n) and carries network round-trip latency; at scale this becomes the dominant bottleneck. The Redis cache layer reduces every repeated lookup to a single O(1) GET against an in-memory store, while MongoDB remains the authoritative source of truth.
The BaseMap Abstraction
All 15 cache services inherit from BaseMap, a thin ioredis wrapper defined in src/lib/common/BaseMap.ts. It is constructed via the factory helper from di-factory so the IoC container can wire it without decorators:
BaseMap subclass is automatically prefixed with connectionKey + ":", preventing namespace collisions between domain services. For example, all signal cache entries live under signal_cache:* and all candle cache entries under candle_cache:*.
TTL Behaviour
WhenttlExpireSeconds is set to any positive number, BaseMap.set calls redis.expire(itemKey, ttlExpireSeconds) immediately after the SET. When it is set to -1 the expire call is skipped entirely, making the entry permanent for the lifetime of Redis. All 15 cache services currently pass -1, meaning cache entries persist until Redis is restarted or explicitly cleared. This is the right default for backtest context keys because the domain data they point to is durable in MongoDB.
Per-Domain Cache Services
Each domain gets its own cache class that encodes the compound key scheme for that domain.SignalCacheService is a representative example:
_id — a short string. The full document is then fetched with findById(_id), which MongoDB resolves via its primary _id index in O(1) time. This two-step pattern (Redis GET → Mongo findById) is always faster than a multi-field compound index scan.
Complete Read Path
SignalDbService.findByContext shows the canonical read path shared by all DB services:
| Scenario | Redis | MongoDB | Net cost |
|---|---|---|---|
| Cache hit | GET (O(1)) | findById on _id (O(1)) | Two in-memory round trips |
| Cache miss | GET → null | findOne on compound index (O(log n)) + Redis SET | One B-tree scan, then O(1) forever after |
| After upsert | SET (synchronous) | Already written | Cache always current |
Write Path Cache Update
After every successfulfindOneAndUpdate, the DB service updates the cache entry inline — within the same logical operation — before returning to the caller:
Cold-start and Redis restart recoveryIf Redis is empty (fresh start, restart, or
FLUSHALL), every first read will be a cache miss. The DB service transparently falls back to MongoDB, retrieves the document via the compound index, and backfills the Redis entry. No manual cache warming step is needed — the cache rebuilds itself organically as each context key is accessed. The try/catch block around the Redis read in findByContext also protects against transient Redis connectivity errors, allowing the system to degrade gracefully to full MongoDB reads rather than failing outright.