8#include "../../include/srfm/tensor/n_asset_manifold.hpp"
18 Eigen::MatrixXd covariance,
19 double c_market) noexcept
22 , covariance_(std::move(covariance))
26 build_inverse_metric();
31std::optional<NAssetManifold>
39 if (c_market <= 0.0) {
44 if (cov.rows() != n || cov.cols() != n) {
49 const double sym_tol = 1e-10;
50 for (
int i = 0; i < n; ++i) {
51 for (
int j = 0; j < n; ++j) {
52 if (std::abs(cov(i, j) - cov(j, i)) > sym_tol) {
59 Eigen::MatrixXd cov_sym = 0.5 * (cov + cov.transpose());
62 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov_sym,
63 Eigen::EigenvaluesOnly);
64 if (eig.info() != Eigen::Success) {
67 if (eig.eigenvalues().minCoeff() <= 0.0) {
76void NAssetManifold::build_metric() noexcept {
77 const int D = n_assets_ + 1;
78 metric_ = Eigen::MatrixXd::Zero(D, D);
81 metric_(0, 0) = -(c_market_ * c_market_);
84 if (covariance_.rows() == n_assets_ && covariance_.cols() == n_assets_) {
85 metric_.block(1, 1, n_assets_, n_assets_) = covariance_;
90void NAssetManifold::build_inverse_metric() noexcept {
91 const int D = n_assets_ + 1;
94 Eigen::FullPivLU<Eigen::MatrixXd> lu(metric_);
95 if (!lu.isInvertible()) {
96 inv_metric_ = Eigen::MatrixXd::Zero(D, D);
101 inv_metric_ = lu.inverse();
107std::optional<Eigen::MatrixXd>
109 if (x.size() != dim()) {
116std::optional<Eigen::MatrixXd>
118 if (x.size() != dim()) {
131 const Eigen::VectorXd& dx)
const noexcept {
132 if (x.size() != dim() || dx.size() != dim()) {
136 return dx.dot(metric_ * dx);
147 if (other.n_assets() != 3) {
151 return n_assets_ >= 3;
(N+1)-dimensional Lorentzian manifold for N financial assets.
std::optional< Eigen::MatrixXd > covariance() const noexcept
Returns the covariance matrix used to build the metric.
std::optional< Eigen::MatrixXd > inverse_metric_at(const Eigen::VectorXd &x) const noexcept
Evaluate the inverse metric g^μν at point x.
std::optional< Eigen::MatrixXd > metric_at(const Eigen::VectorXd &x) const noexcept
Evaluate the metric tensor at point x.
std::optional< double > line_element_sq(const Eigen::VectorXd &x, const Eigen::VectorXd &dx) const noexcept
Compute the squared line element ds² = g_μν dx^μ dx^ν.
static std::optional< NAssetManifold > make(int n, Eigen::MatrixXd cov, double c_market=1.0) noexcept
Factory: validate inputs then construct.
bool reduces_to_4d(const NAssetManifold &other) const noexcept
Check structural compatibility with a 4D (N=3) manifold.
NAssetManifold(int n_assets, Eigen::MatrixXd covariance, double c_market=1.0) noexcept
Construct an NAssetManifold directly.