Monte Carlo API
Submit a forward wealth simulation against a succeeded optimization run, poll its lifecycle, and fetch its artifact and exports. Simulations are child runs: they inherit the parent's frozen optimizer-time inputs and never refetch market data.
Read this before publishing results
Every probability returned here is conditional on the selected model, the frozen optimizer-time inputs, the effective configuration, the engine version and the seed. It is not a calibrated forecast, and no generator has passed out-of-sample validation. See rolling-origin validation.
Any surface presenting these numbers must present the assumptions block alongside them.
/runs/{run_id}/monte_carloEnqueue a simulation on a succeeded parent run. Returns 202 with the child run id.
curl -X POST https://api.foliolab.ai/runs/$RUN_ID/monte_carlo \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "method": "HRP", "horizon_years": 20, "path_count": 25000, "starting_wealth": 2500000, "goal_amount": 12000000, "goal_basis": "real_pre_tax", "contributions": { "amount": 40000, "frequency": "monthly", "escalation_pct": 0.08 }, "rebalance_frequency": "annual", "rgp": "fhs_gjr_garch_vt", "scenarios": ["correlation_spike"] }'
{
"mc_run_id": "6f2c0b6e-6b6a-4a1e-9d2f-6c9b0f6a2b41",
"parent_run_id": "1a5b8e2c-77d1-4f3a-b0c2-9e1d3f4a5b6c",
"status": "queued"
}Request body
The body is a strict schema. Unknown fields are rejected rather than ignored, so a typo cannot silently run a different configuration.
Core
| Field | Type | Description |
|---|---|---|
method | string, required | The parent run's optimization method whose weights are simulated. |
horizon_years | integer 1 to 40, default 15 | Simulation horizon. |
path_count | integer 1,000 to 100,000, default 10,000 | Paths to simulate. Capped by your plan. |
starting_wealth | number, default 1,000,000 | Initial portfolio value in rupees. |
seed | integer or decimal string, optional | Omit to draw and record a fresh seed. Results are byte-reproducible from the echoed config. |
batch_size | integer 128 to 5,000, default 2,000 | Path batch size. Part of the reproducibility contract. |
Return process
| Field | Type | Description |
|---|---|---|
rgp | enum, default fhs_gjr_garch_vt | Return-generating process. See the table below. |
expected_block_length_days | number, optional | Stationary bootstrap expected block length. Omit for automatic Politis-White selection. |
student_t_dof | number > 2, default 5 | Degrees of freedom for the student_t process. |
regime | object | Regime-bootstrap fit settings. |
fhs | object | Filtered historical simulation settings. |
Planning and accounting
| Field | Type | Description |
|---|---|---|
goal_amount | number, optional | Target terminal wealth for the goal probability. |
goal_basis | enum | nominal_pre_tax, nominal_post_tax, real_pre_tax or real_post_tax. |
wealth_floor | number, optional | Solvency floor. A breach is recorded at any month or discontinuous cash-flow event, including t=0. |
wealth_floor_basis | enum, default nominal_pre_tax | Series the floor is evaluated against. |
contributions | object, optional | SIP: amount, frequency, annual escalation_pct. |
withdrawals | object, optional | SWP: amount, frequency, start_year, escalation_mode, escalation_pct. |
inflation | object | enabled and annual_rate_override. Deflates real-basis series. |
tax | object | Indian listed-equity capital gains on a monthly FIFO basis. |
slippage_bps | number 0 to 500, default 0 | Proportional cost on traded value at every modeled trade, not only rebalances. |
Policy and evidence
| Field | Type | Description |
|---|---|---|
rebalance_frequency | none, annual, quarterly, monthly | Default annual. |
rebalance_mode | static or reoptimize | Default static. |
walk_forward | object | reoptimize_frequency, estimation_window, estimation_window_years, weight_observation_grid. |
paired_static_baseline | boolean, default false | Simulate the frozen-weight arm on identical shock coordinates. |
drift | object | mode plus anchor fields. See drift modes below. |
risk_free | object | source: parent_run, explicit or disabled. Metric benchmark only. |
scenarios | array, max 8 | Named scenario arms run beside the base arm under common random numbers. |
precision | object, optional | tier and optional max_paths. Enables adaptive sequential stopping. |
parameter_uncertainty | object, optional | outer_draws and paired_fixed_control. Mutually exclusive with precision. |
Return processes
Which values are accepted also depends on your plan's mc_allowed_processes entitlement.
| Field | Type | Description |
|---|---|---|
fhs_gjr_garch_vt | Default | Filtered historical simulation with a variance-targeted GJR-GARCH volatility model. Needs about 5 years of jointly aligned history; a shorter panel falls back and the result reports generator_fallback. |
fhs_gjr_regime | Selectable | The same filter under a slow-moving variance-regime layer. |
fhs_gjr_regime_uv_fallback | Selectable | The regime layer, falling back to unconditional variance when regime identification fails. |
block_bootstrap | Retired | Politis-Romano stationary block bootstrap. Retired: rolling-origin testing measured simulated volatility 27% to 56% above realized at every horizon. No plan grants it. |
regime_bootstrap | Selectable | Markov regime chain over portfolio returns; blocks drawn from the active state's labelled history. |
fhs_ewma | Selectable | Filtered historical simulation with EWMA conditional volatility. |
fhs_gjr_garch | Selectable | The same filter with a GJR-GARCH volatility model. Failed fits fall back to EWMA per asset. |
gbm_lognormal | Selectable | Lognormal geometric Brownian motion with Ledoit-Wolf shrinkage covariance. |
gaussian | Comparison | Multivariate normal on simple returns. Understates Indian-market tails. |
student_t | Comparison | Multivariate Student-t on simple returns. |
Each process has a minimum history requirement and its own admission checks. The full mathematics for each one is documented under engine methodology.
Drift modes
drift.mode accepts historical (default), override, shrunk and forward_shrunk. A fifth mode, market_forward_shrunk, resolves a versioned market-level Indian equity assumption and accepts no user-supplied anchor values.
Drift modes are plan-gated by mc_allowed_drift_modes. The gate has one deliberate asymmetry: a "*" wildcard expands to every mode except the house-view modes, so the wildcard cannot switch one on by analogy. A missing or malformed key degrades to the four caller-supplied modes, which means the fail-closed direction is “no house view” rather than “no Monte Carlo”. See drift and estimation risk.
/runs/{run_id}/monte_carloEvery simulation submitted against one parent optimization run.
curl https://api.foliolab.ai/runs/$RUN_ID/monte_carlo \ -H "Authorization: Bearer $ACCESS_TOKEN"
/mcAll of the caller's simulations across every parent run, newest first. Cursor paginated.
curl "https://api.foliolab.ai/mc?limit=20&cursor=$NEXT_CURSOR" \ -H "Authorization: Bearer $ACCESS_TOKEN"
limit defaults to 20. Pass the next_cursor from the previous response to page forward.
/mc/{mc_run_id}Lifecycle, inline summary, timing, and signed artifact and export links once the run has succeeded.
{
"mc_run_id": "6f2c0b6e-6b6a-4a1e-9d2f-6c9b0f6a2b41",
"parent_run_id": "1a5b8e2c-77d1-4f3a-b0c2-9e1d3f4a5b6c",
"status": "succeeded",
"method": "HRP",
"engine_version": "mc-v1.21.0",
"seed": "8127364512873645",
"attempt_count": 1,
"created_at": "2026-08-11T09:14:02Z",
"started_at": "2026-08-11T09:14:19Z",
"finished_at": "2026-08-11T09:17:41Z",
"timing": {
"queue_wait_seconds": 17.4,
"execution_seconds": 202.1
},
"summary": {
"run_information": { "...": "..." },
"metric_suite": { "...": "..." },
"model_risk": { "...": "..." },
"assumptions": { "...": "..." }
},
"config": { "...": "the echoed immutable configuration" },
"artifact": {
"signed_url": "https://...",
"bytes": 4821904,
"content_type": "application/json"
},
"exports": {
"pdf": { "signed_url": "https://...", "bytes": 1284512, "filename": "..." },
"xlsx": { "signed_url": "https://...", "bytes": 284512, "filename": "..." }
}
}Timing is two numbers, not one. A run that sat in the queue for four minutes and simulated for forty seconds is not a slow simulation. Both are observations rather than a service level, and a retried run reports the last attempt's execution, which is why the attempt count sits beside them.
Signed links are short lived and are regenerated on each detail request. Do not cache them.
Exports are best effort. A failed export never turns a completed simulation into a failed run, so the exports object may be empty on a succeeded run.
Errors
| Status | Detail | Cause |
|---|---|---|
| 403 | mc_api_key_not_supported | Simulations require a user session or an MCP OAuth grant. Programmatic API keys are not accepted. |
| 403 | mc_not_allowed | The plan has no Monte Carlo access. |
| 403 | mc_path_limit_exceeded:<cap> | path_count exceeds the plan's path cap. The cap is in the detail. |
| 403 | mc_process_not_allowed:<process> | The plan does not include the requested return process. |
| 403 | mc_drift_mode_not_allowed:<mode> | The plan does not include the requested drift mode. |
| 409 | parent_not_ready | The parent optimization run has not succeeded. |
| 422 | MC_METHOD_REQUIRED | method was not pinned on the request. |
| 429 | mc_monthly_limit_exceeded | The plan's monthly simulation meter is exhausted. |
| 429 | mc_inflight_limit_exceeded | At most two simulations may be queued or running at once. |
| 422 | mc_insufficient_history_for_process | The chosen process needs more jointly aligned daily history than the portfolio has. |
| 503 | MC_GOVERNANCE_UNAVAILABLE | The service could not load or apply its model-risk governance record. Retry unchanged. |
Admission and the worker apply the same workload and optimizer-attestation checks, so a row queued under an older policy cannot bypass a newer safety gate when it finally executes. A request the engine cannot honour exactly is refused rather than downgraded.
Plan limits
| Plan | Simulations / month | Paths / run | Generators |
|---|---|---|---|
| Free | None | None | None |
| Pro | 20 | 50,000 | fhs_gjr_garch_vt, regime_bootstrap, fhs_ewma, gbm_lognormal, gaussian, student_t |
| Enterprise | Unlimited | 100,000 | All |
Monte Carlo has its own monthly meter, separate from optimizations and backtests. GET /billing/me reports all three.
Related
Backtests API for the other child-run workflow. Jobs for the parent optimization lifecycle.
Walk-forward re-optimization explains the rebalance_mode and walk_forward fields. Adaptive precision explains precision, and parameter uncertainty explains why the two cannot be combined.
Not investment advice. Past performance is not indicative of future results.