The snapshot illusion: Why modern financial databases deceive backtests

In quantitative research, the integrity of a backtest relies entirely on historical causality. Every simulated decision at timestamp t must be strictly conditioned on information that was released and accessible to market participants on or before t. Yet, in the majority of quantitative backtests that incorporate fundamental or macroeconomic data, this foundational principle is violated.

The root cause lies in how standard financial databases store historical records. Traditional relational database schemas represent the current state of knowledge. When a company restates its prior-year earnings, files an amended SEC Form 10-K/A, or when the Bureau of Economic Analysis (BEA) updates historical GDP figures, standard database pipelines execute an in-place mutation:

Code
UPDATE income_statements 
SET net_income = 85000000 
WHERE ticker = 'ACME' AND period_end = '2023-09-30';

This single SQL update irrevocably destroys historical reality. If a backtest running in 2026 evaluates a trading signal executed on December 1, 2023, querying this table returns the restated $85M figure—even though that restatement was not discovered, audited, or filed until late 2024. In real life, on December 1, 2023, the only number visible to traders was the preliminary $125M print released in the original Form 10-Q.

This phenomenon is a insidious variant of Lookahead Bias in Backtesting. While indicator lookahead errors (such as forgetting a .shift(1) on a price moving average) are easily discovered through code review, database snapshot contamination operates invisibly. The backtest code appears mathematically sound, yet the simulation draws on future information that zero market participants possessed.

The solution to this vulnerability is point in time data (PIT). Point-in-time data is an information architecture where every historical record is tracked by both the accounting period it describes and the exact chronological instant it became known to the market. Without point in time data, backtests systematically overestimate strategy performance, filter out accounting frauds in hindsight, and generate phantom alpha that evaporates upon live capital deployment.


The triad of timestamps: Period end, publication date, and revision date

To model point-in-time data correctly, researchers must differentiate three distinct temporal coordinates for every fundamental and macroeconomic metric:

Code
Timeline of Fundamental Disclosure:
--------------------------------------------------------------------------------------
Event Interval       | Filing Delay (Δt_pub)       | Discovery / Audit Lag (Δt_rev)
[Period Start ───> Period End] ───> [Preliminary Release] ───> [Restatement Filed]
     2023-07-01     2023-09-30          2023-11-09                  2024-04-12
     (Q3 Begins)    (Q3 Closes)         (Form 10-Q filed)           (Form 10-K/A filed)
                         ▲                       ▲                           ▲
                         │                       │                           │
                    period_end            publication_date             revision_date
                 (Economic Reality)       (Market Knowledge)       (Subsequent Truth)

1. Reporting period end (period_end)

The period end timestamp represents the closing date of the accounting or statistical period (e.g., 2023-09-30 for Q3, or 2023-12-31 for fiscal year 2023). This timestamp defines the temporal window of economic activity. It has no physical relation to when that activity was measured, compiled, or published.

2. Publication timestamp (publication_date)

The publication timestamp represents the exact microsecond when the market received the preliminary figures. For public US equities, this corresponds to the SEC EDGAR system acceptance timestamp (e.g., 2023-11-09 17:05:00 UTC). For macroeconomic series such as US Non-Farm Payrolls or the Consumer Price Index (CPI), it represents the official Bureau of Labor Statistics (BLS) press release timestamp (e.g., 08:30:00 EST).

The temporal gap between period end and publication date is the filing delay:

Code
Δt_pub = publication_date - period_end

In equity markets, Δt_pub spans 15 to 45 calendar days for domestic 10-Q quarterly reports, up to 90 days for international annual filings (such as 20-F reports), and up to 120 days for small-cap issuers. If a backtest indexes corporate earnings by period_end, the simulation peeks 15 to 90 days into the future on every single quarterly rebalance.

3. Subsequent restatements (revision_date)

Financial metrics are not static. Companies routinely amend filings to rectify revenue recognition errors, adjust tax liabilities, or restate stock-based compensation. Similarly, macroeconomic agencies publish preliminary, revised, and annual benchmark figures.

The revision date (revision_date) marks the timestamp when a restatement supersedes previous records. A backtesting engine simulating a decision on date t must discard any revisions published at t_rev > t.

Mathematical filtration and causality

