Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
minkowski_momentum.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file include/srfm/minkowski_momentum.hpp
4/// @brief Minkowski Momentum — Round 6 public API.
5///
6/// # Module: Minkowski Momentum
7///
8/// ## Concept
9/// Extends classical momentum to financial spacetime by representing a
10/// portfolio's exposure profile as a four-momentum vector:
11///
12/// p^μ = (E, p_x, p_y, p_z)
13///
14/// Financial interpretation:
15/// - E (energy) = portfolio_return (total return, the "time-like" component)
16/// - p_x (x-momentum) = equity_exposure (e.g. equity beta × portfolio value)
17/// - p_y (y-momentum) = bond_exposure (duration × portfolio value)
18/// - p_z (z-momentum) = commodity_exposure (commodity beta × portfolio value)
19///
20/// ## Key quantities
21///
22/// ### Invariant mass (diversification measure)
23/// ```
24/// m² = E² - p_x² - p_y² - p_z²
25/// ```
26/// A higher invariant mass indicates better diversification: the portfolio's
27/// total return exceeds the sum-in-quadrature of its directional exposures.
28///
29/// ### Rapidity (financial velocity in equity space)
30/// ```
31/// y = 0.5 * ln((E + p_x) / (E - p_x))
32/// ```
33/// Rapidity is additive under successive equity-space boosts, making it a
34/// natural measure of compounded equity momentum.
35///
36/// ## Guarantees
37/// - All methods are `noexcept` where possible
38/// - Return `std::optional` for invalid inputs
39/// - No dynamic allocation; no mutable state in pure-math classes
40/// - Thread-safe (stateless functions)
41
42#include "srfm/types.hpp"
43#include "srfm/constants.hpp"
44
45#include <cmath>
46#include <optional>
47#include <span>
48#include <vector>
49
51
52// ─── FourMomentum ─────────────────────────────────────────────────────────────
53
54/// Financial four-momentum vector p^μ = (E, p_x, p_y, p_z).
55///
56/// Component semantics:
57/// - energy: portfolio return (total, not annualised)
58/// - px: equity exposure
59/// - py: bond exposure
60/// - pz: commodity exposure
62 double energy; ///< E — portfolio return (time-like component)
63 double px; ///< p_x — equity exposure
64 double py; ///< p_y — bond exposure
65 double pz; ///< p_z — commodity exposure
66};
67
68// ─── MinkowskiMomentum ────────────────────────────────────────────────────────
69
70/// Stateless utility class for financial Minkowski four-momentum calculations.
72public:
73 /// Compute the Minkowski interval (invariant mass squared):
74 /// m² = E² - p_x² - p_y² - p_z²
75 ///
76 /// A positive m² indicates a time-like four-momentum (physically
77 /// realisable: the portfolio return dominates its exposures). In the
78 /// financial analogy, m² > 0 means the portfolio is well-diversified.
79 ///
80 /// @param p Four-momentum vector.
81 /// @return m² = E² - p_x² - p_y² - p_z² (may be negative).
82 [[nodiscard]] static double invariant_mass_sq(const FourMomentum& p) noexcept;
83
84 /// Compute the invariant mass (diversification measure):
85 /// m = sqrt(|m²|) with sign preserved (negative if space-like)
86 ///
87 /// Returns nullopt if the four-momentum components are not all finite.
88 ///
89 /// @param p Four-momentum vector.
90 /// @return Signed sqrt of |m²|, or nullopt on invalid input.
91 [[nodiscard]] static std::optional<double>
92 invariant_mass(const FourMomentum& p) noexcept;
93
94 /// Compute the rapidity in equity space:
95 /// y = 0.5 * ln((E + p_x) / (E - p_x))
96 ///
97 /// Rapidity is finite and well-defined when |p_x| < E (i.e. equity
98 /// exposure does not exceed total return).
99 ///
100 /// @param p Four-momentum vector.
101 /// @return Rapidity, or nullopt if E <= |p_x| or inputs are not finite.
102 [[nodiscard]] static std::optional<double>
103 rapidity(const FourMomentum& p) noexcept;
104
105 /// Compute the transverse momentum magnitude:
106 /// p_T = sqrt(p_y² + p_z²)
107 ///
108 /// Represents the combined non-equity exposure.
109 ///
110 /// @param p Four-momentum vector.
111 /// @return p_T >= 0.
112 [[nodiscard]] static double transverse_momentum(const FourMomentum& p) noexcept;
113
114 /// Compute the spatial momentum magnitude:
115 /// |p| = sqrt(p_x² + p_y² + p_z²)
116 ///
117 /// @param p Four-momentum vector.
118 /// @return |p| >= 0.
119 [[nodiscard]] static double spatial_magnitude(const FourMomentum& p) noexcept;
120};
121
122// ─── FourMomentumConservation ─────────────────────────────────────────────────
123
124/// Checks whether a set of trade four-momenta conserves total four-momentum
125/// (i.e. the net change in portfolio exposure sums to the reference vector).
127public:
128 /// Check four-momentum conservation for a collection of trades.
129 ///
130 /// The trades are considered "conserving" if the sum of all four-momentum
131 /// vectors equals the reference vector within *tolerance*.
132 ///
133 /// @param trades Span of four-momentum changes from individual trades.
134 /// @param reference Expected net four-momentum (e.g. zeros for net-flat).
135 /// @param tolerance Per-component absolute tolerance (default 1e-9).
136 /// @return true if all four components are conserved.
137 [[nodiscard]] static bool conserves(
138 std::span<const FourMomentum> trades,
139 const FourMomentum& reference,
140 double tolerance = 1e-9) noexcept;
141
142 /// Sum a collection of four-momenta into a single resultant.
143 ///
144 /// @param momenta Span of four-momentum vectors.
145 /// @return Component-wise sum.
146 [[nodiscard]] static FourMomentum sum(
147 std::span<const FourMomentum> momenta) noexcept;
148};
149
150// ─── MomentumPortfolioOptimizer ───────────────────────────────────────────────
151
152/// Finds portfolio weights that maximise the Minkowski invariant mass
153/// (diversification measure) subject to the constraint that weights sum to 1.
154///
155/// The optimisation is performed by a simple gradient-ascent procedure:
156/// at each step the weight vector is nudged in the direction of increasing m²,
157/// then re-normalised to sum to 1 and clamped to [min_weight, max_weight].
158/// Configuration for the gradient-ascent optimiser. Defined at namespace scope
159/// (and aliased as MomentumPortfolioOptimizer::Config) because GCC rejects a
160/// `= {}` default argument of a nested class with default member initialisers.
162 double learning_rate = 0.01; ///< Step size per iteration
163 int max_iterations = 1000; ///< Maximum number of ascent steps
164 double tolerance = 1e-8; ///< Convergence criterion on m²
165 double min_weight = 0.0; ///< Lower bound on each weight
166 double max_weight = 1.0; ///< Upper bound on each weight
167};
168
170public:
171 /// Configuration for the gradient-ascent optimiser.
173
174 /// Result of a single optimisation run.
175 struct Result {
176 std::vector<double> weights; ///< Optimal weight vector (sums to 1)
177 double max_inv_mass_sq; ///< m² achieved at the optimum
178 int iterations_used; ///< Actual iterations taken
179 bool converged; ///< true if tolerance was reached
180 };
181
182 /// Maximise invariant mass over portfolio weight combinations.
183 ///
184 /// @param returns Asset return vector (one entry per asset).
185 /// @param exposures Matrix (n_assets × 3): [equity, bond, commodity]
186 /// exposure coefficients for each asset.
187 /// @param cfg Optimiser configuration.
188 /// @return Optimisation result, or nullopt on invalid input.
189 [[nodiscard]] static std::optional<Result> optimize(
190 std::span<const double> returns,
191 std::span<const std::array<double,3>> exposures,
192 const Config& cfg = {}) noexcept;
193
194private:
195 /// Compute the portfolio-level FourMomentum from weight vector + data.
196 static FourMomentum _portfolio_momentum(
197 std::span<const double> weights,
198 std::span<const double> returns,
199 std::span<const std::array<double,3>> exposures) noexcept;
200};
201
202} // namespace srfm::minkowski_momentum
static bool conserves(std::span< const FourMomentum > trades, const FourMomentum &reference, double tolerance=1e-9) noexcept
static FourMomentum sum(std::span< const FourMomentum > momenta) noexcept
Stateless utility class for financial Minkowski four-momentum calculations.
static double invariant_mass_sq(const FourMomentum &p) noexcept
static double spatial_magnitude(const FourMomentum &p) noexcept
static double transverse_momentum(const FourMomentum &p) noexcept
static std::optional< double > rapidity(const FourMomentum &p) noexcept
static std::optional< double > invariant_mass(const FourMomentum &p) noexcept
static std::optional< Result > optimize(std::span< const double > returns, std::span< const std::array< double, 3 > > exposures, const Config &cfg={}) noexcept
Physical and financial constants for the SRFM system.
double energy
E — portfolio return (time-like component)
double pz
p_z — commodity exposure
std::vector< double > weights
Optimal weight vector (sums to 1)
Shared primitive types for the Special Relativity in Financial Modeling (SRFM) system.