Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-kit-redis-mongo-docker/llms.txt

Use this file to discover all available pages before exploring further.

Every CacheService in the backtest-kit library stores a mapping from a compound context key — composed of exchangeName, strategyName, and symbol — to the MongoDB _id of the corresponding document. These mappings are held in Redis with no expiry (-1 TTL), so they persist for the full lifetime of the Redis instance. Each service is built by extending BaseMap, a factory-generated base class that provides ten generic Redis hash-map operations scoped to a fixed key namespace.

BaseMap

Factory-generated Redis map with 10 methods. All keys are namespaced under a connectionKey prefix. Iteration uses SCAN batches of 100 to avoid blocking the Redis event loop.

CacheService pattern

Each service extends BaseMap with a fixed connectionKey (e.g., signal_cache), a TTL of -1, and three domain-specific methods: hasXxxId, getXxxId, and setXxxId.

BaseMap

BaseMap is produced by the factory() helper. It accepts a connectionKey namespace string and an optional ttlExpireSeconds value as constructor arguments, then returns a class whose every Redis key is prefixed with connectionKey:.
const ITERATOR_BATCH_SIZE = 100;
const DEFAULT_TTL_EXPIRE_SECONDS = 5 * 60;

export const BaseMap = factory(
  class BaseMap {
    constructor(
      readonly connectionKey: string,
      readonly ttlExpireSeconds: number = DEFAULT_TTL_EXPIRE_SECONDS
    ) {}

    _getItemKey(key: string): string  // returns `${connectionKey}:${key}`

    async set(key: string, value: unknown): Promise<void>
    async get(key: string | null): Promise<unknown | null>
    async delete(key: string): Promise<void>
    async has(key: string): Promise<boolean>
    async clear(): Promise<void>
    async toArray(): Promise<[string, unknown][]>
    async *iterate(): AsyncIterableIterator<readonly [string, unknown]>
    async *keys(): AsyncIterableIterator<string>
    async *values(): AsyncIterableIterator<unknown>
    async size(): Promise<number>
  }
);

export type TBaseMap = InstanceType<ReturnType<typeof BaseMap>>;

Key namespace

Every key stored in Redis follows the pattern connectionKey:subkey. The _getItemKey(key) helper constructs this full Redis key internally — you never need to call it directly. For example, a SignalCacheService entry for the context ccxt-exchange:jan_2026_strategy:TRXUSDT is stored under:
signal_cache:ccxt-exchange:jan_2026_strategy:TRXUSDT

Methods

set
(key: string, value: unknown) => Promise<void>
Writes value to the Redis key connectionKey:key. If ttlExpireSeconds is greater than zero, the key is set with an expiry. When ttlExpireSeconds is -1, no expiry is applied and the key persists indefinitely.
get
(key: string | null) => Promise<unknown | null>
Reads the value stored at connectionKey:key. Returns null when the key does not exist or when key is passed as null.
delete
(key: string) => Promise<void>
Removes the key connectionKey:key from Redis. A no-op if the key does not exist.
has
(key: string) => Promise<boolean>
Returns true if connectionKey:key exists in Redis, false otherwise.
clear
() => Promise<void>
Deletes every key that matches the glob pattern connectionKey:*. Internally uses a SCAN-based cursor loop (batch size ITERATOR_BATCH_SIZE = 100) to avoid issuing a blocking KEYS command on large datasets.
toArray
() => Promise<[string, unknown][]>
Returns all [key, value] pairs under the connectionKey namespace as an array. Uses the same SCAN-based approach as clear().
iterate
() => AsyncIterableIterator<readonly [string, unknown]>
Async generator that yields [key, value] pairs one batch at a time. Prefer this over toArray() when the namespace may contain a large number of keys.
keys
() => AsyncIterableIterator<string>
Async generator that yields only the key portion (with the connectionKey: prefix stripped) of every entry in the namespace.
values
() => AsyncIterableIterator<unknown>
Async generator that yields only the stored values for every entry in the namespace.
size
() => Promise<number>
Returns the total count of keys in the connectionKey namespace. Uses SCAN internally rather than DBSIZE so it only counts keys belonging to this map’s prefix.

TTL and expiry

The default TTL for a BaseMap instance is DEFAULT_TTL_EXPIRE_SECONDS = 300 (5 minutes). All 15 CacheServices override this by passing -1 to the constructor, which disables expiry entirely. Cache entries survive as long as the Redis instance is running and are only removed by an explicit delete(), clear(), or an external Redis flush.
SCAN-based iteration (ITERATOR_BATCH_SIZE = 100) is used by clear, toArray, iterate, keys, values, and size. This ensures Redis is never blocked for more than the time it takes to process 100 keys, regardless of how large the namespace grows.

