Artifex/historical_feature_oracle_v1.py
2026-08-18 14:21:35 +07:00

208 lines
8.9 KiB
Python

"""Standalone runner for recovered historical ``hyperscalper.fast_engine``.
This file intentionally has no Artifex imports. Copy it with a request JSON,
CSV, this file's direct-registry module, and the recovered
``code-5056feb/src`` tree to run an external oracle.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import sys
from pathlib import Path
from typing import Any
import numpy as np
from historical_feature_oracle_direct_registry_v1 import load_direct_registry
ENGINE_REVISION = "code-5056feb"
ARTIFACT = "HISTORICAL_FEATURE_ORACLE_V1_RESULT"
REQUIRED_COLUMNS = ("close", "high", "low", "volume")
def _canonical_bytes(value: object) -> bytes:
return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False).encode("utf-8")
def _sha256_bytes(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def _array_sha256(values: np.ndarray) -> str:
contiguous = np.ascontiguousarray(values)
header = _canonical_bytes({"dtype": contiguous.dtype.str, "shape": contiguous.shape})
return _sha256_bytes(header + b"\0" + contiguous.tobytes())
def _load_ohlcv(path: Path, columns: tuple[str, ...]) -> tuple[np.ndarray, ...]:
# NumPy owns parsing so this runner has no CSV/dataframe dependency.
table = np.genfromtxt(path, delimiter=",", names=True, dtype=None, encoding="utf-8")
table = np.atleast_1d(table)
names = set(table.dtype.names or ())
missing = set(columns) - names
if missing:
raise ValueError(f"CSV is missing required columns: {', '.join(sorted(missing))}")
arrays = tuple(np.asarray(table[name], dtype=np.float64) for name in columns)
if not arrays[0].size or any(array.ndim != 1 or array.shape != arrays[0].shape for array in arrays):
raise ValueError("CSV OHLCV columns must be non-empty equally sized vectors")
return arrays
def _load_registry(source: Path):
package = source / "hyperscalper"
engine_file = package / "fast_engine.py"
if not engine_file.is_file() or not (package / "__init__.py").is_file():
raise ValueError("--recovered-source must contain hyperscalper/fast_engine.py from code-5056feb")
if any(
name in {"artifex", "control_plane"}
or name.startswith(("artifex.", "control_plane."))
for name in sys.modules
):
raise RuntimeError("Artifex modules must not be imported by the historical oracle")
return load_direct_registry(source)
def _requests(payload: dict[str, Any], known_ids: set[int]) -> list[dict[str, Any]]:
if payload.get("artifact") != "HISTORICAL_FEATURE_ORACLE_V1_REQUEST":
raise ValueError("request artifact must be HISTORICAL_FEATURE_ORACLE_V1_REQUEST")
if payload.get("schema_version") != 1 or payload.get("engine_revision") != ENGINE_REVISION:
raise ValueError("unsupported historical oracle request version or engine revision")
semantic_base = {
"engine_revision": payload["engine_revision"],
"input_columns": payload.get("input_columns"),
"output_dtype": payload.get("output_dtype"),
"window_policy": payload.get("window_policy"),
}
if semantic_base["input_columns"] != list(REQUIRED_COLUMNS) or semantic_base["output_dtype"] != "float64":
raise ValueError("request has unsupported input or output semantics")
rows = payload.get("requests")
if not isinstance(rows, list) or not rows:
raise ValueError("request must contain a non-empty requests list")
ids: set[str] = set()
parsed: list[dict[str, Any]] = []
for row in rows:
if not isinstance(row, dict):
raise ValueError("every request must be an object")
request_id = row.get("request_id")
if not isinstance(request_id, str) or not request_id or request_id in ids:
raise ValueError("request_id must be a unique non-empty string")
indicator_id, period, p1 = int(row["indicator_id"]), int(row["period"]), float(row["p1"])
if indicator_id not in known_ids:
raise ValueError(f"unknown historical indicator ID: {indicator_id}")
if period <= 0 or not np.isfinite(p1):
raise ValueError(f"invalid period or p1 for {request_id}")
fingerprint = row.get("semantic_fingerprint")
expected_fingerprint = _sha256_bytes(
_canonical_bytes(
{**semantic_base, "indicator_id": indicator_id, "period": period, "p1": p1}
)
)
if fingerprint != expected_fingerprint:
raise ValueError(f"semantic fingerprint mismatch for {request_id}")
ids.add(request_id)
parsed.append(
{
"request_id": request_id,
"indicator_id": indicator_id,
"period": period,
"p1": p1,
"semantic_fingerprint": fingerprint,
}
)
return parsed
def _windows(payload: dict[str, Any], length: int) -> list[dict[str, int | str]]:
rows = payload.get("windows", [{"window_id": "full", "start": 0, "stop": length}])
if not isinstance(rows, list) or not rows:
raise ValueError("windows must be a non-empty list")
windows = []
for row in rows:
if not isinstance(row, dict):
raise ValueError("every window must be an object")
window_id, start, stop = str(row.get("window_id", "")), int(row["start"]), int(row["stop"])
if not window_id or start < 0 or stop <= start or stop > length:
raise ValueError(f"invalid output window: {window_id}")
windows.append({"window_id": window_id, "start": start, "stop": stop})
return windows
def run(request_path: Path, csv_path: Path, output_dir: Path, recovered_source: Path) -> Path:
payload = json.loads(request_path.read_text(encoding="utf-8"))
if not isinstance(payload, dict):
raise ValueError("request JSON must be an object")
expected_csv_hash = payload.get("input_csv_sha256")
csv_hash = _sha256_bytes(csv_path.read_bytes())
if expected_csv_hash is not None and expected_csv_hash != csv_hash:
raise ValueError("input CSV SHA-256 does not match the request")
columns = tuple(payload.get("input_columns", REQUIRED_COLUMNS))
if columns != REQUIRED_COLUMNS:
raise ValueError("only close, high, low, volume input semantics are supported")
close, high, low, volume = _load_ohlcv(csv_path, columns)
registry, provenance = _load_registry(recovered_source)
requests = _requests(payload, set(registry))
windows = _windows(payload, len(close))
outputs: dict[str, np.ndarray] = {}
records = []
for row in requests:
values = np.asarray(
registry[row["indicator_id"]](close, high, low, volume, row["period"], row["p1"]),
dtype=np.float64,
)
direct = np.asarray(
registry[row["indicator_id"]](close, high, low, volume, row["period"], row["p1"]),
dtype=np.float64,
)
if values.shape != close.shape or not np.array_equal(values, direct, equal_nan=True):
raise RuntimeError(f"direct helper self-validation failed for {row['request_id']}")
outputs[row["request_id"]] = values
records.append(
{
**row,
"dtype": values.dtype.str,
"shape": list(values.shape),
"sha256": _array_sha256(values),
"window_sha256": {
window["window_id"]: _array_sha256(values[window["start"] : window["stop"]])
for window in windows
},
}
)
output_dir.mkdir(parents=True, exist_ok=True)
npz_path = output_dir / "historical_feature_oracle_v1_outputs.npz"
np.savez_compressed(npz_path, **outputs)
result_path = output_dir / "historical_feature_oracle_v1_result.json"
result = {
"schema_version": 1,
"artifact": ARTIFACT,
"engine_revision": ENGINE_REVISION,
"request_sha256": _sha256_bytes(request_path.read_bytes()),
"input_csv_sha256": csv_hash,
"engine_sha256": _sha256_bytes(
(recovered_source / "hyperscalper" / "fast_engine.py").read_bytes()
),
"direct_registry_provenance": provenance,
"row_count": len(close),
"windows": windows,
"outputs_npz": {"path": npz_path.name, "sha256": _sha256_bytes(npz_path.read_bytes())},
"requests": records,
}
result_path.write_bytes(_canonical_bytes(result) + b"\n")
return result_path
def main() -> None:
parser = argparse.ArgumentParser(description="Run recovered code-5056feb historical features offline.")
parser.add_argument("--request", type=Path, required=True)
parser.add_argument("--input-csv", type=Path, required=True)
parser.add_argument("--output-dir", type=Path, required=True)
parser.add_argument("--recovered-source", type=Path, required=True)
args = parser.parse_args()
print(run(args.request, args.input_csv, args.output_dir, args.recovered_source))
if __name__ == "__main__":
main()