"""Offline synthetic v2 backtest evidence and replay boundaries.""" from __future__ import annotations from typing import Any import pytest from quant_engine.factor_contracts import FactorContractError, PayloadValidation from quant_engine.retrospective_backtest_contracts import RetrospectiveBacktestRunRef from quant_engine.retrospective_factor_contracts import RetrospectiveFactorSetRef from test_retrospective_data_contracts import digest, identify, replace_at from test_retrospective_factor_contracts import factor_arguments, decoding_arguments def run_arguments() -> dict[str, Any]: arguments = factor_arguments() factor = RetrospectiveFactorSetRef.create(**arguments) view = next(iter(arguments["foundation"].views.values())) return { "dataset_snapshot": arguments["dataset_snapshot"], "foundation": arguments["foundation"], "factor_set": factor, "universe_digest": digest({"synthetic_universe": 2}), "trading_calendar_revision_ids": view.trading_calendar_revision_ids, "corporate_action_revision_ids": view.corporate_action_revision_ids, "strategy_id": "synthetic.top1", "strategy_version": "1.0.0", "strategy_digest": digest({"synthetic_strategy": "top1"}), "execution_model_version": "1.0.0", "execution_model_digest": digest({"synthetic_execution": 1}), "cost_model_version": "1.0.0", "cost_model_digest": digest({"synthetic_cost": 1}), "random_seed": 7, "code_revision": "d" * 40, "environment_lock_digest": digest({"synthetic_lock": 1}), "configuration_digest": digest({"lag_sessions": 1, "top_k": 1}), "evaluation_at": "2026-09-08T01:09:00Z", "computed_at": "2026-09-08T01:10:00Z", } def run_context(arguments: dict[str, Any]) -> dict[str, Any]: return {key: arguments[key] for key in ("dataset_snapshot", "foundation", "factor_set")} def test_run_identity_closes_observation_inputs_and_preserves_configurations() -> None: arguments = run_arguments() run = RetrospectiveBacktestRunRef.create(**arguments) document = run.to_dict() assert document["schema_version"] == "2.0.0" assert run.run_id.startswith("rhbacktestrunv2:sha256:") assert run.dataset_snapshot_id == arguments["dataset_snapshot"].snapshot_id assert run.foundation_id == arguments["foundation"].foundation_id assert run.factor_set_id == arguments["factor_set"].factor_set_id assert document["usage"] == "retrospective_research" assert document["historical_availability"] == "not_established" assert document["decision_eligible"] is False assert document["execution_validation"] == "not_validated" assert document["observation_cutoff"] == arguments["foundation"].observation_cutoff assert document["replay_attempt"] == 0 assert RetrospectiveBacktestRunRef.from_json(run.to_json(), **run_context(arguments)) == run @pytest.mark.parametrize( ("path", "value"), [ ("schema_version", "1.0.0"), ("schema_version", "2.1.0"), ("historical_availability", "established"), ("usage", "as_available"), ("execution_validation", "validated"), ("decision_eligible", True), ("decision_eligible", 0), ("dataset_content_digest", "sha256:" + "0" * 64), ("foundation_digest", "sha256:" + "0" * 64), ("factor_set_digest", "sha256:" + "0" * 64), ("factor_output_content_digest", "sha256:" + "0" * 64), ("observation_cutoff", "2018-01-02T07:00:00Z"), ("evidence_scope", "real_data"), ("trading_calendar_revision_ids", []), ("corporate_action_revision_ids", ["rhcav2:sha256:" + "0" * 64]), ("evaluation_at", "2026-09-08T01:07:00Z"), ("computed_at", "2026-09-08T01:08:00Z"), ("computed_at", "2026-09-08T01:10:00.0000001Z"), ("random_seed", True), ("strategy_version", "latest"), ("configuration_digest", "../private/a"), ("code_revision", "unknown"), ("replay_attempt", 1), ("replay_reason", "retry"), ("replay_spec_digest", "sha256:" + "0" * 64), ("replay_ancestor_run_ids", ["rhbacktestrunv2:sha256:" + "0" * 64]), ], ) def test_reidentified_run_must_match_exact_context(path: str, value: Any) -> None: arguments = run_arguments() row = RetrospectiveBacktestRunRef.create(**arguments).to_dict() replace_at(row, path, value) identify(row, "run_id", "rhbacktestrunv2:") with pytest.raises(FactorContractError): RetrospectiveBacktestRunRef.from_dict(row, **run_context(arguments)) def test_replay_keeps_input_spec_but_requires_new_actual_attempt_times() -> None: arguments = run_arguments() root = RetrospectiveBacktestRunRef.create(**arguments) replay_args = { **arguments, "parent": root, "replay_reason": "synthetic.retry", "replay_attempt": 1, "evaluation_at": "2026-09-08T01:12:00Z", "computed_at": "2026-09-08T01:13:00Z", } replay = RetrospectiveBacktestRunRef.create(**replay_args) assert replay.replay_spec_digest == root.replay_spec_digest assert replay.run_id != root.run_id assert replay.replay_ancestor_run_ids == (root.run_id,) assert replay.evaluation_at != root.evaluation_at assert ( RetrospectiveBacktestRunRef.from_json( replay.to_json(), **run_context(arguments), parent=root ) == replay ) for changes in ( {"random_seed": 9}, {"configuration_digest": digest({"different_configuration": 1})}, {"evaluation_at": root.evaluation_at}, {"replay_attempt": 2}, {"replay_reason": None}, {"parent": None}, ): with pytest.raises(FactorContractError): RetrospectiveBacktestRunRef.create(**{**replay_args, **changes}) def test_reference_only_factors_can_be_read_but_not_used_to_create_new_runs() -> None: arguments = run_arguments() run = RetrospectiveBacktestRunRef.create(**arguments) factor = arguments["factor_set"] reference = RetrospectiveFactorSetRef.from_dict( factor.to_dict(), definitions=factor._definitions, dataset_snapshot=arguments["dataset_snapshot"], foundation=arguments["foundation"], ) with pytest.raises(FactorContractError): RetrospectiveBacktestRunRef.create(**{**arguments, "factor_set": reference}) restored = RetrospectiveBacktestRunRef.from_dict( run.to_dict(), **{**run_context(arguments), "factor_set": reference} ) assert restored.input_payload_validation is PayloadValidation.REFERENCE_ONLY with pytest.raises(FactorContractError): restored.require_inputs_revalidated() run.require_inputs_revalidated()