CacheService pattern

Each CacheService extends BaseMap with a hardcoded connectionKey and a TTL of -1. On top of the ten inherited methods, every service adds exactly three domain-specific methods.
const REDIS_KEY = "signal_cache";

export class SignalCacheService extends BaseMap(REDIS_KEY, -1) {
  private _cacheKey(
    symbol: string,
    strategyName: string,
    exchangeName: string
  ): string {
    return `${exchangeName}:${strategyName}:${symbol}`;
  }

  public async hasSignalId(
    symbol: string,
    strategyName: string,
    exchangeName: string
  ): Promise<boolean>

  public async getSignalId(
    symbol: string,
    strategyName: string,
    exchangeName: string
  ): Promise<string | null>

  public async setSignalId(row: ISignalRowDoc): Promise<string>
}

The three domain methods

Every CacheService exposes the same trio of methods, named after its domain entity:
MethodDescription
hasXxxId(symbol, strategyName, exchangeName)Returns true if the compound context key exists in Redis. Delegates to super.has(_cacheKey(...)).
getXxxId(symbol, strategyName, exchangeName)Returns the cached MongoDB document ID string, or null on a miss. Delegates to super.get(_cacheKey(...)).
setXxxId(row: IXxxRowDoc)Extracts symbol, strategyName, exchangeName, and _id from the document, builds the compound key, and calls super.set(key, id). Returns the stored ID.

Cache key format

The compound subkey is always assembled in the order exchangeName:strategyName:symbol:
signal_cache:ccxt-exchange:jan_2026_strategy:TRXUSDT
This ordering puts the least-selective segment (exchangeName) first, which groups all entries for a given exchange together when scanning, and the most-selective segment (symbol) last.
All 15 CacheServices use TTL -1 — entries never expire automatically. If you flush a CacheService (e.g., via clear()) the paired DbService’s findByContext will fall back to MongoDB on the next call and re-populate the cache automatically.

All 15 CacheServices

CacheServiceRedis Key PrefixCache Key Pattern
candleCacheServicecandle_cachecandle_cache:{exchangeName}:{strategyName}:{symbol}
signalCacheServicesignal_cachesignal_cache:{exchangeName}:{strategyName}:{symbol}
scheduleCacheServiceschedule_cacheschedule_cache:{exchangeName}:{strategyName}:{symbol}
riskCacheServicerisk_cacherisk_cache:{exchangeName}:{strategyName}:{symbol}
partialCacheServicepartial_cachepartial_cache:{exchangeName}:{strategyName}:{symbol}
breakevenCacheServicebreakeven_cachebreakeven_cache:{exchangeName}:{strategyName}:{symbol}
storageCacheServicestorage_cachestorage_cache:{exchangeName}:{strategyName}:{symbol}
notificationCacheServicenotification_cachenotification_cache:{exchangeName}:{strategyName}:{symbol}
logCacheServicelog_cachelog_cache:{exchangeName}:{strategyName}:{symbol}
measureCacheServicemeasure_cachemeasure_cache:{exchangeName}:{strategyName}:{symbol}
intervalCacheServiceinterval_cacheinterval_cache:{exchangeName}:{strategyName}:{symbol}
memoryCacheServicememory_cachememory_cache:{exchangeName}:{strategyName}:{symbol}
recentCacheServicerecent_cacherecent_cache:{exchangeName}:{strategyName}:{symbol}
stateCacheServicestate_cachestate_cache:{exchangeName}:{strategyName}:{symbol}
sessionCacheServicesession_cachesession_cache:{exchangeName}:{strategyName}:{symbol}

Accessing CacheServices

All 15 cache services are available from the ioc object:
import { ioc } from "backtest-kit";

// Check if a cached ID exists
const exists = await ioc.signalCacheService.hasSignalId(
  "TRXUSDT",
  "jan_2026_strategy",
  "ccxt-exchange"
);

// Read a cached MongoDB document ID
const id = await ioc.signalCacheService.getSignalId(
  "TRXUSDT",
  "jan_2026_strategy",
  "ccxt-exchange"
);

// Iterate all entries in the signal cache namespace
for await (const [key, value] of ioc.signalCacheService.iterate()) {
  console.log(key, value);
}

// Flush the entire signal cache namespace
await ioc.signalCacheService.clear();
Calling clear() on a CacheService removes every key under its connectionKey:* namespace. This affects all symbols, strategies, and exchanges stored in that service. The next findByContext call for any entry will fall back to MongoDB and re-populate the cache, but during the window between the flush and the first read, Redis latency for those lookups is eliminated.

Build docs developers (and LLMs) love