Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
proper_time.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file include/srfm/proper_time.hpp
4/// @brief Proper Time Portfolio module — Round 7 public API.
5///
6/// # Module: Proper Time Portfolio
7///
8/// ## Concept
9/// In Special Relativity the *proper time* τ experienced by a moving observer
10/// is less than the coordinate time t measured by a stationary observer:
11///
12/// τ = t / γ where γ = 1 / √(1 − β²)
13///
14/// ## Financial Interpretation
15/// A high-volatility ("fast-moving") portfolio is analogous to the moving
16/// observer. It takes longer to reach the same information state as a
17/// low-volatility portfolio and therefore experiences "slower" proper time.
18///
19/// ### Mapping
20/// - Coordinate time t → calendar time in years / trading days
21/// - Velocity v = portfolio_vol / c (β ∈ [0, 1))
22/// - Speed of light c = max_vol (configurable, default 0.50 = 50 % ann.)
23/// - Lorentz factor γ = 1 / √(1 − β²)
24/// - Proper time τ = t / γ
25///
26/// ## Key Interpretation
27/// - γ > 1 for any v > 0: high-vol portfolios "age faster" in coordinate
28/// time — each calendar day has a larger impact on their information state.
29/// - adj_sharpe = sharpe / √(effective_age) where effective_age = t · γ
30///
31/// ## Classes
32/// - ProperTime — value type (τ, γ, v)
33/// - ProperTimeClock — integrates dτ = dt / γ(v) over streaming vol obs.
34/// - PortfolioAgingModel — computes effective age and adjusted Sharpe
35/// - RelativisticRebalanceTimer — fires when accumulated Δτ > threshold
36///
37/// ## Guarantees
38/// - No dynamic allocation in the hot path
39/// - All methods noexcept where indicated
40/// - Thread-compatible (external locking required for concurrent mutations)
41
42#include "srfm/constants.hpp"
43
44#include <algorithm>
45#include <cmath>
46#include <stdexcept>
47#include <vector>
48
49namespace srfm::proper_time {
50
51// ─── Constants ────────────────────────────────────────────────────────────────
52
53/// Default maximum portfolio volatility (annualised), analogous to c.
54inline constexpr double DEFAULT_MAX_VOL = 0.50;
55
56// ─── ProperTime ───────────────────────────────────────────────────────────────
57
58/// Value type returned by ProperTime::compute.
60 double tau = 0.0; ///< Elapsed proper time
61 double gamma = 1.0; ///< Lorentz factor γ = 1/√(1−β²)
62 double velocity = 0.0; ///< Normalised velocity β = vol / max_vol
63};
64
65/// Stateless computation of proper-time quantities.
66struct ProperTime {
67 /// Compute ProperTimeValue for a portfolio with given coordinate time and
68 /// velocity.
69 ///
70 /// @param coordinate_time Elapsed coordinate time (years or any unit).
71 /// @param velocity Normalised velocity β = portfolio_vol / max_vol,
72 /// clamped to [0, BETA_MAX_SAFE].
73 /// @returns ProperTimeValue with tau = t / γ.
74 [[nodiscard]] static ProperTimeValue compute(
75 double coordinate_time,
76 double velocity) noexcept;
77
78 /// Compute Lorentz factor γ = 1 / √(1 − β²) for a given velocity.
79 ///
80 /// @param velocity Normalised velocity β ∈ [0, 1).
81 [[nodiscard]] static double gamma_factor(double velocity) noexcept;
82
83 /// Convert a raw portfolio volatility to normalised velocity β.
84 ///
85 /// @param portfolio_vol Annualised volatility (e.g. 0.20 = 20 %).
86 /// @param max_vol Speed-of-light analogue (default 0.50).
87 [[nodiscard]] static double to_velocity(
88 double portfolio_vol,
89 double max_vol = DEFAULT_MAX_VOL) noexcept;
90};
91
92// ─── ProperTimeClock ──────────────────────────────────────────────────────────
93
94/// Integrates proper time τ = ∑ dt / γ(v(t)) over a sequence of volatility
95/// observations.
96///
97/// Each call to tick() advances the clock by dτ = dt_days / γ(v), where v is
98/// derived from the supplied volatility.
100public:
101 /// @param max_vol Volatility cap analogous to the speed of light (default
102 /// DEFAULT_MAX_VOL).
103 explicit ProperTimeClock(double max_vol = DEFAULT_MAX_VOL);
104
105 /// Advance the clock by one observation.
106 ///
107 /// @param new_vol Current annualised portfolio volatility.
108 /// @param dt_days Calendar days elapsed since the last tick (default 1).
109 void tick(double new_vol, double dt_days = 1.0) noexcept;
110
111 /// Total elapsed proper time in days.
112 [[nodiscard]] double elapsed_proper_time() const noexcept {
113 return elapsed_tau_;
114 }
115
116 /// Total elapsed coordinate (calendar) time in days.
117 [[nodiscard]] double elapsed_coordinate_time() const noexcept {
118 return elapsed_t_;
119 }
120
121 /// Current Lorentz factor (from the most recent tick).
122 [[nodiscard]] double current_gamma() const noexcept {
123 return current_gamma_;
124 }
125
126 /// Current normalised velocity β.
127 [[nodiscard]] double current_velocity() const noexcept {
128 return current_beta_;
129 }
130
131 /// Maximum volatility cap.
132 [[nodiscard]] double max_vol() const noexcept { return max_vol_; }
133
134 /// Number of ticks accumulated.
135 [[nodiscard]] std::size_t tick_count() const noexcept { return tick_count_; }
136
137 /// Reset all accumulators.
138 void reset() noexcept;
139
140private:
141 double max_vol_;
142 double elapsed_tau_ = 0.0;
143 double elapsed_t_ = 0.0;
144 double current_gamma_ = 1.0;
145 double current_beta_ = 0.0;
146 std::size_t tick_count_ = 0;
147};
148
149// ─── PortfolioAgingModel ──────────────────────────────────────────────────────
150
151/// Computes the "effective age" of a portfolio accounting for relativistic
152/// time dilation, and produces a Lorentz-adjusted Sharpe ratio.
153///
154/// A high-volatility portfolio "ages faster" in coordinate time:
155///
156/// effective_age = coordinate_age * γ
157/// adj_sharpe = sharpe / √(effective_age)
158///
159/// The adjustment penalises strategies that appear attractive only because
160/// they have not been exposed to enough effective information time.
162public:
163 /// @param max_vol Volatility speed-of-light cap.
165
166 /// Result of one aging computation.
167 struct AgingResult {
168 double coordinate_age; ///< Raw age in the same units as input.
169 double effective_age; ///< coordinate_age * γ.
170 double gamma; ///< Lorentz factor.
171 double adj_sharpe; ///< sharpe / √(effective_age) or 0 if age <= 0.
172 };
173
174 /// Compute effective age and adjusted Sharpe.
175 ///
176 /// @param coordinate_age Calendar age of the strategy (years or days).
177 /// @param portfolio_vol Current annualised volatility.
178 /// @param sharpe Raw (unadjusted) Sharpe ratio.
179 [[nodiscard]] AgingResult compute(
180 double coordinate_age,
181 double portfolio_vol,
182 double sharpe) const noexcept;
183
184 [[nodiscard]] double max_vol() const noexcept { return max_vol_; }
185
186private:
187 double max_vol_;
188};
189
190// ─── RelativisticRebalanceTimer ───────────────────────────────────────────────
191
192/// Suggests rebalancing when accumulated proper time since the last rebalance
193/// exceeds a threshold. This avoids over-trading in high-volatility regimes
194/// where each calendar day has a lower informational content (slow proper time).
195///
196/// In high-vol regimes γ > 1 → dτ = dt / γ < dt, so the timer fires less
197/// frequently in calendar time — correctly reducing turnover when it matters
198/// most.
200public:
201 /// @param threshold_tau Proper-time threshold in days before suggesting a
202 /// rebalance. Default: 5.0 days.
203 /// @param max_vol Volatility cap.
205 double threshold_tau = 5.0,
206 double max_vol = DEFAULT_MAX_VOL);
207
208 /// Advance the timer by one observation.
209 ///
210 /// @param new_vol Current annualised volatility.
211 /// @param dt_days Calendar days elapsed.
212 /// @returns true if a rebalance is recommended.
213 bool tick(double new_vol, double dt_days = 1.0) noexcept;
214
215 /// Accumulated proper time since the last rebalance.
216 [[nodiscard]] double tau_since_rebalance() const noexcept {
217 return tau_since_rebalance_;
218 }
219
220 /// Total number of rebalance events fired.
221 [[nodiscard]] std::size_t rebalance_count() const noexcept {
222 return rebalance_count_;
223 }
224
225 /// Threshold for rebalance trigger.
226 [[nodiscard]] double threshold_tau() const noexcept { return threshold_tau_; }
227
228 /// Reset timer (does not reset rebalance_count).
229 void reset_timer() noexcept;
230
231private:
232 double threshold_tau_;
233 double max_vol_;
234 double tau_since_rebalance_ = 0.0;
235 std::size_t rebalance_count_ = 0;
236 ProperTimeClock clock_;
237};
238
239} // namespace srfm::proper_time
double current_gamma() const noexcept
Current Lorentz factor (from the most recent tick).
void tick(double new_vol, double dt_days=1.0) noexcept
double elapsed_coordinate_time() const noexcept
Total elapsed coordinate (calendar) time in days.
double elapsed_proper_time() const noexcept
Total elapsed proper time in days.
double max_vol() const noexcept
Maximum volatility cap.
std::size_t tick_count() const noexcept
Number of ticks accumulated.
double current_velocity() const noexcept
Current normalised velocity β.
void reset() noexcept
Reset all accumulators.
double tau_since_rebalance() const noexcept
Accumulated proper time since the last rebalance.
std::size_t rebalance_count() const noexcept
Total number of rebalance events fired.
double threshold_tau() const noexcept
Threshold for rebalance trigger.
Physical and financial constants for the SRFM system.
constexpr double DEFAULT_MAX_VOL
Default maximum portfolio volatility (annualised), analogous to c.
double coordinate_age
Raw age in the same units as input.
double adj_sharpe
sharpe / √(effective_age) or 0 if age <= 0.
Value type returned by ProperTime::compute.
double tau
Elapsed proper time.
double gamma
Lorentz factor γ = 1/√(1−β²)
double velocity
Normalised velocity β = vol / max_vol.
Stateless computation of proper-time quantities.
static double gamma_factor(double velocity) noexcept
static double to_velocity(double portfolio_vol, double max_vol=DEFAULT_MAX_VOL) noexcept
static ProperTimeValue compute(double coordinate_time, double velocity) noexcept