Run Monte Carlo simulations in the browser with just 3 lines of code
Configuration is embedded in the WASM binary. No config loading, no initialization calls. Just load the module and run!
That's it! No config files to load. No initialization functions to call. The WASM binary contains everything it needs.
Start with just age and income. The engine infers everything else from demographic data.
// Step 1: Load the WASM module const rustJS = await import('/static/wasm/rust/flash_simulate_rust.js'); const wasmResp = await fetch('/static/wasm/rust/flash_simulate_rust_bg.wasm'); await rustJS.default(await wasmResp.arrayBuffer()); // Step 2: Generate z-scores (deterministic RNG) const trials = 1000, years = 40; const zScores = rustJS.generate_z_scores(BigInt(42), trials * years); // Step 3: Run simulation with MINIMAL input (just age + income!) const input = { current_age: 35, income: 100000, // Everything else is INFERRED by the engine: // - Retirement age (67) // - Savings (from demographics) // - Tax rates (from state) // - Social Security (calculated) // - Life expectancy (from actuarial tables) }; const result = rustJS.run_simulation_tiered( JSON.stringify(input), zScores, '[]', // life_events '[]', // real_assets '[]', // liabilities 2026 // base_year ); // Get percentiles const percentiles = rustJS.compute_percentiles(result, trials, years); console.log('Median terminal wealth:', percentiles.p50[years - 1]);
No init_config(). No add_federal_bracket(). No loading 6 config files. The engine handles it all internally.
Provide more data for more accurate results. The engine always fills in what's missing.
| Tier | User Provides | Engine Infers |
|---|---|---|
| Tier 1 (HOOK) | Age + Income | Everything else (savings, state, allocation, SS, life expectancy) |
| Tier 2 (ENGAGE) | + Total savings, state | Account splits, allocation, tax rates |
| Tier 3 (QUALIFY) | + Account breakdown | Tax optimization parameters |
const input = { current_age: 35, income: 100000, total_savings: 150000, // User provides savings state_code: "CA", // Higher state tax retirement_age: 62, // Early retirement };
const input = { current_age: 45, income: 180000, state_code: "TX", // No state tax filing_status: "married", retirement_age: 60, // Explicit account breakdown (Tier 3) taxable: 200000, // Brokerage account tax_deferred: 450000, // 401(k) + IRA roth: 100000, // Roth IRA cost_basis_ratio: 0.7, // 70% cost basis in taxable // Spouse spouse_age: 43, spouse_income: 95000, spouse_retirement_age: 62, };
All fields except current_age and income are optional.
| Field | Type | Default | Description |
|---|---|---|---|
current_age |
number | required | Current age |
income |
number | required | Annual gross income |
total_savings |
number | inferred | Total savings (if not providing account breakdown) |
state_code |
string | "US_AVG" | Two-letter state code |
retirement_age |
number | 67 | Target retirement age |
filing_status |
string | inferred | "single" or "married" |
sex |
string | "unknown" | "male", "female", or "unknown" (for life expectancy) |
taxable |
number | inferred | Taxable account balance (-1 = infer) |
tax_deferred |
number | inferred | 401(k)/IRA balance (-1 = infer) |
roth |
number | inferred | Roth IRA balance (-1 = infer) |
spouse_age |
number | 0 | Spouse age (0 = no spouse) |
spouse_income |
number | 0 | Spouse annual income |
AssemblyScript provides the same API with a slightly different loading pattern:
// Load AssemblyScript module const asModule = await import('/static/wasm/assemblyscript/simulate.js'); // Generate z-scores const zScores = asModule.generateZScores(BigInt(42), trials * years); // Run tiered simulation const result = asModule.runSimulationTiered( 35, // current_age 100000, // income 0, // total_savings (0 = infer) "", // state_code ("" = infer) 0, // retirement_age (0 = infer) "", // filing_status "", // sex -1, // taxable (-1 = infer) -1, // tax_deferred -1, // roth -1, // cost_basis_ratio 0, // spouse_age 0, // spouse_income 0, // spouse_retirement_age 1000, // trials 40, // years 0, // combined_contribution (0 = infer) zScores, // z-scores 2026 // base_year );
Both engines use PCG32 + Box-Muller for deterministic random number generation. Same seed = same results.
// Generate z-scores with a seed for reproducibility const seed = 42; const count = trials * years; // 1000 * 40 = 40,000 // Rust const zScores = rustJS.generate_z_scores(BigInt(seed), count); // AssemblyScript const zScores = asModule.generateZScores(BigInt(seed), count);
With the same seed and inputs, Rust WASM, AssemblyScript WASM, and Python produce identical results across all 30+ test scenarios.