In stochastic calculus, market information is formalized as a filtration (F_t)_{t >= 0}, representing an increasing family of sigma-algebras where F_t contains all events observable up to time t. A trading action or portfolio weight vector A_t is causal if and only if:

Code
A_t is measurable with respect to F_t (A_t ∈ F_t)

Let X denote an economic variable describing the performance interval [T_0, T_period_end]. The variable X has publication timestamp t_pub and subsequent revision timestamp t_rev. The true knowledge filtration is governed by publication time, not event time:

Code
X_preliminary ∈ F_t  <=>  t >= t_pub
X_revised     ∈ F_t  <=>  t >= t_rev

If a backtest evaluates A_t at time t where t_period_end <= t < t_pub using X_preliminary, or at t_pub <= t < t_rev using X_revised, the decision violates causality:

Code
A_t ∈ F_{t + Δ}  where Δ > 0  (FATAL LOOKAHEAD BIAS)

Bi-temporal data architecture: Valid time vs. transaction time

Solving the snapshot illusion requires a database model built specifically for historical auditing. In database theory, this is implemented through bi-temporal modeling (formalized by Richard Snodgrass and standardized in ISO/IEC 9075:2011).

A bi-temporal system tracks two independent, orthogonal time dimensions for every assertion:

Code
                         Bi-Temporal Coordinate System
       ▲
       │  (Transaction Time / System Time: When the system learned the fact)
       │
2024-04│                             ┌──────────────────────────────┐
       │                             │ Record B: EPS = $0.75        │
       │                             │ (Valid: 2023-Q3, Sys: >=04/24)│
       │  ┌──────────────────────────┴───┐                          │
2023-11│  │ Record A: EPS = $1.25        │                          │
       │  │ (Valid: 2023-Q3, Sys: [11/23, 04/24))                   │
       │  └──────────────────────────────┘                          │
       │                                                            │
───────┼────────────────────────────────────────────────────────────┼────►
       │                      2023-09-30                            │ (Valid Time /
       │                      (Period End)                          │  Business Time)
  1. Valid Time (Business Time): The interval during which the statement was true in the real-world economy. For Q3 2023 fundamentals, the valid time interval is [2023-07-01, 2023-09-30].
  2. Transaction Time (System Time / Knowledge Time): The interval during which the record was stored in the database as current belief: [system_from, system_to).

When an amendment or restatement occurs, the existing record is never overwritten or mutated. Instead, its system_to timestamp is closed out (set to the revision publication timestamp), and a new record is inserted with system_from = revision_timestamp and system_to = infinity.

Evolution of a bi-temporal fundamental record

Consider how ACME Cloud Systems' Q3 2023 EPS evolves across physical time inside a bi-temporal store:

Record IDTickerMetricPeriod End (Valid Time)ValuePublished At (system_from)Superseded At (system_to)Filing Type
REC-101ACMEEPS2023-09-30$1.252023-11-09 17:00 UTC2024-04-12 17:00 UTCForm 10-Q (Original)
REC-102ACMEEPS2023-09-30$0.752024-04-12 17:00 UTCNULL (Active)Form 10-K/A (Restatement)

When an algorithm runs an as-of query at simulation date T_sim = 2024-01-15:

Code
Query Predicate:
  published_at <= '2024-01-15' 
  AND (superseded_at > '2024-01-15' OR superseded_at IS NULL)

The database returns REC-101 (EPS = $1.25), perfectly reflecting what portfolio managers saw on January 15, 2024. If the simulation advances to T_sim = 2024-05-01, the query returns REC-102 (EPS = $0.75). At no point does future auditing knowledge leak backward into past simulation ticks.


Valuation metric distortion: How revised data warps P/E and EV/EBITDA

The quantitative implications of ignoring point-in-time data are severe. Valuation ratios—such as Price-to-Earnings (P/E), Price-to-Book (P/B), and Enterprise Value to EBITDA (EV/EBITDA)—combine daily market pricing with quarterly fundamental disclosures.

Code
P/E_t = Price_t / EPS_TTM(t)

EV/EBITDA_t = (MarketCap_t + TotalDebt_t - Cash_t) / EBITDA_TTM(t)

Market prices update tick-by-tick and are strictly causal. But when EPS_TTM(t) is extracted from a modern restated snapshot, the denominator is infected with future information.

The asymmetry of corporate restatements

