Skip to main content
Every backtest run produces a bundle of 8 artifacts. Together they form a complete, reproducible record of the run: what was computed, what the result was, what data and environment were used, and how to view it. Each file is content-hashed with SHA-256 for tamper detection and reproducibility verification.

The 8-file bundle

#FileFormatPurpose
1summary.jsonJSONOne-line overview: run id, spec ref, result hash, status.
2metrics.jsonJSONFull stats block (sharpe, sortino, cagr, vol, maxDD, …).
3equity_curve.jsonJSONDaily equity values + dates.
4positions.jsonJSONPer-bar per-name weights and exposures.
5data_manifest.jsonJSONPrice panel provenance: source, symbols, date range, panel hash.
6environment_lock.jsonJSONPinned deps: numpy version, kernel version, seed.
7run_trace.jsonJSONThe full trace event stream for the run.
8report.htmlHTMLHuman-readable rendered report (charts + tables).

summary.json

{
  "run_id": "run_abc123",
  "spec_id": "spec_xyz",
  "spec_version": 3,
  "status": "succeeded",
  "result_hash": "sha256:9f2c...",
  "created_at": "2025-01-15T12:00:00Z"
}

metrics.json

The full stats block from the backtest kernel. See Backtest system for the field reference.

equity_curve.json

{
  "dates": ["2024-01-02", "2024-01-03"],
  "equity": [1.0, 1.0023]
}

positions.json

Per-bar weights keyed by date, then by symbol. Used by the web UI to render position charts.

data_manifest.json

{
  "source": "polygon",
  "symbols": ["NVDA", "AMD", "INTC"],
  "start": "2023-01-03",
  "end": "2024-12-31",
  "panel_hash": "sha256:1a2b..."
}

environment_lock.json

{
  "numpy_version": "1.26.4",
  "kernel_version": "doomberg-backtest==0.4.2",
  "seed": 42,
  "python_version": "3.11.7"
}

run_trace.json

The complete ordered list of TraceEvent records for the run. See Trace events.

report.html

A self-contained HTML file with embedded charts (equity curve, drawdown, positions) and the metrics table. Openable in any browser; no external dependencies.

Content hashing

Every artifact file is hashed with SHA-256 over its exact byte content. The hashes are recorded in summary.json (and in the run record). This gives you two guarantees:
  1. Tamper detection. If a file is modified after the run, its hash no longer matches.
  2. Reproducibility verification. Re-run the same spec; if the new result_hash matches the old one, the run is bit-identical.
The result_hash in summary.json is a hash over the metrics.json + equity_curve.json + positions.json hashes. It’s the single fingerprint of the run’s numeric output.

Storage backends

Ithaca supports two artifact storage backends, selected by environment:
BackendWhen usedLocation
memory://Development / localIn-process dict; lost on restart.
file://ProductionDOOMBERG_ARTIFACT_DIR on disk.
Set DOOMBERG_ARTIFACT_DIR in production to a persistent, backed-up volume. Artifacts are written as individual files under <dir>/<run_id>/<filename>.
The backend is chosen at startup; runs do not pick their own backend.

REST API

MethodPathDescription
GET/api/artifactsList artifact bundles for the tenant (optional ?run_id=).
GET/api/artifacts/{id}Fetch a single artifact bundle (all 8 files).

Example: list artifacts

GET /api/artifacts?run_id=run_abc123
Authorization: Bearer dmbg_prod_...
{
  "artifacts": [
    { "run_id": "run_abc123", "files": ["summary.json", "metrics.json", "..."], "result_hash": "sha256:9f2c..." }
  ]
}

Example: fetch a bundle

GET /api/artifacts/run_abc123
Authorization: Bearer dmbg_prod_...
Returns a JSON object with each file’s content and hash. The report.html is returned as a string; the rest are parsed JSON.