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.cpp
Go to the documentation of this file.
1/**
2 * @file src/proper_time.cpp
3 * @brief Implementation of the Proper Time Portfolio module — Round 7.
4 *
5 * See include/srfm/proper_time.hpp for the full API contract and concept
6 * description.
7 */
8
10#include "srfm/constants.hpp"
11
12#include <algorithm>
13#include <cmath>
14
16
17// ─── ProperTime ───────────────────────────────────────────────────────────────
18
19double ProperTime::gamma_factor(double velocity) noexcept {
20 // Clamp to safe range to avoid numerical singularity
21 const double beta = std::clamp(velocity, 0.0, constants::BETA_MAX_SAFE);
22 const double beta_sq = beta * beta;
23 return 1.0 / std::sqrt(1.0 - beta_sq);
24}
25
27 double portfolio_vol,
28 double max_vol) noexcept
29{
30 if (max_vol <= 0.0) {
31 return 0.0;
32 }
33 const double beta = portfolio_vol / max_vol;
34 return std::clamp(beta, 0.0, constants::BETA_MAX_SAFE);
35}
36
38 double coordinate_time,
39 double velocity) noexcept
40{
41 ProperTimeValue result;
42 result.velocity = std::clamp(velocity, 0.0, constants::BETA_MAX_SAFE);
43 result.gamma = gamma_factor(result.velocity);
44 // τ = t / γ (proper time is always ≤ coordinate time for v > 0)
45 result.tau = coordinate_time / result.gamma;
46 return result;
47}
48
49// ─── ProperTimeClock ──────────────────────────────────────────────────────────
50
52 : max_vol_(max_vol > 0.0 ? max_vol : DEFAULT_MAX_VOL)
53{
54}
55
56void ProperTimeClock::tick(double new_vol, double dt_days) noexcept {
57 if (dt_days <= 0.0) {
58 return;
59 }
60
61 // Compute velocity β = vol / max_vol, clamped to [0, BETA_MAX_SAFE]
62 current_beta_ = ProperTime::to_velocity(new_vol, max_vol_);
63 current_gamma_ = ProperTime::gamma_factor(current_beta_);
64
65 // Integrate: dτ = dt / γ
66 const double dtau = dt_days / current_gamma_;
67
68 elapsed_t_ += dt_days;
69 elapsed_tau_ += dtau;
70 ++tick_count_;
71}
72
73void ProperTimeClock::reset() noexcept {
74 elapsed_tau_ = 0.0;
75 elapsed_t_ = 0.0;
76 current_gamma_ = 1.0;
77 current_beta_ = 0.0;
78 tick_count_ = 0;
79}
80
81// ─── PortfolioAgingModel ──────────────────────────────────────────────────────
82
84 : max_vol_(max_vol > 0.0 ? max_vol : DEFAULT_MAX_VOL)
85{
86}
87
89 double coordinate_age,
90 double portfolio_vol,
91 double sharpe) const noexcept
92{
93 AgingResult result;
94 result.coordinate_age = coordinate_age;
95
96 const double beta = ProperTime::to_velocity(portfolio_vol, max_vol_);
97 result.gamma = ProperTime::gamma_factor(beta);
98
99 // Effective age: high-vol portfolios "age faster" in coordinate time
100 result.effective_age = coordinate_age * result.gamma;
101
102 // Adjusted Sharpe: penalise by √(effective_age)
103 if (result.effective_age > 0.0) {
104 result.adj_sharpe = sharpe / std::sqrt(result.effective_age);
105 } else {
106 result.adj_sharpe = 0.0;
107 }
108
109 return result;
110}
111
112// ─── RelativisticRebalanceTimer ───────────────────────────────────────────────
113
115 double threshold_tau,
116 double max_vol)
117 : threshold_tau_(threshold_tau > 0.0 ? threshold_tau : 5.0)
118 , max_vol_(max_vol > 0.0 ? max_vol : DEFAULT_MAX_VOL)
119 , clock_(max_vol_)
120{
121}
122
123bool RelativisticRebalanceTimer::tick(double new_vol, double dt_days) noexcept {
124 if (dt_days <= 0.0) {
125 return false;
126 }
127
128 const double beta = ProperTime::to_velocity(new_vol, max_vol_);
129 const double gamma = ProperTime::gamma_factor(beta);
130 const double dtau = dt_days / gamma;
131
132 tau_since_rebalance_ += dtau;
133 clock_.tick(new_vol, dt_days);
134
135 if (tau_since_rebalance_ >= threshold_tau_) {
136 tau_since_rebalance_ = 0.0;
137 ++rebalance_count_;
138 return true;
139 }
140
141 return false;
142}
143
145 tau_since_rebalance_ = 0.0;
146}
147
148} // namespace srfm::proper_time
AgingResult compute(double coordinate_age, double portfolio_vol, double sharpe) const noexcept
PortfolioAgingModel(double max_vol=DEFAULT_MAX_VOL)
void tick(double new_vol, double dt_days=1.0) noexcept
void reset() noexcept
Reset all accumulators.
ProperTimeClock(double max_vol=DEFAULT_MAX_VOL)
RelativisticRebalanceTimer(double threshold_tau=5.0, double max_vol=DEFAULT_MAX_VOL)
void reset_timer() noexcept
Reset timer (does not reset rebalance_count).
bool tick(double new_vol, double dt_days=1.0) noexcept
Physical and financial constants for the SRFM system.
static constexpr double BETA_MAX_SAFE
Definition constants.hpp:17
constexpr double DEFAULT_MAX_VOL
Default maximum portfolio volatility (annualised), analogous to c.
Proper Time Portfolio module — Round 7 public API.
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.
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