Simulation
Bootstrap, Monte Carlo and stress scenarios with seeded reproducibility.
See the usage guide for task-oriented examples. Signatures below are generated from the public headers at the same commit as the rest of this site.
-
class simulation_result
Owning simulation result with paths, terminal statistics and risk measures.
Instances are created by
analyze_simulation_paths; the constructor that accepts ready-made state is private. Copy and move operations copy or transfer the owned path frame, statistics and terminal distribution.Public Functions
-
simulation_result(const simulation_result&) = default
Copies the path frame, statistics and terminal distribution.
- Parameters:
other – Result to copy.
-
simulation_result(simulation_result&&) = default
Moves the path frame, statistics and terminal distribution.
- Parameters:
other – Result to move from.
-
simulation_result &operator=(const simulation_result&) = default
Assigns by copying the path frame, statistics and terminal distribution.
- Parameters:
other – Result to copy.
- Returns:
This result after assignment.
-
simulation_result &operator=(simulation_result&&) = default
Assigns by moving the path frame, statistics and terminal distribution.
- Parameters:
other – Result to move from.
- Returns:
This result after assignment.
-
~simulation_result() = default
Destroys the owned path frame, statistics and terminal distribution.
-
const dataframe &paths() const noexcept
Returns the owned path frame.
- Returns:
Const reference valid for the lifetime of this result.
-
const simulation_terminal_statistics &statistics() const noexcept
Returns the cached terminal statistics.
- Returns:
Const reference to the statistics computed at construction.
-
std::size_t path_count() const noexcept
Returns the number of simulated paths.
- Returns:
Number of path columns and terminal values.
-
std::size_t observation_count() const noexcept
Returns the number of observations per path.
- Returns:
Number of rows in the path frame index.
-
double terminal_value_at_risk(double alpha = 0.05) const
Computes the terminal value at risk at
alpha.The result is the linearly interpolated
alphapercentile of the terminal values.- Parameters:
alpha – Tail probability in
(0, 1); defaults to 0.05.- Returns:
The percentile, or NaN when
alphais not finite or outside(0, 1).
-
double terminal_conditional_value_at_risk(double alpha = 0.05) const
Computes the terminal conditional value at risk at
alpha.The result is the arithmetic mean of the terminal values at or below the corresponding value at risk.
- Parameters:
alpha – Tail probability in
(0, 1); defaults to 0.05.- Throws:
input_error – If no terminal value lies in the tail or the mean is not finite.
- Returns:
The tail mean, or NaN when
alphais not finite or outside(0, 1).
-
simulation_result(const simulation_result&) = default
-
struct bootstrap_confidence_interval_result
Lower and upper bounds of a percentile bootstrap interval.
-
struct bootstrap_summary_result
Bootstrap summaries for the mean, deviation and ratio statistics.
Public Members
-
bootstrap_summary_statistic mean
Summary of the mean statistic.
-
bootstrap_summary_statistic sample_standard_deviation
Summary of the sample deviation statistic.
-
bootstrap_summary_statistic sharpe_ratio
Summary of the Sharpe-like ratio.
-
bootstrap_summary_statistic sortino_ratio
Summary of the Sortino-like ratio.
-
bootstrap_summary_statistic mean
-
struct bootstrap_summary_statistic
Summary of one bootstrapped statistic.
Public Members
-
double value
Statistic observed on the NaN-cleaned input sample.
-
double standard_error
Sample deviation of the bootstrap draws.
-
bootstrap_confidence_interval_result confidence_interval
Percentile interval of the bootstrap draws.
-
double value
-
struct custom_stress_scenario
User-defined stress transformation.
Each stressed return is
(return + return_shift) * return_multiplier. Names must be non-empty, distinct and must not reuse a predefined name.
-
struct simulation_parameters
Annualized drift and volatility estimated from periodic returns.
-
struct simulation_terminal_percentiles
Terminal-value percentiles using linear interpolation.
-
struct simulation_terminal_statistics
Summary statistics of the terminal path values.
Public Members
-
double mean
Arithmetic mean of terminal values.
-
double sample_standard_deviation
Sample deviation (
n - 1); NaN for one path.
-
double median
Median terminal value.
-
simulation_terminal_percentiles percentiles
Terminal-value percentiles.
-
double mean
-
struct stress_scenario_result
Outcome of one stress scenario.
-
enum class fincore::bootstrap_statistic
Statistic computed for each bootstrap resample.
Values:
-
enumerator mean
Arithmetic mean of the drawn sample.
-
enumerator sample_standard_deviation
Sample deviation (
n - 1); NaN for one value.
-
enumerator median
Median, averaging the two middle values.
-
enumerator sharpe_ratio
Mean / sample deviation, scaled by
sqrt(252).
-
enumerator sortino_ratio
Mean / downside deviation, scaled by
sqrt(252).
-
enumerator minimum
Smallest drawn value.
-
enumerator maximum
Largest drawn value.
-
enumerator mean
-
enum class fincore::predefined_stress_scenario
Predefined stress transformations.
Values:
-
enumerator crash
Sets the middle return to -0.20 (
crash).
-
enumerator spike
Sets the middle return to 0.10 (
spike).
-
enumerator volatility_crush
Halves every return (
vol_crush).
-
enumerator volatility_spike
Doubles every return (
vol_spike).
-
enumerator crash
-
simulation_result fincore::analyze_simulation_paths(const dataframe &paths)
Analyzes a path frame into a simulation result.
The frame must have a non-empty index and only double columns, with each column matching the index length. Each column’s last value is its terminal value and must be finite. The result owns a copy of the paths plus the terminal statistics and distribution.
- Parameters:
paths – Path frame whose columns are simulation paths.
- Throws:
input_error – If the frame is structurally invalid, a terminal value is not finite, or allocation fails.
- Returns:
A result owning the copied paths, terminal statistics and terminal distribution.
-
double fincore::annualize(double value, std::string_view period = "daily")
Annualizes a volatility-like value with the source’s period factors.
Recognized periods are case-insensitive
daily(252),weekly(52),monthly(12) andyearly(1); any other value uses the daily factor. The result isvalue * sqrt(factor).- Parameters:
value – Volatility-like value to scale.
period – Period label; defaults to
daily.
- Returns:
The scaled value.
-
dataframe fincore::antithetic_variates(const dataframe &paths)
Appends antithetic mirror paths to a path frame.
Every double column is retained, and a companion column named
antithetic_<name>is added with values2 * c - x, wherecis the first value of the first double column. The input index and column order are preserved, and mirror columns follow the source columns.- Parameters:
paths – Path frame with only double columns.
- Throws:
input_error – If the frame has no rows or no double columns, contains a non-double column, has mismatched column lengths, a derived name collides with an input name, or a derived name is unrepresentable.
- Returns:
A frame containing the original columns followed by their mirrors.
-
bootstrap_confidence_interval_result fincore::bootstrap_confidence_interval(const dataframe &returns, std::size_t resample_count = 10000U, double alpha = 0.05, bootstrap_statistic statistic = bootstrap_statistic::mean, std::optional<std::uint64_t> seed = std::nullopt, std::string_view column = returns_column)
Computes a percentile bootstrap confidence interval.
The interval spans the
alpha / 2and1 - alpha / 2linearly interpolated percentiles of the generated statistic distribution. Validation ofalphahappens before any resampling.- Parameters:
returns – Frame containing the selected return column.
resample_count – Number of bootstrap draws.
alpha – Significance level in
(0, 1); defaults to 0.05.statistic – Statistic computed for every draw.
seed – Optional deterministic seed.
column – Double return column to resample.
- Throws:
input_error – If
alphais not finite or outside(0, 1), the distribution rejects the input, or generated statistics are not finite.- Returns:
The lower and upper percentile bounds.
-
dataframe fincore::bootstrap_distribution(const dataframe &returns, std::size_t resample_count = 10000U, bootstrap_statistic statistic = bootstrap_statistic::mean, std::optional<std::uint64_t> seed = std::nullopt, std::string_view column = returns_column)
Generates a bootstrap distribution of one statistic.
NaN returns are removed before resampling and infinities are rejected. Each of the
resample_countdraws samples the retained population with replacement at its original size. A suppliedseedmakes the native 64-bit Mersenne Twister stream repeatable; omitting it seeds fromstd::random_device. Native draws are not guaranteed to match any other RNG implementation.- Parameters:
returns – Frame containing the selected return column.
resample_count – Number of bootstrap draws; 0 yields an empty frame after input validation.
statistic – Statistic computed for every draw.
seed – Optional deterministic seed.
column – Double return column to resample.
- Throws:
input_error – If the column or statistic is invalid, no non-NaN return remains, a retained value is infinite, or the output size is unrepresentable.
- Returns:
A frame with an ordinal index and one
bootstrapdouble column.
-
dataframe fincore::bootstrap_distribution(const dataframe &returns, std::span<const std::vector<std::size_t>> draw_indices, bootstrap_statistic statistic = bootstrap_statistic::mean, std::string_view column = returns_column)
Generates a bootstrap distribution from explicit draw indices.
Draws address the NaN-cleaned positional input population. Every draw must contain exactly that population’s size and only in-range indices. No random engine is used. Empty
draw_indicesyields an empty distribution after the input and statistic are validated.- Parameters:
returns – Frame containing the selected return column.
draw_indices – Resampling index sets, one per output row.
statistic – Statistic computed for every draw.
column – Double return column to resample.
- Throws:
input_error – If the column or statistic is invalid, no non-NaN return remains, a retained value is infinite, a draw length or index is invalid, or the output size is unrepresentable.
- Returns:
A frame with an ordinal index and one
bootstrapdouble column.
-
bootstrap_summary_result fincore::bootstrap_summary(const dataframe &returns, std::size_t resample_count = 10000U, double alpha = 0.05, std::optional<std::uint64_t> seed = std::nullopt, std::string_view column = returns_column)
Computes bootstrap summaries for four statistics.
Each statistic is summarized in a separate native run with the supplied seed and reports its observed value, the sample deviation of its draws, and the percentile interval at
alpha / 2and1 - alpha / 2. Validation ofalphaand the resample count happens before input access.- Parameters:
returns – Frame containing the selected return column.
resample_count – Number of draws per statistic; must be at least 2.
alpha – Significance level in
(0, 1); defaults to 0.05.seed – Optional deterministic seed.
column – Double return column to resample.
- Throws:
input_error – If
alphais invalid,resample_countis less than 2, the input is malformed, or an observed or generated summary value is not finite.- Returns:
Summaries for the mean, sample deviation, Sharpe and Sortino statistics.
-
simulation_parameters fincore::estimate_simulation_parameters(const dataframe &returns, std::size_t periods_per_year = 252, std::string_view column = returns_column)
Estimates annualized drift and volatility from a return column.
NaN values are dropped and infinities are rejected; at least two retained returns are required. Drift is the retained mean multiplied by
periods_per_year; volatility is the sample standard deviation (n - 1) multiplied bysqrt(periods_per_year). Timestamp order is not used.- Parameters:
returns – Frame containing the selected double return column.
periods_per_year – Positive number of periods per year.
column – Double return column name.
- Throws:
input_error – If the column is missing or not double,
periods_per_yearis zero, fewer than two finite returns remain, a value is infinite, or arithmetic overflows.- Returns:
Annualized drift and sample volatility.
-
dataframe fincore::gbm_from_returns(const dataframe &returns, std::size_t horizon = 252U, std::size_t path_count = 1000U, std::size_t periods_per_year = 252U, std::optional<std::uint64_t> seed = std::nullopt, std::string_view column = returns_column)
Simulates cumulative-return paths calibrated from historical returns.
Annualized drift and volatility are estimated from the selected return column (NaN values dropped), prices are simulated from 1.0 over
horizonperiods atperiods_per_year, the initial price row is removed, and each path storesprice_t - 1. Columns are namedpath_<n>.- Parameters:
returns – Frame containing the selected return column.
horizon – Number of periods to simulate.
path_count – Number of paths; must be positive.
periods_per_year – Positive periods per year used for calibration and step sizing.
seed – Optional deterministic seed; omitted seeds are not reproducible.
column – Double return column used for calibration.
- Throws:
input_error – If calibration or path generation rejects the input, or the requested names or output shape is unrepresentable.
- Returns:
A frame whose index excludes the initial row and whose path columns hold cumulative returns.
-
dataframe fincore::generate_correlation_breakdown(std::span<const std::string_view> asset_names, double target_correlation = 1.0)
Builds a square correlation breakdown matrix.
The matrix has one row and one double column per asset, in the supplied order, with an ordinal index. Diagonal entries are 1.0 and every off-diagonal entry is
target_correlation, which is retained even when it lies outside [-1, 1]. Emptyasset_namesyields an empty frame.- Parameters:
asset_names – Ordered asset names; entries must be non-empty, distinct and free of embedded NULs.
target_correlation – Finite off-diagonal correlation value.
- Throws:
input_error – If a name is empty, duplicated or contains an embedded NUL, the target is not finite, or the matrix is unrepresentable.
- Returns:
A square frame with one double column per asset.
-
dataframe fincore::geometric_brownian_motion(double initial_value, double annualized_drift, double annualized_volatility, double total_years, double time_step, std::size_t path_count, std::optional<std::uint64_t> seed = std::nullopt)
Simulates geometric Brownian motion price paths.
Each path starts at
initial_valueand evolves fortrunc(total_years / time_step)steps usingS[k + 1] = S[k] * exp((drift - volatility^2 / 2) * time_step + volatility * sqrt(time_step) * Z)with standard normal drawsZ. The output index is ordinal and paths are namedpath_<n>; the first row is the initial value.- Parameters:
initial_value – Starting price of every path.
annualized_drift – Annualized drift of the process.
annualized_volatility – Annualized volatility of the process.
total_years – Total horizon in years.
time_step – Time between observations in years; must be positive.
path_count – Number of paths; must be positive.
seed – Optional deterministic seed; omitted seeds are not reproducible.
- Throws:
input_error – If an input is not finite,
time_stepis not positive,total_yearsis negative,path_countis zero, or the requested index, names or output shape is unrepresentable.- Returns:
A frame with one initial row plus one row per truncated step, and one double column per path.
-
dataframe fincore::latin_hypercube_sampling(std::size_t sample_count, std::size_t dimension_count, std::optional<std::uint64_t> seed = std::nullopt)
Samples a Latin hypercube design.
Every output column is a permutation of
sample_countequal-probability strata in [0, 1), with one uniformly distributed point per stratum. The index is ordinal and columns are namedlhs_dimension_<n>. Zero counts produce the corresponding empty shape. A suppliedseedmakes the native 64-bit Mersenne Twister stream repeatable; omitted seeds are not reproducible and native draws make no cross-implementation RNG claim.- Parameters:
sample_count – Number of rows to generate.
dimension_count – Number of independent dimensions (columns).
seed – Optional deterministic seed.
- Throws:
input_error – If the requested index, names, stratum count or output shape is unrepresentable, or a sampled point is not finite.
- Returns:
A frame with an ordinal index and one double column per dimension.
-
dataframe fincore::scenario_table(std::span<const stress_scenario_result> results)
Builds a tabular summary of stress scenario results.
The table has an ordinal index and one row per result, with the columns
scenario,cumulative_return,max_drawdown,volatilityandfinal_value. Empty input yields a typed empty table.- Parameters:
results – Scenario results to tabulate.
- Returns:
A frame with one row per result.
-
simulation_result fincore::simulate_monte_carlo(const dataframe &returns, std::size_t path_count = 1000U, std::size_t horizon = 252U, bool antithetic = false, std::optional<std::uint64_t> seed = std::nullopt, std::string_view column = returns_column)
Simulates a calibrated Monte Carlo path set from historical returns.
Annualized drift and volatility are estimated from the selected return column (NaN values dropped), geometric Brownian motion is simulated from 1.0 for
horizonsteps at 252 periods per year, and the resulting price paths are converted to cumulative returns. Whenantitheticis true,antithetic_variatesis applied to those paths, so the stored path count is doubled.- Parameters:
returns – Frame containing the return column.
path_count – Number of base paths.
horizon – Number of simulated periods.
antithetic – Whether to append antithetic mirror paths.
seed – Optional deterministic seed; omitted seeds are not reproducible.
column – Double return column used for calibration.
- Throws:
input_error – If calibration or path generation rejects the input.
- Returns:
A simulation result owning the path frame and terminal statistics.
-
simulation_result fincore::simulate_monte_carlo_from_parameters(double annualized_drift, double annualized_volatility, double initial_value = 1.0, std::size_t path_count = 1000U, std::size_t horizon = 252U, std::optional<std::uint64_t> seed = std::nullopt)
Simulates price paths directly from annualized parameters.
Annualized drift and volatility are converted to per-step values (
drift / 252andvolatility / sqrt(252)), andhorizonperiods are simulated with a1 / 252year step. The returned paths start atinitial_valueand include the initial row.- Parameters:
annualized_drift – Annualized drift of the price process.
annualized_volatility – Annualized volatility of the price process.
initial_value – Starting price of every path.
path_count – Number of paths.
horizon – Number of simulated periods.
seed – Optional deterministic seed; omitted seeds are not reproducible.
- Throws:
input_error – If an input is non-finite,
path_countis zero, or the requested index, names or output shape are unrepresentable.- Returns:
A simulation result owning the price paths and terminal statistics.
-
std::vector<stress_scenario_result> fincore::stress_test(const dataframe &returns, std::string_view column = returns_column)
Runs the four predefined stress scenarios in source order.
Applies
crash,spike,vol_crushandvol_spikein that order.- Parameters:
returns – Frame containing the return column.
column – Double return column to stress.
- Throws:
input_error – If the column is missing, not double, empty or contains NaN.
- Returns:
One result per predefined scenario, in source order.
-
std::vector<stress_scenario_result> fincore::stress_test(const dataframe &returns, std::span<const predefined_stress_scenario> scenarios, std::span<const custom_stress_scenario> custom_scenarios = {}, std::string_view column = returns_column)
Runs selected predefined and custom stress scenarios.
Predefined results appear first in caller order, followed by custom results in caller order. NaN returns are rejected, while infinite returns are retained.
- Parameters:
returns – Frame containing the return column.
scenarios – Predefined scenarios to apply; duplicates are rejected.
custom_scenarios – Custom scenarios to apply; names must be non-empty, distinct and not one of
crash,spike,vol_crushorvol_spike.column – Double return column to stress.
- Throws:
input_error – If return validation fails, a predefined scenario is unknown or duplicated, or a custom scenario has an empty, reserved or duplicate name or non-finite parameters.
- Returns:
One result per requested scenario, in the order described above.
-
std::vector<double> fincore::validate_returns(std::span<const double> returns)
Validates and copies a return series.
The source rejects empty input and NaN values; the native contract also rejects infinities so every returned value is finite. Contract failures raise
fincore_errorwith a structured validation category/code.- Parameters:
returns – Return values to validate.
- Throws:
fincore_error – If
returnsis empty, contains NaN, or contains infinity.- Returns:
A validated copy of
returns.
-
std::vector<double> fincore::validate_returns(const dataframe &returns, std::string_view column = returns_column)
Validates and copies the named return column of a frame.
- Parameters:
returns – Frame containing the selected double column.
column – Name of the double return column; must not be empty.
- Throws:
fincore_error – If
columnis empty or missing, the column is not a double column, or the selected values are empty, NaN or infinite.- Returns:
A validated copy of the selected column.
-
constexpr std::string_view fincore::antithetic_path_column_prefix{"antithetic_"}
Prefix of generated antithetic mirror columns.
-
constexpr std::string_view fincore::bootstrap_statistic_column = {"bootstrap"}
Name of the generated bootstrap statistic column.
-
constexpr std::string_view fincore::gbm_path_column_prefix = {"path_"}
Prefix of generated geometric-Brownian-motion path columns.
-
constexpr std::string_view fincore::latin_hypercube_dimension_column_prefix{"lhs_dimension_"}
Prefix of Latin-hypercube dimension columns.
-
constexpr std::string_view fincore::stress_cumulative_return_column{"cumulative_return"}
Name of the cumulative-return column in a scenario table.
-
constexpr std::string_view fincore::stress_final_value_column = {"final_value"}
Name of the final-value column in a scenario table.
-
constexpr std::string_view fincore::stress_max_drawdown_column = {"max_drawdown"}
Name of the maximum-drawdown column in a scenario table.
-
constexpr std::string_view fincore::stress_scenario_name_column = {"scenario"}
Name of the scenario-name column in a scenario table.
-
constexpr std::string_view fincore::stress_volatility_column = {"volatility"}
Name of the volatility column in a scenario table.