Skip to main content
CFDL

Run-config reference

The run-config JSON controls how compiled IR is evaluated — discount rate, as-of date, parameter overrides, the inputs file, named scenarios, and Monte Carlo. Pass it with cfdl run --config run.json, cfdl_sdk.run(config=...), or the API server's config field.

Full shape

{
  "deterministic": {
    "annual_discount_rate": 0.10,
    "valuation_grain": "annual",
    "as_of": "2026-01-01",
    "inputs": "inputs.json",
    "parameters": {
      "inputs.base_rent": 1000.0,
      "inputs.market.new.ti_psf": 80.0
    }
  },
  "scenarios": {
    "stress": {
      "annual_discount_curve": "stressed_wacc",
      "inputs": "stress_inputs.json",
      "parameters": { "inputs.base_rent": 800.0 }
    }
  },
  "monte_carlo": {
    "trial_count": 1000,
    "seed": 12345,
    "distributions": {
      "inputs.exit_multiple": { "kind": "normal", "mean": 8.0, "stdev": 1.0, "clip": [5.0, 12.0] },
      "inputs.growth": { "kind": "uniform", "min": 0.01, "max": 0.05 }
    }
  }
}

Every section is optional. A config that states no discount rate and no discount series runs deterministically and publishes no model.npv, rather than an NPV at a rate nobody chose. The config rejects unknown fields, and a key that matches nothing the model declares is refused (E5033), naming the nearest name it could have meant. The authoritative shape is the run schema; this page restates it.

deterministic

  • annual_discount_rate — the annual discount rate for NPV. The engine publishes it back as run.annual_discount_rate, with run.periods_per_year, and run.as_of when one is stated.
  • annual_discount_curve — in place of the rate, never beside it: the name of a series-shaped assumption the model declares. Each period discounts at the series' annual rate for that period, and the run publishes run.annual_discount_curve in place of run.annual_discount_rate.
  • valuation_grain — "period" (default when omitted): each flow discounts at its own fractional year on the model grid. "annual": cash sums into calendar years and each year discounts once — the convention published sources use, and the setting to reach for when reconciling against one.
  • arithmetic — omitted, expressions evaluate in decimal, which every published number uses. "excel_compat" reproduces a spreadsheet's float64 artifacts, for reconciling against a workbook rather than for producing an answer.
  • as_of — valuation as-of date (YYYY-MM-DD).
  • inputs — an inputs file, below.
  • parameters — override map applied before evaluation.

Parameter keys

One key shape is recognized, and a key of any other shape is refused (E5033):

  • inputs.<name> — an assumption, by its full name, and inputs.<set>.<field> for a set's field. A value is replaced; a distribution is fixed. An assumption derived from an overridden one reads the override, because the run's values land before any assumption is evaluated. A contract term written as inputs.<name> is then drivable by scenarios and Monte Carlo alike without touching the model.

A stream's amount moves through an assumption it reads. The stream.<name>:amount, cfg.<path> and obs.<path> keys are not accepted.

The inputs file

inputs names a JSON document, by a path relative to the run-config file or inline, keyed by full assumption name. Each entry states one shape — a value, a series with its points, interpolation and effective dates, or a quantile with its points — and may cite its own source. A series or quantile entry replaces the model's body, or fills an assumption the model declares with a type and no body. The review page, inputs.assumptions, records the file as the row's origin. A bodiless assumption nothing supplies refuses the run (E5045), and a supplied value outside the assumption's domain or within refuses it too (E5041).

scenarios

Named variants of the deterministic run. Each scenario may override the discount rate or name a discount series, the as-of date, the parameters and the inputs file; a scenario cannot set arithmetic. Results carry one summary per scenario beside the base result: its metrics, its series and annual rollup, its journal, transitions and trace, its slices and its statements, and its own ledger_hash. A declared metric the scenario could not evaluate is listed under omitted with the reason, not published as a number.

The results publish the whole configuration as run, as the run used it: this document with each inputs file's content in place of its path, and a rate or as-of date a caller supplied where the document is silent. It is in no hash; cfdl verify checks it against a package's run.json (Packaging and verifying runs).

monte_carlo

  • trial_count and seed are required — there are no implicit seeds.
  • distributions overrides distributions the model declares, at run time and without touching the model, keyed by inputs.<name>. The kinds match the language's: fixed { value }, normal { mean, stdev }, uniform { min, max }, log_normal { mu, sigma }, triangular { min, mode, max }. Every kind accepts clip: [lo, hi], applied after the draw exactly as the language's clip=[...] is. stddev is a deprecated spelling of stdev; the language's spelling is stdev.

Each assumption draws from its own deterministic stream derived from the seed — results are byte-reproducible, and adding one assumption never changes another's draws.

Precedence

Run-config values override CLI fallbacks (--rate, --as-of). Scenario values override deterministic values for that scenario only.

Where results land

deterministic.metrics, one scenario summary per scenario, and monte_carlo.metrics with mean/stdev/min/max, percentiles p01–p99, and trials — the count of trials that published that name — for every metric, model-declared ones included. See the Results schema.