Empirical accounting literature reveals that corporate restatements are overwhelmingly negative: over 70% of SEC accounting restatements result in downward revisions to previously reported net income and revenue, or upward adjustments to liabilities.

When a backtest runs against restated modern snapshots:

  1. Artificial Outperformance of Distressed Stocks: In 2023, a troubled firm reported strong preliminary earnings (EPS = $1.25), trading at $38.00 (P/E = 9.5x). The market perceived it as a deep-value opportunity. In 2024, an SEC investigation forced a restatement down to $0.75 (real P/E was 15.8x). A naive backtest running modern data evaluates the 2023 trade with the revised $0.75 number, ranks the stock as expensive or deteriorative, and avoids buying it. In live trading, the algorithm would have purchased the stock and suffered the subsequent drawdown.
  2. Ghost Value Traps: Conversely, when positive restatements occur (or when accounting write-offs are shifted between fiscal quarters), historical valuation ranks shuffle retrospectively. Strategies that rank equities into deciles (e.g., top 10% cheapest EV/EBITDA) select a completely synthetic universe that did not exist during the historical trading session.

Comparison: Point-in-time vs. naive snapshot methods

Evaluation DimensionNaive Modern SnapshotLagged Static SnapshotPoint-in-Time Engine
Publication DelayPeeks 15 to 90 days into futureFixed lag applied (e.g., +45 days)Exact timestamp match
Restatement HandlingLeaks future restatements backwardsLeaks future restatements backwardsCausally isolated at revision time
Storage ArchitectureSingle mutated row per entitySingle mutated row with lag offsetsImmutable bi-temporal append log
Query ComplexityFast, simple SQL selectModerate, date math arithmeticBi-temporal interval filtering
Factor Rank IntegritySevere rank correlation breakdownModerate bias100% causal rank fidelity
Audit ReproducibilityZero (results change every year)Poor (changes with each database pull)Absolute (deterministic trial replay)

Hands-on Python: Implementing an As-Of query engine for point-in-time data

To see the divergence in concrete numbers, let us build a production-grade, typed point-in-time query engine in Python. This engine tracks corporate disclosures with bi-temporal intervals, evaluates Trailing Twelve Months (TTM) fundamental metrics, and compares Point-in-Time P/E against a naive modern snapshot.

point_in_time_engine.py
from dataclasses import dataclass
from datetime import date, datetime
from typing import List, Optional
import pandas as pd


@dataclass(frozen=True)
class FundamentalRecord:
    """Represents an immutable fundamental record with bi-temporal validity."""
    ticker: str
    metric: str
    period_end: date
    value: float
    published_at: datetime
    superseded_at: Optional[datetime] = None


class PointInTimeStore:
    """Bi-temporal fundamental store supporting deterministic as-of queries."""

    def __init__(self) -> None:
        self._records: List[FundamentalRecord] = []

    def insert(self, record: FundamentalRecord) -> None:
        self._records.append(record)

    def query_as_of(
        self,
        ticker: str,
        metric: str,
        as_of_timestamp: datetime,
    ) -> pd.DataFrame:
        """Query metrics strictly known to the market as of the given timestamp."""
        matched = [
            {
                "ticker": r.ticker,
                "metric": r.metric,
                "period_end": r.period_end,
                "value": r.value,
                "published_at": r.published_at,
                "superseded_at": r.superseded_at,
            }
            for r in self._records
            if r.ticker == ticker
            and r.metric == metric
            and r.published_at <= as_of_timestamp
            and (r.superseded_at is None or r.superseded_at > as_of_timestamp)
        ]
        if not matched:
            return pd.DataFrame(
                columns=["ticker", "metric", "period_end", "value", "published_at", "superseded_at"]
            )
        df = pd.DataFrame(matched)
        return df.sort_values("period_end").reset_index(drop=True)

    def get_ttm_sum(
        self,
        ticker: str,
        metric: str,
        as_of_timestamp: datetime,
        required_periods: int = 4,
    ) -> Optional[float]:
        """Compute the Trailing Twelve Months (TTM) sum of the last N available quarters."""
        df = self.query_as_of(ticker, metric, as_of_timestamp)
        if len(df) < required_periods:
            return None
        return float(df.tail(required_periods)["value"].sum())


# ----------------------------------------------------------------------
# Demonstration: Simulating ACME Corp SEC Reporting History
# ----------------------------------------------------------------------
engine = PointInTimeStore()

