Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
beta_calculator.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file src/lorentz/beta_calculator.hpp
4/// @brief BetaCalculator — financial-to-physics velocity mapping (AGT-01).
5///
6/// # Module: Beta Calculator
7///
8/// ## Responsibility
9/// Maps raw financial market observables (price time-series, returns, trading
10/// velocity) to the normalised velocity parameter β used throughout SRFM.
11///
12/// This is the entry point for all financial data entering the Lorentz engine.
13/// Every other SRFM module operates on β-values; this module is the only one
14/// that knows about raw prices, returns, and time deltas.
15///
16/// ## Core Formula
17/// ```
18/// β_market = price_velocity / max_observed_velocity
19/// = (dP/dt over window) / max_velocity
20/// ```
21///
22/// ## Design Principle
23/// The market analog of c (speed of light) is `max_velocity` — the fastest
24/// sustained price movement observed or deemed possible. Setting max_velocity
25/// too small risks β > 1 (superluminal, physically nonsensical); too large
26/// pushes everything into the Newtonian regime where γ ≈ 1.
27///
28/// ## Guarantees
29/// - All methods are noexcept static pure functions
30/// - Returned BetaVelocity values are always within the safe range [0, BETA_MAX_SAFE)
31/// or the method returns std::nullopt
32/// - No dynamic allocation — no heap usage on any path
33///
34/// ## NOT Responsible For
35/// - Applying transforms to signals (see lorentz_transform.hpp)
36/// - Loading price data from disk or network (see src/core/data_loader.hpp)
37
38#include "srfm/types.hpp"
39#include "srfm/constants.hpp"
40
41#include <optional>
42#include <span>
43
44namespace srfm::lorentz {
45
46/// Maps financial market observables to the β velocity parameter.
47///
48/// All methods are static. BetaCalculator holds no state — it is a
49/// transformation namespace in class form.
51public:
52 BetaCalculator() = delete;
53
54 // ── Primary Constructors ──────────────────────────────────────────────────
55
56 /// Compute β = |price_velocity| / max_velocity.
57 ///
58 /// The primary factory: given a computed price velocity (dP/dt) and the
59 /// maximum reference velocity, returns the normalised β.
60 ///
61 /// # Arguments
62 /// * `price_velocity` — dP/dt (any finite double, sign preserved for direction)
63 /// * `max_velocity` — Reference maximum velocity (must be > 0)
64 ///
65 /// # Returns
66 /// - `Some(β)` clamped to [0, BETA_MAX_SAFE) if max_velocity > 0
67 /// - `None` if max_velocity ≤ 0 or price_velocity is non-finite
68 ///
69 /// # Look-Ahead Warning
70 /// If `max_velocity` was computed over the full price series (e.g. the global
71 /// maximum velocity), then bar 1's β is normalised by a quantity that includes
72 /// information from bar N — a form of look-ahead bias. This is acceptable for
73 /// offline research / backtesting where the full series is known. For streaming
74 /// or walk-forward applications, use fromPriceVelocityOnline instead.
75 [[nodiscard]] static std::optional<BetaVelocity>
76 fromPriceVelocity(double price_velocity, double max_velocity) noexcept;
77
78 /// Compute β from a single-period percent return and a maximum reference.
79 ///
80 /// β = |return| / max_return
81 ///
82 /// Suitable for daily/intraday return data. Negative returns become
83 /// positive β (speed is always non-negative; direction is separate).
84 ///
85 /// # Returns
86 /// - `Some(β)` ∈ [0, BETA_MAX_SAFE)
87 /// - `None` if max_return ≤ 0 or return is non-finite
88 [[nodiscard]] static std::optional<BetaVelocity>
89 fromReturn(double period_return, double max_return) noexcept;
90
91 /// Compute β from a contiguous price window using central differencing.
92 ///
93 /// Estimates dP/dt over `window` prices with constant `time_delta` between
94 /// samples, then normalises by max_velocity to get β.
95 ///
96 /// Uses the mean absolute velocity over the window to smooth noise.
97 ///
98 /// # Arguments
99 /// * `prices` — Price time series (must have at least 2 elements)
100 /// * `window` — Number of most-recent prices to include (≤ prices.size())
101 /// * `max_velocity` — Reference maximum velocity (must be > 0)
102 /// * `time_delta` — Time between successive prices (must be > 0)
103 ///
104 /// # Returns
105 /// - `Some(β)` normalised mean rolling velocity
106 /// - `None` if inputs are invalid (empty, window < 2, non-finite data)
107 [[nodiscard]] static std::optional<BetaVelocity>
108 fromRollingWindow(std::span<const double> prices,
109 std::size_t window,
110 double max_velocity,
111 double time_delta) noexcept;
112
113 /// Compute a β series online — no look-ahead bias.
114 ///
115 /// For bar i, β_i is normalised by the maximum instantaneous velocity
116 /// observed from bar 0 to bar i only. This means future bars have no
117 /// influence on earlier β values — causal, streaming-safe.
118 ///
119 /// Contrast with fromPriceVelocity which uses a caller-supplied
120 /// `max_velocity` that may have been computed over the full series
121 /// (look-ahead bias).
122 ///
123 /// # Algorithm
124 /// For each bar i:
125 /// 1. Estimate velocity v_i via finite difference at point i using
126 /// only prices[0..i].
127 /// 2. running_max_i = max(running_max_{i-1}, v_i)
128 /// 3. β_i = v_i / running_max_i (or 0 when running_max = 0)
129 ///
130 /// # Arguments
131 /// * `prices` — Full price series (at least 2 elements)
132 /// * `time_delta` — Constant time step between observations (must be > 0)
133 ///
134 /// # Returns
135 /// - `Some(vector<BetaVelocity>)` of length prices.size() — one β per bar
136 /// - `None` if prices.size() < 2, time_delta ≤ 0, or any price is non-finite
137 ///
138 /// # Properties
139 /// - Monotonically non-decreasing running_max
140 /// - β at bar i identical whether or not future bars exist in the series
141 /// - Online and offline methods agree when max velocity occurs at bar 0
142 [[nodiscard]] static std::optional<std::vector<BetaVelocity>>
143 fromPriceVelocityOnline(std::span<const double> prices,
144 double time_delta) noexcept;
145
146 // ── Velocity Estimation ───────────────────────────────────────────────────
147
148 /// Estimate price velocity dP/dt using central finite differences.
149 ///
150 /// For a series p₀…pₙ₋₁ with constant step time_delta:
151 /// v_i = (p_{i+1} − p_{i-1}) / (2·time_delta) for interior points
152 /// v_0 = (p_1 − p_0) / time_delta for the left boundary
153 /// v_n = (pₙ − pₙ₋₁) / time_delta for the right boundary
154 ///
155 /// Returns the mean absolute velocity over the series.
156 ///
157 /// # Returns
158 /// - `Some(v)` ≥ 0
159 /// - `None` if prices has < 2 elements or time_delta ≤ 0
160 [[nodiscard]] static std::optional<double>
161 meanAbsVelocity(std::span<const double> prices, double time_delta) noexcept;
162
163 // ── Classification ────────────────────────────────────────────────────────
164
165 /// Return true if β is in the Newtonian regime (|β| < BETA_NEWTONIAN_THRESHOLD).
166 ///
167 /// In the Newtonian regime γ ≈ 1 + β²/2 — relativistic corrections
168 /// are negligible (less than 0.5%). Classical indicators apply directly.
169 [[nodiscard]] static bool isNewtonian(BetaVelocity beta) noexcept;
170
171 /// Return true if β is in the relativistic regime (|β| ≥ BETA_NEWTONIAN_THRESHOLD).
172 ///
173 /// Relativistic corrections are significant; γ departs from 1 by more
174 /// than ~0.5%. Lorentz-corrected indicators must be used.
175 [[nodiscard]] static bool isRelativistic(BetaVelocity beta) noexcept;
176
177 /// Return true if β is in the valid safe range (|β| < BETA_MAX_SAFE).
178 [[nodiscard]] static bool isValid(BetaVelocity beta) noexcept;
179
180 // ── Utility ───────────────────────────────────────────────────────────────
181
182 /// Clamp an arbitrary raw_beta to the safe range (−BETA_MAX_SAFE, BETA_MAX_SAFE).
183 ///
184 /// Use this as a safety net when β is computed from noisy data that might
185 /// occasionally exceed 1. Does not return nullopt — always produces a valid β.
186 [[nodiscard]] static BetaVelocity clamp(double raw_beta) noexcept;
187
188 /// Relativistic kinetic energy analog: E_k = (γ − 1) · m_eff · c²_market.
189 ///
190 /// The "excess energy" above the rest-frame baseline, representing the
191 /// additional energy a market agent would need to sustain a velocity β.
192 ///
193 /// # Arguments
194 /// * `beta` — Market velocity
195 /// * `effective_mass` — Liquidity proxy (must be > 0)
196 /// * `c_market` — Speed of information (default = SPEED_OF_INFORMATION)
197 ///
198 /// # Returns
199 /// - `Some(E_k)` ≥ 0
200 /// - `None` if effective_mass ≤ 0 or β is invalid
201 [[nodiscard]] static std::optional<double>
203 double effective_mass,
204 double c_market = constants::SPEED_OF_INFORMATION) noexcept;
205
206 /// Relativistic Doppler factor: D = √((1 + β) / (1 − β)).
207 ///
208 /// Models the frequency shift of a signal emitted by a moving market.
209 /// D > 1: observer sees higher frequency (market approaching — momentum).
210 /// D < 1: observer sees lower frequency (market receding — mean-reversion).
211 ///
212 /// # Returns
213 /// - `Some(D)` > 0
214 /// - `None` if β is invalid or |β| ≥ 1 (D would be undefined)
215 [[nodiscard]] static std::optional<double>
216 dopplerFactor(BetaVelocity beta) noexcept;
217};
218
219} // namespace srfm::lorentz
static std::optional< double > meanAbsVelocity(std::span< const double > prices, double time_delta) noexcept
static std::optional< BetaVelocity > fromReturn(double period_return, double max_return) noexcept
static bool isRelativistic(BetaVelocity beta) noexcept
static std::optional< BetaVelocity > fromRollingWindow(std::span< const double > prices, std::size_t window, double max_velocity, double time_delta) noexcept
static std::optional< double > kineticEnergy(BetaVelocity beta, double effective_mass, double c_market=constants::SPEED_OF_INFORMATION) noexcept
static std::optional< BetaVelocity > fromPriceVelocity(double price_velocity, double max_velocity) noexcept
static bool isNewtonian(BetaVelocity beta) noexcept
static std::optional< std::vector< BetaVelocity > > fromPriceVelocityOnline(std::span< const double > prices, double time_delta) noexcept
static std::optional< double > dopplerFactor(BetaVelocity beta) noexcept
static BetaVelocity clamp(double raw_beta) noexcept
static bool isValid(BetaVelocity beta) noexcept
Return true if β is in the valid safe range (|β| < BETA_MAX_SAFE).
Physical and financial constants for the SRFM system.
static constexpr double SPEED_OF_INFORMATION
Definition constants.hpp:37
Shared primitive types for the Special Relativity in Financial Modeling (SRFM) system.