CCPP.Math stands for C++ Calculus Probability Puzzles Math Template Library A C++ template library for quantitative finance algorithms.
A C++ template library + solutions repository that implements mathematical algorithms from two quantitative finance textbooks:
- Stefanica's "Primer for Mathematics of Financial Engineering" → Core math/numerical methods
- Zhou's "Practical Guide to Quant Finance Interviews" → Probability puzzles + algorithms
ccpp.math/
├── include/ # Reusable template functions (integration, root finding, linear algebra, etc.)
└── src/
├── primer_stefanica/ # Math foundations organized by topic
│ └── [calculus, numerical integration, Black-Scholes, PDEs, bonds, etc.]
└── guide_zhou/ # Interview problems organized by type
└── [brain teasers, probability puzzles, stochastic processes, algorithms]
Detailed directory structure mentioned below
mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j4
ctest --output-on-failure
#include "black_scholes.hpp"
using namespace ccpp::math;
BlackScholes::Parameters p{100.0, 100.0, 0.05, 0.2, 1.0};
auto result = BlackScholes::compute_all(p);
std::cout << "Call: " << result.call_price << "\n";
std::cout << "Delta: " << result.delta_call << "\n";
std::cout << "Vega: " << result.vega << "\n";#include "numerical_integration.hpp"
auto f = [](double x) { return x * x; };
double integral = NumericalIntegration<>::simpson(f, 0, 1, 100);#include "root_finding.hpp"
auto f = [](double x) { return x*x - 2; };
auto df = [](double x) { return 2*x; };
auto result = RootFinding<>::newton(f, df, 1.5);#include "GamblersRuin.cpp"
double win_prob = GamblersRuin::win_probability(50, 100, 0.5);
double duration = GamblersRuin::expected_duration(50, 100, 0.51);ccpp.math/
├── CMakeLists.txt
├── README.md
├── .gitignore
├── include/
│ ├── numerical_integration.hpp
│ │ └── integrate_simpson(f, a, b, n) // O(h^4) convergence, loop unrolling
│ │ └── integrate_trapezoidal(f, a, b, n) // O(h^2), vectorized sum
│ │ └── integrate_midpoint(f, a, b, n) // O(h^2), cache-friendly
│ │
│ ├── root_finding.hpp
│ │ └── solve_newton(f, df, x0, tol) // Quadratic convergence
│ │ └── solve_bisection(f, a, b, tol) // Linear convergence, robust
│ │ └── solve_secant(f, x0, x1, tol) // Superlinear convergence
│ │
│ ├── finite_differences.hpp
│ │ └── first_deriv_central(f, x, h) // (f(x+h) - f(x-h))/(2h)
│ │ └── second_deriv_central(f, x, h) // (f(x+h) - 2f(x) + f(x-h))/h^2
│ │ └── first_deriv_forward(f, x, h) // (f(x+h) - f(x))/h
│ │ └── first_deriv_backward(f, x, h) // (f(x) - f(x-h))/h
│ │
│ ├── linear_algebra.hpp
│ │ └── lu_decompose(A) // Gaussian elimination, O(n^3)
│ │ └── cholesky_decompose(A) // A = R^T * R, O(n^3/3)
│ │ └── solve_tridiagonal(a, b, c, d) // Thomas algorithm, O(n)
│ │ └── matrix_multiply(A, B) // Cache-blocked, O(n^3)
│ │
│ ├── statistics.hpp
│ │ └── mean(data) // Single-pass
│ │ └── variance(data, mean) // Welford's algorithm
│ │ └── covariance(x, y) // Online covariance
│ │ └── correlation(x, y) // Pearson coefficient
│ │
│ └── random_generator.hpp
│ └── box_muller_transform() // Generates N(0,1) pairs
│ └── inverse_transform_sampling(F_inv) // Uses uniform RNG
│ └── acceptance_rejection(f, M, g) // Rejection sampling
│
└── src/
│
├── primer_stefanica/
│ │
│ ├── 00_math_preliminaries/
│ │ ├── even_odd_functions/
│ │ │ └── func_parity.cpp
│ │ │ └── is_even(f, domain) // Check f(-x) = f(x)
│ │ │ └── is_odd(f, domain) // Check f(-x) = -f(x)
│ │ │
│ │ ├── useful_sums/
│ │ │ └── summation_formulas.cpp
│ │ │ └── arithmetic_sum(a, d, n) // n(2a + (n-1)d)/2
│ │ │ └── geometric_sum(a, r, n) // a(1-r^n)/(1-r)
│ │ │ └── power_sum_squares(n) // n(n+1)(2n+1)/6
│ │ │ └── power_sum_cubes(n) // [n(n+1)/2]^2
│ │ │
│ │ ├── linear_recursions/
│ │ │ └── fibonacci_recursion.cpp
│ │ │ └── fib_matrix_exp(n) // O(log n) via matrix exponentiation
│ │ │ └── fib_binet(n) // Closed form: φ^n/√5
│ │ │ └── fib_memoized(n) // DP memoization
│ │ │
│ │ └── big_o_notation/
│ │ └── complexity_analyzer.cpp
│ │ └── measure_runtime(algo) // Benchmarking
│ │ └── estimate_complexity(data) // Curve fitting
│ │
│ ├── 01_calculus_options/
│ │ ├── differentiation/
│ │ │ └── derivatives.cpp
│ │ │ └── power_rule(n, x) // d/dx(x^n) = nx^(n-1)
│ │ │ └── chain_rule(f, g, x) // (f∘g)' = f'(g(x))g'(x)
│ │ │ └── product_rule(f, g, x) // (fg)' = f'g + fg'
│ │ │ └── quotient_rule(f, g, x) // (f/g)' = (f'g - fg')/g^2
│ │ │
│ │ ├── integration/
│ │ │ └── integrals.cpp
│ │ │ └── integrate_power(n, a, b) // ∫x^n dx = x^(n+1)/(n+1)
│ │ │ └── integrate_exp(a, b) // ∫e^x dx = e^x
│ │ │ └── integrate_trig(func, a, b) // ∫sin, cos, tan
│ │ │ └── integrate_by_parts(u, dv) // ∫u dv = uv - ∫v du
│ │ │
│ │ ├── limits/
│ │ │ └── limit_solver.cpp
│ │ │ └── lhopital_rule(f, g, x0) // lim f/g = lim f'/g'
│ │ │ └── squeeze_theorem(g, f, h) // g ≤ f ≤ h convergence
│ │ │ └── epsilon_delta(f, x0, L) // Formal definition check
│ │ │
│ │ ├── multivariable_functions/
│ │ │ └── gradients_hessians.cpp
│ │ │ └── compute_gradient(f, x) // ∇f = [∂f/∂x₁, ...]
│ │ │ └── compute_hessian(f, x) // H_ij = ∂²f/∂xᵢ∂xⱼ
│ │ │ └── directional_deriv(f, x, v) // ∇f · v̂
│ │ │
│ │ ├── european_options/
│ │ │ └── plain_vanilla_payoff.cpp
│ │ │ └── call_payoff(S, K) // max(S - K, 0)
│ │ │ └── put_payoff(S, K) // max(K - S, 0)
│ │ │ └── forward_payoff(S, K) // S - K
│ │ │
│ │ └── put_call_parity/
│ │ └── parity_check.cpp
│ │ └── verify_parity(C, P, S, K) // C - P = S - Ke^(-rT)
│ │ └── synthetic_call(P, S, K) // C = P + S - Ke^(-rT)
│ │ └── synthetic_put(C, S, K) // P = C - S + Ke^(-rT)
│ │
│ ├── 02_numerical_integration_bonds/
│ │ ├── integration_rules/
│ │ │ └── composite_rules.cpp
│ │ │ └── adaptive_simpson(f, a, b) // Recursive subdivision
│ │ │ └── romberg_integration(f, a, b) // Richardson extrapolation
│ │ │ └── gaussian_quadrature(f, a, b) // Legendre polynomials
│ │ │
│ │ ├── interest_rate_curves/
│ │ │ ├── forward_rates.cpp
│ │ │ │ └── compute_forward_rate(t1, t2) // f(t1,t2) = -∂ln P(t)/∂t
│ │ │ │ └── instantaneous_forward(t) // f(0,t) from zero curve
│ │ │ │
│ │ │ └── compounding.cpp
│ │ │ └── continuous_compound(r, t) // e^(rt)
│ │ │ └── discrete_compound(r, n, t) // (1 + r/n)^(nt)
│ │ │ └── effective_annual_rate(r, m) // (1 + r/m)^m - 1
│ │ │
│ │ └── bond_math/
│ │ ├── bond_pricing.cpp
│ │ │ └── price_from_ytm(flows, y) // Σ CF_i * e^(-y*t_i)
│ │ │ └── ytm_from_price(flows, P) // Newton solve for y
│ │ │ └── spot_rate_discount(flows) // Bootstrap zero rates
│ │ │
│ │ └── duration_convexity.cpp
│ │ └── macaulay_duration(flows) // -B'/B
│ │ └── modified_duration(D, y) // D/(1+y)
│ │ └── dv01(B, y) // -dB/dy per bp
│ │ └── convexity(flows, y) // B''/B
│ │
│ ├── 03_probability_black_scholes/
│ │ ├── continuous_probability/
│ │ │ └── pdf_cdf_utils.cpp
│ │ │ └── normal_pdf(x, μ, σ) // (2πσ²)^(-1/2) exp(-(x-μ)²/2σ²)
│ │ │ └── normal_cdf(x) // 0.5 * erfc(-x/√2)
│ │ │ └── lognormal_pdf(x, μ, σ) // Transform from normal
│ │ │ └── inverse_normal_cdf(p) // Beasley-Springer-Moro
│ │ │
│ │ ├── black_scholes_formula/
│ │ │ └── bs_pricer_optimized.cpp
│ │ │ └── calculate_d1_d2(S, K, r, σ, T) // d1, d2 formulas
│ │ │ └── call_price(S, K, r, σ, T) // S*N(d1) - K*e^(-rT)*N(d2)
│ │ │ └── put_price(S, K, r, σ, T) // K*e^(-rT)*N(-d2) - S*N(-d1)
│ │ │ └── digital_call(S, K, r, σ, T) // e^(-rT)*N(d2)
│ │ │
│ │ ├── greeks/
│ │ │ └── delta_gamma_vega.cpp
│ │ │ └── call_delta(S, K, r, σ, T) // N(d1)
│ │ │ └── put_delta(S, K, r, σ, T) // N(d1) - 1
│ │ │ └── gamma(S, K, r, σ, T) // N'(d1)/(S*σ*√T)
│ │ │ └── vega(S, K, r, σ, T) // S*√T*N'(d1)
│ │ │ └── theta_call(S, K, r, σ, T) // -S*N'(d1)*σ/2√T - rKe^(-rT)N(d2)
│ │ │ └── rho_call(S, K, r, σ, T) // K*T*e^(-rT)*N(d2)
│ │ │
│ │ └── hedging/
│ │ └── delta_hedge_simulator.cpp
│ │ └── rebalance_portfolio(Δ, S) // Adjust shares to match Δ
│ │ └── pnl_tracking(positions) // Mark-to-market
│ │ └── hedging_error(actual, theo) // Discretization + transaction costs
│ │
│ ├── 04_lognormal_risk_neutral/
│ │ ├── lognormal_variables/
│ │ │ └── lognormal_dist.cpp
│ │ │ └── lognormal_mean(μ, σ) // exp(μ + σ²/2)
│ │ │ └── lognormal_variance(μ, σ) // (e^(σ²) - 1)e^(2μ+σ²)
│ │ │ └── lognormal_moments(μ, σ, n) // E[X^n] = exp(nμ + n²σ²/2)
│ │ │
│ │ └── risk_neutral_derivation/
│ │ └── risk_neutral_expectation.cpp
│ │ └── drift_adjustment(μ, σ, r) // μ → r - σ²/2
│ │ └── martingale_check(S_process) // E^Q[S_T|F_t] = S_t*e^(r(T-t))
│ │ └── girsanov_transform(dW, θ) // dW^Q = dW + θ dt
│ │
│ ├── 05_taylor_series/
│ │ ├── one_variable/
│ │ │ └── taylor_expansion_1d.cpp
│ │ │ └── taylor_exp(x, n_terms) // Σ x^n/n!
│ │ │ └── taylor_sin(x, n_terms) // Σ (-1)^n x^(2n+1)/(2n+1)!
│ │ │ └── taylor_ln(x, n_terms) // Σ (-1)^(n+1)(x-1)^n/n
│ │ │
│ │ ├── multivariable/
│ │ │ └── taylor_expansion_nd.cpp
│ │ │ └── taylor_2d(f, x0, h) // f + ∇f·h + h^T*H*h/2
│ │ │ └── quadratic_approx(f, x0) // Second-order expansion
│ │ │
│ │ └── atm_approximations/
│ │ └── bs_approx_formulas.cpp
│ │ └── atm_call_approx(S, σ, T) // S*σ*√(T/2π)
│ │ └── atm_vega_approx(S, σ, T) // S*√T/√(2π)
│ │ └── delta_approx_moneyness(m) // N(m/(σ√T))
│ │
│ ├── 06_finite_difference_pde/
│ │ ├── finite_differences/
│ │ │ └── difference_schemes.cpp
│ │ │ └── forward_difference(u, dx) // (u_{i+1} - u_i)/dx
│ │ │ └── backward_difference(u, dx) // (u_i - u_{i-1})/dx
│ │ │ └── central_difference(u, dx) // (u_{i+1} - u_{i-1})/(2dx)
│ │ │ └── three_point_laplacian(u, dx) // (u_{i+1} - 2u_i + u_{i-1})/dx²
│ │ │
│ │ └── bs_pde/
│ │ └── bs_pde_grid_solver.cpp
│ │ └── explicit_euler(grid, dt) // u^(n+1) = u^n + α(...), α < 0.5
│ │ └── implicit_euler(grid, dt) // Solve tridiagonal system
│ │ └── crank_nicolson(grid, dt) // θ = 0.5 scheme
│ │ └── boundary_conditions(grid) // Dirichlet/Neumann
│ │
│ ├── 07_multivariable_calculus/
│ │ ├── extrema/
│ │ │ └── lagrange_optimizer.cpp
│ │ │ └── lagrange_multiplier(f, g) // ∇f = λ∇g
│ │ │ └── constrained_min(f, constraints) // KKT conditions
│ │ │ └── classify_critical_point(H) // Eigenvalues of Hessian
│ │ │
│ │ └── random_generation/
│ │ └── box_muller_generator.cpp
│ │ └── box_muller() // Z1 = √(-2ln U1)cos(2πU2)
│ │ └── polar_rejection() // Alternate method
│ │ └── validate_normality(samples) // χ² test
│ │
│ └── 08_roots_implied_vol/
│ ├── nonlinear_solvers/
│ │ ├── newton_raphson.cpp
│ │ │ └── solve_scalar(f, df, x0) // x_new = x - f/f'
│ │ │ └── solve_vector(F, J, x0) // Newton for systems
│ │ │
│ │ ├── bisection.cpp
│ │ │ └── solve(f, a, b, tol) // Halve interval [a,b]
│ │ │ └── illinois_method(f, a, b) // Modified regula falsi
│ │ │
│ │ └── secant.cpp
│ │ └── solve(f, x0, x1, tol) // x_new = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
│ │
│ ├── implied_volatility/
│ │ └── implied_vol_solver.cpp
│ │ └── solve_iv_newton(C_mkt, params) // Newton on C_mkt - BS(σ)
│ │ └── solve_iv_brent(C_mkt, params) // Brent's method
│ │ └── vega_analytical(σ, params) // Derivative for Newton
│ │ └── iv_initial_guess(K, S) // Brenner-Subrahmanyam
│ │
│ └── bootstrapping/
│ └── yield_curve_bootstrap.cpp
│ └── bootstrap_zero_rates(bonds) // Iterative solve
│ └── interpolate_rates(t, knots) // Linear/cubic spline
│ └── forward_rate_from_zeros(r, t1, t2) // (r2*t2 - r1*t1)/(t2-t1)
│
└── guide_zhou/
│
├── brain_teasers/
│ ├── screwy_pirates/
│ │ └── PirateGoldSplit.cpp
│ │ └── solve_distribution(N) // Backward induction
│ │ └── pirate_gets_coin(i, N) // i odd → gets 1
│ │
│ ├── tiger_and_sheep/
│ │ └── TigerSurvival.cpp
│ │ └── will_eat(N_tigers) // (N-1) % 2 == 0
│ │
│ ├── birthday_problem/
│ │ └── BirthdayParadox.cpp
│ │ └── prob_collision(n) // 1 - 365!/(365^n*(365-n)!)
│ │ └── min_people_for_prob(p) // Binary search for n
│ │
│ ├── burning_ropes/
│ │ └── RopeTimer.cpp
│ │ └── measure_time(t_target) // Light both ends strategy
│ │
│ ├── defective_ball/
│ │ └── BallWeighing.cpp
│ │ └── min_weighings(N_balls) // log_3(N)
│ │ └── decision_tree(weights) // Ternary tree
│ │
│ ├── trailing_zeros/
│ │ └── FactorialZeros.cpp
│ │ └── count_zeros(n) // Σ floor(n/5^i)
│ │
│ ├── box_packing/
│ │ └── BoxPacker.cpp
│ │ └── can_pack(boxes, container) // 3D bin packing heuristic
│ │
│ ├── calendar_cubes/
│ │ └── CubeFaceSolver.cpp
│ │ └── find_digits() // Constraint satisfaction
│ │
│ ├── coin_piles/
│ │ └── CoinFlipper.cpp
│ │ └── expected_flips(n) // Geometric series
│ │
│ ├── mislabeled_bags/
│ │ └── FruitBagLogic.cpp
│ │ └── identify_bags() // Single draw logic
│ │
│ └── wise_men/
│ └── WiseMenStrategy.cpp
│ └── determine_hat_color() // Parity strategy
│
├── calculus_linear_algebra/
│ ├── limits_derivatives/
│ │ └── DerivativeCalculator.cpp
│ │ └── symbolic_derivative(expr) // AD implementation
│ │ └── numerical_derivative(f, x) // Central difference
│ │
│ ├── integration/
│ │ └── IntegralSolver.cpp
│ │ └── symbolic_integral(expr) // Pattern matching
│ │ └── numerical_integral(f, a, b) // Adaptive quadrature
│ │
│ ├── matrix_operations/
│ │ └── MatrixOps.cpp
│ │ └── eigenvalues_qr(A) // QR algorithm
│ │ └── determinant_lu(A) // Via LU decomposition
│ │ └── inverse_gauss_jordan(A) // Augmented matrix
│ │
│ └── decompositions/
│ └── LUCholesky.cpp
│ └── lu_factorize(A) // Doolittle algorithm
│ └── cholesky_factorize(A) // R^T*R decomposition
│ └── solve_linear_system(L, U, b) // Forward/back substitution
│
├── probability_theory/
│ ├── coin_toss_game/
│ │ └── CoinGameSim.cpp
│ │ └── expected_payoff() // E = Σ P(i)*payoff(i)
│ │ └── variance_payoff() // E[X²] - E[X]²
│ │
│ ├── drunk_passenger/
│ │ └── SeatProbability.cpp
│ │ └── prob_correct_seat(n) // 0.5 for n ≥ 2
│ │ └── recursive_formula(n) // Symmetry argument
│ │
│ ├── n_points_circle/
│ │ └── CirclePoints.cpp
│ │ └── prob_semicircle(n) // n/2^(n-1)
│ │
│ ├── poker_hands/
│ │ └── PokerCombinatorics.cpp
│ │ └── prob_flush() // C(13,5)*4 / C(52,5)
│ │ └── prob_straight() // Count straights
│ │
│ ├── hopping_rabbit/
│ │ └── RabbitStairs.cpp
│ │ └── ways_to_top(n) // F(n) = F(n-1) + F(n-2)
│ │
│ ├── application_letters/
│ │ └── EnvelopeDerangement.cpp
│ │ └── count_derangements(n) // !n = (n-1)*(!(n-1) + !(n-2))
│ │ └── prob_no_match(n) // !n / n!
│ │
│ ├── monty_hall/
│ │ └── MontyHallSim.cpp
│ │ └── simulate_stay_strategy() // Win rate = 1/3
│ │ └── simulate_switch_strategy() // Win rate = 2/3
│ │
│ ├── amoeba_population/
│ │ └── AmoebaExtinction.cpp
│ │ └── extinction_prob() // Branching process
│ │
│ ├── candies_jar/
│ │ └── CandyProbability.cpp
│ │ └── prob_last_candy(color) // Combinatorial argument
│ │
│ └── russian_roulette/
│ └── RouletteSurvival.cpp
│ └── survival_prob(strategy) // Compare spin vs no-spin
│
├── stochastic_process/
│ ├── gamblers_ruin/
│ │ └── GamblersRuin.cpp
│ │ └── win_probability(i, N, p) // (1-(q/p)^i)/(1-(q/p)^N)
│ │ └── expected_duration(i, N, p) // i/(p-q) - N(1-(q/p)^i)/(...)
│ │
│ ├── dice_question/
│ │ └── DiceRollExpectation.cpp
│ │ └── expected_rolls_until_6() // Geometric: 1/p = 6
│ │ └── expected_distinct_faces() // Coupon collector
│ │
│ ├── coin_triplets/
│ │ └── CoinSequenceMartingale.cpp
│ │ └── expected_flips_HHT() // 8 (vs 10 for HTT)
│ │ └── martingale_proof() // E[T_A] derivation
│ │
│ ├── color_balls/
│ │ └── BallColorMarkov.cpp
│ │ └── transition_matrix() // P_ij for state transitions
│ │ └── stationary_distribution() // π = πP
│ │
│ ├── drunk_man_walk/
│ │ └── RandomWalk1D.cpp
│ │ └── first_passage_time(x0, a) // E[T] for symmetric walk
│ │ └── probability_reach_a(x0, a, b) // Gambler's ruin
│ │
│ ├── dynamic_dice/
│ │ └── DynamicProgrammingDice.cpp
│ │ └── optimal_stopping(n_rolls) // V(n) = max(accept, continue)
│ │ └── threshold_values() // Precompute optimal thresholds
│ │
│ └── dynamic_card/
│ └── OptimalCardStopping.cpp
│ └── secretary_problem() // Optimal strategy: n/e
│ └── expected_value() // 1/e ≈ 0.37
│
├── finance_options/
│ ├── put_call_parity/
│ │ └── ParityArbitrage.cpp
│ │ └── detect_arbitrage(C, P, S, K) // Check C - P = S - Ke^(-rT)
│ │ └── arbitrage_pnl() // Profit from violation
│ │
│ ├── american_vs_european/
│ │ └── OptionComparison.cpp
│ │ └── early_exercise_boundary() // Optimal exercise for American
│ │ └── price_difference(params) // American premium
│ │
│ ├── straddle_bull_spread/
│ │ └── OptionStrategyPayoff.cpp
│ │ └── straddle_payoff(S, K) // |S - K|
│ │ └── bull_spread_payoff(S, K1, K2) // max(0, min(S-K1, K2-K1))
│ │
│ ├── portfolio_optimization/
│ │ └── MeanVarianceOptimizer.cpp
│ │ └── efficient_frontier(μ, Σ) // Markowitz optimization
│ │ └── optimal_weights(target_return) // Solve QP
│ │
│ └── value_at_risk/
│ └── VaRCalculator.cpp
│ └── historical_var(returns, α) // α-quantile
│ └── parametric_var(μ, σ, α) // Gaussian assumption
│ └── monte_carlo_var(model, α) // Simulation-based
│
└── algorithms_numerical/
├── number_swap/
│ └── BitwiseSwap.cpp
│ └── swap_xor(a, b) // a ^= b; b ^= a; a ^= b
│
├── unique_elements/
│ └── UniqueFilter.cpp
│ └── find_unique_xor(arr) // XOR all elements
│ └── find_unique_hash(arr) // Hash set O(n)
│
├── horners_algorithm/
│ └── PolynomialEval.cpp
│ └── horner_eval(coeffs, x) // a_n + x(a_(n-1) + x(...))
│
├── moving_average/
│ └── MovingAvgWindow.cpp
│ └── sma_sliding_window(data, k) // O(n) with queue
│ └── ema_exponential(data, α) // α*x_t + (1-α)*EMA_(t-1)
│
├── sorting_algorithms/
│ └── QuickMergeSort.cpp
│ └── quicksort_inplace(arr) // Average O(n log n)
│ └── mergesort_stable(arr) // Guaranteed O(n log n)
│ └── heapsort(arr) // In-place O(n log n)
│
├── random_permutation/
│ └── KnuthShuffle.cpp
│ └── fisher_yates_shuffle(arr) // Swap arr[i] with arr[rand(i,n)]
│
├── fibonacci_numbers/
│ └── FibOptimized.cpp
│ └── fib_iterative(n) // O(n) space O(1)
│ └── fib_matrix_power(n) // [[1,1],[1,0]]^n, O(log n)
│
├── max_contiguous_subarray/
│ └── KadaneAlgorithm.cpp
│ └── kadane(arr) // current_max = max(arr[i], current_max + arr[i])
│
└── pi_estimation/
└── MonteCarloPi.cpp
└── estimate_pi_circle(n_samples) // 4 * (points_in_circle / total)
└── estimate_pi_buffon(n_drops) // 2L/(πd) for needle drops
-
Stefanica, D. "A Primer for the Mathematics of Financial Engineering" (2nd ed.)
- Chapters: Calculus, Integration, Probability, Black-Scholes, PDEs, Bonds, Implied Vol
-
Zhou, P., Serrano-Fontaine, A. "A Practical Guide to Quantitative Finance Interviews"
- Sections: Brain teasers, Probability, Stochastic processes, Option strategies
- C++17 or higher (for std::optional, structured bindings)
- GCC 7+, Clang 5+, MSVC 2017+
- OpenMP for parallel algorithms (optional)
- Calculus: Derivatives, integrals, limits, multivariable functions
- Probability: Continuous distributions, normal/lognormal PDFs, Black-Scholes
- Numerical Methods: Finite differences, PDE solvers, Taylor series
- Bonds & Rates: Duration, convexity, yield curve bootstrapping
- Stochastic: Lognormal processes, risk-neutral valuation, Girsanov
- Interview Problems: Brain teasers, probability puzzles, stochastic processes
# Create build directory
mkdir build && cd build
# Configure (C++17 required)
cmake .. -DCMAKE_BUILD_TYPE=Release
# Compile
make -j4
# Run tests
ctest --output-on-failure