# Q4 2022: Filed 2023-02-24 after market close (17:00 UTC)
engine.insert(
    FundamentalRecord("ACME", "EPS", date(2022, 12, 31), 0.80, datetime(2023, 2, 24, 17, 0))
)

# Q1 2023: Filed 2023-05-09 after market close
engine.insert(
    FundamentalRecord("ACME", "EPS", date(2023, 3, 31), 0.90, datetime(2023, 5, 9, 17, 0))
)

# Q2 2023: Filed 2023-08-10 after market close
engine.insert(
    FundamentalRecord("ACME", "EPS", date(2023, 6, 30), 1.05, datetime(2023, 8, 10, 17, 0))
)

# Q3 2023:
# Initially reported $1.25 on 2023-11-09.
# Restated down to $0.75 on 2024-04-12 via Form 10-K/A due to revenue deferral.
engine.insert(
    FundamentalRecord(
        "ACME", "EPS", date(2023, 9, 30), 1.25,
        datetime(2023, 11, 9, 17, 0), datetime(2024, 4, 12, 17, 0)
    )
)
engine.insert(
    FundamentalRecord(
        "ACME", "EPS", date(2023, 9, 30), 0.75,
        datetime(2024, 4, 12, 17, 0), None
    )
)

# Q4 2023:
# Initially reported $1.30 on 2024-02-27.
# Restated down to $0.95 on 2024-08-15 via Form 10-Q/A.
engine.insert(
    FundamentalRecord(
        "ACME", "EPS", date(2023, 12, 31), 1.30,
        datetime(2024, 2, 27, 17, 0), datetime(2024, 8, 15, 17, 0)
    )
)
engine.insert(
    FundamentalRecord(
        "ACME", "EPS", date(2023, 12, 31), 0.95,
        datetime(2024, 8, 15, 17, 0), None
    )
)

# Conventional modern snapshot (what an external REST API returns today)
snapshot_data = {
    date(2022, 12, 31): 0.80,
    date(2023, 3, 31): 0.90,
    date(2023, 6, 30): 1.05,
    date(2023, 9, 30): 0.75,   # Restated modern value
    date(2023, 12, 31): 0.95,  # Restated modern value
}

# Historical simulation check dates and closing prices
checkpoints = [
    ("2023-11-15 16:00", datetime(2023, 11, 15, 16, 0), 38.00),
    ("2024-01-15 16:00", datetime(2024, 1, 15, 16, 0), 40.00),
    ("2024-03-05 16:00", datetime(2024, 3, 5, 16, 0), 42.00),
    ("2024-05-10 16:00", datetime(2024, 5, 10, 16, 0), 33.00),
    ("2024-09-01 16:00", datetime(2024, 9, 1, 16, 0), 28.00),
]

comparison_rows = []
for label, ts, price in checkpoints:
    # 1. Point-in-Time TTM EPS
    pit_ttm = engine.get_ttm_sum("ACME", "EPS", ts, required_periods=4)
    pit_pe = price / pit_ttm if pit_ttm else None

    # 2. Naive Snapshot: matches records where period_end <= current date
    # Notice this also leaks Q4 2023 on 2024-01-15 because period_end (2023-12-31) <= 2024-01-15!
    naive_available = [v for p_end, v in snapshot_data.items() if p_end <= ts.date()]
    naive_ttm = sum(naive_available[-4:]) if len(naive_available) >= 4 else None
    naive_pe = price / naive_ttm if naive_ttm else None

    pe_delta = (naive_pe - pit_pe) if (naive_pe and pit_pe) else 0.0

    comparison_rows.append({
        "Sim Timestamp": label,
        "Price": f"${price:.2f}",
        "PIT TTM": f"${pit_ttm:.2f}" if pit_ttm else "N/A",
        "PIT P/E": f"{pit_pe:.2f}" if pit_pe else "N/A",
        "Naive TTM": f"${naive_ttm:.2f}" if naive_ttm else "N/A",
        "Naive P/E": f"{naive_pe:.2f}" if naive_pe else "N/A",
        "P/E Distortion": f"{pe_delta:+.2f}",
    })

comparison_df = pd.DataFrame(comparison_rows)
print(comparison_df.to_string(index=False))

Execution output and analysis

Executing the above script yields the following empirical comparison:

