Monte Carlo · Methodology

Monte Carlo Engine Methodology

mc-v1.7.1

A complete description of what the forward simulator actually does: where its inputs come from, which return-generating process draws each future day, how drift is resolved, what is subtracted along the way, and how every reported number is defined. Nothing here is a forecast claim. This page exists so you can audit the assumptions behind any probability the product shows you.

For the product-level tour of what the feature does and how to run it, start with Forward Monte Carlo Simulation.

The pipeline, in order

Every simulation runs the same seven stages. Each stage is independently configurable and independently disclosed in the result, which is what makes the output auditable rather than merely plausible-looking.

  1. 1

    Frozen calibration inputs

    The simulation loads the exact aligned return panel and CPI series that the parent optimization used, as an immutable content-addressed artifact, and verifies its SHA-256 digest before use. It does not refetch today's market history. Optimized weights and simulated history therefore share one data vintage, and a missing or corrupt artifact fails closed rather than silently substituting fresh data.

  2. 2

    Return-generating process

    One of seven selectable processes draws daily asset returns for every path. This is the single biggest modeling choice in the run, and the spread between processes is real model risk rather than noise to be hidden.

  3. 3

    Drift resolution and estimation risk

    The centre of the simulated distribution is set by the drift layer, and per-path mean perturbation propagates the fact that the historical mean is itself an estimate with a large standard error.

  4. 4

    Portfolio accounting

    Asset returns are aggregated into portfolio wealth under your weights, with rebalancing at the configured frequency and proportional trade costs on every modeled trade.

  5. 5

    Cash flows

    SIP contributions and SWP withdrawals are applied on the monthly grid, tracked against a unitized NAV so a deposit is never mistaken for a return. Withdrawals are grossed up for modeled tax and cost.

  6. 6

    Tax and inflation overlays

    Realized gains at withdrawals, rebalances and terminal liquidation are taxed under a monthly FIFO cohort approximation, and real-wealth outputs are deflated by CPI aligned to the same historical days the return blocks were sampled from.

  7. 7

    Statistics and intervals

    Percentile fans, goal and depletion probabilities with Wilson intervals, drawdown and underwater-spell distributions, and forward VaR/CVaR with separate bootstrap intervals are computed across paths.

The seven return-generating processes

A return-generating process answers one question: given the frozen history, how is tomorrow's cross-section of asset returns drawn? Everything downstream, including the tax and inflation overlays, is identical across processes. Only this stage differs.

None of these has been shown to forecast better than the others. FolioLab does not publish a “best” process, because no rolling-origin validation harness has established one. Running two processes and comparing the range is more informative than trusting any single one.

ProcessFamilyReturn supportMinimum aligned history
Stationary block bootstrap
block_bootstrap

The default. Resamples random-length blocks of complete historical days, so observed shocks, same-day cross-asset moves and local ordering survive.

ResamplingSimple returns, clipped4 rows structurally, 32 for automatic block-length selection
Regime-switching bootstrap
regime_bootstrap

A fitted Markov chain moves each path between calm and stressed states; days are resampled from the active state's labeled history.

ResamplingSimple returns, clipped252 rows for the regime fit, else falls back to the plain bootstrap
Filtered historical simulation, EWMA
fhs_ewma

Divides history by each holding's estimated volatility, resamples the standardized shock rows, then rebuilds volatility forward from today's level.

Conditional volatilityLog returns, positive756 rows, about 3 trading years
Filtered historical simulation, GJR-GARCH
fhs_gjr_garch

The same filter, with a volatility model in which losses raise future risk more than equivalent gains. Failed fits fall back to EWMA per asset.

Conditional volatilityLog returns, positive1,260 rows, about 5 trading years
Lognormal GBM
gbm_lognormal

Independent Gaussian log returns with a Ledoit-Wolf shrinkage covariance. An analytical reference point, not a realism upgrade.

Parametric benchmarkLog returns, positive60 rows
Multivariate Student-t
student_t

Fat-tailed draws with covariance matched to history and one shared mixing variable per day, so the cross-section fattens together.

Parametric comparisonSimple returns, clipped4 rows
Multivariate Gaussian
gaussian

Normal draws on the historical mean and covariance. The thin-tailed reference case: it understates Indian-market tails by design.

Parametric comparisonSimple returns, clipped4 rows

Why return support matters

