Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
portfolio_manifold.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file include/portfolio_manifold.hpp
4/// @brief N-Asset Minkowski Covariance Matrix and Spacetime Causal Graph.
5///
6/// # Module: Portfolio Manifold
7///
8/// ## Responsibility
9/// Extend the 4D financial spacetime manifold to an N-asset setting.
10/// Each asset is represented as a spacetime event in an (N+1)-dimensional
11/// Lorentzian manifold (1 time axis + N price axes). The module provides:
12///
13/// - `AssetEvent` — A single market observation for one asset.
14/// - `MinkowskiCovariance` — Accumulates N asset events and computes an
15/// NxN spacetime-interval covariance matrix.
16/// - `SpacetimeCausalGraph` — Directed graph where edge (i→j) exists iff
17/// asset_i is TIMELIKE-separated from asset_j.
18///
19/// ## Physical Interpretation
20/// Two assets are TIMELIKE-separated when their spacetime interval
21/// ds²(i,j) = −c²·Δt² + ΔP² + ΔV² + ΔM² < 0
22/// meaning asset_i "precedes" asset_j causally inside the market light cone.
23/// The hypothesis is that causal (TIMELIKE) pairs exhibit positive lead-lag
24/// correlation — asset_i's move CAUSES a future move in asset_j.
25///
26/// ## Guarantees
27/// - All fallible operations return std::optional.
28/// - No raw pointers; Eigen3 owns all matrix storage.
29/// - Thread-safe reads: const methods are safe for concurrent access.
30///
31/// ## Dependencies
32/// - Eigen3 (matrix arithmetic)
33/// - srfm/manifold/n_asset_interval.hpp (NAssetEvent, IntervalType)
34/// - srfm/tensor/n_asset_manifold.hpp (NAssetManifold metric)
35
38#include "srfm/constants.hpp"
39
40#include <Eigen/Dense>
41#include <optional>
42#include <string>
43#include <vector>
44
45namespace srfm::portfolio {
46
47// ─── AssetEvent ───────────────────────────────────────────────────────────────
48
49/// A single market observation for one identified asset.
50///
51/// Embeds the observation as a 4-vector in financial spacetime:
52/// [t, P, V, M] (time, price, volume, market_cap)
53struct AssetEvent {
54 std::string asset_id; ///< Ticker or unique identifier for this asset
55 double t; ///< Market time coordinate (bar index or epoch seconds)
56 double P; ///< Price coordinate (spatial axis 1)
57 double V; ///< Volume coordinate (spatial axis 2)
58 double M; ///< Market-cap coordinate (spatial axis 3)
59
60 /// Convert to a 4-vector [t, P, V, M] compatible with the 4D manifold.
61 [[nodiscard]] Eigen::Vector4d to_four_vector() const noexcept;
62
63 /// Convert to an NAssetEvent with a single price coordinate (for use with
64 /// manifold::NAssetInterval when operating in 1-asset mode).
65 [[nodiscard]] manifold::NAssetEvent to_nasset_event() const noexcept;
66};
67
68// ─── MinkowskiCovariance ──────────────────────────────────────────────────────
69
70/// Accumulates a set of AssetEvents and computes an NxN covariance matrix
71/// whose (i,j) entry is derived from the spacetime interval between asset i
72/// and asset j.
73///
74/// ## Algorithm
75/// For each ordered pair (i, j):
76/// ds²(i,j) = −c²·Δt² + ΔP² + ΔV² + ΔM²
77/// where Δx = event_j − event_i in each coordinate.
78///
79/// The covariance entry C(i,j) is defined as:
80/// C(i,j) = exp(−|ds²(i,j)|) (Gaussian kernel over interval)
81///
82/// This maps:
83/// - TIMELIKE pairs (ds² ≪ 0) → near 0 (strongly causal, large |ds²|)
84/// - LIGHTLIKE pairs (ds² ≈ 0) → 1.0 (maximally correlated at light cone)
85/// - SPACELIKE pairs (ds² ≫ 0) → near 0 (stochastic, acausal)
86///
87/// The diagonal is set to 1.0 (each asset is perfectly correlated with itself).
88///
89/// ## Usage
90/// ```cpp
91/// MinkowskiCovariance mc;
92/// mc.add_asset(AssetEvent{"AAPL", 1.0, 150.0, 1e8, 2.4e12});
93/// mc.add_asset(AssetEvent{"MSFT", 1.0, 290.0, 8e7, 2.1e12});
94/// auto cov = mc.compute_spacetime_covariance();
95/// // cov is a 2x2 Eigen::MatrixXd
96/// ```
98public:
99 /// Construct with optional speed-of-information parameter.
100 ///
101 /// @param c_market Speed-of-information constant (default: 1.0).
102 explicit MinkowskiCovariance(double c_market =
104
105 /// Add an asset event to the manifold.
106 ///
107 /// Events are stored in insertion order. The i-th added event becomes
108 /// row/column i of the output covariance matrix.
109 ///
110 /// @param event Asset event to add.
111 void add_asset(AssetEvent event);
112
113 /// Return the number of asset events currently stored.
114 [[nodiscard]] std::size_t size() const noexcept;
115
116 /// Compute the NxN Minkowski covariance matrix.
117 ///
118 /// Requires at least 2 assets; returns nullopt if fewer are stored.
119 ///
120 /// @return NxN Eigen::MatrixXd where N = size(), or nullopt on failure.
121 [[nodiscard]] std::optional<Eigen::MatrixXd>
122 compute_spacetime_covariance() const noexcept;
123
124 /// Compute the raw spacetime interval ds²(i, j) between asset pair (i, j).
125 ///
126 /// @param i Index of first asset (0-based).
127 /// @param j Index of second asset (0-based).
128 /// @return ds²(i, j), or nullopt if indices are out of range.
129 [[nodiscard]] std::optional<double>
130 interval_correlation(std::size_t i, std::size_t j) const noexcept;
131
132 /// Classify the spacetime interval between asset pair (i, j).
133 ///
134 /// @param i Index of first asset (0-based).
135 /// @param j Index of second asset (0-based).
136 /// @return IntervalType (TIMELIKE / LIGHTLIKE / SPACELIKE), or nullopt
137 /// if indices are out of range.
138 [[nodiscard]] std::optional<manifold::IntervalType>
139 classify_pair(std::size_t i, std::size_t j) const noexcept;
140
141 /// Read-only access to the stored asset events.
142 [[nodiscard]] const std::vector<AssetEvent>& events() const noexcept;
143
144 /// Clear all stored events.
145 void clear() noexcept;
146
147private:
148 /// Compute ds²(i, j) from raw asset events.
149 [[nodiscard]] double raw_interval(std::size_t i,
150 std::size_t j) const noexcept;
151
152 std::vector<AssetEvent> events_;
153 double c_market_;
154};
155
156// ─── SpacetimeCausalGraph ─────────────────────────────────────────────────────
157
158/// Directed causal graph over a set of asset events.
159///
160/// An edge (i → j) is added when asset_i is TIMELIKE-separated from asset_j:
161/// ds²(i, j) < −LIGHTLIKE_THRESHOLD
162///
163/// Under the "causal influence hypothesis", a TIMELIKE edge means asset_i's
164/// price dynamics causally precede and may predict asset_j's dynamics.
165///
166/// ## Representation
167/// The adjacency matrix A is an NxN boolean matrix (stored as Eigen::MatrixXi):
168/// A(i, j) = 1 iff ds²(i, j) < −LIGHTLIKE_THRESHOLD
169/// A(i, i) = 0 (no self-loops)
170///
171/// ## Usage
172/// ```cpp
173/// MinkowskiCovariance mc;
174/// mc.add_asset(AssetEvent{"AAPL", 0.0, 150.0, 1e8, 2.4e12});
175/// mc.add_asset(AssetEvent{"MSFT", 1.0, 290.0, 8e7, 2.1e12});
176/// auto graph = SpacetimeCausalGraph::build(mc);
177/// if (graph) {
178/// auto adj = graph->adjacency_matrix();
179/// // adj(0,1) == 1 means AAPL causally precedes MSFT
180/// }
181/// ```
183public:
184 /// Build the causal graph from a MinkowskiCovariance instance.
185 ///
186 /// Requires at least 2 asset events. Returns nullopt if fewer are available.
187 ///
188 /// @param mc MinkowskiCovariance with N >= 2 stored events.
189 /// @return SpacetimeCausalGraph, or nullopt on failure.
190 [[nodiscard]] static std::optional<SpacetimeCausalGraph>
191 build(const MinkowskiCovariance& mc) noexcept;
192
193 /// Return the NxN adjacency matrix.
194 /// A(i,j) = 1 means edge (i→j) exists (asset_i TIMELIKE before asset_j).
195 [[nodiscard]] const Eigen::MatrixXi& adjacency_matrix() const noexcept;
196
197 /// Return true iff an edge (i → j) exists.
198 ///
199 /// @param i Source asset index (0-based).
200 /// @param j Destination asset index (0-based).
201 [[nodiscard]] bool has_edge(std::size_t i, std::size_t j) const noexcept;
202
203 /// Return the number of assets (graph nodes).
204 [[nodiscard]] std::size_t n_assets() const noexcept;
205
206 /// Return the out-degree of node i (number of assets that i causally precedes).
207 [[nodiscard]] int out_degree(std::size_t i) const noexcept;
208
209 /// Return the in-degree of node j (number of assets that causally precede j).
210 [[nodiscard]] int in_degree(std::size_t j) const noexcept;
211
212 /// Return asset IDs in the order they were added.
213 [[nodiscard]] const std::vector<std::string>& asset_ids() const noexcept;
214
215private:
216 explicit SpacetimeCausalGraph(Eigen::MatrixXi adjacency,
217 std::vector<std::string> ids) noexcept;
218
219 Eigen::MatrixXi adj_; ///< NxN adjacency matrix
220 std::vector<std::string> asset_ids_; ///< Asset identifiers in index order
221};
222
223} // namespace srfm::portfolio
Physical and financial constants for the SRFM system.
Spacetime interval computations for N-asset events.
N-Asset Lorentzian Manifold for Special Relativistic Financial Mechanics.
static constexpr double SPEED_OF_INFORMATION
Definition constants.hpp:37
Eigen::Vector4d to_four_vector() const noexcept
Convert to a 4-vector [t, P, V, M] compatible with the 4D manifold.
manifold::NAssetEvent to_nasset_event() const noexcept
std::string asset_id
Ticker or unique identifier for this asset.
double M
Market-cap coordinate (spatial axis 3)
double P
Price coordinate (spatial axis 1)
double V
Volume coordinate (spatial axis 2)
double t
Market time coordinate (bar index or epoch seconds)