Artifex/tests/test_hyperscalper_cohort_materialization.py
2026-08-18 02:00:53 +07:00

260 lines
9.7 KiB
Python

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)