from datetime import UTC, datetime, timedelta from hashlib import sha256 from inspect import getsource import numpy as np import pytest from control_plane.trading_studio import cohort_materialization as materialization from control_plane.trading_studio.management.commands.canary_hyperscalper_cohort_001 import ( Command as CanaryCommand, ) from control_plane.trading_studio.management.commands.materialize_hyperscalper_cohort_001 import ( DATASET_SHA256, DATASET_VERSION_ID, Command, ) def row(index): return { "timestamp": datetime(2025, 1, 1, tzinfo=UTC) + timedelta(minutes=index), "open": 1.0, "high": 1.1, "low": 0.9, "close": 1.0, } def test_canonical_manifest_serialization_is_sorted_pretty_ascii_without_newline(): manifest = {"z": "cafe", "a": [1, {"b": True}]} serialized = materialization.canonical_json(manifest) assert ( serialized == '{\n "a": [\n 1,\n {\n "b": true\n }\n ],\n "z": "cafe"\n}' ) assert sha256(serialized.encode()).hexdigest() == ( "c1f9b496e9724f3cf4b0ab781589f6d8db6e48f5de90f9ea9c39defb20748dc9" ) def test_manifest_requires_canonical_self_semantic_and_lineage_hashes(monkeypatch): monkeypatch.setattr(materialization, "MANIFEST_HASH_PREFIX", "") records = [ { "rank": 1, "source_strategy_id": 490761, "source_name": "B7435 TP1.8/SL0.8", "base_family": "B7435", "combo": [79, 30, 8.0], "old_selection_metrics": {"id": 490761}, "old_final_metrics": {"id": 490761}, } ] monkeypatch.setattr( materialization, "SEMANTIC_DIGEST", materialization.semantic_digest(records) ) manifest = {"members": records, "lineage": {"source": "frozen"}} manifest["lineage_sha256"] = materialization.digest(manifest["lineage"]) manifest["manifest_sha256"] = materialization.digest(manifest) materialization.validate_manifest(manifest, cohort=True) manifest["lineage"]["source"] = "changed" manifest["manifest_sha256"] = materialization.digest( {key: value for key, value in manifest.items() if key != "manifest_sha256"} ) with pytest.raises(ValueError, match="lineage"): materialization.validate_manifest(manifest, cohort=True) def test_semantic_digest_uses_compact_sorted_projection_and_required_full_digest(): assert materialization.SEMANTIC_DIGEST == ( "cc697ea359f20ccc83c5d62f5b406a3532c1d7411191423059164aafe5931254" ) records = [ { "rank": 2, "source_strategy_id": 2, "source_name": "B2", "base_family": "B2", "combo": [2], "old_selection_metrics": {"id": 2}, "old_final_metrics": {"id": 2}, }, { "rank": 1, "source_strategy_id": 1, "source_name": "B1", "base_family": "B1", "combo": [1], "old_selection_metrics": {"id": 1}, "old_final_metrics": {"id": 1}, }, ] with pytest.raises(ValueError, match="uniquely ordered"): materialization.semantic_digest(records) def test_reconstructed_folds_have_exact_train_embargo_and_test_windows(): rows = [row(index) for index in range(materialization.DATASET_RECORD_COUNT)] folds = materialization.reconstruct_folds(rows, "timestamp") assert len(folds) == 4 for fold in folds: assert fold["train"]["end_index"] - fold["train"]["start_index"] + 1 == 14_400 assert fold["embargo"]["bars"] == 35 assert fold["embargo"]["status"] == "EXCLUDED" assert fold["embargo"]["start_index"] == fold["train"]["end_index"] + 1 assert fold["test"]["start_index"] == fold["embargo"]["end_index"] + 1 assert fold["test"]["end_index"] - fold["test"]["start_index"] + 1 == 7_200 assert fold["provenance"] == "RECONSTRUCTED_FROM_FROZEN_SPEC_V1" def test_csv_validation_rejects_noncontinuous_timestamps(monkeypatch, tmp_path): monkeypatch.setattr(materialization, "DATASET_RECORD_COUNT", 3) path = tmp_path / "dataset.csv" path.write_text( "timestamp,open,high,low,close\n" "1735689600,1,1.1,0.9,1\n" "1735689720,1,1.1,0.9,1\n" "1735690000,1,1.1,0.9,1\n", encoding="utf-8", ) rows, headers = materialization.load_csv(path, "timestamp") manifest = {"columns": headers, "timestamp_field": "timestamp"} with pytest.raises(ValueError, match="continuity"): materialization.validate_rows(rows, headers, manifest) def test_dataset_manifest_treats_sha256_as_the_csv_artifact_hash_not_a_self_hash(): manifest = { "artifact": "artifact://binance_btcusdt_spot_2m_180d.csv", "sha256": "a" * 64, "row_count": materialization.DATASET_RECORD_COUNT, "fields": ["timestamp", "open", "high", "low", "close", "volume"], "monotonic_timestamps": True, "schema_valid": True, } materialization.validate_dataset_manifest(manifest) manifest["schema_valid"] = False with pytest.raises(ValueError, match="declarations"): materialization.validate_dataset_manifest(manifest) def test_existing_dataset_recovery_uses_crypto_hyperscalper_and_real_artifact_path(): source = getsource(Command._dataset) assert 'slug != "crypto-hyperscalper"' in source assert "(root / DATASET_CSV).resolve()" in source assert '"first_timestamp"' in source assert '"last_timestamp"' in source def test_actual_shape_member_maps_to_stable_semantic_ids_and_authorized_dataset(): member = { "rank": 1, "source_strategy_id": 490761, "source_name": "B7435 TP1.8/SL0.8", "base_family": "B7435", "combo": [79, 30, 8.0], "old_selection_metrics": {"id": 490761}, "old_final_metrics": {"id": 490761}, } assert Command._fingerprint(member) == Command._fingerprint(dict(member)) assert Command._member_id(member) == Command._member_id(dict(member)) assert str(DATASET_VERSION_ID) == "1f224db9-cbb8-4aec-8575-98c4b0279a83" assert DATASET_SHA256 == "7fb56bb05b0edc2348407765cd693efadf334307c25877dfb52acfe4221e5d00" def test_prior_cohort_policy_preserves_historic_manifest_when_reconstruction_is_added(): policy = {"manifest_sha256": "4d20historic", "prior_note": "preserve"} assert Command._historic_manifest_sha(policy) == "4d20historic" policy["reconstruction_v1"] = {"folds": ["reconstructed"]} assert policy["prior_note"] == "preserve" assert Command._historic_manifest_sha(policy) == "4d20historic" def test_canary_reads_reconstruction_v1_instead_of_obsolete_frozen_manifest_policy(): source = getsource(CanaryCommand._validate_reconstruction) assert 'get("reconstruction_v1")' in source assert "DATASET_VERSION_ID" in source assert "reconstruct_folds" in source assert "frozen_manifest" not in source def test_canary_uses_native_state_and_keeps_continuous_context(): rows = [ {**row(index), "volume": 100.0} for index in range(3) ] state = { "trend": np.array([1.0, 2.0, 3.0]), "signal": np.array([4.0, 5.0, 6.0]), "trigger": np.array([0.5, 0.5, 0.5]), "confirm": np.array([7.0, 8.0, 9.0]), "vol": np.array([10.0, 11.0, 12.0]), "trend_color": np.array([0, 1, 1]), "signal_color": np.array([0, 1, 1]), "decision": np.array([0, 1, -1]), } bars = CanaryCommand._bars(rows, state, {"start_index": 1, "end_index": 2}) source = getsource(CanaryCommand) assert [bar.signal for bar in bars] == [1, -1] assert bars[0].context == (2.0, 5.0, 0.5, 8.0, 11.0, 1.0, 1.0) assert bars[0].reference == "hs22-native:1" assert "compute_hs22_state" in source assert "compute_combo_state" not in source assert "precomputed" not in source def test_canary_derives_signed_decisions_from_native_hs22_state(monkeypatch): state = { "trigger": np.array([1.0, 1.0, 1.0]), "confirm": np.array([0.0, 0.0, 0.0]), "vol": np.array([1.0, 1.0, 1.0]), "signal_color": np.array([0, 1, -1]), "trend_color": np.array([0, 1, -1]), } monkeypatch.setattr( ( "control_plane.trading_studio.management.commands." "canary_hyperscalper_cohort_001.compute_hs22_state" ), lambda *args: state, ) rows = [ {"close": 1.0, "high": 1.0, "low": 1.0, "volume": 1.0}, {"close": 2.0, "high": 2.0, "low": 2.0, "volume": 1.0}, {"close": 0.5, "high": 0.5, "low": 0.5, "volume": 1.0}, ] combo = [0.0] * 22 combo[17:21] = [-1.0, 1.0, -1.0, 1.0] actual = CanaryCommand._native_state(rows, {"combo": combo}) assert actual["decision"].tolist() == [0, 1, -1] def test_selection_source_must_match_declared_path_and_all_frozen_member_records(tmp_path): source = tmp_path / "selection.json" selection = { "selected": [ { "selection": {"id": 1, "name": "B1"}, "final": {"id": 1, "name": "B1"}, } ] * 20 } source.write_text(__import__("json").dumps(selection), encoding="utf-8") members = [ { "source_strategy_id": 1, "source_name": "B1", "old_selection_metrics": {"id": 1, "name": "B1"}, "old_final_metrics": {"id": 1, "name": "B1"}, } for _ in range(20) ] manifest = {"source_report": str(source), "members": members} assert materialization.validate_selection_source(manifest, selection, source) selection["selected"][0]["selection"]["id"] = 2 with pytest.raises(ValueError, match="does not reproduce"): materialization.validate_selection_source(manifest, selection, source)