Skip to main content

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.

All MongoDB persistence in backtest-kit-redis-mongo-docker is organised into 15 Mongoose schemas, one per domain concept. Each schema is defined in src/schema/ and registered as a Mongoose model that a corresponding DbService wraps. Every schema uses { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" } } to get automatic timestamp management, and each defines a compound unique index that prevents duplicate entries for the same logical context. Schemas that track time-series or state snapshots include a when field (a Unix timestamp in milliseconds) to record the business-time of the last write.
Collection: candle-items
Model file: src/schema/Candle.schema.ts
Unique index: (symbol, interval, timestamp)
const CandleSchema: Schema<CandleDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    interval:     { type: String, required: true, enum: INTERVAL_ENUM, index: true },
    timestamp:    { type: Number, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    open:         { type: Number, required: true },
    high:         { type: Number, required: true },
    low:          { type: Number, required: true },
    close:        { type: Number, required: true },
    volume:       { type: Number, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" } }
);

CandleSchema.index({ symbol: 1, interval: 1, timestamp: 1 }, { unique: true });
The interval field is constrained to the enum ["1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","1d"]. This schema is the only one where exchangeName is part of the document but not part of the unique index — the uniqueness constraint is on the OHLCV data tuple itself.
Collection: signal-items
Model file: src/schema/Signal.schema.ts
Unique index: (symbol, strategyName, exchangeName)
const SignalSchema: Schema<SignalDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

SignalSchema.index(
  { symbol: 1, strategyName: 1, exchangeName: 1 },
  { unique: true }
);
Stores the latest ISignalRow payload for a given (symbol, strategyName, exchangeName) triplet. The DbService uses upsert to keep exactly one document per context. minimize: false ensures empty objects in payload are preserved.
Collection: schedule-items
Model file: src/schema/Schedule.schema.ts
Unique index: (symbol, strategyName, exchangeName)
const ScheduleSchema: Schema<ScheduleDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

ScheduleSchema.index(
  { symbol: 1, strategyName: 1, exchangeName: 1 },
  { unique: true }
);
Persists the IScheduledSignalRow payload for scheduled signals. Structurally identical to signal-items but models a different domain concept.
Collection: risk-items
Model file: src/schema/Risk.schema.ts
Unique index: (riskName, exchangeName)
Has when: Yes
const RiskSchema: Schema<RiskDocument> = new Schema(
  {
    riskName:     { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    positions:    { type: Schema.Types.Mixed, required: true, default: [] },
    when:         { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

RiskSchema.index({ riskName: 1, exchangeName: 1 }, { unique: true });
Stores the RiskData positions array for a named risk manager on a given exchange. when records the business-time of the last position update. positions defaults to an empty array.
Collection: partial-items
Model file: src/schema/Partial.schema.ts
Unique index: (symbol, strategyName, exchangeName, signalId)
Has when: Yes
const PartialSchema: Schema<PartialDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    signalId:     { type: String, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true, default: {} },
    when:         { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

PartialSchema.index(
  { symbol: 1, strategyName: 1, exchangeName: 1, signalId: 1 },
  { unique: true }
);
Stores PartialData per signal instance. The signalId field is what makes this a per-signal (rather than per-strategy) record.
Collection: breakeven-items
Model file: src/schema/Breakeven.schema.ts
Unique index: (symbol, strategyName, exchangeName, signalId)
Has when: Yes
const BreakevenSchema: Schema<BreakevenDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    signalId:     { type: String, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true, default: {} },
    when:         { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

BreakevenSchema.index(
  { symbol: 1, strategyName: 1, exchangeName: 1, signalId: 1 },
  { unique: true }
);
Structurally identical to partial-items but stores BreakevenData. Both schemas use the same four-field compound unique index.
Collection: storage-items
Model file: src/schema/Storage.schema.ts
Unique index: (backtest, signalId)
const StorageSchema: Schema<StorageDocument> = new Schema(
  {
    backtest:  { type: Boolean, required: true, index: true },
    signalId:  { type: String, required: true, index: true },
    payload:   { type: Schema.Types.Mixed, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

StorageSchema.index({ backtest: 1, signalId: 1 }, { unique: true });
Stores IStorageSignalRow payloads. The backtest boolean separates backtest records from live/paper trading records, so the same signalId can exist in both modes without conflict.
Collection: notification-items
Model file: src/schema/Notification.schema.ts
Unique index: (backtest, notificationId)
const NotificationSchema: Schema<NotificationDocument> = new Schema(
  {
    backtest:        { type: Boolean, required: true, index: true },
    notificationId:  { type: String, required: true, index: true },
    payload:         { type: Schema.Types.Mixed, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

NotificationSchema.index({ backtest: 1, notificationId: 1 }, { unique: true });
Follows the same backtest-scoped pattern as storage-items, storing NotificationModel payloads keyed by notificationId.
Collection: log-items
Model file: src/schema/Log.schema.ts
Unique index: (entryId) — single-field unique
const LogSchema: Schema<LogDocument> = new Schema(
  {
    entryId:  { type: String, required: true, unique: true, index: true },
    payload:  { type: Schema.Types.Mixed, required: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);
The only schema with a single-field unique constraint. Each ILogEntry is keyed by a globally unique entryId. There is no backtest scope — logs are shared across modes.
Collection: measure-items
Model file: src/schema/Measure.schema.ts
Unique index: (bucket, entryKey)
Soft-delete: Yes (removed field)
const MeasureSchema: Schema<MeasureDocument> = new Schema(
  {
    bucket:    { type: String, required: true, index: true },
    entryKey:  { type: String, required: true, index: true },
    payload:   { type: Schema.Types.Mixed, required: true },
    removed:   { type: Boolean, required: true, default: false, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

MeasureSchema.index({ bucket: 1, entryKey: 1 }, { unique: true });
Supports soft-delete via the removed boolean. MeasureDbService.softRemove(bucket, key) sets removed: true rather than deleting the document. Reads check row.removed before returning data.
Collection: interval-items
Model file: src/schema/Interval.schema.ts
Unique index: (bucket, entryKey)
Has when: Yes
Soft-delete: Yes (removed field)
const IntervalSchema: Schema<IntervalDocument> = new Schema(
  {
    bucket:    { type: String, required: true, index: true },
    entryKey:  { type: String, required: true, index: true },
    payload:   { type: Schema.Types.Mixed, required: true },
    removed:   { type: Boolean, required: true, default: false, index: true },
    when:      { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

IntervalSchema.index({ bucket: 1, entryKey: 1 }, { unique: true });
Extends the measure-items pattern with a when field to track business-time of the last interval write.
Collection: memory-items
Model file: src/schema/Memory.schema.ts
Unique index: (signalId, bucketName, memoryId)
Has when: Yes
Soft-delete: Yes (removed field)
const MemorySchema: Schema<MemoryDocument> = new Schema(
  {
    signalId:    { type: String, required: true, index: true },
    bucketName:  { type: String, required: true, index: true },
    memoryId:    { type: String, required: true, index: true },
    payload:     { type: Schema.Types.Mixed, required: true },
    removed:     { type: Boolean, required: true, default: false, index: true },
    when:        { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

MemorySchema.index(
  { signalId: 1, bucketName: 1, memoryId: 1 },
  { unique: true }
);
Stores per-signal, per-bucket MemoryData entries. The three-part compound key allows a single signal to have multiple named memory buckets, each with multiple entries.
Collection: recent-items
Model file: src/schema/Recent.schema.ts
Unique index: (symbol, strategyName, exchangeName, frameName, backtest)
Has when: Yes
const RecentSchema: Schema<RecentDocument> = new Schema(
  {
    symbol:       { type: String, required: true, index: true },
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    frameName:    { type: String, required: true, index: true },
    backtest:     { type: Boolean, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true },
    when:         { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

RecentSchema.index(
  { symbol: 1, strategyName: 1, exchangeName: 1, frameName: 1, backtest: 1 },
  { unique: true }
);
The broadest compound index in the codebase — five fields — uniquely identifies the most-recent IPublicSignalRow for a given (symbol, strategy, exchange, frame, mode) combination.
Collection: state-items
Model file: src/schema/State.schema.ts
Unique index: (signalId, bucketName)
Has when: Yes
const StateSchema: Schema<StateDocument> = new Schema(
  {
    signalId:    { type: String, required: true, index: true },
    bucketName:  { type: String, required: true, index: true },
    payload:     { type: Schema.Types.Mixed, required: true },
    when:        { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

StateSchema.index({ signalId: 1, bucketName: 1 }, { unique: true });
Stores a single StateData snapshot per (signalId, bucketName) pair. Unlike memory-items, there is no memoryId — one state record per bucket per signal.
Collection: session-items
Model file: src/schema/Session.schema.ts
Unique index: (strategyName, exchangeName, frameName)
Has when: Yes
const SessionSchema: Schema<SessionDocument> = new Schema(
  {
    strategyName: { type: String, required: true, index: true },
    exchangeName: { type: String, required: true, index: true },
    frameName:    { type: String, required: true, index: true },
    payload:      { type: Schema.Types.Mixed, required: true },
    when:         { type: Number, required: true, index: true },
  },
  { timestamps: { createdAt: "createDate", updatedAt: "updatedDate" }, minimize: false }
);

SessionSchema.index(
  { strategyName: 1, exchangeName: 1, frameName: 1 },
  { unique: true }
);
Persists SessionData for a strategy running on a given exchange and frame combination. One session record per (strategy, exchange, frame) triplet.

Summary Table

CollectionUnique IndexHas whenSoft-delete
candle-items(symbol, interval, timestamp)NoNo
signal-items(symbol, strategyName, exchangeName)NoNo
schedule-items(symbol, strategyName, exchangeName)NoNo
risk-items(riskName, exchangeName)YesNo
partial-items(symbol, strategyName, exchangeName, signalId)YesNo
breakeven-items(symbol, strategyName, exchangeName, signalId)YesNo
storage-items(backtest, signalId)NoNo
notification-items(backtest, notificationId)NoNo
log-items(entryId)NoNo
measure-items(bucket, entryKey)NoYes
interval-items(bucket, entryKey)YesYes
memory-items(signalId, bucketName, memoryId)YesYes
recent-items(symbol, strategyName, exchangeName, frameName, backtest)YesNo
state-items(signalId, bucketName)YesNo
session-items(strategyName, exchangeName, frameName)YesNo

Build docs developers (and LLMs) love