Code
   Sim Timestamp  Price PIT TTM PIT P/E Naive TTM Naive P/E P/E Distortion
2023-11-15 16:00 $38.00   $4.00    9.50     $3.50     10.86          +1.36
2024-01-15 16:00 $40.00   $4.00   10.00     $3.65     10.96          +0.96
2024-03-05 16:00 $42.00   $4.50    9.33     $3.65     11.51          +2.18
2024-05-10 16:00 $33.00   $4.00    8.25     $3.65      9.04          +0.79
2024-09-01 16:00 $28.00   $3.65    7.67     $3.65      7.67          +0.00

Notice the critical discrepancies exposed by this comparison:

  1. The Double Failure on 2024-01-15: On January 15, 2024, the naive engine commits two simultaneous errors. First, it accesses Q4 2023 figures because period_end = 2023-12-31 is prior to the simulation date—completely oblivious to the fact that Q4 earnings were not released until late February (a 43-day lookahead breach). Second, it evaluates Q3 using the restated $0.75 figure instead of the $1.25 number the market traded on.
  2. Valuation Multiple Inversion on 2024-03-05: Following the genuine release of Q4 earnings on February 27, the real market had a trailing TTM EPS of $4.50 (0.90 + 1.05 + 1.25 + 1.30). With the stock at $42.00, the real Point-in-Time P/E was 9.33x. The naive snapshot reported a P/E of 11.51x—a massive +23.3% distortion. A quantitative value rule requiring P/E &lt; 10.0 would have executed an entry in real life, but was skipped entirely in the flawed backtest.

Disentangling PIT architecture from merge_asof and survivorship bias

In quantitative trading discussions, developers frequently conflate three related but fundamentally distinct concepts: Point-in-Time data architecture, pandas.merge_asof, and survivorship bias. Disentangling these mechanisms is essential for designing robust research pipelines.

Code
┌────────────────────────────────────────────────────────────────────────┐
│                        Data Pipeline Taxonomies                        │
├─────────────────────────┬──────────────────────────────────────────────┤
│ Concept                 │ Operational Domain                           │
├─────────────────────────┼──────────────────────────────────────────────┤
│ 1. Point-in-Time Data   │ Knowledge State: What facts were known about │
│    Architecture         │ entity X at timestamp t?                     │
├─────────────────────────┼──────────────────────────────────────────────┤
│ 2. pandas.merge_asof    │ Algorithmic Join Operator: How do we align   │
│                         │ irregularly timed records on an index?       │
├─────────────────────────┼──────────────────────────────────────────────┤
│ 3. Survivorship Bias    │ Universe Selection: Which entities existed   │
│                         │ and were tradable at timestamp t?            │
└─────────────────────────┴──────────────────────────────────────────────┘

1. PIT architecture vs. pandas.merge_asof

Many researchers assume that calling pandas.merge_asof automatically makes their backtest point-in-time compliant. This is an incorrect assumption.

pandas.merge_asof is simply an alignment operator. It performs an inexact backward match between two sorted temporal indexes (for instance, attaching the latest filed balance sheet to daily price bars).

However, merge_asof operates only on the columns supplied to it. If the dataframe fed into merge_asof contains modern restated numbers, or if the timestamp column used for the join is period_end rather than publication_timestamp, merge_asof merely executes lookahead contamination with high computational speed.

merge_asof_trap.py
# DANGEROUS: Using merge_asof does NOT guarantee Point-in-Time compliance!
# If fundamentals_df contains restated values or is indexed on period_end:
df_aligned = pd.merge_asof(
    price_df.sort_values("timestamp"),
    fundamentals_df.sort_values("period_end"),  # LOOKAHEAD: Indexing on period end
    by="ticker",
    left_on="timestamp",
    right_on="period_end",
    direction="backward",
)

To use merge_asof causally, the right dataframe must be pre-filtered by an as-of query engine, and the join key must strictly be published_at:

causal_merge_asof.py
# CAUSAL: Merging on publication timestamp using pre-filtered PIT records
df_aligned = pd.merge_asof(
    price_df.sort_values("timestamp"),
    pit_records_df.sort_values("published_at"),
    by="ticker",
    left_on="timestamp",
    right_on="published_at",
    direction="backward",
)

2. PIT data vs. survivorship bias

