/** * Econometric Model Executor * Runs the built-in TypeScript simulation models (debt Monte Carlo, VAR impulse responses) * with validated parameters. No user-supplied code is executed. */ import { SandboxResult } from "../contracts/tool_outputs.js"; import { runVarImpulseSimulation, VarInputPayload } from "./templates/var_shock_model.js"; import { MonteCarloDebtInputPayload, simulateDebtTrajectory } from "./templates/monte_carlo_debt.js"; export type EconometricModel = SandboxResult["model"]; export const ECONOMETRIC_MODELS: EconometricModel[] = ["debt_monte_carlo", "var_irf"]; export function executeEconometricModel( executionId: string, model: "debt_monte_carlo", params: MonteCarloDebtInputPayload ): SandboxResult; export function executeEconometricModel(executionId: string, model: "var_irf", params: VarInputPayload): SandboxResult; export function executeEconometricModel( executionId: string, model: EconometricModel, params: MonteCarloDebtInputPayload | VarInputPayload ): SandboxResult; export function executeEconometricModel( executionId: string, model: EconometricModel, params: MonteCarloDebtInputPayload | VarInputPayload ): SandboxResult { const startTime = Date.now(); try { if (model === "debt_monte_carlo") { const mc = simulateDebtTrajectory(params as MonteCarloDebtInputPayload); return { execution_id: executionId, success: true, model, computed_metrics: mc.summary_metrics, stderr_log: "", execution_time_ms: Date.now() - startTime, trajectory_curves: mc.trajectory_curves, }; } const varResult = runVarImpulseSimulation(params as VarInputPayload); return { execution_id: executionId, success: true, model, computed_metrics: varResult.summary_metrics, stderr_log: "", execution_time_ms: Date.now() - startTime, impulse_responses: varResult.impulse_projections, }; } catch (err: unknown) { const errorMsg = err instanceof Error ? err.message : String(err); return { execution_id: executionId, success: false, model, computed_metrics: {}, stderr_log: `Model execution error: ${errorMsg}`, execution_time_ms: Date.now() - startTime, }; } } export function executeEconometricScript( executionId: string, _pythonCode: string, datasetJson: string ): SandboxResult { let parsed: any = {}; try { parsed = typeof datasetJson === "string" ? JSON.parse(datasetJson) : datasetJson || {}; } catch (_e) { parsed = {}; } // gdp_growth_rate is a percent (World Bank units); real_growth_mean is already a fraction. const pct = Number(parsed.gdp_growth_rate); const frac = Number(parsed.real_growth_mean); const growthFraction = Number.isFinite(pct) && parsed.gdp_growth_rate !== null && parsed.gdp_growth_rate !== "" ? pct / 100 : Number.isFinite(frac) && parsed.real_growth_mean !== null && parsed.real_growth_mean !== "" ? frac : 0.042; return executeEconometricModel( executionId, "debt_monte_carlo", { initial_debt_to_gdp: numberOr(parsed.initial_debt_to_gdp, 28.1), primary_balance_pct_gdp: numberOr(parsed.primary_balance_pct_gdp, -2.3), real_growth_mean: growthFraction, real_growth_std: 0.015, effective_interest_rate_mean: 0.038, effective_interest_rate_std: 0.005, fiscal_multiplier: numberOr(parsed.fiscal_multiplier, 1.35), capex_shock_pct_gdp: numberOr(parsed.capex_shock_pct_gdp, 1.5), horizon_years: numberOr(parsed.horizon_years, 15) } ); } function numberOr(value: unknown, fallback: number): number { if (value === null || value === undefined || value === "") return fallback; const n = Number(value); return Number.isFinite(n) ? n : fallback; }