30 return config_.include_lightlike;
37std::vector<CausalHistory>
39 std::span<const core::OHLCV> bars,
40 std::span<const manifold::SpacetimeEvent> events
42 const std::size_t N = bars.size();
43 assert(events.size() == N &&
"bars and events must have the same size");
45 std::vector<CausalHistory> histories;
48 for (std::size_t i = 0; i < N; ++i) {
53 const std::size_t look_start = (i >= config_.look_back)
54 ? (i - config_.look_back)
57 for (std::size_t j = look_start; j < i; ++j) {
62 events[j], events[i], config_.c_market
64 if (!ds2.has_value())
continue;
68 if (is_causal(interval_type)) {
73 if (config_.verbose) {
75 "[causal_cone] bar={} prev={} ds2={:.4f} type={}\n",
81 histories.push_back(std::move(h));
86std::optional<CausalSignal>
89 std::span<const double> returns,
92 const auto& preds = history.predecessor_indices;
93 if (preds.empty())
return std::nullopt;
94 if (bar_idx >= returns.size())
return std::nullopt;
97 std::vector<double> causal_rets;
98 causal_rets.reserve(preds.size());
99 for (std::size_t idx : preds) {
100 if (idx < returns.size()) {
101 causal_rets.push_back(returns[idx]);
104 if (causal_rets.empty())
return std::nullopt;
108 for (
double r : causal_rets) sum += r;
109 const double mean = sum /
static_cast<double>(causal_rets.size());
113 for (
double r : causal_rets) var += (r - mean) * (r - mean);
114 const double vol = (causal_rets.size() > 1)
115 ? std::sqrt(var /
static_cast<double>(causal_rets.size() - 1))
119 double momentum = 0.0;
120 double weight_sum = 0.0;
121 for (std::size_t k = 0; k < causal_rets.size(); ++k) {
122 double w =
static_cast<double>(k + 1);
123 momentum += w * causal_rets[k];
126 if (weight_sum > 0.0) momentum /= weight_sum;
129 const std::size_t look_start = (bar_idx >= config_.look_back)
130 ? (bar_idx - config_.look_back)
132 double all_sum = 0.0;
133 std::size_t all_count = 0;
134 for (std::size_t k = look_start; k < bar_idx && k < returns.size(); ++k) {
135 all_sum += returns[k];
138 const double all_mean = (all_count > 0) ? (all_sum / all_count) : 0.0;
147 sig.
n_total = history.total_bars_scanned;
156 "CausalSharpe={:.4f} BaselineSharpe={:.4f} "
157 "SharpeImprovement={:+.4f} | "
158 "CausalSortino={:.4f} BaselineSortino={:.4f} | "
159 "MeanCausalFraction={:.1%}",
175 : filter_(filter_cfg)
176 , engine_(engine_cfg)
179std::optional<CausalBacktestResult>
181 const std::size_t N = bars.size();
182 const std::size_t min_bars = filter_.look_back() + 30;
183 if (N < min_bars)
return std::nullopt;
190 std::vector<core::PipelineBar> pipeline_bars;
191 pipeline_bars.reserve(N);
195 for (
auto& bar : bars) {
197 if (pb) pipeline_bars.push_back(*pb);
201 if (pipeline_bars.size() < min_bars)
return std::nullopt;
204 std::vector<manifold::SpacetimeEvent> events;
205 events.reserve(pipeline_bars.size());
206 for (
const auto& pb : pipeline_bars) events.push_back(pb.event);
210 const std::size_t offset = N - pipeline_bars.size();
211 std::span<const core::OHLCV> aligned_bars = bars.subspan(offset);
214 auto histories = filter_.build_histories(aligned_bars, events);
215 const std::size_t M = histories.size();
218 std::vector<double> returns;
220 for (
const auto& pb : pipeline_bars) returns.push_back(pb.price_return);
223 std::vector<backtest::BarData> causal_data;
224 std::vector<backtest::BarData> baseline_data;
225 causal_data.reserve(M);
226 baseline_data.reserve(M);
228 double total_causal_fraction = 0.0;
229 std::size_t signal_count = 0;
231 for (std::size_t i = 0; i < M; ++i) {
232 const auto& pb = pipeline_bars[i];
233 auto sig = filter_.compute_signal(histories[i], returns, i);
235 double causal_signal = sig ? sig->causal_momentum : 0.0;
236 double baseline_signal = sig ? sig->all_bars_mean_return : pb.price_return;
238 causal_data.push_back({
239 .raw_signal = causal_signal,
241 .benchmark = pb.price_return,
243 baseline_data.push_back({
244 .raw_signal = baseline_signal,
246 .benchmark = pb.price_return,
250 total_causal_fraction += sig->causal_fraction;
257 auto causal_result = bt.
run(causal_data, returns);
258 auto baseline_result = bt.
run(baseline_data, returns);
260 if (!causal_result || !baseline_result)
return std::nullopt;
266 ? (total_causal_fraction / signal_count)
Causal Cone Filter — light-cone analogue for financial time series.
std::optional< BacktestComparison > run(std::span< const BarData > bars, std::span< const double > asset_returns) const noexcept
CausalBacktest(CausalConeFilter::Config filter_cfg=CausalConeFilter::Config{}, core::EngineConfig engine_cfg=core::EngineConfig{}) noexcept
Construct with optional filter and engine configs.
std::optional< CausalBacktestResult > run(std::span< const core::OHLCV > bars) const noexcept
std::vector< CausalHistory > build_histories(std::span< const core::OHLCV > bars, std::span< const manifold::SpacetimeEvent > events) const noexcept
std::optional< CausalSignal > compute_signal(const CausalHistory &history, std::span< const double > returns, std::size_t bar_idx) const noexcept
CausalConeFilter(Config config=Config{}) noexcept
Construct with an optional configuration.
Orchestrates the full relativistic signal-processing pipeline.
std::optional< PipelineBar > process_stream_bar(const OHLCV &bar) noexcept
static IntervalType classify(double interval_squared) noexcept
static std::optional< double > compute(const SpacetimeEvent &a, const SpacetimeEvent &b, double c_market=constants::SPEED_OF_INFORMATION) noexcept
Physical and financial constants for the SRFM system.
Spacetime Market Manifold — AGT-02 public API (implemented by AGT-06).
const char * to_string(IntervalType t) noexcept
Convert IntervalType to a human-readable string.
IntervalType
Causal character of a spacetime interval.
@ Timelike
ds² < 0 — causal market movement (β < c)
@ Spacelike
ds² > 0 — stochastic regime (no causal link)
@ Lightlike
ds² ≈ 0 — information propagation at c
CoordinateNormalizer — rolling z-score normalizer for SpacetimeEvent.
Comparison of CausalSignal-based strategy vs all-bars baseline strategy.
backtest::PerformanceMetrics baseline_metrics
Performance of the all-bars baseline strategy.
double sharpe_improvement() const noexcept
Improvement in Sharpe ratio: causal − baseline.
double mean_causal_fraction
Mean fraction of bars that were causal across the full dataset.
backtest::PerformanceMetrics causal_metrics
Performance of the causal-only signal strategy.
std::string to_string() const
Format a one-line human-readable summary.
Configuration for the causal cone filter.
std::vector< std::size_t > predecessor_indices
Indices into the original bar array for each causal predecessor.
std::size_t total_bars_scanned
Number of bars scanned (including SPACELIKE/excluded ones).
manifold::SpacetimeEvent event
The current bar (the "effect" event).
std::vector< manifold::SpacetimeEvent > causal_predecessors
std::size_t n_causal
Number of causal predecessor bars used.
std::size_t n_total
Total bars in the look-back window.
double causal_fraction
Fraction of bars that are causal.
double causal_mean_return
Mean return, causal bars only.
double causal_momentum
Weighted momentum from causal bars.
double causal_vol
Volatility of causal bar returns.
double all_bars_mean_return
Baseline: mean over ALL look-back bars.
Configuration parameters for the core engine.