///|
/// Deterministic workload suite used for release smoke tests and published
/// performance measurements. The report intentionally excludes wall-clock
/// time so that the values remain reproducible across machines.
fn hash_double(hash : UInt64, value : Double) -> UInt64 {
let mut next = hash
let mut bits = value.reinterpret_as_uint64()
let prime : UInt64 = 0x100000001b3UL
let mut i = 0
while i < 8 {
next = (next ^ (bits & 0xffUL)) * prime
bits = bits >> 8
i = i + 1
}
next
}
///|
fn times_grid(steps : Int, maturity : Double) -> Array[Double] {
let times = Array::make(steps + 1, 0.0)
let dt = maturity / steps.to_double()
let mut i = 0
while i <= steps {
times[i] = i.to_double() * dt
i = i + 1
}
times
}
///|
fn gbm_checksum() -> UInt64 {
let process = @stochastic.GBMProcess::new(100.0, 0.04, 0.2)
let times = times_grid(64, 1.0)
let paths = process.generate_matrix(
2000,
times,
@core.RngEngine::splitmix(20260823UL),
)
let mut hash : UInt64 = 0xcbf29ce484222325UL
let mut p = 0
while p < paths.num_paths() {
hash = hash_double(hash, paths.get(p, paths.num_steps() - 1))
p = p + 1
}
hash
}
///|
fn sobol_checksum() -> UInt64 {
let sequence = @qmc.SobolSequence::new(32)
let mut hash : UInt64 = 0xcbf29ce484222325UL
let mut i = 0
while i < 4096 {
let point = sequence.next_point()
let mut d = 0
while d < point.length() {
hash = hash_double(hash, point[d])
d = d + 1
}
i = i + 1
}
hash
}
///|
fn price_european() -> @pricing.OptionPriceResult {
@pricing.price_european_option_mc(
@pricing.Call,
@stochastic.GBMProcess::new(100.0, 0.03, 0.2),
100.0,
0.03,
1.0,
2000,
@core.RngEngine::splitmix(1001UL),
)
}
///|
fn price_barrier() -> @pricing.OptionPriceResult {
@pricing.price_barrier_option_mc(
@pricing.Call,
@pricing.DownAndOut,
@stochastic.GBMProcess::new(100.0, 0.03, 0.2),
100.0,
80.0,
0.03,
times_grid(16, 1.0),
2000,
@core.RngEngine::splitmix(1002UL),
)
}
///|
fn portfolio_checksum() -> UInt64 {
let first = @portfolio.Position::new(
"asset-0",
1.0,
100.0,
100.5,
@portfolio.Equity,
).unwrap()
let positions = Array::make(64, first)
let mut i = 0
while i < positions.length() {
positions[i] = @portfolio.Position::new(
"asset-" + i.to_string(),
(i + 1).to_double(),
100.0 + (i % 7).to_double(),
100.5 + (i % 11).to_double(),
@portfolio.Equity,
).unwrap()
i = i + 1
}
let portfolio = @portfolio.Portfolio::new(positions, 10000.0).unwrap()
let mut hash : UInt64 = 0xcbf29ce484222325UL
let mut scenario = 0
while scenario < 256 {
let shocks = Array::make(64, @portfolio.ScenarioShock::{
id: "asset-0",
additive: 0.0,
proportional: 0.0,
})
let mut p = 0
while p < shocks.length() {
shocks[p] = @portfolio.ScenarioShock::{
id: "asset-" + p.to_string(),
additive: (scenario % 5).to_double() - 2.0,
proportional: ((p + scenario) % 9).to_double() / 100.0 - 0.04,
}
p = p + 1
}
let report = portfolio.report(shocks).unwrap()
hash = hash_double(hash, report.pnl)
hash = hash_double(hash, report.concentration)
scenario = scenario + 1
}
hash
}
///|
fn implied_volatility_result() -> @calibration.ImpliedVolResult {
let target = @pricing.black_scholes_price(
@pricing.Call,
100.0,
105.0,
0.03,
0.2,
1.0,
)
@calibration.implied_volatility(
@pricing.Call,
100.0,
105.0,
0.03,
1.0,
target,
1.0e-10,
100,
).unwrap()
}
///|
/// Build the deterministic benchmark report consumed by CI and documentation.
pub fn benchmark_report() -> String {
let european = price_european()
let barrier = price_barrier()
let implied = implied_volatility_result()
let sb = StringBuilder::new()
sb.write_string(
"benchmark=gbm_terminal_paths paths=2000 steps=64 checksum=" +
gbm_checksum().to_string() +
"\n",
)
sb.write_string(
"benchmark=sobol_32d points=4096 checksum=" +
sobol_checksum().to_string() +
"\n",
)
sb.write_string(
"benchmark=european_call paths=2000 price=" +
european.price.to_string() +
" standard_error=" +
european.standard_error.to_string() +
"\n",
)
sb.write_string(
"benchmark=barrier_call paths=2000 price=" +
barrier.price.to_string() +
" standard_error=" +
barrier.standard_error.to_string() +
"\n",
)
sb.write_string(
"benchmark=portfolio_scenario positions=64 scenarios=256 checksum=" +
portfolio_checksum().to_string() +
"\n",
)
sb.write_string(
"benchmark=implied_volatility iterations=" +
implied.iterations.to_string() +
" residual=" +
implied.residual.to_string() +
" volatility=" +
implied.volatility.to_string() +
"\n",
)
sb.to_string()
}
///|
/// Release benchmark executable entry point.
fn main {
println(benchmark_report())
}