The three log-domain processes build gross returns as where is a simulated log return. Gross returns are therefore positive by construction: a holding can approach zero but can never go through it, and no corrective clipping exists on those paths.

The four simple-return processes can in principle emit a gross return at or below zero. A disclosed lower gross-return clip prevents negative wealth. The clip is reported with the result, including how often it bound, so you can see whether it was cosmetic or load-bearing. For the bootstrap families it is effectively inert, because resampled historical rows never contain a total loss. For the Gaussian and Student-t processes it is a real part of the model, which is one reason both are labeled comparison processes rather than planning models.

What every process shares

Whole-row sampling

Both bootstrap families and both FHS variants resample complete cross-sectional rows rather than each asset independently. A day when everything fell together stays a day when everything falls together, so cross-asset correlation, coskewness and cokurtosis are preserved exactly rather than approximated by a covariance matrix.

Batch-stable state

Paths are simulated in memory-bounded batches, but sampler state carries across chunk boundaries. A bootstrap block that spans a month boundary stays one block, and an FHS conditional-variance recursion is never reset mid-path by an implementation detail.

Common random numbers

Crisis scenarios are paired with the base run through common random numbers, so the difference between a scenario and its base isolates the stress instead of mixing in fresh sampling noise.

Reproducibility

Results reproduce when the seed, configuration, engine version and immutable input digest all match. The seed alone is not a complete reproducibility claim, and the result records all four so the claim can be checked rather than assumed.

Variance reduction

For the plain block bootstrap, the first block start of every path is stratified over the historical index rather than drawn uniformly: path of draws its opening row uniformly inside the stratum

where is the number of historical rows. This is a Latin hypercube-style stratification. It guarantees the set of starting points covers the whole sample evenly instead of clustering by chance, which tightens tail-quantile estimates at no computational cost and without changing the target distribution.

Stratification is disabled when a crisis scenario supplies over-sampling weights, because weighted starts and stratified starts make contradictory assumptions about the start distribution. The regime bootstrap also draws first starts uniformly within the opening regime's rows, so it does not stratify either.

Availability by plan

Process availability is a plan entitlement. The four original processes, block_bootstrap, regime_bootstrap, gaussian and student_t, form the baseline lineup. The compute-heavier additions, fhs_ewma, fhs_gjr_garch and gbm_lognormal, are gated separately. The configuration form shows processes outside your entitlement as disabled with the reason rather than hiding them, and a request for a process you cannot run is rejected with 403 mc_process_not_allowed rather than being silently downgraded to something else.

Path counts are capped separately: 25,000 per run on Pro and 50,000 on Enterprise, with a workload safety limit that can further restrict presets for long horizons, many assets, or several scenarios at once. More paths reduce sampling noise in the reported probabilities. They do not reduce model uncertainty, which is what the process comparison is for.

The rest of the methodology

References

  • Politis, D. N., & Romano, J. P. (1994). The Stationary Bootstrap. Journal of the American Statistical Association, 89(428), 1303–1313.
  • Politis, D. N., & White, H. (2004). Automatic Block-Length Selection for the Dependent Bootstrap. Econometric Reviews, 23(1), 53–70.
  • Patton, A., Politis, D. N., & White, H. (2009). Correction to Automatic Block-Length Selection for the Dependent Bootstrap. Econometric Reviews, 28(4), 372–375.
  • Hamilton, J. D. (1989). A New Approach to the Economic Analysis of Nonstationary Time Series and the Business Cycle. Econometrica, 57(2), 357–384.
  • Barone-Adesi, G., Giannopoulos, K., & Vosper, L. (1999). VaR without Correlations for Portfolios of Derivative Securities. Journal of Futures Markets, 19(5), 583–602.
  • Glosten, L. R., Jagannathan, R., & Runkle, D. E. (1993). On the Relation between the Expected Value and the Volatility of the Nominal Excess Return on Stocks. Journal of Finance, 48(5), 1779–1801.
  • Newey, W. K., & West, K. D. (1987). A Simple, Positive Semi-Definite, Heteroskedasticity and Autocorrelation Consistent Covariance Matrix. Econometrica, 55(3), 703–708.
  • Ledoit, O., & Wolf, M. (2004). A Well-Conditioned Estimator for Large-Dimensional Covariance Matrices. Journal of Multivariate Analysis, 88(2), 365–411.
  • Wilson, E. B. (1927). Probable Inference, the Law of Succession, and Statistical Inference. Journal of the American Statistical Association, 22(158), 209–212.