While point-in-time data resolves information accuracy, survivorship bias resolves universe membership:

  • Survivorship Bias: Answering which companies were tradable in the investment universe on date t. If you test a strategy from 2010 to 2025 using the modern S&P 500 member list, you exclude Enron, Lehman Brothers, and hundreds of delisted, acquired, or bankrupt entities, artificially inflating Sharpe ratios.
  • Point-in-Time Data: Answering what was known about those companies on date t. Even if your universe correctly includes Lehman Brothers on September 1, 2008 (eliminating survivorship bias), using 2010 bankruptcy liquidator restatements of Lehman's 2007 balance sheet violates point-in-time causality.

Both biases must be addressed simultaneously: your universe constituents must be selected via point-in-time index rosters, and each constituent's features must be queried via bi-temporal as-of engines.

Institutional data verification checklist

Before incorporating any fundamental or macroeconomic dataset into a production backtest, verify it against this six-point audit checklist:

  • Publication Timestamp Precision: Does every row contain an immutable publication_date with hour, minute, and second resolution (e.g., SEC EDGAR filing stamp), rather than just a calendar date?
  • Bi-Temporal Versioning: Does the data vendor preserve prior preliminary prints as distinct rows, or do they overwrite historical cells when restatements occur?
  • Market Close Awareness: If an earnings release occurs at 16:05 UTC (after market close), is the effective trading availability set to the next trading day's market open?
  • Corporate Action Decoupling: Are per-share fundamental metrics (like EPS or Book Value per share) unadjusted in the raw store, and dynamically adjusted using only stock splits executed on or before the simulation date?
  • Macroeconomic Revision Handling: Are preliminary releases of GDP, payrolls, and inflation indices tracked separately from subsequent benchmark revisions?
  • Immutable Trial Logging: Are the exact dataset versions, query timestamps, and hash identifiers persisted in a local database for trial auditing?

Point-in-time hygiene in single-asset bar-by-bar backtesting

In single-asset algorithmic research—such as quantitative strategies running on OpenBacktesting (0.2.1, Python >=3.12,<3.15)—market data is processed deterministically in a chronological bar-by-bar event loop.

OpenBacktesting is intentionally architected for single-asset historical OHLCV bar-by-bar research with SQLite trial persistence, inspectable trades, orders, and equity curves. While OpenBacktesting does not include a multi-asset portfolio accounting engine or live broker connectivity, its strict bar-by-bar processing model provides the ideal foundation for point-in-time integrity.

When combining auxiliary fundamental signals or macroeconomic filters with single-asset price bars, apply these three core engineering rules:

Code
                       Causal Bar-by-Bar Processing
┌────────────────────────────────────────────────────────────────────────┐
│ Simulation Clock: bar_t.timestamp                                     │
│                                                                        │
│ 1. Market Price Bar: [Open, High, Low, Close, Volume] for bar_t        │
│ 2. Auxiliary PIT Query: query_as_of(symbol, as_of=bar_t.timestamp)     │
│ 3. Signal Generation: signal = evaluate(bar_t, pit_fundamental)       │
│ 4. Order Staging: order submitted for execution at bar_{t+1}.open      │
└────────────────────────────────────────────────────────────────────────┘
  1. Synchronize on Bar Open or Close Timestamps: Never query auxiliary data using system clock time (datetime.now()) or end-of-day dates. The query parameter must explicitly be as_of = current_bar.timestamp.
  2. Respect the After-Hours Boundary: If a company files its quarterly report at 16:15 on date T, an intraday or daily bar closing at 16:00 on date T cannot condition its signal on that report. The new fundamental metric is only available for the bar closing at or after 09:30 on date T+1.
  3. Persist Data Provenance in SQLite: When running research trials, persist the unique version hash or snapshot timestamp of your auxiliary dataset alongside the strategy hyperparameters. OpenBacktesting stores trial configurations and trade logs in SQLite, ensuring that any performance metric can be audited against the exact data state used during execution.

Summary: The cost of ignoring historical reality

A backtest that ignores point in time data does not measure strategy alpha. It measures the predictive power of future accounting corrections applied retroactively to historical asset prices.

By implementing bi-temporal schemas, tracking publication timestamps, and decoupling reporting periods from market availability dates, quantitative researchers ensure that historical simulations honor physical time. Only strategies that survive rigorous point-in-time evaluation can be deployed into live markets with statistical confidence.