Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
spacetime_manifold.hpp
Go to the documentation of this file.
1#pragma once
2/**
3 * @file spacetime_manifold.hpp
4 * @brief Minkowski spacetime manifold tracker — interval and regime classifier.
5 *
6 * Module: include/srfm/stream/
7 * Owner: AGT-10 (Builder) — 2026-03-01
8 *
9 * Responsibility
10 * --------------
11 * Maintain a running record of Lorentz-transformed tick coordinates and compute
12 * the Minkowski spacetime interval between consecutive events:
13 *
14 * Δs² = Δt'² − Δx'² (c = 1 in normalised units)
15 *
16 * Classify the interval into a Regime (TIMELIKE / LIGHTLIKE / SPACELIKE) and
17 * use it to modulate the relativistic signal strength.
18 *
19 * Spacetime interval interpretation
20 * ----------------------------------
21 * Δs² > +ε → TIMELIKE — causally connected; signal is amplified by Δs.
22 * Δs² < −ε → SPACELIKE — acausally separated; signal is attenuated.
23 * |Δs²| ≤ ε → LIGHTLIKE — on the light cone; signal passes through unscaled.
24 *
25 * The output `signal` field is:
26 * TIMELIKE : +√|Δs²|
27 * SPACELIKE : −√|Δs²|
28 * LIGHTLIKE : 0.0
29 *
30 * Guarantees
31 * ----------
32 * • O(1) per tick: stores only the previous transformed event.
33 * • noexcept: all methods are noexcept.
34 * • Safe first tick: returns LIGHTLIKE / 0.0 when no previous event exists.
35 * • Finite: output signal is always finite for finite Lorentz inputs.
36 *
37 * NOT Responsible For
38 * -------------------
39 * • Computing (t', x') (LorentzTransform)
40 * • Scaling by γ·m_eff (SignalProcessor combines all stages)
41 * • Persistence (in-memory state only)
42 */
43
44#include <cmath>
45#include "stream_signal.hpp"
46
47namespace srfm::stream {
48
49// ── ManifoldResult ────────────────────────────────────────────────────────────
50
51/**
52 * @brief Result of a single manifold update — interval, regime, and signal.
53 */
55 double ds2{0.0}; ///< Minkowski interval Δs² = Δt'² − Δx'².
56 Regime regime{Regime::LIGHTLIKE}; ///< Spacetime classification.
57 double signal{0.0}; ///< ±√|Δs²| (signed by regime).
58};
59
60// ── SpacetimeManifold ─────────────────────────────────────────────────────────
61
62/**
63 * @brief Minkowski interval computer for sequential Lorentz-boosted events.
64 *
65 * @code
66 * SpacetimeManifold manifold;
67 * auto result = manifold.update(ev.t_prime, ev.x_prime);
68 * // result.regime → TIMELIKE / LIGHTLIKE / SPACELIKE
69 * // result.signal → signed sqrt of interval
70 * @endcode
71 */
73public:
74 /**
75 * @brief Construct with a custom lightlike tolerance.
76 *
77 * @param epsilon Absolute |Δs²| threshold for LIGHTLIKE classification.
78 * Defaults to 1e-6 (appropriate for normalised z-score coords).
79 */
80 explicit SpacetimeManifold(double epsilon = 1e-6) noexcept
81 : epsilon_{epsilon > 0.0 ? epsilon : 1e-6}
82 {}
83
84 // ── State mutation ─────────────────────────────────────────────────────────
85
86 /**
87 * @brief Record a new transformed event and compute the interval from the last.
88 *
89 * On the first call (no previous event), returns LIGHTLIKE with signal = 0.
90 *
91 * @param t_prime Boosted time coordinate from LorentzTransform.
92 * @param x_prime Boosted space coordinate from LorentzTransform.
93 * @return ManifoldResult with ds2, regime, and signal for this step.
94 *
95 * @note noexcept.
96 */
97 [[nodiscard]] ManifoldResult update(double t_prime,
98 double x_prime) noexcept {
99 ManifoldResult result;
100
101 if (!has_prev_) {
102 // First event — no interval to compute.
103 prev_t_prime_ = t_prime;
104 prev_x_prime_ = x_prime;
105 has_prev_ = true;
106 result.ds2 = 0.0;
107 result.regime = Regime::LIGHTLIKE;
108 result.signal = 0.0;
109 return result;
110 }
111
112 // Δt' and Δx' between consecutive events.
113 const double dt = t_prime - prev_t_prime_;
114 const double dx = x_prime - prev_x_prime_;
115
116 // Minkowski interval (c = 1).
117 const double ds2 = dt * dt - dx * dx;
118 result.ds2 = ds2;
119
120 // Classify.
121 if (ds2 > epsilon_) {
122 result.regime = Regime::TIMELIKE;
123 result.signal = std::sqrt(ds2);
124 } else if (ds2 < -epsilon_) {
125 result.regime = Regime::SPACELIKE;
126 result.signal = -std::sqrt(-ds2);
127 } else {
128 result.regime = Regime::LIGHTLIKE;
129 result.signal = 0.0;
130 }
131
132 // Slide the window.
133 prev_t_prime_ = t_prime;
134 prev_x_prime_ = x_prime;
135
136 return result;
137 }
138
139 // ── Accessors ──────────────────────────────────────────────────────────────
140
141 /// Whether at least one event has been ingested.
142 [[nodiscard]] bool has_previous() const noexcept { return has_prev_; }
143
144 /// Previous boosted time coordinate.
145 [[nodiscard]] double prev_t_prime() const noexcept { return prev_t_prime_; }
146
147 /// Previous boosted space coordinate.
148 [[nodiscard]] double prev_x_prime() const noexcept { return prev_x_prime_; }
149
150 /// Lightlike tolerance ε.
151 [[nodiscard]] double epsilon() const noexcept { return epsilon_; }
152
153 // ── Reset ──────────────────────────────────────────────────────────────────
154
155 /**
156 * @brief Reset all state as if no events have been seen.
157 *
158 * Preserves the configured epsilon.
159 */
160 void reset() noexcept {
161 has_prev_ = false;
162 prev_t_prime_ = 0.0;
163 prev_x_prime_ = 0.0;
164 }
165
166 // ── Stateless helper ──────────────────────────────────────────────────────
167
168 /**
169 * @brief Compute the Minkowski interval for an arbitrary pair of events.
170 *
171 * Does not mutate any state.
172 *
173 * @param dt Time separation Δt'.
174 * @param dx Space separation Δx'.
175 * @return Minkowski interval Δs² = Δt'² − Δx'².
176 * @note noexcept — pure arithmetic.
177 */
178 [[nodiscard]] static double interval(double dt, double dx) noexcept {
179 return dt * dt - dx * dx;
180 }
181
182 /**
183 * @brief Classify a precomputed interval value.
184 *
185 * @param ds2 Minkowski interval value.
186 * @param epsilon Lightlike tolerance.
187 * @return Regime classification.
188 * @note noexcept.
189 */
190 [[nodiscard]] static Regime classify(double ds2,
191 double epsilon = 1e-6) noexcept {
192 if (ds2 > epsilon) return Regime::TIMELIKE;
193 if (ds2 < -epsilon) return Regime::SPACELIKE;
194 return Regime::LIGHTLIKE;
195 }
196
197private:
198 double epsilon_; ///< Lightlike tolerance.
199 bool has_prev_{false}; ///< Whether a previous event has been stored.
200 double prev_t_prime_{0.0}; ///< Previous boosted time coordinate.
201 double prev_x_prime_{0.0}; ///< Previous boosted space coordinate.
202};
203
204} // namespace srfm::stream
Minkowski interval computer for sequential Lorentz-boosted events.
void reset() noexcept
Reset all state as if no events have been seen.
bool has_previous() const noexcept
Whether at least one event has been ingested.
static double interval(double dt, double dx) noexcept
Compute the Minkowski interval for an arbitrary pair of events.
static Regime classify(double ds2, double epsilon=1e-6) noexcept
Classify a precomputed interval value.
double epsilon() const noexcept
Lightlike tolerance ε.
SpacetimeManifold(double epsilon=1e-6) noexcept
Construct with a custom lightlike tolerance.
double prev_x_prime() const noexcept
Previous boosted space coordinate.
double prev_t_prime() const noexcept
Previous boosted time coordinate.
ManifoldResult update(double t_prime, double x_prime) noexcept
Record a new transformed event and compute the interval from the last.
Regime
Spacetime interval regime derived from the Lorentz-transformed coordinates of consecutive ticks.
StreamRelativisticSignal — output unit of the signal-processing pipeline.
Result of a single manifold update — interval, regime, and signal.
double signal
±√|Δs²| (signed by regime).
double ds2
Minkowski interval Δs² = Δt'² − Δx'².
Regime regime
Spacetime classification.