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 asrun.annual_discount_rate, withrun.periods_per_year, andrun.as_ofwhen 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 publishesrun.annual_discount_curvein place ofrun.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, andinputs.<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 asinputs.<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_countandseedare required — there are no implicit seeds.distributionsoverrides distributions the model declares, at run time and without touching the model, keyed byinputs.<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 acceptsclip: [lo, hi], applied after the draw exactly as the language'sclip=[...]is.stddevis a deprecated spelling ofstdev; the language's spelling isstdev.
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.